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
|