version 0.2.11
[fms.git] / src / freenet / messageinserter.cpp
1 #include "../../include/freenet/messageinserter.h"\r
2 #include "../../include/freenet/messagexml.h"\r
3 \r
4 MessageInserter::MessageInserter()\r
5 {\r
6         Initialize();\r
7 }\r
8 \r
9 MessageInserter::MessageInserter(FCPv2 *fcp):IIndexInserter<std::string>(fcp)\r
10 {\r
11         Initialize();\r
12 }\r
13 \r
14 void MessageInserter::CheckForNeededInsert()\r
15 {\r
16         bool didinsert=false;\r
17         // only do 1 insert at a time\r
18         if(m_inserting.size()==0)\r
19         {\r
20                 SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.PrivateKey IS NOT NULL AND tblLocalIdentity.PrivateKey <> '' AND tblMessageInserts.Inserted='false';");\r
21                 st.Step();\r
22 \r
23                 while(st.RowReturned() && m_inserting.size()==0)\r
24                 {\r
25                         std::string messageuuid="";\r
26                         st.ResultText(0,messageuuid);\r
27 \r
28                         // make sure there are no uninserted files attached to this message\r
29                         SQLite3DB::Statement st2=m_db->Prepare("SELECT FileInsertID FROM tblFileInserts WHERE Key IS NULL AND MessageUUID=?;");\r
30                         st2.Bind(0,messageuuid);\r
31                         st2.Step();\r
32 \r
33                         if(st2.RowReturned()==false)\r
34                         {\r
35                                 StartInsert(messageuuid);\r
36                         }\r
37 \r
38                         st.Step();\r
39                 }\r
40         }\r
41 }\r
42 \r
43 const bool MessageInserter::HandlePutFailed(FCPMessage &message)\r
44 {\r
45         int index;\r
46         int localidentityid;\r
47         std::vector<std::string> idparts;\r
48         StringFunctions::Split(message["Identifier"],"|",idparts);\r
49         StringFunctions::Convert(idparts[2],localidentityid);\r
50         StringFunctions::Convert(idparts[3],index);\r
51 \r
52         // fatal put - or data exists - insert bogus index into database so we'll try to insert this message again\r
53         if(message["Fatal"]=="true" || message["Code"]=="9")\r
54         {\r
55                 SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');");\r
56                 st.Bind(0,localidentityid);\r
57                 st.Bind(1,idparts[6]);\r
58                 st.Bind(2,index);\r
59                 st.Step();\r
60         }\r
61 \r
62         RemoveFromInsertList(idparts[1]);\r
63 \r
64         return true;\r
65 }\r
66 \r
67 const bool MessageInserter::HandlePutSuccessful(FCPMessage &message)\r
68 {\r
69         MessageXML xml;\r
70         DateTime date;\r
71         int localidentityid;\r
72         int index;\r
73         std::vector<std::string> idparts;\r
74 \r
75         StringFunctions::Split(message["Identifier"],"|",idparts);\r
76         StringFunctions::Convert(idparts[3],index);\r
77         StringFunctions::Convert(idparts[2],localidentityid);\r
78 \r
79         SQLite3DB::Statement st=m_db->Prepare("UPDATE tblMessageInserts SET Day=?, InsertIndex=?, Inserted='true' WHERE MessageUUID=?;");\r
80         st.Bind(0,idparts[6]);\r
81         st.Bind(1,index);\r
82         st.Bind(2,idparts[1]);\r
83         st.Step();\r
84 \r
85         // insert record into temp table so MessageList will be inserted ASAP\r
86         date.SetToGMTime();\r
87         st=m_db->Prepare("INSERT INTO tmpMessageListInsert(LocalIdentityID,Date) VALUES(?,?);");\r
88         st.Bind(0,localidentityid);\r
89         st.Bind(1,date.Format("%Y-%m-%d"));\r
90         st.Step();\r
91 \r
92         // update the messageuuid to the real messageuuid\r
93         st=m_db->Prepare("SELECT MessageXML FROM tblMessageInserts WHERE MessageUUID=?;");\r
94         st.Bind(0,idparts[1]);\r
95         st.Step();\r
96         if(st.RowReturned())\r
97         {\r
98                 std::string xmldata="";\r
99                 st.ResultText(0,xmldata);\r
100                 xml.ParseXML(xmldata);\r
101                 xml.SetMessageID(idparts[4]);\r
102 \r
103                 SQLite3DB::Statement st2=m_db->Prepare("UPDATE tblMessageInserts SET MessageUUID=?, MessageXML=? WHERE MessageUUID=?;");\r
104                 st2.Bind(0,idparts[4]);\r
105                 st2.Bind(1,xml.GetXML());\r
106                 st2.Bind(2,idparts[1]);\r
107                 st2.Step();\r
108 \r
109                 //update file insert MessageUUID as well\r
110                 st2=m_db->Prepare("UPDATE tblFileInserts SET MessageUUID=? WHERE MessageUUID=?;");\r
111                 st2.Bind(0,idparts[4]);\r
112                 st2.Bind(1,idparts[1]);\r
113                 st2.Step();\r
114         }\r
115 \r
116         RemoveFromInsertList(idparts[1]);\r
117 \r
118         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageInserter::HandlePutSuccessful successfully inserted message "+message["Identifier"]);\r
119 \r
120         return true;\r
121 }\r
122 \r
123 void MessageInserter::Initialize()\r
124 {\r
125         m_fcpuniquename="MessageInserter";\r
126 }\r
127 \r
128 void MessageInserter::StartInsert(const std::string &messageuuid)\r
129 {\r
130         MessageXML xmlfile;\r
131         DateTime now;\r
132         now.SetToGMTime();\r
133         SQLite3DB::Statement st=m_db->Prepare("SELECT MessageXML,PrivateKey,tblLocalIdentity.LocalIdentityID,PublicKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE MessageUUID=?;");\r
134         st.Bind(0,messageuuid);\r
135         st.Step();\r
136 \r
137         if(st.RowReturned())\r
138         {\r
139                 int localidentityid;\r
140                 std::string idstr;\r
141                 std::string xml;\r
142                 std::string xmlsizestr;\r
143                 std::string privatekey;\r
144                 std::string publickey;\r
145                 FCPMessage message;\r
146                 std::string indexstr;\r
147                 int index=0;\r
148                 \r
149                 st.ResultText(0,xml);\r
150                 st.ResultText(1,privatekey);\r
151                 st.ResultInt(2,localidentityid);\r
152                 st.ResultText(3,publickey);\r
153                 StringFunctions::Convert(localidentityid,idstr);\r
154 \r
155                 st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblMessageInserts WHERE Day=? AND LocalIdentityID=?;");\r
156                 st.Bind(0,now.Format("%Y-%m-%d"));\r
157                 st.Bind(1,localidentityid);\r
158                 st.Step();\r
159 \r
160                 if(st.ResultNull(0)==false)\r
161                 {\r
162                         st.ResultInt(0,index);\r
163                         index++;\r
164                 }\r
165                 StringFunctions::Convert(index,indexstr);\r
166 \r
167                 xmlfile.ParseXML(xml);\r
168 \r
169                 // add file attachments to xml - must do this before we change UUID\r
170                 st=m_db->Prepare("SELECT Key, Size FROM tblFileInserts WHERE MessageUUID=?;");\r
171                 st.Bind(0,xmlfile.GetMessageID());\r
172                 st.Step();\r
173                 while(st.RowReturned())\r
174                 {\r
175                         std::string key="";\r
176                         int size;\r
177                         \r
178                         st.ResultText(0,key);\r
179                         st.ResultInt(1,size);\r
180 \r
181                         xmlfile.AddFileAttachment(key,size);\r
182 \r
183                         st.Step();\r
184                 }\r
185 \r
186                 // recreate messageuuid in xml - UUID of message will not match entry in MessageInserts table until we successfully insert it\r
187                 // see HandlePutSuccessful\r
188                 // if we don't already have an @sskpart - add it\r
189                 if(xmlfile.GetMessageID().find("@")==std::string::npos)\r
190                 {\r
191                         // remove - and ~ from publickey part\r
192                         std::string publickeypart=StringFunctions::Replace(StringFunctions::Replace(publickey.substr(4,43),"-",""),"~","");\r
193                         xmlfile.SetMessageID(xmlfile.GetMessageID()+"@"+publickeypart);\r
194                 }\r
195                 xml=xmlfile.GetXML();\r
196 \r
197                 StringFunctions::Convert(xml.size(),xmlsizestr);\r
198 \r
199                 message.SetName("ClientPut");\r
200                 message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|Message|"+indexstr+".xml";\r
201                 message["Identifier"]=m_fcpuniquename+"|"+messageuuid+"|"+idstr+"|"+indexstr+"|"+xmlfile.GetMessageID()+"|"+message["URI"];\r
202                 message["UploadFrom"]="direct";\r
203                 message["DataLength"]=xmlsizestr;\r
204                 m_fcp->SendMessage(message);\r
205                 m_fcp->SendRaw(xml.c_str(),xml.size());\r
206 \r
207                 m_inserting.push_back(messageuuid);\r
208 \r
209                 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageInserter::StartInsert started message insert "+message["URI"]);\r
210         }\r
211 \r
212 }\r