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

  1 mike  1.2 //%/////////////////////////////////////////////////////////////////////////////
  2           //
  3           // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
  4           //
  5           // Permission is hereby granted, free of charge, to any person obtaining a copy
  6           // of this software and associated documentation files (the "Software"), to 
  7           // deal in the Software without restriction, including without limitation the 
  8           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
  9           // sell copies of the Software, and to permit persons to whom the Software is
 10           // furnished to do so, subject to the following conditions:
 11           // 
 12           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN 
 13           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 14           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 15           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 16           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
 17           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
 18           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 19           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 20           //
 21           //==============================================================================
 22 mike  1.2 //
 23           // Author: Mike Brasher (mbrasher@bmc.com)
 24           //
 25           // Modified By:
 26           //
 27           //%/////////////////////////////////////////////////////////////////////////////
 28           
 29           #include <Pegasus/Common/Config.h>
 30           #include <cstring>
 31           #include "Monitor.h"
 32           #include "MessageQueue.h"
 33           #include "Socket.h"
 34 kumpf 1.4 #include <Pegasus/Common/Tracer.h>
 35 mike  1.2 
 36           #ifdef PEGASUS_OS_TYPE_WINDOWS
 37           # if defined(FD_SETSIZE) && FD_SETSIZE != 1024
 38           #  error "FD_SETSIZE was not set to 1024 prior to the last inclusion \
 39           of <winsock.h>. It may have been indirectly included (e.g., by including \
 40           <windows.h>). Find the inclusion of that header which is visible to this \
 41           compilation unit and #define FD_SETZIE to 1024 prior to that inclusion; \
 42           otherwise, less than 64 clients (the default) will be able to connect to the \
 43           CIMOM. PLEASE DO NOT SUPPRESS THIS WARNING; PLEASE FIX THE PROBLEM."
 44 mday  1.5 
 45 mike  1.2 # endif
 46           # define FD_SETSIZE 1024
 47 mday  1.5 # include <windows.h>
 48 mike  1.2 #else
 49           # include <sys/types.h>
 50           # include <sys/socket.h>
 51           # include <sys/time.h>
 52           # include <netinet/in.h>
 53           # include <netdb.h>
 54           # include <arpa/inet.h>
 55           # include <unistd.h>
 56           #endif
 57           
 58           PEGASUS_USING_STD;
 59           
 60           PEGASUS_NAMESPACE_BEGIN
 61           
 62           ////////////////////////////////////////////////////////////////////////////////
 63           //
 64           // MonitorRep
 65           //
 66           ////////////////////////////////////////////////////////////////////////////////
 67           
 68           struct MonitorRep
 69 mike  1.2 {
 70               fd_set rd_fd_set;
 71               fd_set wr_fd_set;
 72               fd_set ex_fd_set;
 73               fd_set active_rd_fd_set;
 74               fd_set active_wr_fd_set;
 75               fd_set active_ex_fd_set;
 76           };
 77           
 78           ////////////////////////////////////////////////////////////////////////////////
 79           //
 80           // Monitor
 81           //
 82           ////////////////////////////////////////////////////////////////////////////////
 83           
 84           Monitor::Monitor()
 85           {
 86               Socket::initializeInterface();
 87           
 88               _rep = new MonitorRep;
 89               FD_ZERO(&_rep->rd_fd_set);
 90 mike  1.2     FD_ZERO(&_rep->wr_fd_set);
 91               FD_ZERO(&_rep->ex_fd_set);
 92               FD_ZERO(&_rep->active_rd_fd_set);
 93               FD_ZERO(&_rep->active_wr_fd_set);
 94               FD_ZERO(&_rep->active_ex_fd_set);
 95           }
 96           
 97           Monitor::~Monitor()
 98           {
 99               Socket::uninitializeInterface();
100           }
101           
102           Boolean Monitor::run(Uint32 milliseconds)
103           {
104           #ifdef PEGASUS_OS_TYPE_WINDOWS
105           
106               // Windows select() has a strange little bug. It returns immediately if
107               // there are no descriptors in the set even if the timeout is non-zero.
108               // To work around this, we call Sleep() for now:
109           
110               if (_entries.size() == 0)
111 mike  1.2 	Sleep(milliseconds);
112           
113           #endif
114           
115               // Check for events on the selected file descriptors. Only do this if
116               // there were no undispatched events from last time.
117           
118               static int count = 0;
119           
120               if (count == 0)
121               {
122           	memcpy(&_rep->active_rd_fd_set, &_rep->rd_fd_set, sizeof(fd_set));
123           	memcpy(&_rep->active_wr_fd_set, &_rep->wr_fd_set, sizeof(fd_set));
124           	memcpy(&_rep->active_ex_fd_set, &_rep->ex_fd_set, sizeof(fd_set));
125           
126 mike  1.3 	const Uint32 SECONDS = milliseconds / 1000;
127           	const Uint32 MICROSECONDS = (milliseconds % 1000) * 1000;
128           	struct timeval tv = { SECONDS, MICROSECONDS };
129 mike  1.2 
130           	count = select(
131           	    FD_SETSIZE,
132           	    &_rep->active_rd_fd_set,
133           	    &_rep->active_wr_fd_set,
134           	    &_rep->active_ex_fd_set,
135           	    &tv);
136           
137           	if (count == 0)
138           	    return false;
139           #ifdef PEGASUS_OS_TYPE_WINDOWS
140           	else if (count == SOCKET_ERROR)
141           #else
142           	else if (count == -1)
143           #endif
144           	{
145           	    count = 0;
146           	    return false;
147           	}
148               }
149           
150 mike  1.2     for (Uint32 i = 0, n = _entries.size(); i < n; i++)
151               {
152           	Sint32 socket = _entries[i].socket;
153           	Uint32 events = 0;
154           
155           	if (FD_ISSET(socket, &_rep->active_rd_fd_set))
156           	    events |= SocketMessage::READ;
157           
158           	if (FD_ISSET(socket, &_rep->active_wr_fd_set))
159           	    events |= SocketMessage::WRITE;
160           
161           	if (FD_ISSET(socket, &_rep->active_ex_fd_set))
162           	    events |= SocketMessage::EXCEPTION;
163           
164           	if (events)
165           	{
166 kumpf 1.4             Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
167                          "Monitor::run - Socket Event Detected events = %d", events);
168           
169 mike  1.2 	    MessageQueue* queue = MessageQueue::lookup(_entries[i].queueId);
170           
171           	    if (!queue)
172           		unsolicitSocketMessages(_entries[i].queueId);
173           
174           
175           	    Message* message = new SocketMessage(socket, events);
176           	    queue->enqueue(message);
177           
178           	    if (events & SocketMessage::WRITE)
179           	    {
180           		FD_CLR(socket, &_rep->active_wr_fd_set);
181 kumpf 1.4                 Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
182                              "Monitor::run FD_CLR WRITE");
183 mike  1.2 	    }
184           
185           	    if (events & SocketMessage::EXCEPTION)
186           	    {
187           		FD_CLR(socket, &_rep->active_ex_fd_set);
188 kumpf 1.4                 Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
189                              "Monitor::run FD_CLR EXECEPTION");
190 mike  1.2 	    }
191           
192           	    if (events & SocketMessage::READ)
193           	    {
194           		FD_CLR(socket, &_rep->active_rd_fd_set);
195 kumpf 1.4                 Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
196                              "Monitor::run FD_CLR READ");
197 mike  1.2 	    }
198           
199           	    count--;
200           	    return true;
201           	}
202               }
203           
204               return false;
205           }
206           
207           Boolean Monitor::solicitSocketMessages(
208               Sint32 socket, 
209               Uint32 events,
210               Uint32 queueId)
211           {
212 kumpf 1.4     PEG_METHOD_ENTER(TRC_HTTP, "Monitor::solictSocketMessage");
213           
214 mike  1.2     // See whether a handler is already registered for this one:
215           
216               Uint32 pos = _findEntry(socket);
217           
218               if (pos != PEGASUS_NOT_FOUND)
219 kumpf 1.4     {
220                   PEG_METHOD_EXIT();
221 mike  1.2 	return false;
222 kumpf 1.4     }
223 mike  1.2 
224               // Set the events:
225           
226               if (events & SocketMessage::READ)
227           	FD_SET(socket, &_rep->rd_fd_set);
228           
229               if (events & SocketMessage::WRITE)
230           	FD_SET(socket, &_rep->wr_fd_set);
231           
232               if (events & SocketMessage::EXCEPTION)
233           	FD_SET(socket, &_rep->ex_fd_set);
234           
235               // Add the entry to the list:
236           
237               _MonitorEntry entry = { socket, queueId };
238               _entries.append(entry);
239           
240               // Success!
241           
242 kumpf 1.4     PEG_METHOD_EXIT();
243 mike  1.2     return true;
244           }
245           
246           Boolean Monitor::unsolicitSocketMessages(Sint32 socket)
247           {
248 kumpf 1.4     PEG_METHOD_ENTER(TRC_HTTP, "Monitor::unsolicitSocketMessage");
249           
250 mike  1.2     // Look for the given entry and remove it:
251           
252               for (Uint32 i = 0, n = _entries.size(); i < n; i++)
253               {
254           	if (_entries[i].socket == socket)
255           	{
256           	    Sint32 socket = _entries[i].socket;
257           	    FD_CLR(socket, &_rep->rd_fd_set);
258           	    FD_CLR(socket, &_rep->wr_fd_set);
259           	    FD_CLR(socket, &_rep->ex_fd_set);
260           	    _entries.remove(i);
261 kumpf 1.4             PEG_METHOD_EXIT();
262 mike  1.2 	    return true;
263           	}
264               }
265           
266 kumpf 1.4     PEG_METHOD_EXIT();
267 mike  1.2     return false;
268           }
269           
270           Uint32 Monitor::_findEntry(Sint32 socket) const
271           {
272               for (Uint32 i = 0, n = _entries.size(); i < n; i++)
273               {
274           	if (_entries[i].socket == socket)
275           	    return i;
276               }
277           
278               return PEG_NOT_FOUND;
279           }
280           
281           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2