1 martin 1.51 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.52 //
|
3 martin 1.51 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.52 //
|
10 martin 1.51 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.52 //
|
17 martin 1.51 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.52 //
|
20 martin 1.51 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.52 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.51 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.52 //
|
28 martin 1.51 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 david.dillard 1.36 #ifndef Pegasus_Monitor_h
33 #define Pegasus_Monitor_h
|
34 mike 1.2
35 #include <Pegasus/Common/Config.h>
|
36 kumpf 1.12 #include <Pegasus/Common/ArrayInternal.h>
|
37 mike 1.2 #include <Pegasus/Common/String.h>
38 #include <Pegasus/Common/Message.h>
|
39 mday 1.4 #include <Pegasus/Common/ModuleController.h>
|
40 kumpf 1.33 #include <Pegasus/Common/Socket.h>
|
41 mday 1.16 #include <Pegasus/Common/Sharable.h>
|
42 david.dillard 1.36 #include <Pegasus/Common/Linkage.h>
|
43 joyce.j 1.31 #include <Pegasus/Common/AutoPtr.h>
|
44 mike 1.2
45 PEGASUS_NAMESPACE_BEGIN
46
|
47 kumpf 1.48 class PEGASUS_COMMON_LINKAGE MonitorEntry
|
48 mike 1.2 {
|
49 mday 1.15 public:
|
50 kumpf 1.48 enum Status
51 {
52 STATUS_IDLE,
53 STATUS_BUSY,
54 STATUS_DYING,
55 STATUS_EMPTY
56 };
|
57 kumpf 1.45
|
58 kumpf 1.48 enum Type
|
59 kumpf 1.45 {
|
60 kumpf 1.48 TYPE_ACCEPTOR,
61 TYPE_CONNECTION,
|
62 kumpf 1.49 TYPE_TICKLER
|
63 kumpf 1.48 };
|
64 kumpf 1.45
|
65 kumpf 1.48 MonitorEntry()
|
66 kumpf 1.45 {
|
67 kumpf 1.48 reset();
|
68 kumpf 1.45 }
69
|
70 kumpf 1.48 MonitorEntry(
71 SocketHandle socket_,
72 Uint32 queueId_,
73 Uint32 status_,
74 Uint32 type_)
75 : socket(socket_),
76 queueId(queueId_),
77 status(status_),
78 type(type_)
|
79 kumpf 1.45 {
80 }
81
|
82 kumpf 1.48 // NOTE: Using the default implementation of the copy constructor and
83 // assignment operator.
84
85 void reset()
|
86 kumpf 1.45 {
|
87 kumpf 1.48 socket = PEGASUS_INVALID_SOCKET;
88 queueId = 0;
89 status = STATUS_EMPTY;
|
90 kumpf 1.50 type = TYPE_TICKLER;
|
91 kumpf 1.45 }
92
|
93 kumpf 1.48 SocketHandle socket;
94 Uint32 queueId;
95 Uint32 status;
96 Uint32 type;
|
97 mike 1.2 };
98
99 /** This message occurs when there is activity on a socket. */
100 class SocketMessage : public Message
101 {
102 public:
103
|
104 kumpf 1.45 enum Events { READ = 1, WRITE = 2, EXCEPTION = 4 };
|
105 mike 1.2
|
106 kumpf 1.45 SocketMessage(SocketHandle socket_, Uint32 events_)
107 : Message(SOCKET_MESSAGE), socket(socket_), events(events_)
108 {
109 }
|
110 david.dillard 1.36
|
111 kumpf 1.45 SocketHandle socket;
112 Uint32 events;
|
113 mike 1.2 };
114
|
115 kumpf 1.46 /**
|
116 kumpf 1.50 This message is sent to a connection owner (HTTPAcceptor) so it can do
117 any necessary cleanup of the connection.
118 */
119 class CloseConnectionMessage : public Message
120 {
121 public:
122
123 CloseConnectionMessage(SocketHandle socket_)
124 : Message(CLOSE_CONNECTION_MESSAGE), socket(socket_)
125 {
126 }
127
128 SocketHandle socket;
129 };
130
131 /**
|
132 kumpf 1.46 The Tickler class provides a loopback socket connection that can be
133 included in a select() socket array to allow the select() call to return
134 on demand.
135 */
136 class Tickler
137 {
138 public:
139 /**
|
140 kumpf 1.47 Constructs a Tickler object and initializes its connection.
141 @exception Exception if the initialization fails.
|
142 kumpf 1.46 */
|
143 kumpf 1.47 Tickler();
|
144 kumpf 1.46
|
145 kumpf 1.47 ~Tickler();
|
146 kumpf 1.46
|
147 kumpf 1.49 /**
148 Causes a read event on the tickle socket.
149 */
150 void notify();
151
152 /**
153 Consumes all read events on the tickle socket.
154 */
155 void reset();
|
156 kumpf 1.46
|
157 kumpf 1.49 SocketHandle getReadHandle()
|
158 kumpf 1.46 {
159 return _serverSocket;
160 }
161
162 private:
|
163 kumpf 1.47 /**
164 Initializes the Tickler connection.
165 @exception Exception if the initialization fails.
166 */
167 void _initialize();
168
169 /**
170 Uninitializes the Tickler connection.
171 */
172 void _uninitialize();
173
|
174 kumpf 1.46 SocketHandle _listenSocket;
175 SocketHandle _clientSocket;
176 SocketHandle _serverSocket;
177 };
178
|
179 mike 1.2 /** This class monitors system-level events and notifies its clients of these
180 events by posting messages to their queues.
181
182 The monitor generates following message types:
183
184 <ul>
|
185 mday 1.15 <li> SocketMessage - occurs when activity on a socket </li>
|
186 mike 1.2 </ul>
187
188 Clients solicit these messages by calling one of the following methods:
189
190 <ul>
|
191 mday 1.15 <li> solicitSocketMessages() </li>
|
192 mike 1.2 </ul>
193
194 The following example shows how to solicit socket messages:
195
196 <pre>
|
197 mday 1.15 Monitor monitor;
198 Sint32 socket;
199 Uint32 queueId;
|
200 mike 1.2
|
201 mday 1.4
|
202 mday 1.15 ...
|
203 mike 1.2
|
204 mday 1.15 monitor.solicitSocketMessages(
|
205 david.dillard 1.36 socket,
206 SocketMessage::READ | SocketMessage::WRITE,
|
207 mday 1.15 queueId);
|
208 mike 1.2 </pre>
209
210 Each time activity occurs on the given socket, a SocketMessage is
211 enqueued on the given queue.
212
213 In order the monitor to generate messages, it must be run by calling
214 the run() method as shown below:
215
216 <pre>
|
217 mday 1.15 Monitor monitor;
|
218 mike 1.2
|
219 mday 1.15 ...
|
220 mike 1.2
|
221 mday 1.15 Uint32 milliseconds = 5000;
222 monitor.run(milliseconds);
|
223 mike 1.2 </pre>
224
225 In this example, the monitor is run for five seconds. The run method
226 returns after the first message is occurs or five seconds has transpired
227 (whichever occurs first).
228 */
229 class PEGASUS_COMMON_LINKAGE Monitor
230 {
|
231 mday 1.15 public:
|
232 kumpf 1.45 /** Default constructor. */
233 Monitor();
|
234 david.dillard 1.36
|
235 kumpf 1.45 /** This destruct deletes all handlers which were installed. */
236 ~Monitor();
|
237 mike 1.2
|
238 kumpf 1.45 /** Sets the state of the monitor entry to the specified state.
239 This is used to synchronize the monitor and the worker
240 thread. Bug# 2057 */
|
241 kumpf 1.48 void setState(
242 Uint32 index,
243 MonitorEntry::Status status);
|
244 kumpf 1.45
|
245 kumpf 1.46 void tickle();
|
246 kumpf 1.45
247 /** Monitor system-level for the given number of milliseconds. Post a
248 message to the corresponding queue when such an event occurs.
249 Return after the time has elapsed or a single event has occurred,
250 whichever occurs first.
251
252 @param timeoutMsec the number of milliseconds to wait for an event.
253 */
254 void run(Uint32 timeoutMsec);
255
256 /** Solicit interest in SocketMessages. Note that there may only
257 be one solicitor per socket.
258
259 @param socket the socket to monitor for activity.
260 @param queueId of queue on which to post socket messages.
261 @return false if messages have already been solicited on this socket.
262 */
263 int solicitSocketMessages(
264 SocketHandle socket,
265 Uint32 queueId,
|
266 kumpf 1.48 Uint32 type);
|
267 kumpf 1.45
268 /** Unsolicit messages on the given socket.
269
270 @param socket on which to unsolicit messages.
271 @return false if no such solicitation has been made on the given socket.
272 */
273 void unsolicitSocketMessages(SocketHandle);
274
275 /** stop listening for client connections
276 */
277 void stopListeningForConnections(Boolean wait);
|
278 kumpf 1.18
|
279 jsafrane 1.54 Mutex& getLock();
|
280 mike 1.2 private:
|
281 david.dillard 1.36
|
282 kumpf 1.48 Array<MonitorEntry> _entries;
283 /**
284 This mutex must be locked when accessing the _entries array or any
285 of its MonitorEntry objects.
286 */
287 Mutex _entriesMutex;
288
|
289 kumpf 1.45 AtomicInt _stopConnections;
290 Semaphore _stopConnectionsSem;
|
291 kumpf 1.48
|
292 kumpf 1.45 /** tracks how many times solicitSocketCount() has been called */
293 Uint32 _solicitSocketCount;
|
294 kumpf 1.48
|
295 kumpf 1.46 Tickler _tickler;
|
296 mike 1.2 };
|
297 mday 1.15
|
298 mike 1.2 PEGASUS_NAMESPACE_END
299
300 #endif /* Pegasus_Monitor_h */
|