PageRenderTime 23ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/opencog/embodiment/Control/MessagingSystem/NetworkElement.h

https://github.com/midnightcoder/gracula
C Header | 344 lines | 88 code | 62 blank | 194 comment | 0 complexity | 573a20c23492427debe3fe5e988107db MD5 | raw file
  1. /*
  2. * opencog/embodiment/Control/MessagingSystem/NetworkElement.h
  3. *
  4. * Copyright (C) 2002-2009 Novamente LLC
  5. * All Rights Reserved
  6. * Author(s): Andre Senna
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License v3 as
  10. * published by the Free Software Foundation and including the exceptions
  11. * at http://opencog.org/wiki/Licenses
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program; if not, write to:
  20. * Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22. */
  23. #ifndef NETWORKELEMENT_H
  24. #define NETWORKELEMENT_H
  25. #include <set>
  26. #include <queue>
  27. #include <pthread.h>
  28. #include <string>
  29. #include <vector>
  30. #include <exception>
  31. #include "Message.h"
  32. #include "MessageCentral.h"
  33. #include "MemoryMessageCentral.h"
  34. #include <opencog/util/Logger.h>
  35. #include <opencog/util/exceptions.h>
  36. #include <boost/asio.hpp>
  37. using boost::asio::ip::tcp;
  38. namespace MessagingSystem
  39. {
  40. class ServerSocket;
  41. /**
  42. * The basic class of communications layer is a NetworkElement (NE). The idea here is that every entity
  43. * (namely, every process) in the PB network should have a NetworkElement member to enter PB network
  44. * and exchange information with other units.
  45. *
  46. * So a PB server should have a loop to check and process all incoming messages of the type it is supposed
  47. * to receive.
  48. */
  49. class NetworkElement
  50. {
  51. protected:
  52. std::string myId; // identification of this NE in PB network (set in constructor)
  53. /**
  54. * This method is used to mark the an element as an unavailable one. Default
  55. * implementation just add the element id to the unavailable list. If the
  56. * element is the router, them all messages in router are lost, so set the
  57. * numberof unread messages to zero.
  58. *
  59. * Subclasses are supposed to override this method to take the corresponding
  60. * actions such as stopping idle tasks.
  61. *
  62. * @param id The element that should be marked as unavailable
  63. */
  64. void markAsUnavailableElement(const std::string &id);
  65. /**
  66. * This method is used to mark the an element as an available one. Default
  67. * implementation removes the element id from the list and if it is the router
  68. * a hansdshake operation is executed.
  69. *
  70. * Subclasses may override this method to
  71. * take the corresponding actions when necessary.
  72. *
  73. * @param id The element that should be marked as available
  74. */
  75. void markAsAvailableElement(const std::string &id);
  76. /**
  77. * Notify this object is already initialized (used by subclass when its initialization is done)
  78. */
  79. void markAsInitialized();
  80. /**
  81. * Check if subclass already marked this as initialized
  82. */
  83. bool isInitialized();
  84. private:
  85. pthread_cond_t mainThreadBed; // main thread is put in this bed when waiting for messages retireving
  86. pthread_mutex_t messageQueueLock; // lock used coordinate manipulation of the messageQueue (main thread and listener thread)
  87. pthread_mutex_t tickLock; // lock used coordinate manipulation of the messageQueue (main thread and listener thread)
  88. pthread_mutex_t socketAccessLock;
  89. pthread_t socketListenerThread; // thread which will listen to the port
  90. pthread_attr_t socketListenerAttr;
  91. static bool stopListenerThreadFlag; // control flag used to make listener thread finish and return.
  92. static bool socketListenerIsReady; // control flag used to indicate listener is ready.
  93. int numberOfUnreadMessages; // control the number of unread messages stored in router for this network element
  94. int lastNumberOfUnreadMessages; // the last number of unread messages stored in router for this network element. Used for tick overflow (over process) ...
  95. int tickNumber; // control the number of unread messages stored in router for this network element
  96. std::string ipAddress; // ip of the network card this server will listen to
  97. int portNumber; // port this NE will listen to (set in constructor)
  98. MemoryMessageCentral messageCentral;
  99. std::string routerID;
  100. std::string routerIP;
  101. int routerPort;
  102. char threadArgs[256]; // used to pass arguments to static method called by listener thread
  103. boost::asio::io_service io_service;
  104. tcp::socket* sock;
  105. static std::vector<ServerSocket*> serverSockets;
  106. /**
  107. * Used to hold the ids of the NetworkElements that are currently
  108. * unavailable. To be removed from the list an IS_AVAILABLE_COMPONENT <id>
  109. * message is sent to the router, and with an 'OK'answer the component
  110. * id is removed.
  111. *
  112. * IMPORTANT:
  113. * This list can also hold the router's id if it goes down. In that case
  114. * the remove action remains the same since if the router is able to
  115. * receive the message it is up and will answer 'OK'
  116. */
  117. std::set<std::string> unavailableElements;
  118. /**
  119. * Flag that indicates the subclass of NetworkElement is already initialized
  120. */
  121. bool subclass_initialized;
  122. void addTick();
  123. int getTick();
  124. /**
  125. * This method takes control of the thread started to listen to the port this
  126. * NetworkElement is supposed to listen to.
  127. *
  128. * @param arg A pointer to an integer with the port number the thread is supposed
  129. * to listen to.
  130. */
  131. static void *portListener(void *arg);
  132. /**
  133. * Convenience method called in constructor to delegate socket listening to another thread
  134. * @return true if listener was initialized and it's ready for usage. False otherwise
  135. */
  136. bool startListener();
  137. /**
  138. * Convenience method used to simplify the flow of retrieveMessages(). It creates the proper message to be sent to router and send it away.
  139. */
  140. void requestUnreadMessages(int limit);
  141. /**
  142. * Convenience method called in constructor to perform initial handshaking with router.
  143. */
  144. void handshakeWithRouter();
  145. public:
  146. bool noAckMessages; // flag to define if the protocol should use ACK messages (OK,FAILED) or not.
  147. // ***********************************************/
  148. // Constructors/destructors
  149. virtual ~NetworkElement();
  150. /**
  151. * Builds thje object and perform the handshake with the Router:
  152. * (a) Request access passing an identification string and a port number (the port this NE will listen to)
  153. * (b) Receive an OK or a failure message indicating that this NE could not join PB network.
  154. * (c) Starts a secondary thread which will listen to the given port to process commands from the Router
  155. * (the main thread returns from constructor)
  156. *
  157. * @param myId A string which will identify this NE. Other NEs may use to string to discover this NE's actual id.
  158. * @param portNumber The port number this NE will listen to
  159. */
  160. NetworkElement(const std::string &myId, const std::string &ip, int portNumber);
  161. /**
  162. * Empty constructor which does not initialize (ie, does not contact router for handshaking).
  163. * Useful to build unit tests.
  164. */
  165. NetworkElement();
  166. /**
  167. * Initializes the object and perform the handshake with the Router:
  168. * (a) Request access passing an identification string and a port number (the port this NE will listen to)
  169. * (b) Receive an OK or a failure message indicating that this NE could not join PB network.
  170. * (c) Starts a secondary thread which will listen to the given port to process commands from the Router
  171. * (the main thread returns from constructor)
  172. *
  173. * @param myId A string which will identify this NE. Other NEs may use to string to discover this NE's actual id.
  174. * @param portNumber The port number this NE will listen to
  175. */
  176. void initialize(const std::string &myId, const std::string &ip, int portNumber);
  177. /**
  178. * Convenience method to be called when the network element is being
  179. * destroyed and should notify Router to erase ip/port information.
  180. */
  181. void logoutFromRouter();
  182. // ***********************************************/
  183. // API
  184. /**
  185. * Return true if the component is available or false otherwise
  186. *
  187. * @param id The id of the element to be checked
  188. */
  189. bool isElementAvailable(const std::string& id);
  190. /**
  191. * Return true if there are new unread messages waiting in the router.
  192. * It is a local check, no communication is actually performed.
  193. * This method just returns a local boolean state variable which is set
  194. * assynchronously by the router when a new message to this NE arrives.
  195. *
  196. * @return true if there are new unread messages waiting in the router or false otherwise.
  197. */
  198. bool haveUnreadMessage();
  199. /**
  200. * Contacts the Router and retrieve at most N unread messages.
  201. *
  202. * @param limit Max number of messages which will be retrieved
  203. */
  204. bool retrieveMessages(int limit = -1);
  205. /**
  206. * Send a Message. Information about target is encapsulated inside the Message.
  207. *
  208. * @param msg The message to be sent.
  209. */
  210. virtual bool sendMessage(Message &msg);
  211. /**
  212. * Convenience method to encapsulate the code which acts as client when sending requests to router
  213. * @return true if the command was sent successfully, and false otherwise
  214. */
  215. virtual bool sendCommandToRouter(const std::string &cmd);
  216. // END OF API
  217. const std::string &getIPAddress();
  218. int getPortNumber();
  219. const std::string &getID();
  220. // ***********************************************/
  221. // ServerSocket call-back
  222. // Although the following methods are public, they are not supposed to be called
  223. // by other classes other than ServerProxy. They are called on assynchronous call-back
  224. // from requests arriving in the listened port.
  225. /**
  226. * This method is supposed to be called by ServerSocket to notify NE that
  227. * a new message has arrived in the Router targeted to this NE (the message
  228. * is still in the Router). It shaw not be called by anyone else.
  229. */
  230. void newMessageInRouter(int numMessages);
  231. /**
  232. * This method is supposed to be called by ServerSocket to notify NE that at
  233. * least one new message has been actually delivered by the Router. It shaw
  234. * not be called by anyone else.
  235. */
  236. void newMessageRead(const std::string &from, const std::string &to, int type, const std::string &msg);
  237. /**
  238. * This method is supposed to be called by ServerSocket to notify NE that all
  239. * unread messages have been received from the Router. It shaw not be called
  240. * by anyone else.
  241. */
  242. void noMoreMessages();
  243. /**
  244. * This method is supposed to be called by ServerSocket to notify NE that the given
  245. * element is unavailable to receive messages. It shaw not be called by anyone else.
  246. */
  247. void unavailableElement(const std::string &id);
  248. /**
  249. * This method is supposed to be called by ServerSocket to notify NE that the given
  250. * element is available to receive messages (after being unavailable for a while since
  251. * by default all components are assume to be available at start up).
  252. * It shaw not be called by anyone else.
  253. */
  254. void availableElement(const std::string &id);
  255. /**
  256. * Set stopListenerThread tag to true and stop listerning the messages
  257. */
  258. void stopListenerThread();
  259. /**
  260. * Open a connection to Router
  261. * Return true if a connection was already stabilished or false if errors occurred
  262. */
  263. bool connectToRouter( void );
  264. /**
  265. * Sends a string message to router using a persistent socket connection
  266. */
  267. std::string sendMessageToRouter( const std::string& message );
  268. /**
  269. * Methods for accessing incoming queue
  270. */
  271. unsigned int getIncomingQueueSize();
  272. bool isIncomingQueueEmpty();
  273. Message* popIncomingQueue();
  274. /**
  275. * Method to check if NetworkElment is still listenning to its tcp port
  276. */
  277. static bool isListenerThreadStopped() {
  278. return !stopListenerThreadFlag;
  279. }
  280. }; // class
  281. } // namespace
  282. #endif