#include "ThreadMonitor.h" #include "GlobalConfigFile.h" #include "SimpleLogFile.h" #include "ServerConnection.h" ///////////////////////////////////////////////////////////////////// // ServerConnection ///////////////////////////////////////////////////////////////////// void ServerConnection::checkPing() { if (!shouldTryToConnect()) return; const time_t now = time(NULL); TalkWithServer *talkWithServer = getConnection(false); if (!talkWithServer) { // The connection is down. if (now > _connectionBlackout) { // Try to recreate the connection. //TclList msg; //msg<disconnect(); ThreadMonitor::find().increment("ping not found"); } else { // Time to send another ping TalkWithServer::Message message; message["command"] = "ping"; message["response"] = "1"; _talkWithServer->sendMessage(message, this, CI_PING, false); _nextPingTime = time(NULL) + 5; _pingSent = true; } } } void ServerConnection::onMessage(std::string bytes, int clientId, TalkWithServer::CancelId cancelId) { ThreadMonitor &tm = ThreadMonitor::find(); switch (clientId) { case CI_PING: { // Ping received. Send another one in 5 seconds. //std::cout<<"ciPing"<wantsRead()) callbacks.waitForRead(_talkWithServer->getHandle()); if (_talkWithServer && shouldTryToConnect()) if (_talkWithServer->wantsWrite()) callbacks.waitForWrite(_talkWithServer->getHandle()); // Check approximately once per second for the pings. These don't have to be // very precise. callbacks.wakeAfterMs(1000); } void ServerConnection::awake(std::set< int > const &woken) { checkPing(); if (_talkWithServer) _talkWithServer->wakeUp(); if (_talkWithServer && _talkWithServer->pendingResponseCount()) _talkWithServer->doResponses(); } void ServerConnection::onNewConnection(TalkWithServer *talkWithServer) { // Our own onConnect logic is build into getConnection(). If we put it // here, the subclass might forget to call this. A subclass should be // able to add stuff, but there's no reason for it to get rid of our // stuff. } bool ServerConnection::shouldTryToConnect() { // The default is a simple case where we always want to connect. This // is common. return true; } TalkWithServer *ServerConnection::getConnection(bool createIfRequired) { // This replaces checkConnection() in some other code. if (_talkWithServer && _talkWithServer->disconnected()) { _talkWithServer->cancelAll(); delete _talkWithServer; _talkWithServer = NULL; } if (!createIfRequired) // We've put this object into a simpler state. Either _talkWithServer is // null or it's ready to go. return _talkWithServer; if (_talkWithServer) // _talkWithServer was already ready to go. return _talkWithServer; _talkWithServer = new TalkWithServer(_name); _talkWithServer->connect(getServerName(), getServerPort()); if (_talkWithServer->disconnected()) // Unable to open the connection. // Return what we have to avoid a NULL pointer. return _talkWithServer; onNewConnection(_talkWithServer); // Request a new ping ASAP. _nextPingTime = 0; _pingSent = false; return _talkWithServer; } ServerConnection::ServerConnection(std::string const &name) : IContainerThreadUser(IContainerThread::primary()), _name(name), _talkWithServer(NULL), _connectionBlackout(0) { } ServerConnection::~ServerConnection() { if (_talkWithServer) delete _talkWithServer; } ///////////////////////////////////////////////////////////////////// // ForeverServerConnection ///////////////////////////////////////////////////////////////////// bool ForeverServerConnection::getAndParseAddress(std::string const &configName) { const std::string input = getConfigItem(configName, "NOT FOUND"); const std::vector< std::string > pieces = explode(":", input); const bool success = pieces.size() == 2; TclList msg; msg<