version 0.1.0
[fms.git] / include / freenet / iindexrequester.h
diff --git a/include/freenet/iindexrequester.h b/include/freenet/iindexrequester.h
new file mode 100644 (file)
index 0000000..6ba9ae7
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef _iindexrequester_\r
+#define _iindexrequester_\r
+\r
+#include "../idatabase.h"\r
+#include "../ilogger.h"\r
+#include "../datetime.h"\r
+#include "../option.h"\r
+#include "../stringfunctions.h"\r
+#include "ifreenetregistrable.h"\r
+#include "ifcpconnected.h"\r
+#include "ifcpmessagehandler.h"\r
+#include "iperiodicprocessor.h"\r
+\r
+template <class IDTYPE>\r
+class IIndexRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
+{\r
+public:\r
+       IIndexRequester();\r
+       IIndexRequester(FCPv2 *fcp);\r
+\r
+       virtual void FCPConnected();\r
+       virtual void FCPDisconnected();\r
+       virtual const bool HandleMessage(FCPMessage &message);\r
+\r
+       virtual void Process();\r
+\r
+       virtual void RegisterWithThread(FreenetMasterThread *thread);\r
+\r
+protected:\r
+       void InitializeIIndexRequester();\r
+       virtual void Initialize()=0;            // initialize m_maxrequests and m_fcpuniquename\r
+       virtual void PopulateIDList()=0;\r
+       virtual void StartRequest(const IDTYPE &id)=0;\r
+       virtual const bool HandleAllData(FCPMessage &message)=0;\r
+       virtual const bool HandleGetFailed(FCPMessage &message)=0;\r
+       virtual void RemoveFromRequestList(const IDTYPE id);\r
+\r
+       DateTime m_tempdate;\r
+       std::string m_messagebase;\r
+       std::map<IDTYPE,bool> m_ids;                    // map of all ids we know and whether we have requested file from them yet\r
+       std::vector<IDTYPE> m_requesting;               // list of ids we are currently requesting from\r
+\r
+       // these MUST be populated by child class\r
+       long m_maxrequests;\r
+       std::string m_fcpuniquename;\r
+\r
+};\r
+\r
+template <class IDTYPE>\r
+IIndexRequester<IDTYPE>::IIndexRequester()\r
+{\r
+       InitializeIIndexRequester();\r
+}\r
+\r
+template <class IDTYPE>\r
+IIndexRequester<IDTYPE>::IIndexRequester(FCPv2 *fcp):IFCPConnected(fcp)\r
+{\r
+       InitializeIIndexRequester();\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::FCPConnected()\r
+{\r
+       // make sure variables have been initialized by the derived class\r
+       if(m_maxrequests==-1)\r
+       {\r
+               m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
+       }\r
+       if(m_fcpuniquename=="")\r
+       {\r
+               m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
+       }\r
+       if(m_fcpuniquename.find("|")!=std::string::npos)\r
+       {\r
+               m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character!  This is not a valid character!");\r
+       }\r
+\r
+       m_requesting.clear();\r
+       PopulateIDList();\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::FCPDisconnected()\r
+{\r
+       \r
+}\r
+\r
+template <class IDTYPE>\r
+const bool IIndexRequester<IDTYPE>::HandleMessage(FCPMessage &message)\r
+{\r
+\r
+       if(message["Identifier"].find(m_fcpuniquename)==0)\r
+       {\r
+               if(message.GetName()=="DataFound")\r
+               {\r
+                       return true;\r
+               }\r
+\r
+               if(message.GetName()=="AllData")\r
+               {\r
+                       return HandleAllData(message);\r
+               }\r
+\r
+               if(message.GetName()=="GetFailed")\r
+               {\r
+                       return HandleGetFailed(message);\r
+               }\r
+\r
+               if(message.GetName()=="IdentifierCollision")\r
+               {\r
+                       // remove one of the ids from the requesting list\r
+                       IDTYPE id;\r
+                       std::vector<std::string> idparts;\r
+                       StringFunctions::Split(message["Identifier"],"|",idparts);\r
+                       StringFunctions::Convert(idparts[1],id);\r
+                       RemoveFromRequestList(id);\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::InitializeIIndexRequester()\r
+{\r
+       m_maxrequests=-1;\r
+       m_fcpuniquename="";\r
+\r
+       Option::instance()->Get("MessageBase",m_messagebase);\r
+       m_tempdate.SetToGMTime();\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::Process()\r
+{\r
+       // max is the smaller of the config value or the total number of identities we will request from\r
+       long max=m_maxrequests>m_ids.size() ? m_ids.size() : m_maxrequests;\r
+\r
+       // try to keep up to max requests going\r
+       if(m_requesting.size()<max)\r
+       {\r
+               std::map<IDTYPE,bool>::iterator i=m_ids.begin();\r
+               while(i!=m_ids.end() && (*i).second==true)\r
+               {\r
+                       i++;\r
+               }\r
+\r
+               if(i!=m_ids.end())\r
+               {\r
+                       StartRequest((*i).first);\r
+               }\r
+               else\r
+               {\r
+                       // we requested from all ids in the list, repopulate the list\r
+                       PopulateIDList();\r
+               }\r
+       }\r
+       // 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
+       // this will recheck for ids every minute\r
+       DateTime now;\r
+       now.SetToGMTime();\r
+       if(m_tempdate<(now-(1.0/1440.0)))\r
+       {\r
+               PopulateIDList();\r
+               m_tempdate=now;\r
+       }\r
+\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::RegisterWithThread(FreenetMasterThread *thread)\r
+{\r
+       thread->RegisterFCPConnected(this);\r
+       thread->RegisterFCPMessageHandler(this);\r
+       thread->RegisterPeriodicProcessor(this);\r
+}\r
+\r
+template <class IDTYPE>\r
+void IIndexRequester<IDTYPE>::RemoveFromRequestList(const IDTYPE id)\r
+{\r
+       std::vector<IDTYPE>::iterator i=m_requesting.begin();\r
+       while(i!=m_requesting.end() && (*i)!=id)\r
+       {\r
+               i++;\r
+       }\r
+       if(i!=m_requesting.end())\r
+       {\r
+               m_requesting.erase(i);\r
+       }\r
+}\r
+\r
+#endif // _iindexrequester_\r