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 Tracer::LEVEL3,
|
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 kumpf 1.54 Boolean noMoreRequests = waitUntilNoMoreRequests(requestPending);
|
152 kumpf 1.8
|
153 marek 1.55 PEG_TRACE((
154 TRC_SHUTDOWN,
|
155 marek 1.56 Tracer::LEVEL4,
|
156 kumpf 1.50 "ShutdownService::shutdown - All outstanding CIM operations "
|
157 marek 1.55 "complete = %s",
158 (noMoreRequests) ? "true" : "false"));
|
159 david 1.19
|
160 kumpf 1.8 //
|
161 kumpf 1.65 // Send a shutdown signal to the CIMServer. CIMServer itself will take
162 // care of shutting down the CimomServices and deleting them. In other
163 // words, _DO_ _NOT_ call 'shutdownCimomServices' from a provider.
|
164 kumpf 1.8 //
|
165 kumpf 1.65 _cimserver->shutdown();
166
167 PEG_TRACE_CSTRING(TRC_SHUTDOWN, Tracer::LEVEL3,
168 "ShutdownService::shutdown - CIMServer instructed to shut down.");
|
169 mike 1.2 }
|
170 kumpf 1.50 catch (Exception& e)
|
171 mike 1.2 {
|
172 thilo.boehm 1.58 PEG_TRACE((TRC_SHUTDOWN, Tracer::LEVEL2,
173 "Error occurred during CIMServer shutdown: %s",
174 (const char*)e.getMessage().getCString()));
|
175 mike 1.2 }
|
176 kumpf 1.50 catch (...)
|
177 kumpf 1.9 {
|
178 marek 1.56 PEG_TRACE_CSTRING(TRC_SHUTDOWN, Tracer::LEVEL2,
|
179 carolann.graves 1.42 "Unexpected error occurred during CIMServer shutdown. ");
|
180 kumpf 1.9 }
181
|
182 kumpf 1.12 PEG_METHOD_EXIT();
|
183 mike 1.2 }
184
185 /**********************************************************/
186 /* private methods */
187 /**********************************************************/
188
|
189 konrad.r 1.39 void ShutdownService::shutdownCimomServices()
|
190 mike 1.2 {
|
191 carolann.graves 1.42 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdownCimomServices");
|
192 kumpf 1.12
|
193 chip 1.4 //
|
194 kumpf 1.8 // Shutdown the Indication Service
195 //
196 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDICATIONSERVICE);
197
198 // Shutdown the Indication Handler Service
199 _sendShutdownRequestToService(PEGASUS_QUEUENAME_INDHANDLERMANAGER);
200
|
201 konrad.r 1.39 // PEGASUS_QUEUENAME_EXPORTRESPENCODER
202 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTRESPENCODER);
|
203 kumpf 1.50
|
204 kumpf 1.8 //
205 // shutdown CIM Export Request Dispatcher Service
206 //
207 _sendShutdownRequestToService(PEGASUS_QUEUENAME_EXPORTREQDISPATCHER);
208
|
209 kumpf 1.50 //
|
210 mday 1.24 // shutdown CIM Operation Request Dispatcher Service
211 //
212 _sendShutdownRequestToService(PEGASUS_QUEUENAME_OPREQDISPATCHER);
213
|
214 konrad.r 1.39 // shutdown CIM Provider Manager
215 _sendShutdownRequestToService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
216
217 // shutdown ModuleController also called ControlService.
218 _sendShutdownRequestToService(PEGASUS_QUEUENAME_CONTROLSERVICE);
|
219 mday 1.20
|
220 kumpf 1.12 PEG_METHOD_EXIT();
|
221 kumpf 1.8 }
222
|
223 kumpf 1.50 void ShutdownService::_sendShutdownRequestToService(const char* serviceName)
|
224 kumpf 1.8 {
|
225 kumpf 1.50 MessageQueueService* _mqs = static_cast<MessageQueueService*>(_controller);
226
|
227 venkat.puvvada 1.60 MessageQueue *queue = MessageQueue::lookup(serviceName);
|
228 kumpf 1.50 Uint32 _queueId;
|
229 venkat.puvvada 1.60 if (queue)
230 {
231 _queueId = queue->getQueueId();
232 }
233 else
|
234 kumpf 1.50 {
235 // service not found, just return
236 return;
237 }
238 // send a Stop (this is a legacy message that in some of the MQS does
239 // termination of its internal stuff. Then follow it with a Stop (to
|
240 venkat.puvvada 1.62 // open up its incoming queue), and then with a AsyncIoClose
|
241 kumpf 1.50 // which closes the incoming queue.
242
243 // All of these messages MUST be sequential. Do not use SendForget or
244 // SendAsync as those are asynchronous and their receipt is guaranteed
245 // to be undeterministic and possibly out of sequence (which is something
246 // we do not want).
|
247 konrad.r 1.39
|
248 kumpf 1.46 CimServiceStop stop_message(
|
249 kumpf 1.50 NULL,
|
250 venkat.puvvada 1.68 _queueId);
|
251 kumpf 1.50
|
252 kumpf 1.47 AutoPtr<AsyncReply> StopAsyncReply(
253 _controller->ClientSendWait(_queueId, &stop_message));
|
254 mday 1.26
|
255 kumpf 1.46 CimServiceStart start_message(
|
256 kumpf 1.50 NULL,
|
257 venkat.puvvada 1.68 _queueId);
|
258 mday 1.26
|
259 kumpf 1.47 AutoPtr <AsyncReply> StartAsyncReply(
260 _controller->ClientSendWait(_queueId, &start_message));
|
261 kumpf 1.8
|
262 venkat.puvvada 1.62 AsyncIoClose close_request(
|
263 kumpf 1.50 NULL,
|
264 venkat.puvvada 1.68 _queueId);
|
265 kumpf 1.8
|
266 kumpf 1.47 AutoPtr <AsyncReply> CloseAsyncReply(
267 _controller->ClientSendWait(_queueId, &close_request));
|
268 mike 1.2 }
269
|
270 kumpf 1.65 void ShutdownService::shutdownProviders()
|
271 mike 1.2 {
|
272 kumpf 1.65 PEG_METHOD_ENTER(TRC_SHUTDOWN, "ShutdownService::shutdownProviders");
|
273 kumpf 1.12
|
274 kumpf 1.8 //
275 // get provider manager service
276 //
|
277 kumpf 1.50 MessageQueue* queue =
|
278 kumpf 1.8 MessageQueue::lookup(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
279
280 if (queue == 0)
|
281 kumpf 1.12 {
282 PEG_METHOD_EXIT();
|
283 kumpf 1.8 return;
|
284 kumpf 1.12 }
|
285 kumpf 1.8
|
286 kumpf 1.50 MessageQueueService* _service = dynamic_cast<MessageQueueService*>(queue);
|
287 kumpf 1.52 PEGASUS_ASSERT(_service != 0);
|
288 kumpf 1.8 Uint32 _queueId = _service->getQueueId();
289
|
290 kumpf 1.50 //
|
291 kumpf 1.8 // create stop all providers request
292 //
|
293 kumpf 1.50 CIMStopAllProvidersRequestMessage* stopRequest =
294 new CIMStopAllProvidersRequestMessage(
295 XmlWriter::getNextMessageId(),
|
296 venkat.puvvada 1.68.8.1 QueueIdStack(_queueId),
297 _shutdownTimeout);
|
298 mike 1.2
299 //
|
300 kumpf 1.8 // create async request message
|
301 mike 1.2 //
|
302 kumpf 1.50 AsyncLegacyOperationStart* asyncRequest =
303 new AsyncLegacyOperationStart(
|
304 kumpf 1.8 NULL,
305 _queueId,
|
306 venkat.puvvada 1.59 stopRequest);
|
307 kumpf 1.8
|
308 kumpf 1.50 // Use SendWait, which is serialized and waits. Do not use asynchronous
309 // callback as the response might be received _after_ the provider or
310 // this service has been deleted.
311
312 AsyncReply* asyncReply =
313 _controller->ClientSendWait(_queueId, asyncRequest);
314 CIMStopAllProvidersResponseMessage* response =
315 reinterpret_cast<CIMStopAllProvidersResponseMessage*>(
316 (static_cast<AsyncLegacyOperationResult*>(asyncReply))->get_result());
|
317 kumpf 1.8
318 if (response->cimException.getCode() != CIM_ERR_SUCCESS)
319 {
|
320 kumpf 1.50 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
321 kumpf 1.57 MessageLoaderParms(
322 "Server.ShutdownService.CIM_PROVIDER_SHUTDOWN",
|
323 kumpf 1.66 "A provider shutdown exception has occurred: $0",
324 response->cimException.getMessage()));
|
325 kumpf 1.8 }
326
327 delete asyncRequest;
328 delete asyncReply;
329 delete response;
330
|
331 kumpf 1.12 PEG_METHOD_EXIT();
|
332 kumpf 1.8 }
333
|
334 konrad.r 1.39 Boolean ShutdownService::waitUntilNoMoreRequests(Boolean requestPending)
|
335 kumpf 1.8 {
|
336 kumpf 1.54 Uint32 waitTime = _shutdownTimeout; // maximum wait time in seconds
337 const Uint32 waitInterval = 1; // one second wait interval
338 Uint32 requestCount;
|
339 kumpf 1.8
340 //
341 // Loop and wait one second until either there is no more requests
342 // or until timeout expires.
343 //
|
344 kumpf 1.54 while (waitTime > 0)
|
345 kumpf 1.8 {
|
346 kumpf 1.54 requestCount = _cimserver->getOutstandingRequestCount();
347 if (requestCount <= (requestPending ? 1 : 0))
348 {
349 return true;
350 }
351
|
352 marek 1.55 PEG_TRACE((
353 TRC_SHUTDOWN,
354 Tracer::LEVEL4,
|
355 kumpf 1.54 "ShutdownService waiting for outstanding CIM operations to "
|
356 marek 1.55 "complete. Request count: %d",
357 requestCount));
|
358 kumpf 1.50 Threads::sleep(waitInterval * 1000);
|
359 kumpf 1.54 waitTime -= waitInterval;
|
360 kumpf 1.50 }
|
361 kumpf 1.8
|
362 kumpf 1.54 return _cimserver->getOutstandingRequestCount() <= (requestPending ? 1 : 0);
|
363 mike 1.2 }
364
365 PEGASUS_NAMESPACE_END
|