1 karl 1.43 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.35 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.29 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.35 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.37 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.43 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
15 chip 1.4 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
18 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 kumpf 1.11 //
|
21 chip 1.4 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
22 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
24 chip 1.4 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
27 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
|
30 kumpf 1.11 //==============================================================================
|
31 mike 1.2 //
32 //%////////////////////////////////////////////////////////////////////////////
33
34
35 /////////////////////////////////////////////////////////////////////////////
|
36 chip 1.4 // ShutdownService
|
37 mike 1.2 /////////////////////////////////////////////////////////////////////////////
38
39 #include <Pegasus/Common/Config.h>
40 #include <Pegasus/Server/ShutdownExceptions.h>
41 #include <Pegasus/Server/CIMServerState.h>
42 #include <Pegasus/Server/ShutdownService.h>
|
43 kumpf 1.8 #include <Pegasus/Common/XmlWriter.h>
44 #include <Pegasus/Common/Message.h>
45 #include <Pegasus/Common/CimomMessage.h>
46 #include <Pegasus/Common/CIMMessage.h>
47 #include <Pegasus/Common/MessageQueueService.h>
|
48 kumpf 1.12 #include <Pegasus/Common/Tracer.h>
|
49 kumpf 1.50
|
50 mday 1.20 #if defined(PEGASUS_OS_TYPE_UNIX)
|
51 kumpf 1.50 # include <sys/types.h>
|
52 mday 1.20 #endif
|
53 humberto 1.22
|
54 mike 1.2 PEGASUS_USING_STD;
55
56 PEGASUS_NAMESPACE_BEGIN
57
58 /**
|
59 kumpf 1.8 The constant representing the shutdown timeout property name
|
60 mike 1.2 */
61 static String SHUTDOWN_TIMEOUT_PROPERTY = "shutdownTimeout";
62
|
63 chip 1.4 /**
|
64 kumpf 1.50 Initialize ShutdownService instance
|
65 mike 1.2 */
66 ShutdownService* ShutdownService::_instance = 0;
67
|
68 chip 1.4 /**
|
69 kumpf 1.50 Initialize all other class variables
|
70 kumpf 1.3 */
|
71 kumpf 1.50 CIMServer* ShutdownService::_cimserver = 0;
72 Uint32 ShutdownService::_shutdownTimeout = 0;
73 ModuleController* ShutdownService::_controller = 0;
|
74 kumpf 1.3
|
75 mike 1.2 /** Constructor. */
|
76 kumpf 1.5 ShutdownService::ShutdownService(CIMServer* cimserver)
|
77 mike 1.2 {
|
78 kumpf 1.5 _cimserver = cimserver;
|
79 kumpf 1.8
80 //
81 // get module controller
82 //
|
83 kumpf 1.47 _controller = ModuleController::getModuleController();
|
84 mike 1.2 }
|
85 kumpf 1.50
|
86 konrad.r 1.40 /**
|
87 kumpf 1.50 Terminates the shutdown service
|
88 konrad.r 1.40 */
|
89 kumpf 1.50 void ShutdownService::destroy()
|
90 konrad.r 1.40 {
|
91 kumpf 1.45 delete _instance;
92 _instance = 0;
|
93 konrad.r 1.40 }
|
94 kumpf 1.50
|
95 mike 1.2 /** Destructor. */
96 ShutdownService::~ShutdownService()
97 {
98 }
99
|
100 chip 1.4 /**
|
101 kumpf 1.50 return a pointer to the ShutdownService instance.
|
102 mike 1.2 */
|
103 kumpf 1.5 ShutdownService* ShutdownService::getInstance(CIMServer* cimserver)
|
104 mike 1.2 {
|
105 chip 1.4 if (!_instance)
|
106 mike 1.2 {
|
107 kumpf 1.5 _instance = new ShutdownService(cimserver);
|
108 mike 1.2 }
109 return _instance;
110 }
111
|
112 chip 1.4 /**
113 The shutdown method to be called by the ShutdownProvider to
|
114 thilo.boehm 1.51 process a shutdown request from the cimcli client.
|
115 mike 1.2 */
|
116 kumpf 1.18 void ShutdownService::shutdown(
117 Boolean force,
118 Uint32 timeout,
119 Boolean requestPending)
|
120 mike 1.2 {
|
121 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdown");
|
122 kumpf 1.12
|
123 mike 1.2 //
124 // Initialize variables
125 //
126 Boolean timeoutExpired = false;
127 Boolean noMoreRequests = false;
128
|
129 kumpf 1.12 _shutdownTimeout = timeout;
130
|
131 kumpf 1.8 try
|
132 mike 1.2 {
|
133 kumpf 1.8 //
134 // set CIMServer state to TERMINATING
135 //
136 _cimserver->setState(CIMServerState::TERMINATING);
137
|
138 kumpf 1.50 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
139 "ShutdownService::shutdown - CIM server state set to "
140 "CIMServerState::TERMINATING");
|
141 david 1.19
|
142 kumpf 1.8 //
143 // Tell the CIMServer to stop accepting new client connection requests.
144 //
145 _cimserver->stopClientConnection();
146
|
147 david 1.19
|
148 kumpf 1.50 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
149 "ShutdownService::shutdown - No longer accepting new client "
150 "connection requests.");
|
151 david 1.19
|
152 kumpf 1.8 //
153 // Determine if there are any outstanding CIM operation requests
154 // (take into account that one of the request is the shutdown request).
155 //
156 Uint32 requestCount = _cimserver->getOutstandingRequestCount();
|
157 kumpf 1.18 if (requestCount > (requestPending ? 1 : 0))
|
158 kumpf 1.8 {
|
159 david 1.19
|
160 kumpf 1.50 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
161 "ShutdownService::shutdown - Waiting for outstanding CIM "
162 "operations to complete. Request count: $0",
163 requestCount);
|
164 konrad.r 1.39 noMoreRequests = waitUntilNoMoreRequests(requestPending);
|
165 kumpf 1.8 }
166 else
167 {
168 noMoreRequests = true;
169 }
170
|
171 kumpf 1.50 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
172 "ShutdownService::shutdown - All outstanding CIM operations "
173 "complete");
|
174 david 1.19
|
175 kumpf 1.8 //
176 // proceed to shutdown the CIMServer
177 //
178 _shutdownCIMServer();
|
179 mike 1.2 }
|
180 kumpf 1.50 catch (CIMException& e)
|
181 mike 1.2 {
|
182 kumpf 1.23 PEG_TRACE_STRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
183 kumpf 1.12 "Error occurred during CIMServer shutdown: " + e.getMessage());
|
184 mike 1.2 }
|
185 kumpf 1.50 catch (Exception& e)
|
186 mike 1.2 {
|
187 kumpf 1.23 PEG_TRACE_STRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
188 kumpf 1.12 "Error occurred during CIMServer shutdown: " + e.getMessage());
|
189 mike 1.2 }
|
190 kumpf 1.50 catch (...)
|
191 kumpf 1.9 {
|
192 marek 1.53 PEG_TRACE_CSTRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
193 carolann.graves 1.42 "Unexpected error occurred during CIMServer shutdown. ");
|
194 kumpf 1.9 }
195
|
196 mike 1.2 //
197 // All done
198 //
|
199 kumpf 1.12 PEG_METHOD_EXIT();
|
200 mike 1.2 }
201
202 /**********************************************************/
203 /* private methods */
204 /**********************************************************/
205
|
206 kumpf 1.12 void ShutdownService::_shutdownCIMServer()
|
207 mike 1.2 {
|
208 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::_shutdownCIMServer");
|
209 mike 1.2
|
210 chip 1.4 //
|
211 kumpf 1.9 // Shutdown the providers
|
212 mike 1.2 //
|
213 mday 1.24
|
214 kumpf 1.9 _shutdownProviders();
|
215 mike 1.2
|
216 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
|
217 kumpf 1.50 "ShutdownService::_shutdownCIMServer - CIM server provider shutdown "
218 "complete");
|
219 david 1.19
|
220 chip 1.4 //
|
221 kumpf 1.50 // Send a shutdown signal to the CIMServer. CIMServer itself will take
222 // care of shutting down the CimomServices and deleting them. In other
223 // words, _DO_ _NOT_ call 'shutdownCimomServices' from a provider.
|
224 mike 1.2 //
|
225 konrad.r 1.39 _cimserver->shutdown();
|
226 chip 1.4
|
227 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
|
228 kumpf 1.50 "ShutdownService::_shutdownCIMServer - Cimom services shutdown "
229 "complete");
|
230 david 1.19
|
231 kumpf 1.12 PEG_METHOD_EXIT();
|
232 mike 1.2 }
233
|
234 konrad.r 1.39 void ShutdownService::shutdownCimomServices()
|
235 mike 1.2 {
|
236 carolann.graves 1.42 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdownCimomServices");
|
237 kumpf 1.12
|
238 chip 1.4 //
|
239 kumpf 1.8 // Shutdown the Indication Service
240 //
241 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDICATIONSERVICE);
242
243 // Shutdown the Indication Handler Service
244 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDHANDLERMANAGER);
245
|
246 konrad.r 1.39 // PEGASUS_QUEUENAME_OPRESPENCODER
247 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPRESPENCODER);
248
249 // PEGASUS_QUEUENAME_EXPORTRESPENCODER
250 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTRESPENCODER);
|
251 kumpf 1.50
|
252 kumpf 1.8 //
253 // shutdown Authenticator Delegator Service
254 //
255 _sendShutdownRequestToService(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR);
256
257 //
258 // shutdown CIM Operation Request Authorizer Service
259 //
260 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQAUTHORIZER);
261
262 //
263 // shutdown CIM Operation Request Decoder Service
264 //
265 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDECODER);
266
267
268 //
269 // shutdown CIM Export Request Decoder Service
270 //
271 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDECODER);
272
|
273 mike 1.2 //
|
274 kumpf 1.8 // shutdown CIM Export Request Dispatcher Service
275 //
276 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDISPATCHER);
277
|
278 kumpf 1.50 //
279 // shutdown binary message handler
|
280 mday 1.20 //
281 _sendShutdownRequestToService(PEGASUS_QUEUENAME_BINARY_HANDLER);
|
282 kumpf 1.50
|
283 mday 1.24 //
284 // shutdown CIM Operation Request Dispatcher Service
285 //
286 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDISPATCHER);
287
|
288 konrad.r 1.39 // shutdown CIM Provider Manager
289 _sendShutdownRequestToService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
290
291 // shutdown ModuleController also called ControlService.
292 _sendShutdownRequestToService(PEGASUS_QUEUENAME_CONTROLSERVICE);
|
293 mday 1.20
|
294 kumpf 1.12 PEG_METHOD_EXIT();
|
295 kumpf 1.8 }
296
|
297 kumpf 1.50 void ShutdownService::_sendShutdownRequestToService(const char* serviceName)
|
298 kumpf 1.8 {
|
299 kumpf 1.50 MessageQueueService* _mqs = static_cast<MessageQueueService*>(_controller);
300
301 Array<Uint32> _services;
302 Uint32 _queueId;
|
303 kumpf 1.8
|
304 kumpf 1.50 _mqs->find_services(String(serviceName), 0, 0, &_services);
305
306 if (_services.size() == 0 )
307 {
308 // service not found, just return
309 return;
310 }
311 _queueId = _services[0];
312
313 // send a Stop (this is a legacy message that in some of the MQS does
314 // termination of its internal stuff. Then follow it with a Stop (to
315 // open up its incoming queue), and then with a AsyncIoctl::IO_CLOSE
316 // which closes the incoming queue.
317
318 // All of these messages MUST be sequential. Do not use SendForget or
319 // SendAsync as those are asynchronous and their receipt is guaranteed
320 // to be undeterministic and possibly out of sequence (which is something
321 // we do not want).
|
322 konrad.r 1.39
|
323 kumpf 1.46 CimServiceStop stop_message(
|
324 kumpf 1.50 NULL,
325 _queueId,
326 _controller->getQueueId(),
327 true);
328
|
329 kumpf 1.47 AutoPtr<AsyncReply> StopAsyncReply(
330 _controller->ClientSendWait(_queueId, &stop_message));
|
331 mday 1.26
|
332 kumpf 1.46 CimServiceStart start_message(
|
333 kumpf 1.50 NULL,
334 _queueId,
335 _controller->getQueueId(),
336 true);
|
337 mday 1.26
|
338 kumpf 1.47 AutoPtr <AsyncReply> StartAsyncReply(
339 _controller->ClientSendWait(_queueId, &start_message));
|
340 kumpf 1.8
|
341 kumpf 1.46 AsyncIoctl close_request(
|
342 kumpf 1.50 NULL,
343 _queueId,
344 _controller->getQueueId(),
345 false,
346 AsyncIoctl::IO_CLOSE,
347 0,
348 0);
|
349 kumpf 1.8
|
350 kumpf 1.47 AutoPtr <AsyncReply> CloseAsyncReply(
351 _controller->ClientSendWait(_queueId, &close_request));
|
352 mike 1.2 }
353
354 void ShutdownService::_shutdownProviders()
355 {
|
356 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::_shutdownProviders");
|
357 kumpf 1.12
|
358 kumpf 1.8 //
359 // get provider manager service
360 //
|
361 kumpf 1.50 MessageQueue* queue =
|
362 kumpf 1.8 MessageQueue::lookup(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
363
364 if (queue == 0)
|
365 kumpf 1.12 {
366 PEG_METHOD_EXIT();
|
367 kumpf 1.8 return;
|
368 kumpf 1.12 }
|
369 kumpf 1.8
|
370 kumpf 1.50 MessageQueueService* _service = dynamic_cast<MessageQueueService*>(queue);
|
371 kumpf 1.52 PEGASUS_ASSERT(_service != 0);
|
372 kumpf 1.8 Uint32 _queueId = _service->getQueueId();
373
|
374 kumpf 1.50 //
|
375 kumpf 1.8 // create stop all providers request
376 //
|
377 kumpf 1.50 CIMStopAllProvidersRequestMessage* stopRequest =
378 new CIMStopAllProvidersRequestMessage(
379 XmlWriter::getNextMessageId(),
380 QueueIdStack(_queueId));
|
381 mike 1.2
382 //
|
383 kumpf 1.8 // create async request message
|
384 mike 1.2 //
|
385 kumpf 1.50 AsyncLegacyOperationStart* asyncRequest =
386 new AsyncLegacyOperationStart(
|
387 kumpf 1.8 NULL,
388 _queueId,
389 stopRequest,
390 _queueId);
391
|
392 kumpf 1.50 // Use SendWait, which is serialized and waits. Do not use asynchronous
393 // callback as the response might be received _after_ the provider or
394 // this service has been deleted.
395
396 AsyncReply* asyncReply =
397 _controller->ClientSendWait(_queueId, asyncRequest);
398 CIMStopAllProvidersResponseMessage* response =
399 reinterpret_cast<CIMStopAllProvidersResponseMessage*>(
400 (static_cast<AsyncLegacyOperationResult*>(asyncReply))->get_result());
|
401 kumpf 1.8
402 if (response->cimException.getCode() != CIM_ERR_SUCCESS)
403 {
|
404 kumpf 1.50 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
405 "Server.ShutdownService.CIM_PROVIDER_SHUTDOWN",
406 "$0 - CIM provider shutdown exception has occurred.",
407 "ShutdownService::_shutdownProviders");
|
408 humberto 1.22
|
409 kumpf 1.8 CIMException e = response->cimException;
410 delete asyncRequest;
411 delete asyncReply;
412 delete response;
|
413 kumpf 1.12 PEG_METHOD_EXIT();
|
414 kumpf 1.50 throw e;
|
415 kumpf 1.8 }
416
417 delete asyncRequest;
418 delete asyncReply;
419 delete response;
420
|
421 kumpf 1.12 PEG_METHOD_EXIT();
|
422 kumpf 1.8 }
423
|
424 konrad.r 1.39 Boolean ShutdownService::waitUntilNoMoreRequests(Boolean requestPending)
|
425 kumpf 1.8 {
426 Uint32 maxWaitTime = _shutdownTimeout; // maximum wait time in seconds
427 Uint32 waitInterval = 1; // one second wait interval
428
429 Uint32 requestCount = _cimserver->getOutstandingRequestCount();
430
431 //
432 // Loop and wait one second until either there is no more requests
433 // or until timeout expires.
434 //
|
435 kumpf 1.50 while (requestCount > (requestPending ? 1 : 0) && maxWaitTime > 0)
|
436 kumpf 1.8 {
|
437 kumpf 1.50 Threads::sleep(waitInterval * 1000);
438 maxWaitTime -= waitInterval;
439 requestCount = _cimserver->getOutstandingRequestCount();
440 }
|
441 kumpf 1.8
442 if (requestCount > 1)
443 return false;
444 else
445 return true;
|
446 mike 1.2 }
447
448 PEGASUS_NAMESPACE_END
|