(file) Return to Monitor.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/Monitor.cpp between version 1.1 and 1.2

version 1.1, 2001/07/26 17:19:09 version 1.2, 2001/12/13 14:54:01
Line 0 
Line 1 
   //%/////////////////////////////////////////////////////////////////////////////
   //
   // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
   //
   // Permission is hereby granted, free of charge, to any person obtaining a copy
   // of this software and associated documentation files (the "Software"), to
   // deal in the Software without restriction, including without limitation the
   // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   // sell copies of the Software, and to permit persons to whom the Software is
   // furnished to do so, subject to the following conditions:
   //
   // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
   // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
   // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
   // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
   // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
   // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   //
   //==============================================================================
   //
   // Author: Mike Brasher (mbrasher@bmc.com)
   //
   // Modified By:
   //
   //%/////////////////////////////////////////////////////////////////////////////
   
   #include <Pegasus/Common/Config.h>
   #include <cstring>
   #include "Monitor.h"
   #include "MessageQueue.h"
   #include "Socket.h"
   
   #ifdef PEGASUS_OS_TYPE_WINDOWS
   # if defined(FD_SETSIZE) && FD_SETSIZE != 1024
   #  error "FD_SETSIZE was not set to 1024 prior to the last inclusion \
   of <winsock.h>. It may have been indirectly included (e.g., by including \
   <windows.h>). Find the inclusion of that header which is visible to this \
   compilation unit and #define FD_SETZIE to 1024 prior to that inclusion; \
   otherwise, less than 64 clients (the default) will be able to connect to the \
   CIMOM. PLEASE DO NOT SUPPRESS THIS WARNING; PLEASE FIX THE PROBLEM."
   # endif
   # define FD_SETSIZE 1024
   # include <winsock2.h>
   #else
   # include <sys/types.h>
   # include <sys/socket.h>
   # include <sys/time.h>
   # include <netinet/in.h>
   # include <netdb.h>
   # include <arpa/inet.h>
   # include <unistd.h>
   #endif
   
   PEGASUS_USING_STD;
   
   PEGASUS_NAMESPACE_BEGIN
   
   ////////////////////////////////////////////////////////////////////////////////
   //
   // MonitorRep
   //
   ////////////////////////////////////////////////////////////////////////////////
   
   struct MonitorRep
   {
       fd_set rd_fd_set;
       fd_set wr_fd_set;
       fd_set ex_fd_set;
       fd_set active_rd_fd_set;
       fd_set active_wr_fd_set;
       fd_set active_ex_fd_set;
   };
   
   ////////////////////////////////////////////////////////////////////////////////
   //
   // Monitor
   //
   ////////////////////////////////////////////////////////////////////////////////
   
   Monitor::Monitor()
   {
       Socket::initializeInterface();
   
       _rep = new MonitorRep;
       FD_ZERO(&_rep->rd_fd_set);
       FD_ZERO(&_rep->wr_fd_set);
       FD_ZERO(&_rep->ex_fd_set);
       FD_ZERO(&_rep->active_rd_fd_set);
       FD_ZERO(&_rep->active_wr_fd_set);
       FD_ZERO(&_rep->active_ex_fd_set);
   }
   
   Monitor::~Monitor()
   {
       Socket::uninitializeInterface();
   }
   
   Boolean Monitor::run(Uint32 milliseconds)
   {
   #ifdef PEGASUS_OS_TYPE_WINDOWS
   
       // Windows select() has a strange little bug. It returns immediately if
       // there are no descriptors in the set even if the timeout is non-zero.
       // To work around this, we call Sleep() for now:
   
       if (_entries.size() == 0)
           Sleep(milliseconds);
   
   #endif
   
       // Check for events on the selected file descriptors. Only do this if
       // there were no undispatched events from last time.
   
       static int count = 0;
   
       if (count == 0)
       {
           memcpy(&_rep->active_rd_fd_set, &_rep->rd_fd_set, sizeof(fd_set));
           memcpy(&_rep->active_wr_fd_set, &_rep->wr_fd_set, sizeof(fd_set));
           memcpy(&_rep->active_ex_fd_set, &_rep->ex_fd_set, sizeof(fd_set));
   
           const Uint32 SEC = milliseconds / 1000;
           const Uint32 USEC = (milliseconds % 1000) * 1000;
           struct timeval tv = { SEC, USEC };
   
           count = select(
               FD_SETSIZE,
               &_rep->active_rd_fd_set,
               &_rep->active_wr_fd_set,
               &_rep->active_ex_fd_set,
               &tv);
   
           if (count == 0)
               return false;
   #ifdef PEGASUS_OS_TYPE_WINDOWS
           else if (count == SOCKET_ERROR)
   #else
           else if (count == -1)
   #endif
           {
               count = 0;
               return false;
           }
       }
   
       for (Uint32 i = 0, n = _entries.size(); i < n; i++)
       {
           Sint32 socket = _entries[i].socket;
           Uint32 events = 0;
   
           if (FD_ISSET(socket, &_rep->active_rd_fd_set))
               events |= SocketMessage::READ;
   
           if (FD_ISSET(socket, &_rep->active_wr_fd_set))
               events |= SocketMessage::WRITE;
   
           if (FD_ISSET(socket, &_rep->active_ex_fd_set))
               events |= SocketMessage::EXCEPTION;
   
           if (events)
           {
               MessageQueue* queue = MessageQueue::lookup(_entries[i].queueId);
   
               if (!queue)
                   unsolicitSocketMessages(_entries[i].queueId);
   
   
               Message* message = new SocketMessage(socket, events);
               queue->enqueue(message);
   
               if (events & SocketMessage::WRITE)
               {
                   FD_CLR(socket, &_rep->active_wr_fd_set);
               }
   
               if (events & SocketMessage::EXCEPTION)
               {
                   FD_CLR(socket, &_rep->active_ex_fd_set);
               }
   
               if (events & SocketMessage::READ)
               {
                   FD_CLR(socket, &_rep->active_rd_fd_set);
               }
   
               count--;
               return true;
           }
       }
   
       return false;
   }
   
   Boolean Monitor::solicitSocketMessages(
       Sint32 socket,
       Uint32 events,
       Uint32 queueId)
   {
       // See whether a handler is already registered for this one:
   
       Uint32 pos = _findEntry(socket);
   
       if (pos != PEGASUS_NOT_FOUND)
           return false;
   
       // Set the events:
   
       if (events & SocketMessage::READ)
           FD_SET(socket, &_rep->rd_fd_set);
   
       if (events & SocketMessage::WRITE)
           FD_SET(socket, &_rep->wr_fd_set);
   
       if (events & SocketMessage::EXCEPTION)
           FD_SET(socket, &_rep->ex_fd_set);
   
       // Add the entry to the list:
   
       _MonitorEntry entry = { socket, queueId };
       _entries.append(entry);
   
       // Success!
   
       return true;
   }
   
   Boolean Monitor::unsolicitSocketMessages(Sint32 socket)
   {
       // Look for the given entry and remove it:
   
       for (Uint32 i = 0, n = _entries.size(); i < n; i++)
       {
           if (_entries[i].socket == socket)
           {
               Sint32 socket = _entries[i].socket;
               FD_CLR(socket, &_rep->rd_fd_set);
               FD_CLR(socket, &_rep->wr_fd_set);
               FD_CLR(socket, &_rep->ex_fd_set);
               _entries.remove(i);
               return true;
           }
       }
   
       return false;
   }
   
   Uint32 Monitor::_findEntry(Sint32 socket) const
   {
       for (Uint32 i = 0, n = _entries.size(); i < n; i++)
       {
           if (_entries[i].socket == socket)
               return i;
       }
   
       return PEG_NOT_FOUND;
   }
   
   PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2