1 martin 1.63 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.64 //
|
3 martin 1.63 // 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.64 //
|
10 martin 1.63 // 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.64 //
|
17 martin 1.63 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.64 //
|
20 martin 1.63 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.64 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.63 // 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.64 //
|
28 martin 1.63 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%////////////////////////////////////////////////////////////////////////////
31
32
33 /////////////////////////////////////////////////////////////////////////////
|
34 chip 1.4 // ShutdownService
|
35 mike 1.2 /////////////////////////////////////////////////////////////////////////////
36
37 #include <Pegasus/Common/Config.h>
38 #include <Pegasus/Server/ShutdownExceptions.h>
39 #include <Pegasus/Server/CIMServerState.h>
40 #include <Pegasus/Server/ShutdownService.h>
|
41 kumpf 1.8 #include <Pegasus/Common/XmlWriter.h>
42 #include <Pegasus/Common/Message.h>
43 #include <Pegasus/Common/CimomMessage.h>
44 #include <Pegasus/Common/CIMMessage.h>
45 #include <Pegasus/Common/MessageQueueService.h>
|
46 kumpf 1.12 #include <Pegasus/Common/Tracer.h>
|
47 kumpf 1.50
|
48 mday 1.20 #if defined(PEGASUS_OS_TYPE_UNIX)
|
49 kumpf 1.50 # include <sys/types.h>
|
50 mday 1.20 #endif
|
51 humberto 1.22
|
52 mike 1.2 PEGASUS_USING_STD;
53
54 PEGASUS_NAMESPACE_BEGIN
55
56 /**
|
57 kumpf 1.8 The constant representing the shutdown timeout property name
|
58 mike 1.2 */
59 static String SHUTDOWN_TIMEOUT_PROPERTY = "shutdownTimeout";
60
|
61 chip 1.4 /**
|
62 kumpf 1.50 Initialize ShutdownService instance
|
63 mike 1.2 */
64 ShutdownService* ShutdownService::_instance = 0;
65
|
66 chip 1.4 /**
|
67 kumpf 1.50 Initialize all other class variables
|
68 kumpf 1.3 */
|
69 kumpf 1.50 CIMServer* ShutdownService::_cimserver = 0;
70 Uint32 ShutdownService::_shutdownTimeout = 0;
71 ModuleController* ShutdownService::_controller = 0;
|
72 kumpf 1.3
|
73 mike 1.2 /** Constructor. */
|
74 kumpf 1.5 ShutdownService::ShutdownService(CIMServer* cimserver)
|
75 mike 1.2 {
|
76 kumpf 1.5 _cimserver = cimserver;
|
77 kumpf 1.8
78 //
79 // get module controller
80 //
|
81 kumpf 1.47 _controller = ModuleController::getModuleController();
|
82 mike 1.2 }
|
83 kumpf 1.50
|
84 konrad.r 1.40 /**
|
85 kumpf 1.50 Terminates the shutdown service
|
86 konrad.r 1.40 */
|
87 kumpf 1.50 void ShutdownService::destroy()
|
88 konrad.r 1.40 {
|
89 kumpf 1.45 delete _instance;
90 _instance = 0;
|
91 konrad.r 1.40 }
|
92 kumpf 1.50
|
93 mike 1.2 /** Destructor. */
94 ShutdownService::~ShutdownService()
95 {
96 }
97
|
98 chip 1.4 /**
|
99 kumpf 1.50 return a pointer to the ShutdownService instance.
|
100 mike 1.2 */
|
101 kumpf 1.5 ShutdownService* ShutdownService::getInstance(CIMServer* cimserver)
|
102 mike 1.2 {
|
103 chip 1.4 if (!_instance)
|
104 mike 1.2 {
|
105 kumpf 1.5 _instance = new ShutdownService(cimserver);
|
106 mike 1.2 }
107 return _instance;
108 }
109
|
110 chip 1.4 /**
111 The shutdown method to be called by the ShutdownProvider to
|
112 thilo.boehm 1.51 process a shutdown request from the cimcli client.
|
113 mike 1.2 */
|
114 kumpf 1.18 void ShutdownService::shutdown(
115 Boolean force,
116 Uint32 timeout,
117 Boolean requestPending)
|
118 mike 1.2 {
|
119 kumpf 1.23 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdown");
|
120 kumpf 1.12
121 _shutdownTimeout = timeout;
122
|
123 kumpf 1.8 try
|
124 mike 1.2 {
|
125 kumpf 1.8 //
126 // set CIMServer state to TERMINATING
127 //
128 _cimserver->setState(CIMServerState::TERMINATING);
129
|
130 marek 1.55 PEG_TRACE_CSTRING(
131 TRC_SHUTDOWN,
|
132 marek 1.56 Tracer::LEVEL4,
|
133 kumpf 1.50 "ShutdownService::shutdown - CIM server state set to "
134 "CIMServerState::TERMINATING");
|
135 david 1.19
|
136 kumpf 1.8 //
137 // Tell the CIMServer to stop accepting new client connection requests.
138 //
139 _cimserver->stopClientConnection();
140
|
141 marek 1.55 PEG_TRACE_CSTRING(
142 TRC_SHUTDOWN,
|
143 dl.meetei 1.74 Tracer::LEVEL4,
|
144 kumpf 1.50 "ShutdownService::shutdown - No longer accepting new client "
145 "connection requests.");
|
146 david 1.19
|
147 kumpf 1.8 //
148 // Determine if there are any outstanding CIM operation requests
149 // (take into account that one of the request is the shutdown request).
150 //
|
151 ashok.pathak 1.73 waitUntilNoMoreRequests(requestPending);
|
152 david 1.19
|
153 kumpf 1.8 //
|
154 kumpf 1.65 // Send a shutdown signal to the CIMServer. CIMServer itself will take
155 // care of shutting down the CimomServices and deleting them. In other
156 // words, _DO_ _NOT_ call 'shutdownCimomServices' from a provider.
|
157 kumpf 1.8 //
|
158 kumpf 1.65 _cimserver->shutdown();
159
|
160 dl.meetei 1.74 PEG_TRACE_CSTRING(TRC_SHUTDOWN, Tracer::LEVEL4,
|
161 kumpf 1.65 "ShutdownService::shutdown - CIMServer instructed to shut down.");
|
162 mike 1.2 }
|
163 kumpf 1.50 catch (Exception& e)
|
164 mike 1.2 {
|
165 thilo.boehm 1.58 PEG_TRACE((TRC_SHUTDOWN, Tracer::LEVEL2,
166 "Error occurred during CIMServer shutdown: %s",
167 (const char*)e.getMessage().getCString()));
|
168 mike 1.2 }
|
169 kumpf 1.50 catch (...)
|
170 kumpf 1.9 {
|
171 marek 1.56 PEG_TRACE_CSTRING(TRC_SHUTDOWN, Tracer::LEVEL2,
|
172 carolann.graves 1.42 "Unexpected error occurred during CIMServer shutdown. ");
|
173 kumpf 1.9 }
174
|
175 kumpf 1.12 PEG_METHOD_EXIT();
|
176 mike 1.2 }
177
178 /**********************************************************/
179 /* private methods */
180 /**********************************************************/
181
|
182 konrad.r 1.39 void ShutdownService::shutdownCimomServices()
|
183 mike 1.2 {
|
184 carolann.graves 1.42 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdownCimomServices");
|
185 kumpf 1.12
|
186 chip 1.4 //
|
187 kumpf 1.8 // Shutdown the Indication Service
188 //
189 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDICATIONSERVICE);
190
191 // Shutdown the Indication Handler Service
192 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDHANDLERMANAGER);
193
|
194 konrad.r 1.39 // PEGASUS_QUEUENAME_EXPORTRESPENCODER
195 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTRESPENCODER);
|
196 kumpf 1.50
|
197 kumpf 1.8 //
198 // shutdown CIM Export Request Dispatcher Service
199 //
200 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDISPATCHER);
201
|
202 kumpf 1.50 //
|
203 mday 1.24 // shutdown CIM Operation Request Dispatcher Service
204 //
205 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDISPATCHER);
206
|
207 konrad.r 1.39 // shutdown CIM Provider Manager
208 _sendShutdownRequestToService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
209
210 // shutdown ModuleController also called ControlService.
211 _sendShutdownRequestToService(PEGASUS_QUEUENAME_CONTROLSERVICE);
|
212 mday 1.20
|
213 kumpf 1.12 PEG_METHOD_EXIT();
|
214 kumpf 1.8 }
215
|
216 kumpf 1.50 void ShutdownService::_sendShutdownRequestToService(const char* serviceName)
|
217 kumpf 1.8 {
|
218 venkat.puvvada 1.60 MessageQueue *queue = MessageQueue::lookup(serviceName);
|
219 kumpf 1.50 Uint32 _queueId;
|
220 venkat.puvvada 1.60 if (queue)
221 {
222 _queueId = queue->getQueueId();
223 }
224 else
|
225 kumpf 1.50 {
226 // service not found, just return
227 return;
228 }
229 // send a Stop (this is a legacy message that in some of the MQS does
230 // termination of its internal stuff. Then follow it with a Stop (to
|
231 venkat.puvvada 1.62 // open up its incoming queue), and then with a AsyncIoClose
|
232 kumpf 1.50 // which closes the incoming queue.
233
234 // All of these messages MUST be sequential. Do not use SendForget or
235 // SendAsync as those are asynchronous and their receipt is guaranteed
236 // to be undeterministic and possibly out of sequence (which is something
237 // we do not want).
|
238 konrad.r 1.39
|
239 kumpf 1.46 CimServiceStop stop_message(
|
240 kumpf 1.50 NULL,
|
241 venkat.puvvada 1.68 _queueId);
|
242 kumpf 1.50
|
243 kumpf 1.47 AutoPtr<AsyncReply> StopAsyncReply(
244 _controller->ClientSendWait(_queueId, &stop_message));
|
245 mday 1.26
|
246 kumpf 1.46 CimServiceStart start_message(
|
247 kumpf 1.50 NULL,
|
248 venkat.puvvada 1.68 _queueId);
|
249 mday 1.26
|
250 kumpf 1.47 AutoPtr <AsyncReply> StartAsyncReply(
251 _controller->ClientSendWait(_queueId, &start_message));
|
252 kumpf 1.8
|
253 venkat.puvvada 1.62 AsyncIoClose close_request(
|
254 kumpf 1.50 NULL,
|
255 venkat.puvvada 1.68 _queueId);
|
256 kumpf 1.8
|
257 kumpf 1.47 AutoPtr <AsyncReply> CloseAsyncReply(
258 _controller->ClientSendWait(_queueId, &close_request));
|
259 mike 1.2 }
260
|
261 kumpf 1.65 void ShutdownService::shutdownProviders()
|
262 mike 1.2 {
|
263 venkat.puvvada 1.71 _shutdownProviders(true);
264 _shutdownProviders(false);
265 }
266
267 void ShutdownService::_shutdownProviders(Boolean controlProviders)
268 {
269 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::_shutdownProviders");
|
270 kumpf 1.12
|
271 kumpf 1.8 //
|
272 venkat.puvvada 1.71 // get provider manager service or control service
|
273 kumpf 1.8 //
|
274 kumpf 1.50 MessageQueue* queue =
|
275 venkat.puvvada 1.71 controlProviders ?
276 MessageQueue::lookup(PEGASUS_QUEUENAME_CONTROLSERVICE) :
277 MessageQueue::lookup(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
|
278 kumpf 1.8
279 if (queue == 0)
|
280 kumpf 1.12 {
281 PEG_METHOD_EXIT();
|
282 kumpf 1.8 return;
|
283 kumpf 1.12 }
|
284 kumpf 1.8
|
285 kumpf 1.50 MessageQueueService* _service = dynamic_cast<MessageQueueService*>(queue);
|
286 kumpf 1.52 PEGASUS_ASSERT(_service != 0);
|
287 kumpf 1.8 Uint32 _queueId = _service->getQueueId();
288
|
289 kumpf 1.50 //
|
290 kumpf 1.8 // create stop all providers request
291 //
|
292 kumpf 1.50 CIMStopAllProvidersRequestMessage* stopRequest =
293 new CIMStopAllProvidersRequestMessage(
294 XmlWriter::getNextMessageId(),
|
295 venkat.puvvada 1.70 QueueIdStack(_queueId),
296 _shutdownTimeout);
|
297 mike 1.2
298 //
|
299 kumpf 1.8 // create async request message
|
300 mike 1.2 //
|
301 venkat.puvvada 1.71 AsyncRequest *asyncRequest;
302
303 if (controlProviders)
304 {
305 asyncRequest = new AsyncModuleOperationStart(
306 0,
307 _queueId,
308 String(),
309 stopRequest);
310 }
311 else
312 {
313 asyncRequest = new AsyncLegacyOperationStart(
314 0,
|
315 kumpf 1.8 _queueId,
|
316 venkat.puvvada 1.59 stopRequest);
|
317 venkat.puvvada 1.71 }
318
|
319 kumpf 1.8
|
320 kumpf 1.50 // Use SendWait, which is serialized and waits. Do not use asynchronous
321 // callback as the response might be received _after_ the provider or
322 // this service has been deleted.
323
324 AsyncReply* asyncReply =
325 _controller->ClientSendWait(_queueId, asyncRequest);
|
326 venkat.puvvada 1.71
327
328 MessageType msgType = asyncReply->getType();
329 PEGASUS_ASSERT((msgType == ASYNC_ASYNC_LEGACY_OP_RESULT) ||
330 (msgType == ASYNC_ASYNC_MODULE_OP_RESULT));
331
332 CIMStopAllProvidersResponseMessage *response;
333
334 if (msgType == ASYNC_ASYNC_LEGACY_OP_RESULT)
335 {
336 response = reinterpret_cast<CIMStopAllProvidersResponseMessage *>(
337 (static_cast<AsyncLegacyOperationResult *>(
338 asyncReply))->get_result());
339 }
340 else
341 {
342 response = reinterpret_cast<CIMStopAllProvidersResponseMessage*>(
343 (static_cast<AsyncModuleOperationResult *>(
344 asyncReply))->get_result());
345 }
|
346 kumpf 1.8
347 if (response->cimException.getCode() != CIM_ERR_SUCCESS)
348 {
|
349 kumpf 1.50 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
350 kumpf 1.57 MessageLoaderParms(
351 "Server.ShutdownService.CIM_PROVIDER_SHUTDOWN",
|
352 kumpf 1.66 "A provider shutdown exception has occurred: $0",
353 response->cimException.getMessage()));
|
354 kumpf 1.8 }
355
356 delete asyncRequest;
357 delete asyncReply;
358 delete response;
359
|
360 kumpf 1.12 PEG_METHOD_EXIT();
|
361 kumpf 1.8 }
362
|
363 ashok.pathak 1.73 void ShutdownService::waitUntilNoMoreRequests(Boolean requestPending)
|
364 kumpf 1.8 {
|
365 kumpf 1.54 Uint32 waitTime = _shutdownTimeout; // maximum wait time in seconds
366 const Uint32 waitInterval = 1; // one second wait interval
367 Uint32 requestCount;
|
368 kumpf 1.8
369 //
370 // Loop and wait one second until either there is no more requests
371 // or until timeout expires.
372 //
|
373 kumpf 1.54 while (waitTime > 0)
|
374 kumpf 1.8 {
|
375 kumpf 1.54 requestCount = _cimserver->getOutstandingRequestCount();
376 if (requestCount <= (requestPending ? 1 : 0))
377 {
|
378 ashok.pathak 1.73 break;
|
379 kumpf 1.54 }
380
|
381 marek 1.55 PEG_TRACE((
382 TRC_SHUTDOWN,
383 Tracer::LEVEL4,
|
384 kumpf 1.54 "ShutdownService waiting for outstanding CIM operations to "
|
385 marek 1.55 "complete. Request count: %d",
386 requestCount));
|
387 kumpf 1.50 Threads::sleep(waitInterval * 1000);
|
388 kumpf 1.54 waitTime -= waitInterval;
|
389 kumpf 1.50 }
|
390 kumpf 1.8
|
391 ashok.pathak 1.73 PEG_TRACE((
392 TRC_SHUTDOWN,
393 Tracer::LEVEL4,
394 "ShutdownService::shutdown - All outstanding CIM operations "
395 "complete = %s",
396 ((_cimserver->getOutstandingRequestCount()) <=
397 (requestPending ? 1 : 0)) ? "true" : "false"));
|
398 mike 1.2 }
399
400 PEGASUS_NAMESPACE_END
|