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 // Author: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
33 //
|
34 david 1.19 // Modified By: Dave Rosckes (rosckes@us.ibm.com)
|
35 a.arora 1.33 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
|
36 a.arora 1.34 // Amit K Arora, IBM (amita@in.ibm.com) for Bug#1090
|
37 kumpf 1.36 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
38 mike 1.2 //
39 //%////////////////////////////////////////////////////////////////////////////
40
41
42 /////////////////////////////////////////////////////////////////////////////
|
43 chip 1.4 // ShutdownService
|
44 mike 1.2 /////////////////////////////////////////////////////////////////////////////
45
46 #include <Pegasus/Common/Config.h>
47 #include <Pegasus/Server/ShutdownExceptions.h>
48 #include <Pegasus/Server/CIMServerState.h>
49 #include <Pegasus/Server/ShutdownService.h>
|
50 kumpf 1.8 #include <Pegasus/Common/XmlWriter.h>
51 #include <Pegasus/Common/Message.h>
52 #include <Pegasus/Common/CimomMessage.h>
53 #include <Pegasus/Common/CIMMessage.h>
54 #include <Pegasus/Common/MessageQueueService.h>
|
55 kumpf 1.12 #include <Pegasus/Common/Tracer.h>
|
56 mday 1.20 #if defined(PEGASUS_OS_TYPE_UNIX)
57 #include <sys/types.h>
58 #endif
|
59 humberto 1.22
|
60 mike 1.2 PEGASUS_USING_STD;
61
62 PEGASUS_NAMESPACE_BEGIN
63
64 /**
|
65 kumpf 1.8 The constant representing the shutdown timeout property name
|
66 mike 1.2 */
67 static String SHUTDOWN_TIMEOUT_PROPERTY = "shutdownTimeout";
68
|
69 chip 1.4 /**
70 Initialize ShutdownService instance
|
71 mike 1.2 */
72 ShutdownService* ShutdownService::_instance = 0;
73
|
74 chip 1.4 /**
75 Initialize all other class variables
|
76 kumpf 1.3 */
|
77 kumpf 1.8 CIMServer* ShutdownService::_cimserver = 0;
78 Uint32 ShutdownService::_shutdownTimeout = 0;
79 ModuleController* ShutdownService::_controller = 0;
|
80 kumpf 1.3
|
81 mike 1.2 /** Constructor. */
|
82 kumpf 1.5 ShutdownService::ShutdownService(CIMServer* cimserver)
|
83 mike 1.2 {
|
84 kumpf 1.5 _cimserver = cimserver;
|
85 kumpf 1.8
86 //
87 // get module controller
88 //
|
89 kumpf 1.47 _controller = ModuleController::getModuleController();
|
90 mike 1.2 }
|
91 konrad.r 1.40 /**
92 Terminates the shutdown service
93 */
94 void
|
95 konrad.r 1.41 ShutdownService::destroy(void)
|
96 konrad.r 1.40 {
|
97 kumpf 1.45 delete _instance;
98 _instance = 0;
|
99 konrad.r 1.40 }
|
100 mike 1.2 /** Destructor. */
101 ShutdownService::~ShutdownService()
102 {
|
103 humberto 1.22
|
104 mike 1.2 }
105
|
106 chip 1.4 /**
|
107 mike 1.2 return a pointer to the ShutdownService instance.
108 */
|
109 kumpf 1.5 ShutdownService* ShutdownService::getInstance(CIMServer* cimserver)
|
110 mike 1.2 {
|
111 chip 1.4 if (!_instance)
|
112 mike 1.2 {
|
113 kumpf 1.5 _instance = new ShutdownService(cimserver);
|
114 mike 1.2 }
115 return _instance;
116 }
117
|
118 chip 1.4 /**
119 The shutdown method to be called by the ShutdownProvider to
|
120 mike 1.2 process a shutdown request from the CLI client.
121 */
|
122 kumpf 1.18 void ShutdownService::shutdown(
123 Boolean force,
124 Uint32 timeout,
125 Boolean requestPending)
|
126 mike 1.2 {
|
127 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdown");
|
128 kumpf 1.12
|
129 mike 1.2 //
130 // Initialize variables
131 //
132 Boolean timeoutExpired = false;
133 Boolean noMoreRequests = false;
134
|
135 kumpf 1.12 _shutdownTimeout = timeout;
136
|
137 kumpf 1.8 try
|
138 mike 1.2 {
|
139 kumpf 1.8 //
140 // set CIMServer state to TERMINATING
141 //
142 _cimserver->setState(CIMServerState::TERMINATING);
143
|
144 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
145 "ShutdownService::shutdown - CIM server state set to CIMServerState::TERMINATING");
146
|
147 kumpf 1.8 //
148 // Tell the CIMServer to stop accepting new client connection requests.
149 //
150 _cimserver->stopClientConnection();
151
|
152 david 1.19
153 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
154 "ShutdownService::shutdown - No longer accepting new client connection requests.");
155
|
156 kumpf 1.8 //
157 // Determine if there are any outstanding CIM operation requests
158 // (take into account that one of the request is the shutdown request).
159 //
160 Uint32 requestCount = _cimserver->getOutstandingRequestCount();
|
161 kumpf 1.18 if (requestCount > (requestPending ? 1 : 0))
|
162 kumpf 1.8 {
|
163 david 1.19
164 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
165 "ShutdownService::shutdown - Waiting for outstanding CIM operations to complete. Request count: $0",
166 requestCount);
|
167 konrad.r 1.39 noMoreRequests = waitUntilNoMoreRequests(requestPending);
|
168 kumpf 1.8 }
169 else
170 {
171 noMoreRequests = true;
172 }
173
|
174 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
175 "ShutdownService::shutdown - All outstanding CIM operations complete");
176
|
177 kumpf 1.8 //
178 // proceed to shutdown the CIMServer
179 //
180 _shutdownCIMServer();
|
181 mike 1.2 }
|
182 kumpf 1.8 catch(CIMException & e)
|
183 mike 1.2 {
|
184 kumpf 1.23 PEG_TRACE_STRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
185 kumpf 1.12 "Error occurred during CIMServer shutdown: " + e.getMessage());
|
186 mike 1.2 }
|
187 kumpf 1.8 catch(Exception & e)
|
188 mike 1.2 {
|
189 kumpf 1.23 PEG_TRACE_STRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
190 kumpf 1.12 "Error occurred during CIMServer shutdown: " + e.getMessage());
|
191 mike 1.2 }
192
|
193 kumpf 1.9 catch(...)
194 {
|
195 kumpf 1.23 PEG_TRACE_STRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
196 carolann.graves 1.42 "Unexpected error occurred during CIMServer shutdown. ");
|
197 kumpf 1.9 }
198
|
199 mike 1.2 //
200 // All done
201 //
|
202 kumpf 1.12 PEG_METHOD_EXIT();
|
203 mike 1.2 return;
204 }
205
206 /**********************************************************/
207 /* private methods */
208 /**********************************************************/
209
|
210 kumpf 1.12 void ShutdownService::_shutdownCIMServer()
|
211 mike 1.2 {
|
212 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::_shutdownCIMServer");
|
213 mike 1.2
|
214 chip 1.4 //
|
215 kumpf 1.9 // Shutdown the providers
|
216 mike 1.2 //
|
217 mday 1.24
|
218 kumpf 1.9 _shutdownProviders();
|
219 mike 1.2
|
220 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
221 "ShutdownService::_shutdownCIMServer - CIM server provider shutdown complete");
222
|
223 chip 1.4 //
|
224 konrad.r 1.39 // Send a shutdown signal to the CIMServer. CIMServer itself will take care of
225 // shutting down the CimomServices and deleting them. In other words,
226 // _DO_ _NOT_ call 'shutdownCimomServices' from a provider.
|
227 mike 1.2 //
|
228 konrad.r 1.39 _cimserver->shutdown();
|
229 chip 1.4
|
230 david 1.19 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
231 "ShutdownService::_shutdownCIMServer - Cimom services shutdown complete");
232
233
|
234 kumpf 1.12 PEG_METHOD_EXIT();
|
235 mike 1.2 return;
236 }
237
|
238 konrad.r 1.39 void ShutdownService::shutdownCimomServices()
|
239 mike 1.2 {
|
240 carolann.graves 1.42 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdownCimomServices");
|
241 kumpf 1.12
|
242 chip 1.4 //
|
243 kumpf 1.8 // Shutdown the Indication Service
244 //
245 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDICATIONSERVICE);
246
247 // Shutdown the Indication Handler Service
248 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDHANDLERMANAGER);
249
|
250 konrad.r 1.39 // PEGASUS_QUEUENAME_OPRESPENCODER
251 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPRESPENCODER);
252
253 // PEGASUS_QUEUENAME_EXPORTRESPENCODER
254 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTRESPENCODER);
|
255 kumpf 1.8 //
256 // shutdown Authenticator Delegator Service
257 //
258 _sendShutdownRequestToService(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR);
259
260 //
261 // shutdown CIM Operation Request Authorizer Service
262 //
|
263 konrad.r 1.39
|
264 kumpf 1.8 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQAUTHORIZER);
265
266 //
267 // shutdown CIM Operation Request Decoder Service
268 //
269 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDECODER);
270
271
272 //
273 // shutdown CIM Export Request Decoder Service
274 //
|
275 mday 1.24
|
276 kumpf 1.8 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDECODER);
277
|
278 mike 1.2 //
|
279 kumpf 1.8 // shutdown CIM Export Request Dispatcher Service
280 //
281 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDISPATCHER);
282
|
283 mday 1.20 //
284 // shutdown binary message handler
285 //
286 _sendShutdownRequestToService(PEGASUS_QUEUENAME_BINARY_HANDLER);
287
|
288 mday 1.24 //
289 // shutdown CIM Operation Request Dispatcher Service
290 //
291 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDISPATCHER);
292
|
293 konrad.r 1.39 // shutdown CIM Provider Manager
294 _sendShutdownRequestToService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
295
296 // shutdown ModuleController also called ControlService.
297
298 _sendShutdownRequestToService(PEGASUS_QUEUENAME_CONTROLSERVICE);
|
299 mday 1.20
|
300 kumpf 1.12 PEG_METHOD_EXIT();
|
301 kumpf 1.8 return;
302 }
303
304 void ShutdownService::_sendShutdownRequestToService(const char * serviceName)
305 {
306
|
307 mday 1.27 MessageQueueService* _mqs = static_cast<MessageQueueService*>(_controller);
308
|
309 mday 1.28 Array<Uint32> _services;
310 Uint32 _queueId;
|
311 konrad.r 1.39
|
312 mday 1.28 _mqs->find_services(String(serviceName), 0, 0, &_services);
|
313 mday 1.27
|
314 mday 1.28 if (_services.size() == 0 )
|
315 mday 1.27 {
316 // service not found, just return
317 return;
318 }
|
319 mday 1.28 _queueId = _services[0];
|
320 konrad.r 1.39
321 // send a Stop (this is a legacy message that in some of the MQS does termination
322 // of its internal stuff. Then follow it with a Stop (to open up its incoming queue),
323 // and then with a AsyncIoctl::IO_CLOSE which closes the incoming queue.
324
325 // All of these messages MUST be sequential. Do not use SendForget or SendAsync as those
|
326 carolann.graves 1.42 // are asynchronous and their receipt is guaranteed to be undeterministic and possibly
|
327 konrad.r 1.39 // out of sequence (which is something we do not want).
328
|
329 kumpf 1.46 CimServiceStop stop_message(
|
330 mday 1.26 NULL,
331 _queueId,
332 _controller->getQueueId(),
|
333 konrad.r 1.39 true);
334
|
335 kumpf 1.47 AutoPtr<AsyncReply> StopAsyncReply(
336 _controller->ClientSendWait(_queueId, &stop_message));
|
337 mday 1.26
|
338 kumpf 1.46 CimServiceStart start_message(
|
339 mday 1.26 NULL,
340 _queueId,
341 _controller->getQueueId(),
|
342 konrad.r 1.39 true);
|
343 mday 1.26
|
344 kumpf 1.47 AutoPtr <AsyncReply> StartAsyncReply(
345 _controller->ClientSendWait(_queueId, &start_message));
|
346 kumpf 1.8
|
347 kumpf 1.46 AsyncIoctl close_request(
|
348 mday 1.26 NULL,
349 _queueId,
350 _controller->getQueueId(),
351 false,
352 AsyncIoctl::IO_CLOSE,
353 0,
354 0);
|
355 kumpf 1.8
|
356 kumpf 1.47 AutoPtr <AsyncReply> CloseAsyncReply(
357 _controller->ClientSendWait(_queueId, &close_request));
|
358 mike 1.2
359 return;
360 }
361
362 void ShutdownService::_shutdownProviders()
363 {
|
364 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::_shutdownProviders");
|
365 kumpf 1.12
|
366 kumpf 1.8 //
367 // get provider manager service
368 //
369 MessageQueue * queue =
370 MessageQueue::lookup(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
371
372 if (queue == 0)
|
373 kumpf 1.12 {
374 PEG_METHOD_EXIT();
|
375 kumpf 1.8 return;
|
376 kumpf 1.12 }
|
377 kumpf 1.8
378 MessageQueueService * _service = dynamic_cast<MessageQueueService *>(queue);
379 Uint32 _queueId = _service->getQueueId();
380
381 //
382 // create stop all providers request
383 //
384 CIMStopAllProvidersRequestMessage * stopRequest =
385 new CIMStopAllProvidersRequestMessage(
386 XmlWriter::getNextMessageId (),
387 QueueIdStack(_queueId));
|
388 mike 1.2
389 //
|
390 kumpf 1.8 // create async request message
|
391 mike 1.2 //
|
392 kumpf 1.8 AsyncLegacyOperationStart * asyncRequest =
393 new AsyncLegacyOperationStart (
394 NULL,
395 _queueId,
396 stopRequest,
397 _queueId);
398
|
399 carolann.graves 1.42 // Use SendWait, which is serialized and waits. Do not use asynchronous callback
|
400 konrad.r 1.39 // as the response might be received _after_ the provider or this service has
401 // been deleted.
|
402 kumpf 1.8
|
403 kumpf 1.47 AsyncReply * asyncReply = _controller->ClientSendWait(
|
404 mday 1.20 _queueId,
405 asyncRequest);
|
406 kumpf 1.8 CIMStopAllProvidersResponseMessage * response =
407 reinterpret_cast<CIMStopAllProvidersResponseMessage *>(
408 (static_cast<AsyncLegacyOperationResult *>(asyncReply))->get_result());
409
410 if (response->cimException.getCode() != CIM_ERR_SUCCESS)
411 {
|
412 humberto 1.22 // l10n
413
414 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
415 "Server.ShutdownService.CIM_PROVIDER_SHUTDOWN",
416 "$0 - CIM provider shutdown exception has occurred.",
417 "ShutdownService::_shutdownProviders");
418
419 // Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
420 // "ShutdownService::_shutdownProviders - CIM provider shutdown exception has occurred.");
421
|
422 kumpf 1.8 CIMException e = response->cimException;
423 delete asyncRequest;
424 delete asyncReply;
425 delete response;
|
426 kumpf 1.12 PEG_METHOD_EXIT();
|
427 kumpf 1.8 throw (e);
428 }
429
430 delete asyncRequest;
431 delete asyncReply;
432 delete response;
433
|
434 kumpf 1.12 PEG_METHOD_EXIT();
|
435 mike 1.2 return;
|
436 kumpf 1.8 }
437
|
438 konrad.r 1.39 Boolean ShutdownService::waitUntilNoMoreRequests(Boolean requestPending)
|
439 kumpf 1.8 {
|
440 mday 1.20
|
441 kumpf 1.8 Uint32 maxWaitTime = _shutdownTimeout; // maximum wait time in seconds
442 Uint32 waitInterval = 1; // one second wait interval
443
444 Uint32 requestCount = _cimserver->getOutstandingRequestCount();
445
446 //
447 // Loop and wait one second until either there is no more requests
448 // or until timeout expires.
449 //
|
450 kumpf 1.18 while (requestCount > (requestPending ? 1 : 0) &&
451 maxWaitTime > 0)
|
452 kumpf 1.8 {
|
453 mike 1.48 Threads::sleep(waitInterval * 1000);
|
454 kumpf 1.44 maxWaitTime -= waitInterval;
455 requestCount = _cimserver->getOutstandingRequestCount();
|
456 kumpf 1.8 }
457
458 if (requestCount > 1)
459 return false;
460 else
461 return true;
|
462 mike 1.2 }
463
464 PEGASUS_NAMESPACE_END
|