version 0.1.9
[fms.git] / include / freenet / iindexrequester.h
1 #ifndef _iindexrequester_\r
2 #define _iindexrequester_\r
3 \r
4 #include "../idatabase.h"\r
5 #include "../ilogger.h"\r
6 #include "../datetime.h"\r
7 #include "../option.h"\r
8 #include "../stringfunctions.h"\r
9 #include "ifreenetregistrable.h"\r
10 #include "ifcpconnected.h"\r
11 #include "ifcpmessagehandler.h"\r
12 #include "iperiodicprocessor.h"\r
13 \r
14 template <class IDTYPE>\r
15 class IIndexRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
16 {\r
17 public:\r
18         IIndexRequester();\r
19         IIndexRequester(FCPv2 *fcp);\r
20 \r
21         virtual void FCPConnected();\r
22         virtual void FCPDisconnected();\r
23         virtual const bool HandleMessage(FCPMessage &message);\r
24 \r
25         virtual void Process();\r
26 \r
27         virtual void RegisterWithThread(FreenetMasterThread *thread);\r
28 \r
29 protected:\r
30         void InitializeIIndexRequester();\r
31         virtual void Initialize()=0;            // initialize m_maxrequests and m_fcpuniquename\r
32         virtual void PopulateIDList()=0;\r
33         virtual void StartRequest(const IDTYPE &id)=0;\r
34         virtual const bool HandleAllData(FCPMessage &message)=0;\r
35         virtual const bool HandleGetFailed(FCPMessage &message)=0;\r
36         virtual void RemoveFromRequestList(const IDTYPE id);\r
37 \r
38         DateTime m_tempdate;\r
39         std::string m_messagebase;\r
40         std::map<IDTYPE,bool> m_ids;                    // map of all ids we know and whether we have requested file from them yet\r
41         std::vector<IDTYPE> m_requesting;               // list of ids we are currently requesting from\r
42 \r
43         // these MUST be populated by child class\r
44         long m_maxrequests;\r
45         std::string m_fcpuniquename;\r
46 \r
47 };\r
48 \r
49 template <class IDTYPE>\r
50 IIndexRequester<IDTYPE>::IIndexRequester()\r
51 {\r
52         InitializeIIndexRequester();\r
53 }\r
54 \r
55 template <class IDTYPE>\r
56 IIndexRequester<IDTYPE>::IIndexRequester(FCPv2 *fcp):IFCPConnected(fcp)\r
57 {\r
58         InitializeIIndexRequester();\r
59 }\r
60 \r
61 template <class IDTYPE>\r
62 void IIndexRequester<IDTYPE>::FCPConnected()\r
63 {\r
64         // make sure variables have been initialized by the derived class\r
65         if(m_maxrequests==-1)\r
66         {\r
67                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
68         }\r
69         if(m_fcpuniquename=="")\r
70         {\r
71                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
72         }\r
73         if(m_fcpuniquename.find("|")!=std::string::npos)\r
74         {\r
75                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character!  This is not a valid character!");\r
76         }\r
77 \r
78         m_requesting.clear();\r
79         PopulateIDList();\r
80 }\r
81 \r
82 template <class IDTYPE>\r
83 void IIndexRequester<IDTYPE>::FCPDisconnected()\r
84 {\r
85         \r
86 }\r
87 \r
88 template <class IDTYPE>\r
89 const bool IIndexRequester<IDTYPE>::HandleMessage(FCPMessage &message)\r
90 {\r
91 \r
92         if(message["Identifier"].find(m_fcpuniquename)==0)\r
93         {\r
94                 if(message.GetName()=="DataFound")\r
95                 {\r
96                         return true;\r
97                 }\r
98 \r
99                 if(message.GetName()=="AllData")\r
100                 {\r
101                         return HandleAllData(message);\r
102                 }\r
103 \r
104                 if(message.GetName()=="GetFailed")\r
105                 {\r
106                         return HandleGetFailed(message);\r
107                 }\r
108 \r
109                 if(message.GetName()=="IdentifierCollision")\r
110                 {\r
111                         // remove one of the ids from the requesting list\r
112                         IDTYPE id;\r
113                         std::vector<std::string> idparts;\r
114                         StringFunctions::Split(message["Identifier"],"|",idparts);\r
115                         StringFunctions::Convert(idparts[1],id);\r
116                         RemoveFromRequestList(id);\r
117                         return true;\r
118                 }\r
119         }\r
120 \r
121         return false;\r
122 }\r
123 \r
124 template <class IDTYPE>\r
125 void IIndexRequester<IDTYPE>::InitializeIIndexRequester()\r
126 {\r
127         m_maxrequests=-1;\r
128         m_fcpuniquename="";\r
129 \r
130         Option::Instance()->Get("MessageBase",m_messagebase);\r
131         m_tempdate.SetToGMTime();\r
132 }\r
133 \r
134 template <class IDTYPE>\r
135 void IIndexRequester<IDTYPE>::Process()\r
136 {\r
137         // max is the smaller of the config value or the total number of ids we will request from\r
138         typename std::map<IDTYPE,bool>::size_type max=m_maxrequests>m_ids.size() ? m_ids.size() : m_maxrequests;\r
139 \r
140         // try to keep up to max requests going\r
141         if(m_requesting.size()<max)\r
142         {\r
143                 typename std::map<IDTYPE,bool>::iterator i=m_ids.begin();\r
144 \r
145                 while(i!=m_ids.end() && (*i).second==true)\r
146                 {\r
147                         i++;\r
148                 }\r
149 \r
150                 if(i!=m_ids.end())\r
151                 {\r
152                         StartRequest((*i).first);\r
153                 }\r
154                 else\r
155                 {\r
156                         // we requested from all ids in the list, repopulate the list\r
157                         PopulateIDList();\r
158                 }\r
159         }\r
160         // 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
161         // this will recheck for ids every minute\r
162         DateTime now;\r
163         now.SetToGMTime();\r
164         if(m_ids.size()==0 && m_tempdate<(now-(1.0/1440.0)))\r
165         {\r
166                 PopulateIDList();\r
167                 m_tempdate=now;\r
168         }\r
169 \r
170 }\r
171 \r
172 template <class IDTYPE>\r
173 void IIndexRequester<IDTYPE>::RegisterWithThread(FreenetMasterThread *thread)\r
174 {\r
175         thread->RegisterFCPConnected(this);\r
176         thread->RegisterFCPMessageHandler(this);\r
177         thread->RegisterPeriodicProcessor(this);\r
178 }\r
179 \r
180 template <class IDTYPE>\r
181 void IIndexRequester<IDTYPE>::RemoveFromRequestList(const IDTYPE id)\r
182 {\r
183         typename std::vector<IDTYPE>::iterator i=m_requesting.begin();\r
184         while(i!=m_requesting.end() && (*i)!=id)\r
185         {\r
186                 i++;\r
187         }\r
188         if(i!=m_requesting.end())\r
189         {\r
190                 m_requesting.erase(i);\r
191         }\r
192 }\r
193 \r
194 #endif  // _iindexrequester_\r