1 #ifndef _iindexrequester_
\r
2 #define _iindexrequester_
\r
4 #include "../idatabase.h"
\r
5 #include "../ilogger.h"
\r
6 #include "../option.h"
\r
7 #include "../stringfunctions.h"
\r
8 #include "ifreenetregistrable.h"
\r
9 #include "ifcpconnected.h"
\r
10 #include "ifcpmessagehandler.h"
\r
11 #include "iperiodicprocessor.h"
\r
13 #include <Poco/DateTime.h>
\r
14 #include <Poco/Timestamp.h>
\r
15 #include <Poco/Timespan.h>
\r
17 #include <algorithm>
\r
23 template <class IDTYPE>
\r
24 class IIndexRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger
\r
28 IIndexRequester(FCPv2::Connection *fcp);
\r
29 virtual ~IIndexRequester() {}
\r
31 virtual void FCPConnected();
\r
32 virtual void FCPDisconnected();
\r
33 virtual const bool HandleMessage(FCPv2::Message &message);
\r
35 virtual void Process();
\r
37 virtual void RegisterWithThread(FreenetMasterThread *thread);
\r
40 void InitializeIIndexRequester();
\r
41 virtual void Initialize()=0; // initialize m_maxrequests and m_fcpuniquename
\r
42 virtual void PopulateIDList()=0;
\r
43 virtual void StartRequest(const IDTYPE &id)=0;
\r
44 virtual const bool HandleAllData(FCPv2::Message &message)=0;
\r
45 virtual const bool HandleGetFailed(FCPv2::Message &message)=0;
\r
46 virtual void RemoveFromRequestList(const IDTYPE id);
\r
48 Poco::DateTime m_tempdate;
\r
49 Poco::DateTime m_lastreceived;
\r
50 Poco::DateTime m_lastpopulated;
\r
51 std::string m_messagebase;
\r
52 std::map<IDTYPE,bool> m_ids; // map of all ids we know and whether we have requested file from them yet
\r
53 std::vector<IDTYPE> m_requesting; // list of ids we are currently requesting from
\r
55 // these MUST be populated by child class
\r
57 std::string m_fcpuniquename;
\r
61 template <class IDTYPE>
\r
62 IIndexRequester<IDTYPE>::IIndexRequester()
\r
64 InitializeIIndexRequester();
\r
67 template <class IDTYPE>
\r
68 IIndexRequester<IDTYPE>::IIndexRequester(FCPv2::Connection *fcp):IFCPConnected(fcp)
\r
70 InitializeIIndexRequester();
\r
73 template <class IDTYPE>
\r
74 void IIndexRequester<IDTYPE>::FCPConnected()
\r
76 // make sure variables have been initialized by the derived class
\r
77 if(m_maxrequests==-1)
\r
79 m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");
\r
81 if(m_fcpuniquename=="")
\r
83 m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");
\r
85 if(m_fcpuniquename.find("|")!=std::string::npos)
\r
87 m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename "+m_fcpuniquename+" contains | character! This is not a valid character!");
\r
90 m_lastreceived=Poco::Timestamp();
\r
91 m_requesting.clear();
\r
93 m_lastpopulated=Poco::Timestamp();
\r
96 template <class IDTYPE>
\r
97 void IIndexRequester<IDTYPE>::FCPDisconnected()
\r
102 template <class IDTYPE>
\r
103 const bool IIndexRequester<IDTYPE>::HandleMessage(FCPv2::Message &message)
\r
106 if(message["Identifier"].find(m_fcpuniquename)==0)
\r
109 m_lastreceived=Poco::Timestamp();
\r
111 if(message.GetName()=="DataFound")
\r
116 if(message.GetName()=="AllData")
\r
118 return HandleAllData(message);
\r
121 if(message.GetName()=="GetFailed")
\r
123 return HandleGetFailed(message);
\r
126 if(message.GetName()=="IdentifierCollision")
\r
128 // remove one of the ids from the requesting list
\r
130 std::vector<std::string> idparts;
\r
131 StringFunctions::Split(message["Identifier"],"|",idparts);
\r
132 StringFunctions::Convert(idparts[1],id);
\r
133 RemoveFromRequestList(id);
\r
141 template <class IDTYPE>
\r
142 void IIndexRequester<IDTYPE>::InitializeIIndexRequester()
\r
145 m_fcpuniquename="";
\r
147 Option::Instance()->Get("MessageBase",m_messagebase);
\r
148 m_tempdate=Poco::Timestamp();
\r
149 m_lastreceived=Poco::Timestamp();
\r
150 m_lastpopulated=Poco::Timestamp();
\r
151 m_lastpopulated-=Poco::Timespan(0,0,10,0,0);
\r
154 template <class IDTYPE>
\r
155 void IIndexRequester<IDTYPE>::Process()
\r
157 Poco::DateTime now;
\r
159 // max is the smaller of the config value or the total number of ids we will request from
\r
160 typename std::map<IDTYPE,bool>::size_type max=m_maxrequests>m_ids.size() ? m_ids.size() : m_maxrequests;
\r
162 // try to keep up to max requests going
\r
163 if(m_requesting.size()<max)
\r
165 typename std::map<IDTYPE,bool>::iterator i=m_ids.begin();
\r
167 while(i!=m_ids.end() && (*i).second==true)
\r
174 StartRequest((*i).first);
\r
178 // we requested from all ids in the list, repopulate the list (only every 10 minutes)
\r
179 if(m_lastpopulated<(now-Poco::Timespan(0,0,10,0,0)))
\r
182 m_lastpopulated=Poco::Timestamp();
\r
186 // special case - if there were 0 ids on the list when we started then we will never get a chance to repopulate the list
\r
187 // this will recheck for ids every minute
\r
188 if(m_ids.size()==0 && m_tempdate<(now-Poco::Timespan(0,0,1,0,0)))
\r
193 // if we haven't received any messages to this object in 10 minutes, clear the requests and repopulate id list
\r
194 if(m_ids.size()>0 && m_lastreceived<(now-Poco::Timespan(0,0,10,0,0)))
\r
196 m_log->error("IIndexRequester<IDTYPE>::Process "+m_fcpuniquename+" Object has not received any messages in 10 minutes. Restarting requests.");
\r
202 template <class IDTYPE>
\r
203 void IIndexRequester<IDTYPE>::RegisterWithThread(FreenetMasterThread *thread)
\r
205 thread->RegisterFCPConnected(this);
\r
206 thread->RegisterFCPMessageHandler(this);
\r
207 thread->RegisterPeriodicProcessor(this);
\r
210 template <class IDTYPE>
\r
211 void IIndexRequester<IDTYPE>::RemoveFromRequestList(const IDTYPE id)
\r
213 typename std::vector<IDTYPE>::iterator i=std::find(m_requesting.begin(),m_requesting.end(),id);
\r
215 if(i!=m_requesting.end())
\r
217 m_requesting.erase(i);
\r
221 #endif // _iindexrequester_
\r