Poller.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 $Header$
00004 
00005 */
00006 
00007 #include <stdio.h>
00008 #include <sys/types.h>
00009 #include <sys/select.h>
00010 #include <unistd.h>
00011 #include <strings.h>
00012 #include <string.h>
00013 #include <fcntl.h>
00014 
00015 #include "Error.h"
00016 #include "TcpConnection.h"
00017 #include "TcpServer.h"
00018 
00019 #include "Poller.h"
00020 
00021 // Public methods.
00022 
00023 Poller::Poller() : Object()
00024 {
00025   _tv.tv_sec = POLLER_SESSION_TIMEOUT / 1000;
00026   _tv.tv_usec = (POLLER_SESSION_TIMEOUT % 1000) * 1000;
00027 
00028   DEBUG("Poller timeout: %d secs, %d millisecs.", (int)_tv.tv_sec, (int)_tv.tv_usec);
00029 
00030   _maxSocket = 0;
00031 
00032   FD_ZERO(&_allSet);
00033 }
00034 
00035 Poller::~Poller()
00036 {
00037 }
00038 
00039 int Poller::add(Socket *sock)
00040 {
00041   if (!sock)
00042     return ERROR(MSG_NULL_POINTER);
00043 
00044   int s = sock->socket();
00045 
00046   _sockets.insert(sock);
00047 
00048   FD_SET(s, &_allSet);
00049 
00050   if (s > _maxSocket)
00051     _maxSocket = s;
00052 
00053   DEBUG("Added socket %d.", s);
00054 
00055   return OK;
00056 }
00057 
00058 int Poller::remove(Socket *sock)
00059 {
00060   if (!sock)
00061     return ERROR(MSG_NULL_POINTER);
00062 
00063   SocketList::iterator f = _sockets.find(sock);
00064 
00065   if (f == _sockets.end())
00066     return ERROR(MSG_POLLER_UNKNOWN_CONNECTION);
00067 
00068   _sockets.erase(f);
00069 
00070   int s;
00071   if ((s = sock->socket()) >= 0)
00072     FD_CLR(s, &_allSet);
00073 
00074   DEBUG("Removed socket %d.", s);
00075 
00076   return OK;
00077 }
00078 
00079 int Poller::poll()
00080 {
00081   SocketList::iterator i;
00082   SocketList::iterator f;
00083   SocketList connectionsForDeletion;
00084   int readySocketsNum;
00085   fd_set readSet, writeSet;
00086   int sock;
00087   Socket *sck;
00088   TcpConnection *tcpConnection;
00089   bool yes;
00090   int res;
00091 
00092   readSet = _allSet;
00093   writeSet = _allSet;
00094 
00095   if ((readySocketsNum = select(_maxSocket + 1, &readSet, &writeSet, NULL, &_tv)) != 0) {
00096     if (readySocketsNum < 0)
00097       return ERROR(MSG_POLLER_SELECT, strerror(errno));
00098 
00099     for (i = _sockets.begin(); i != _sockets.end(); ++i) {
00100       sck = *i;
00101       if ((sock = sck->_socket) < 0) {
00102         connectionsForDeletion.insert(sck);
00103         continue;
00104       }
00105       if (FD_ISSET(sock, &readSet)) {
00106         TcpServer *server;
00107         if ((server = TCP_SERVER(sck))) { // New connection to TCP server.
00108           if (FAILED(res = server->accept(&tcpConnection)))
00109             return ERROR_BACKTRACE(res);
00110           DEBUG("Accepted new TCP connection.");
00111         } else {
00112             Connection *connection = queryInterface<Connection>(sck);
00113             if (!connection)
00114               return ERROR(MSG_NO_INTERFACE, "Connection");
00115             if (FAILED(res = connection->isAlive(yes)))
00116               return ERROR_BACKTRACE(res);
00117             if (yes) {
00118 //              DEBUG("New data arrived.");
00119               if (FAILED(res = connection->setDataReady()))
00120                 ERROR_BACKTRACE(res);
00121             } else {
00122                 FD_CLR(sock, &_allSet);
00123                 if (FAILED(res = connection->setDead()))
00124                   ERROR_BACKTRACE(res);
00125                 connectionsForDeletion.insert(connection);
00126                 DEBUG("Dead connection closed.");
00127               }
00128           }
00129       } else
00130           if (FD_ISSET(sock, &writeSet))
00131             if ((tcpConnection = queryInterface<TcpConnection>(sck)))
00132               if (tcpConnection->_status == TCP_CONNECTION_STATUS_DISCONNECTED) {
00133                 DEBUG("TCP connection connected.");
00134                 if (FAILED(res = tcpConnection->setConnected()))
00135                   ERROR_BACKTRACE(res);
00136               }
00137       if (--readySocketsNum <= 0)
00138         break; // No more descriptors.
00139     }
00140     if (connectionsForDeletion.size() > 0)
00141       DEBUG("Connections for deletion: %u.", connectionsForDeletion.size());
00142     for (i = connectionsForDeletion.begin(); i != connectionsForDeletion.end(); ++i)
00143       if (FAILED(res = remove(*i)))
00144         ERROR_BACKTRACE(res);
00145   }
00146 
00147   return OK;
00148 }

Generated on Thu Sep 6 20:11:25 2007 for Pylon Application Platform by  doxygen 1.5.1