version 0.3.33
[fms.git] / src / freenet / identityinserter.cpp
1 #include "../../include/freenet/identityinserter.h"\r
2 #include "../../include/freenet/identityxml.h"\r
3 #include "../../include/stringfunctions.h"\r
4 #include "../../include/option.h"\r
5 \r
6 #include <Poco/DateTimeFormatter.h>\r
7 #include <Poco/DateTimeParser.h>\r
8 \r
9 #ifdef XMEM\r
10         #include <xmem.h>\r
11 #endif\r
12 \r
13 IdentityInserter::IdentityInserter(SQLite3DB::DB *db):IDatabase(db)\r
14 {\r
15         Initialize();\r
16 }\r
17 \r
18 IdentityInserter::IdentityInserter(SQLite3DB::DB *db, FCPv2::Connection *fcp):IDatabase(db),IFCPConnected(fcp)\r
19 {\r
20         Initialize();\r
21 }\r
22 \r
23 void IdentityInserter::CheckForNeededInsert()\r
24 {\r
25         Poco::DateTime now;\r
26         Poco::DateTime date;\r
27 \r
28         // set date to 1 hour back\r
29         date-=Poco::Timespan(0,1,0,0,0);\r
30 \r
31         // Because of importance of Identity.xml, if we are now at the next day we immediately want to insert identities so change the date back to 12:00 AM so we find all identities not inserted yet today\r
32         if(date.day()!=now.day())\r
33         {\r
34                 date=now;\r
35                 date.assign(date.year(),date.month(),date.day(),0,0,0);\r
36         }\r
37 \r
38         SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND InsertingIdentity='false' AND (LastInsertedIdentity<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"' OR LastInsertedIdentity IS NULL) ORDER BY LastInsertedIdentity;");\r
39         \r
40         if(rs.Empty()==false)\r
41         {\r
42                 StartInsert(rs.GetInt(0));\r
43         }\r
44 \r
45 }\r
46 \r
47 void IdentityInserter::FCPConnected()\r
48 {\r
49         m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false';");\r
50 }\r
51 \r
52 \r
53 void IdentityInserter::FCPDisconnected()\r
54 {\r
55         \r
56 }\r
57 \r
58 const bool IdentityInserter::HandleMessage(FCPv2::Message &message)\r
59 {\r
60 \r
61         if(message["Identifier"].find("IdentityInserter")==0)\r
62         {\r
63                 Poco::DateTime now;\r
64                 std::vector<std::string> idparts;\r
65 \r
66                 StringFunctions::Split(message["Identifier"],"|",idparts);\r
67                 m_lastreceivedmessage=now;\r
68 \r
69                 // no action for URIGenerated\r
70                 if(message.GetName()=="URIGenerated")\r
71                 {\r
72                         return true;\r
73                 }\r
74 \r
75                 // no action for IdentifierCollision\r
76                 if(message.GetName()=="IdentifierCollision")\r
77                 {\r
78                         return true;\r
79                 }\r
80 \r
81                 if(message.GetName()=="PutSuccessful")\r
82                 {\r
83         \r
84                         // do check to make sure this is the non-editioned SSK - we ignore failure/success for editioned SSK for now\r
85                         if(message["Identifier"].find(".xml")!=std::string::npos)\r
86                         {\r
87                                 // a little hack here - if we just inserted index yesterday and it is now the next day - we would have inserted todays date not yesterdays as LastInsertedIdentity.\r
88                                 // If this is the case, we will skip updating LastInsertedIdentity so that we can insert this identity again for today\r
89                                 Poco::DateTime lastdate;\r
90                                 int tzdiff=0;\r
91                                 Poco::DateTimeParser::tryParse("%Y-%m-%d",idparts[4],lastdate,tzdiff);\r
92                                 if(lastdate.day()==now.day())\r
93                                 {\r
94                                         m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false', LastInsertedIdentity='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
95                                 }\r
96                                 else\r
97                                 {\r
98                                         m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false' WHERE LocalIdentityID="+idparts[1]+";");\r
99                                 }\r
100                                 m_db->Execute("INSERT INTO tblLocalIdentityInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
101                                 m_log->debug("IdentityInserter::HandleMessage inserted Identity xml");\r
102                         }\r
103                         else\r
104                         {\r
105                                 m_log->trace("IdentityInserter::HandleMessage inserted editioned Identity xml");\r
106                         }\r
107                         return true;\r
108                 }\r
109 \r
110                 if(message.GetName()=="PutFailed")\r
111                 {\r
112                         // do check to make sure this is the non-editioned SSK - we ignore failure/success for editioned SSK for now\r
113                         if(message["Identifier"].find(".xml")!=std::string::npos)\r
114                         {\r
115                                 m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false' WHERE LocalIdentityID="+idparts[1]+";");\r
116                                 m_log->debug("IdentityInserter::HandleMessage failure inserting Identity xml.  Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
117                                 \r
118                                 // if code 9 (collision), then insert index into inserted table\r
119                                 if(message["Code"]=="9")\r
120                                 {\r
121                                         m_db->Execute("INSERT INTO tblLocalIdentityInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
122                                 }\r
123                         }\r
124                         else\r
125                         {\r
126                                 m_log->trace("IdentityInserter::HandleMessage PutFailed for editioned SSK error code "+message["Code"]+ " id "+message["Identifier"]);\r
127                         }\r
128                         \r
129                         return true;\r
130                 }\r
131 \r
132         }\r
133 \r
134         return false;\r
135 \r
136 }\r
137 \r
138 void IdentityInserter::Initialize()\r
139 {\r
140         m_lastchecked=Poco::Timestamp();\r
141         m_lastreceivedmessage=Poco::Timestamp();\r
142 }\r
143 \r
144 void IdentityInserter::Process()\r
145 {\r
146         Poco::DateTime now;\r
147 \r
148         if(m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
149         {\r
150                 CheckForNeededInsert();\r
151                 m_lastchecked=now;\r
152         }\r
153 \r
154         if(m_lastreceivedmessage<(now-Poco::Timespan(0,0,10,0,0)))\r
155         {\r
156                 SQLite3DB::Statement st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE InsertingIdentity='true';");\r
157                 st.Step();\r
158                 if(st.RowReturned())\r
159                 {\r
160                         m_log->debug("IdentityInserter::Process 10 minutes have passed without an insert response from the node.  Restarting inserts.");\r
161                         m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false';");\r
162                 }\r
163         }\r
164 \r
165 }\r
166 \r
167 void IdentityInserter::RegisterWithThread(FreenetMasterThread *thread)\r
168 {\r
169         thread->RegisterFCPConnected(this);\r
170         thread->RegisterFCPMessageHandler(this);\r
171         thread->RegisterPeriodicProcessor(this);\r
172 }\r
173 \r
174 void IdentityInserter::StartInsert(const long localidentityid)\r
175 {\r
176         Poco::DateTime date;\r
177         std::string idstring;\r
178 \r
179         StringFunctions::Convert(localidentityid,idstring);\r
180 \r
181         SQLite3DB::Recordset rs=m_db->Query("SELECT Name,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite,FreesiteEdition FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");\r
182 \r
183         if(rs.Empty()==false)\r
184         {\r
185                 IdentityXML idxml;\r
186                 FCPv2::Message mess;\r
187                 Poco::DateTime now;\r
188                 std::string messagebase;\r
189                 std::string data;\r
190                 std::string datasizestr;\r
191                 std::string privatekey;\r
192                 long index=0;\r
193                 std::string indexstr;\r
194                 std::string singleuse="false";\r
195                 std::string publishtrustlist="false";\r
196                 std::string publishboardlist="false";\r
197                 std::string freesiteedition="";\r
198                 int edition=-1;\r
199 \r
200                 now=Poco::Timestamp();\r
201 \r
202                 SQLite3DB::Recordset rs2=m_db->Query("SELECT MAX(InsertIndex) FROM tblLocalIdentityInserts WHERE LocalIdentityID="+idstring+" AND Day='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"';");\r
203                 if(rs2.Empty()==false)\r
204                 {\r
205                         if(rs2.GetField(0)==NULL)\r
206                         {\r
207                                 index=0;\r
208                         }\r
209                         else\r
210                         {\r
211                                 index=rs2.GetInt(0)+1;\r
212                         }\r
213                 }\r
214                 StringFunctions::Convert(index,indexstr);\r
215 \r
216                 Option option(m_db);\r
217                 option.Get("MessageBase",messagebase);\r
218 \r
219                 if(rs.GetField(0))\r
220                 {\r
221                         idxml.SetName(rs.GetField(0));\r
222                 }\r
223 \r
224                 if(rs.GetField(1))\r
225                 {\r
226                         privatekey=rs.GetField(1);\r
227                 }\r
228 \r
229                 if(rs.GetField(2))\r
230                 {\r
231                         singleuse=rs.GetField(2);\r
232                 }\r
233                 singleuse=="true" ? idxml.SetSingleUse(true) : idxml.SetSingleUse(false);\r
234 \r
235                 if(rs.GetField(3))\r
236                 {\r
237                         publishtrustlist=rs.GetField(3);\r
238                 }\r
239                 publishtrustlist=="true" ? idxml.SetPublishTrustList(true) : idxml.SetPublishTrustList(false);\r
240 \r
241                 if(rs.GetField(4))\r
242                 {\r
243                         publishboardlist=rs.GetField(4);\r
244                 }\r
245                 publishboardlist=="true" ? idxml.SetPublishBoardList(true) : idxml.SetPublishBoardList(false);\r
246 \r
247                 if(rs.GetField(5) && rs.GetField(6))\r
248                 {\r
249                         if(std::string(rs.GetField(5))=="true")\r
250                         {\r
251                                 freesiteedition=rs.GetField(6);\r
252                                 StringFunctions::Convert(freesiteedition,edition);\r
253                                 idxml.SetFreesiteEdition(edition);\r
254                         }\r
255                 }\r
256 \r
257                 data=idxml.GetXML();\r
258                 StringFunctions::Convert(data.size(),datasizestr);\r
259 \r
260                 mess.SetName("ClientPut");\r
261                 mess["URI"]=privatekey+messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|Identity|"+indexstr+".xml";\r
262                 mess["Identifier"]="IdentityInserter|"+idstring+"|"+indexstr+"|"+mess["URI"];\r
263                 mess["UploadFrom"]="direct";\r
264                 mess["DataLength"]=datasizestr;\r
265                 m_fcp->Send(mess);\r
266                 m_fcp->Send(std::vector<char>(data.begin(),data.end()));\r
267 \r
268                 // test insert as editioned SSK\r
269                 mess.Clear();\r
270                 mess.SetName("ClientPut");\r
271                 mess["URI"]=privatekey+messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|Identity-"+indexstr;\r
272                 mess["Identifier"]="IdentityInserter|"+mess["URI"];\r
273                 mess["UploadFrom"]="direct";\r
274                 mess["DataLength"]=datasizestr;\r
275                 m_fcp->Send(mess);\r
276                 m_fcp->Send(std::vector<char>(data.begin(),data.end()));\r
277 \r
278                 m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='true' WHERE LocalIdentityID="+idstring+";");\r
279 \r
280         }\r
281 }\r