1 karl 1.75 //%2006////////////////////////////////////////////////////////////////////////
|
2 chip 1.1 //
|
3 karl 1.59 // 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.15 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.59 // 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.63 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.75 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 chip 1.1 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // 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 // 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 karl 1.59 //
|
21 chip 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // 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 // 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 // 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 //==============================================================================
31 //
32 // Author: Chip Vincent (cvincent@us.ibm.com)
33 //
34 // Modified By: Carol Ann Krug Graves, Hewlett-Packard Company
35 // (carolann_graves@hp.com)
36 // Mike Day, IBM (mdday@us.ibm.com)
37 // Karl Schopmeyer(k.schopmeyer@opengroup.org) - Fix associators.
|
38 chip 1.9 // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
|
39 schuur 1.19 // Adrian Schuur, IBM (schuur@de.ibm.com)
|
40 a.arora 1.37 // Amit K Arora (amita@in.ibm.com) for PEP-101
|
41 kumpf 1.39 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
42 se.gupta 1.41 // Seema Gupta (gseema@in.ibm.com for PEP135)
|
43 jim.wunderlich 1.69 // Jim Wunderlich (Jim_Wunderlich@prodigy.net)
|
44 aruran.ms 1.71 // Aruran, IBM (ashanmug@in.ibm.com)for Bug# 3881
|
45 chip 1.1 //
46 //%/////////////////////////////////////////////////////////////////////////////
47
48 #include "ProviderManagerService.h"
49
50 #include <Pegasus/Common/Config.h>
|
51 kumpf 1.65 #include <Pegasus/Common/PegasusVersion.h>
|
52 chip 1.1 #include <Pegasus/Common/Constants.h>
53 #include <Pegasus/Common/CIMMessage.h>
|
54 kumpf 1.39 #include <Pegasus/Common/Thread.h>
|
55 chip 1.1 #include <Pegasus/Common/Tracer.h>
56 #include <Pegasus/Common/Logger.h>
|
57 a.arora 1.37 #include <Pegasus/Common/AutoPtr.h>
|
58 kumpf 1.50 #include <Pegasus/Common/Constants.h>
|
59 chip 1.1
|
60 chip 1.6 #include <Pegasus/Config/ConfigManager.h>
61
|
62 kumpf 1.39 #include <Pegasus/ProviderManager2/BasicProviderManagerRouter.h>
|
63 kumpf 1.51 #include <Pegasus/ProviderManager2/OOPProviderManagerRouter.h>
|
64 brian.campbell 1.60 #include <Pegasus/ProviderManager2/OperationResponseHandler.h>
|
65 chip 1.17
|
66 chip 1.1 PEGASUS_NAMESPACE_BEGIN
67
|
68 chip 1.11 inline Boolean _isSupportedRequestType(const Message * message)
69 {
70 // ATTN: needs implementation
71
72 // for now, assume all requests are valid
73
74 return(true);
|
75 chip 1.3 }
76
77 inline Boolean _isSupportedResponseType(const Message * message)
78 {
|
79 chip 1.11 // ATTN: needs implementation
80
81 // for now, assume all responses are invalid
|
82 chip 1.3
|
83 chip 1.11 return(false);
|
84 chip 1.3 }
85
|
86 schuur 1.19 ProviderManagerService* ProviderManagerService::providerManagerService=NULL;
|
87 kumpf 1.39 Uint32 ProviderManagerService::_indicationServiceQueueId = PEG_NOT_FOUND;
|
88 schuur 1.19
|
89 chip 1.1 ProviderManagerService::ProviderManagerService(void)
90 : MessageQueueService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP)
91 {
|
92 schuur 1.19 providerManagerService=this;
|
93 chip 1.1 }
94
|
95 schuur 1.25 ProviderManagerService::ProviderManagerService(
96 ProviderRegistrationManager * providerRegistrationManager,
97 CIMRepository * repository)
|
98 chip 1.1 : MessageQueueService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP)
99 {
|
100 schuur 1.19 providerManagerService=this;
|
101 schuur 1.25 _repository=repository;
|
102 dj.gorey 1.31
|
103 kumpf 1.38 _providerRegistrationManager = providerRegistrationManager;
|
104 kumpf 1.44
105 _unloadIdleProvidersBusy = 0;
106
|
107 kumpf 1.62 _basicProviderManagerRouter = 0;
108 _oopProviderManagerRouter = 0;
109
110 // Determine which ProviderManagerRouter(s) to use
111
|
112 kumpf 1.51 ConfigManager* configManager = ConfigManager::getInstance();
|
113 kumpf 1.62 Boolean forceProviderProcesses = String::equal(
114 configManager->getCurrentValue("forceProviderProcesses"), "true");
115
116 #ifdef PEGASUS_DISABLE_PROV_USERCTXT
117 if (forceProviderProcesses)
|
118 kumpf 1.51 {
|
119 kumpf 1.76 _oopProviderManagerRouter = new OOPProviderManagerRouter(
120 indicationCallback, responseChunkCallback);
|
121 kumpf 1.51 }
122 else
123 {
|
124 kumpf 1.76 _basicProviderManagerRouter = new BasicProviderManagerRouter(
125 indicationCallback, responseChunkCallback);
|
126 kumpf 1.62 }
127 #else
|
128 kumpf 1.76 _oopProviderManagerRouter = new OOPProviderManagerRouter(
129 indicationCallback, responseChunkCallback);
|
130 kumpf 1.62
131 if (!forceProviderProcesses)
132 {
|
133 kumpf 1.76 _basicProviderManagerRouter = new BasicProviderManagerRouter(
134 indicationCallback, responseChunkCallback);
|
135 kumpf 1.51 }
|
136 kumpf 1.62 #endif
|
137 chip 1.1 }
138
139 ProviderManagerService::~ProviderManagerService(void)
140 {
|
141 kumpf 1.62 delete _basicProviderManagerRouter;
142 delete _oopProviderManagerRouter;
|
143 schuur 1.19 providerManagerService=NULL;
|
144 chip 1.1 }
145
146 Boolean ProviderManagerService::messageOK(const Message * message)
147 {
148 PEGASUS_ASSERT(message != 0);
149
|
150 chip 1.3 if(_isSupportedRequestType(message))
|
151 chip 1.1 {
|
152 chip 1.3 return(MessageQueueService::messageOK(message));
|
153 chip 1.1 }
154
|
155 chip 1.3 return(false);
|
156 chip 1.1 }
157
158 void ProviderManagerService::handleEnqueue(void)
159 {
160 Message * message = dequeue();
161
162 handleEnqueue(message);
163 }
164
165 void ProviderManagerService::handleEnqueue(Message * message)
166 {
167 PEGASUS_ASSERT(message != 0);
168
169 AsyncLegacyOperationStart * asyncRequest;
170
171 if(message->_async != NULL)
172 {
173 asyncRequest = static_cast<AsyncLegacyOperationStart *>(message->_async);
174 }
175 else
176 {
177 chip 1.1 asyncRequest = new AsyncLegacyOperationStart(
178 get_next_xid(),
179 0,
180 this->getQueueId(),
181 message,
182 this->getQueueId());
183 }
184
185 _handle_async_request(asyncRequest);
186 }
187
188 void ProviderManagerService::_handle_async_request(AsyncRequest * request)
189 {
190 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
191 "ProviderManagerService::_handle_async_request");
192
193 PEGASUS_ASSERT((request != 0) && (request->op != 0));
194
195 if(request->getType() == async_messages::ASYNC_LEGACY_OP_START)
196 {
197 request->op->processing();
198 chip 1.1
199 _incomingQueue.enqueue(request->op);
|
200 konrad.r 1.68 ThreadStatus rtn = PEGASUS_THREAD_OK;
201 while (( rtn =_thread_pool->allocate_and_awaken(
202 (void *)this, ProviderManagerService::handleCimOperation)) != PEGASUS_THREAD_OK)
203 {
204 if (rtn==PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
205 pegasus_yield();
206 else
207 {
208 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
209 "Not enough threads to service provider manager." );
210
211 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
212 "Could not allocate thread for %s.",
213 getQueueName());
|
214 aruran.ms 1.71 break;
|
215 konrad.r 1.68 }
216 }
|
217 chip 1.1 }
218 else
219 {
220 // pass all other operations to the default handler
221 MessageQueueService::_handle_async_request(request);
222 }
223
224 PEG_METHOD_EXIT();
225
226 return;
227 }
228
|
229 kumpf 1.57 // Note: This method should not throw an exception. It is used as a thread
230 // entry point, and any exceptions thrown are ignored.
|
231 kumpf 1.39 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
|
232 kumpf 1.67 ProviderManagerService::handleCimOperation(void* arg)
|
233 chip 1.1 {
|
234 kumpf 1.39 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
235 "ProviderManagerService::handleCimOperation");
|
236 chip 1.1
|
237 kumpf 1.67 PEGASUS_ASSERT(arg != 0);
|
238 chip 1.8
|
239 chip 1.1 // get the service from argument
|
240 kumpf 1.67 ProviderManagerService* service =
|
241 kumpf 1.39 reinterpret_cast<ProviderManagerService *>(arg);
|
242 kumpf 1.67 PEGASUS_ASSERT(service != 0);
|
243 chip 1.1
|
244 kumpf 1.67 try
|
245 chip 1.1 {
|
246 kumpf 1.67 if (service->_incomingQueue.size() == 0)
247 {
248 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
249 "ProviderManagerService::handleCimOperation() called with no "
250 "op node in queue");
|
251 chip 1.1
|
252 kumpf 1.67 PEG_METHOD_EXIT();
253 return(PEGASUS_THREAD_RETURN(1));
254 }
|
255 chip 1.1
|
256 kumpf 1.67 AsyncOpNode* op = service->_incomingQueue.dequeue();
|
257 chip 1.1
|
258 kumpf 1.67 if ((op == 0) || (op->_request.count() == 0))
259 {
260 // ATTN: This may dereference a null pointer!
261 MessageQueue* queue = MessageQueue::lookup(op->_source_queue);
|
262 chip 1.1
|
263 kumpf 1.67 PEGASUS_ASSERT(queue != 0);
|
264 chip 1.1
|
265 kumpf 1.67 PEG_METHOD_EXIT();
|
266 chip 1.1
|
267 kumpf 1.67 // no request in op node
268 return(PEGASUS_THREAD_RETURN(1));
269 }
|
270 chip 1.1
|
271 kumpf 1.67 AsyncRequest* request =
272 static_cast<AsyncRequest*>(op->_request.next(0));
|
273 chip 1.1
|
274 kumpf 1.67 if ((request == 0) ||
275 (request->getType() != async_messages::ASYNC_LEGACY_OP_START))
276 {
277 // reply with NAK
278 PEG_METHOD_EXIT();
279 return(PEGASUS_THREAD_RETURN(0));
280 }
|
281 chip 1.1
|
282 kumpf 1.39 Message* legacy =
283 static_cast<AsyncLegacyOperationStart *>(request)->get_action();
|
284 chip 1.1
|
285 chip 1.8 if(_isSupportedRequestType(legacy))
|
286 chip 1.1 {
|
287 a.arora 1.37 AutoPtr<Message> xmessage(legacy);
|
288 chip 1.1
|
289 chip 1.8 // Set the client's requested language into this service thread.
290 // This will allow functions in this service to return messages
291 // in the correct language.
|
292 kumpf 1.39 CIMMessage* msg = dynamic_cast<CIMMessage *>(legacy);
|
293 chip 1.8
|
294 kumpf 1.39 if (msg != 0)
|
295 chip 1.8 {
|
296 kumpf 1.74 AcceptLanguageList* langs = new AcceptLanguageList(
|
297 kumpf 1.67 ((AcceptLanguageListContainer)msg->operationContext.get(
298 AcceptLanguageListContainer::NAME)).getLanguages());
|
299 chip 1.8 Thread::setLanguages(langs);
300 }
301 else
302 {
303 Thread::clearLanguages();
304 }
|
305 chip 1.1
306 service->handleCimRequest(op, legacy);
|
307 chip 1.3 }
|
308 chip 1.8 }
|
309 konrad.r 1.66 catch (const Exception& e)
|
310 kumpf 1.67 {
|
311 konrad.r 1.66 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
312 kumpf 1.67 "Unexpected exception in handleCimOperation: " + e.getMessage());
313 }
|
314 konrad.r 1.66 catch (...)
|
315 kumpf 1.67 {
|
316 konrad.r 1.66 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
317 kumpf 1.67 "Unexpected exception in handleCimOperation.");
318 }
|
319 chip 1.1
320 PEG_METHOD_EXIT();
321
322 return(PEGASUS_THREAD_RETURN(0));
323 }
324
|
325 kumpf 1.39 void ProviderManagerService::handleCimRequest(
326 AsyncOpNode * op,
327 Message * message)
|
328 chip 1.1 {
|
329 kumpf 1.39 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
330 "ProviderManagerService::handleCimRequest");
|
331 chip 1.1
|
332 kumpf 1.38 CIMRequestMessage * request = dynamic_cast<CIMRequestMessage *>(message);
333 PEGASUS_ASSERT(request != 0);
|
334 chip 1.1
335 // get request from op node
336 AsyncRequest * async = static_cast<AsyncRequest *>(op->_request.next(0));
|
337 kumpf 1.38 PEGASUS_ASSERT(async != 0);
338
339 Message * response = 0;
|
340 kumpf 1.58 Boolean consumerLookupFailed = false;
|
341 chip 1.1
|
342 kumpf 1.58 if (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
343 {
344 //
345 // Get a ProviderIdContainer for ExportIndicationRequestMessage.
346 // Note: This can be removed when the CIMExportRequestDispatcher
347 // is updated to add the ProviderIdContainer to the message.
348 //
349 CIMInstance providerModule;
350 CIMInstance provider;
351 const CIMExportIndicationRequestMessage* expRequest =
352 dynamic_cast<const CIMExportIndicationRequestMessage*>(request);
353 if (_providerRegistrationManager->lookupIndicationConsumer(
354 expRequest->destinationPath, provider, providerModule))
355 {
356 request->operationContext.insert(
357 ProviderIdContainer(providerModule, provider));
358 }
359 else
360 {
361 consumerLookupFailed = true;
362 }
363 kumpf 1.58 }
364
365 if (consumerLookupFailed)
366 {
367 CIMResponseMessage* cimResponse = request->buildResponse();
368 cimResponse->cimException = PEGASUS_CIM_EXCEPTION(
369 CIM_ERR_NOT_SUPPORTED, String::EMPTY);
370 response = cimResponse;
371 }
372 else if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
|
373 kumpf 1.46 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
|
374 kumpf 1.40 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE) ||
|
375 kumpf 1.45 (request->getType() == CIM_INITIALIZE_PROVIDER_REQUEST_MESSAGE))
|
376 kumpf 1.38 {
|
377 kumpf 1.45 // Handle CIMOperationRequestMessage, CIMExportIndicationRequestMessage,
|
378 kumpf 1.46 // CIMIndicationRequestMessage, and CIMInitializeProviderRequestMessage.
379 // (These should be blocked when the provider module is disabled.)
|
380 kumpf 1.45
|
381 kumpf 1.46 //
382 // Get the provider module instance to check for a disabled module
383 //
384 CIMInstance providerModule;
|
385 kumpf 1.45
|
386 kumpf 1.58 // The provider ID container is added to the OperationContext
387 // by the CIMOperationRequestDispatcher for all CIM operation
388 // requests to providers, so it does not need to be added again.
389 // CIMInitializeProviderRequestMessage also has a provider ID
390 // container.
391 ProviderIdContainer pidc =
392 request->operationContext.get(ProviderIdContainer::NAME);
393 providerModule = pidc.getModule();
|
394 kumpf 1.38
|
395 kumpf 1.45 //
396 // Check if the target provider is disabled
397 //
398 Boolean moduleDisabled = false;
399 Uint32 pos = providerModule.findProperty(CIMName("OperationalStatus"));
400 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
401 Array<Uint16> operationalStatus;
402 providerModule.getProperty(pos).getValue().get(operationalStatus);
403
404 for(Uint32 i = 0; i < operationalStatus.size(); i++)
405 {
|
406 kumpf 1.50 if ((operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPED) ||
407 (operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPING))
|
408 kumpf 1.45 {
409 moduleDisabled = true;
410 break;
411 }
412 }
413
414 if (moduleDisabled)
415 {
416 //
417 // Send a "provider blocked" response
418 //
419 CIMResponseMessage* cimResponse = request->buildResponse();
420 cimResponse->cimException = PEGASUS_CIM_EXCEPTION_L(
421 CIM_ERR_ACCESS_DENIED,
422 MessageLoaderParms(
423 "ProviderManager.ProviderManagerService.PROVIDER_BLOCKED",
424 "provider blocked."));
425 response = cimResponse;
|
426 w.white 1.70
427 STAT_COPYDISPATCHER
|
428 kumpf 1.45 }
429 else
430 {
431 //
432 // Forward the request to the appropriate ProviderManagerRouter
433 //
|
434 kumpf 1.62 response = _processMessage(request);
|
435 kumpf 1.45 }
|
436 schuur 1.19 }
|
437 kumpf 1.38 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
438 {
439 // Handle CIMEnableModuleRequestMessage
440 CIMEnableModuleRequestMessage * emReq =
441 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
442
443 CIMInstance providerModule = emReq->providerModule;
|
444 dj.gorey 1.31
|
445 kumpf 1.38 try
446 {
|
447 kumpf 1.39 // Forward the request to the ProviderManager
|
448 kumpf 1.62 response = _processMessage(request);
|
449 kumpf 1.38
450 // If successful, update provider module status to OK
451 // ATTN: Use CIMEnableModuleResponseMessage operationalStatus?
452 CIMEnableModuleResponseMessage * emResp =
453 dynamic_cast<CIMEnableModuleResponseMessage*>(response);
454 if (emResp->cimException.getCode() == CIM_ERR_SUCCESS)
455 {
456 _updateProviderModuleStatus(
|
457 kumpf 1.50 providerModule, CIM_MSE_OPSTATUS_VALUE_STOPPED,
458 CIM_MSE_OPSTATUS_VALUE_OK);
|
459 kumpf 1.38 }
460 }
461 catch (Exception& e)
462 {
463 // Get the OperationalStatus property from the provider module
464 Array<Uint16> operationalStatus;
465 CIMValue itValue = emReq->providerModule.getProperty(
466 emReq->providerModule.findProperty("OperationalStatus"))
467 .getValue();
468 itValue.get(operationalStatus);
469
470 if (response != 0)
471 {
472 delete response;
473 }
474
475 response = new CIMEnableModuleResponseMessage(
476 request->messageId,
477 CIMException(CIM_ERR_FAILED, e.getMessage()),
478 request->queueIds.copyAndPop(),
479 operationalStatus);
480 kumpf 1.38 }
481 }
482 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
483 {
484 // Handle CIMDisableModuleRequestMessage
485 CIMDisableModuleRequestMessage * dmReq =
486 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
487
488 CIMInstance providerModule = dmReq->providerModule;
489 Boolean updateModuleStatus = !dmReq->disableProviderOnly;
490
491 try
492 {
493 // Change module status from OK to STOPPING
494 if (updateModuleStatus)
495 {
496 _updateProviderModuleStatus(
|
497 kumpf 1.50 providerModule, CIM_MSE_OPSTATUS_VALUE_OK,
498 CIM_MSE_OPSTATUS_VALUE_STOPPING);
|
499 kumpf 1.38 }
500
|
501 kumpf 1.39 // Forward the request to the ProviderManager
|
502 kumpf 1.62 response = _processMessage(request);
|
503 kumpf 1.38
504 // Update provider module status based on success or failure
505 if (updateModuleStatus)
506 {
507 CIMDisableModuleResponseMessage * dmResp =
508 dynamic_cast<CIMDisableModuleResponseMessage*>(response);
509 if (dmResp->cimException.getCode() != CIM_ERR_SUCCESS)
510 {
511 // Disable operation failed. Module not stopped.
512 _updateProviderModuleStatus(
|
513 kumpf 1.50 providerModule, CIM_MSE_OPSTATUS_VALUE_STOPPING,
514 CIM_MSE_OPSTATUS_VALUE_OK);
|
515 kumpf 1.38 }
516 else
517 {
518 // Disable may or may not have been successful,
519 // depending on whether there are outstanding requests.
520 // Use last operationalStatus entry.
521 _updateProviderModuleStatus(
|
522 kumpf 1.50 providerModule, CIM_MSE_OPSTATUS_VALUE_STOPPING,
|
523 kumpf 1.38 dmResp->operationalStatus[
524 dmResp->operationalStatus.size()-1]);
525 }
526 }
527 }
528 catch (Exception& e)
529 {
530 // Get the OperationalStatus property from the provider module
531 Array<Uint16> operationalStatus;
532 CIMValue itValue = dmReq->providerModule.getProperty(
533 dmReq->providerModule.findProperty("OperationalStatus"))
534 .getValue();
535 itValue.get(operationalStatus);
536
537 if (response != 0)
538 {
539 delete response;
540 }
541
542 response = new CIMDisableModuleResponseMessage(
543 request->messageId,
544 kumpf 1.38 CIMException(CIM_ERR_FAILED, e.getMessage()),
545 request->queueIds.copyAndPop(),
546 operationalStatus);
547 }
548 }
549 else
550 {
|
551 kumpf 1.62 response = _processMessage(request);
|
552 schuur 1.23 }
|
553 chip 1.13
|
554 schuur 1.19 AsyncLegacyOperationResult * async_result =
555 new AsyncLegacyOperationResult(
556 async->getKey(),
557 async->getRouting(),
558 op,
559 response);
|
560 chip 1.13
|
561 schuur 1.19 _complete_op_node(op, ASYNC_OPSTATE_COMPLETE, 0, 0);
|
562 chip 1.13
|
563 schuur 1.19 PEG_METHOD_EXIT();
564 }
|
565 chip 1.13
|
566 kumpf 1.76 void ProviderManagerService::responseChunkCallback(
567 CIMRequestMessage* request,
568 CIMResponseMessage* response)
|
569 brian.campbell 1.60 {
570 CIMStatusCode code = CIM_ERR_SUCCESS;
571 String message;
572
573 try
574 {
575 // only incomplete messages are processed because the caller ends up
576 // sending the complete() stage
|
577 kumpf 1.76 PEGASUS_ASSERT(response->isComplete() == false);
|
578 brian.campbell 1.60
579 AsyncLegacyOperationStart *requestAsync =
|
580 kumpf 1.76 dynamic_cast<AsyncLegacyOperationStart *>(request->_async);
|
581 brian.campbell 1.60 PEGASUS_ASSERT(requestAsync);
582 AsyncOpNode *op = requestAsync->op;
583 PEGASUS_ASSERT(op);
|
584 kumpf 1.76 PEGASUS_ASSERT(!response->_async);
585 response->_async = new AsyncLegacyOperationResult(
586 requestAsync->getKey(), requestAsync->getRouting(), op, response);
|
587 brian.campbell 1.60
588 // set the destination
589 op->_op_dest = op->_callback_response_q;
590
591 MessageQueueService *service =
592 dynamic_cast<MessageQueueService *>(op->_callback_response_q);
593
594 PEGASUS_ASSERT(service);
595
596 // the last chunk MUST be sent last, so use execute the callback
597 // not all chunks are going through the dispatcher's chunk
598 // resequencer, so this must be a synchronous call here
599 // After the call is done, response and asyncResponse are now invalid
600 // as they have been sent and deleted externally
601
602 op->_async_callback(op, service, op->_callback_ptr);
603 }
604
605 catch(CIMException &e)
606 {
607 code = e.getCode();
608 brian.campbell 1.60 message = e.getMessage();
609 }
610 catch(Exception &e)
611 {
612 code = CIM_ERR_FAILED;
613 message = e.getMessage();
614 }
615 catch(...)
616 {
617 code = CIM_ERR_FAILED;
618 message = cimStatusCodeToString(code);
619 }
620
621 if (code != CIM_ERR_SUCCESS)
|
622 kumpf 1.76 response->cimException = PEGASUS_CIM_EXCEPTION(code, message);
|
623 brian.campbell 1.60 }
624
|
625 kumpf 1.62 Message* ProviderManagerService::_processMessage(CIMRequestMessage* request)
626 {
627 Message* response = 0;
628
629 if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
|
630 carolann.graves 1.64 (request->getType() ==
631 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
|
632 kumpf 1.62 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
633 {
634 if (_basicProviderManagerRouter)
635 {
636 response = _basicProviderManagerRouter->processMessage(request);
637 }
638
639 if (_oopProviderManagerRouter)
640 {
641 // Note: These responses do not contain interesting data, so just
642 // use the last one.
643 if (response)
644 {
645 delete response;
646 }
647
648 response = _oopProviderManagerRouter->processMessage(request);
649 }
650 }
651 else
652 {
653 kumpf 1.62 CIMInstance providerModule;
654
655 if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
656 {
657 CIMEnableModuleRequestMessage* emReq =
658 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
659 providerModule = emReq->providerModule;
660 }
661 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
662 {
663 CIMDisableModuleRequestMessage* dmReq =
664 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
665 providerModule = dmReq->providerModule;
666 }
667 else
668 {
669 ProviderIdContainer pidc =
670 request->operationContext.get(ProviderIdContainer::NAME);
671 providerModule = pidc.getModule();
672 }
673
674 kumpf 1.62 Uint16 userContext = 0;
675 Uint32 pos = providerModule.findProperty(
676 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
677 if (pos != PEG_NOT_FOUND)
678 {
679 providerModule.getProperty(pos).getValue().get(userContext);
680 }
681
682 // Forward the request to the appropriate ProviderManagerRouter, based
683 // on the CIM Server configuration and the UserContext setting.
684
685 ConfigManager* configManager = ConfigManager::getInstance();
686 Boolean forceProviderProcesses = String::equal(
687 configManager->getCurrentValue("forceProviderProcesses"), "true");
688
689 if (forceProviderProcesses
690 #ifndef PEGASUS_DISABLE_PROV_USERCTXT
691 || (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
692 || (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
693 || ((userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED) &&
694 !System::isPrivilegedUser(System::getEffectiveUserName()))
695 kumpf 1.62 #endif
696 )
697 {
698 response = _oopProviderManagerRouter->processMessage(request);
699 }
700 else
701 {
702 response = _basicProviderManagerRouter->processMessage(request);
703 }
704 }
705
706 return response;
707 }
708
|
709 kumpf 1.44 void ProviderManagerService::unloadIdleProviders()
710 {
711 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
712 "ProviderManagerService::unloadIdleProviders");
|
713 konrad.r 1.68 ThreadStatus rtn = PEGASUS_THREAD_OK;
|
714 kumpf 1.44 // Ensure that only one _unloadIdleProvidersHandler thread runs at a time
715 _unloadIdleProvidersBusy++;
|
716 mike 1.72 if ((_unloadIdleProvidersBusy.get() == 1) &&
|
717 konrad.r 1.68 ((rtn = _thread_pool->allocate_and_awaken(
718 (void*)this, ProviderManagerService::_unloadIdleProvidersHandler))==PEGASUS_THREAD_OK))
|
719 kumpf 1.44 {
720 // _unloadIdleProvidersBusy is decremented in
721 // _unloadIdleProvidersHandler
722 }
723 else
724 {
725 // If we fail to allocate a thread, don't retry now.
726 _unloadIdleProvidersBusy--;
727 }
|
728 konrad.r 1.68 if (rtn != PEGASUS_THREAD_OK)
729 {
730 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
731 "Not enough threads to unload idle providers.");
732
733 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
734 "Could not allocate thread for %s to unload idle providers.",
735 getQueueName());
736 }
|
737 kumpf 1.44 PEG_METHOD_EXIT();
738 }
739
740 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
741 ProviderManagerService::_unloadIdleProvidersHandler(void* arg) throw()
|
742 chip 1.1 {
|
743 kumpf 1.44 try
744 {
745 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
746 "ProviderManagerService::unloadIdleProvidersHandler");
747
748 ProviderManagerService* myself =
749 reinterpret_cast<ProviderManagerService*>(arg);
750
|
751 kumpf 1.62 if (myself->_basicProviderManagerRouter)
|
752 kumpf 1.44 {
|
753 kumpf 1.62 try
754 {
755 myself->_basicProviderManagerRouter->unloadIdleProviders();
756 }
757 catch (...)
758 {
759 // Ignore errors
760 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
761 "Unexpected exception from "
762 "BasicProviderManagerRouter::_unloadIdleProviders");
763 }
|
764 kumpf 1.44 }
|
765 kumpf 1.62
766 if (myself->_oopProviderManagerRouter)
|
767 kumpf 1.44 {
|
768 kumpf 1.62 try
769 {
770 myself->_oopProviderManagerRouter->unloadIdleProviders();
771 }
772 catch (...)
773 {
774 // Ignore errors
775 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
776 "Unexpected exception from "
777 "OOPProviderManagerRouter::_unloadIdleProviders");
778 }
|
779 kumpf 1.44 }
780
781 myself->_unloadIdleProvidersBusy--;
782 PEG_METHOD_EXIT();
783 }
784 catch (...)
785 {
786 // Ignore errors
787 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
788 "Unexpected exception in _unloadIdleProvidersHandler");
789 }
790
791 return(PEGASUS_THREAD_RETURN(0));
|
792 kumpf 1.38 }
793
794 // Updates the providerModule instance and the ProviderRegistrationManager
795 void ProviderManagerService::_updateProviderModuleStatus(
796 CIMInstance& providerModule,
797 Uint16 fromStatus,
798 Uint16 toStatus)
799 {
800 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
801 "ProviderManagerService::_updateProviderModuleStatus");
802
803 Array<Uint16> operationalStatus;
804 String providerModuleName;
805
806 Uint32 pos = providerModule.findProperty(CIMName("Name"));
807 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
808 providerModule.getProperty(pos).getValue().get(providerModuleName);
809
810 //
811 // get operational status
812 //
813 kumpf 1.38 pos = providerModule.findProperty(CIMName("OperationalStatus"));
814 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
815 CIMProperty operationalStatusProperty = providerModule.getProperty(pos);
816 CIMValue operationalStatusValue = operationalStatusProperty.getValue();
817
818 if (!operationalStatusValue.isNull())
819 {
820 operationalStatusValue.get(operationalStatus);
821 }
822
823 //
824 // update module status
825 //
826 for (Uint32 i = operationalStatus.size(); i > 0; i--)
827 {
828 if (operationalStatus[i-1] == fromStatus)
829 {
830 operationalStatus.remove(i-1);
831 }
832 }
833
834 kumpf 1.38 operationalStatus.append(toStatus);
835
836 if (_providerRegistrationManager->setProviderModuleStatus(
837 providerModuleName, operationalStatus) == false)
838 {
839 throw PEGASUS_CIM_EXCEPTION_L(
840 CIM_ERR_FAILED,
841 MessageLoaderParms(
842 "ProviderManager.ProviderManagerService."
843 "SET_MODULE_STATUS_FAILED",
844 "set module status failed."));
845 }
846
847 operationalStatusProperty.setValue(CIMValue(operationalStatus));
848
849 PEG_METHOD_EXIT();
|
850 kumpf 1.39 }
851
852 void ProviderManagerService::indicationCallback(
853 CIMProcessIndicationRequestMessage* request)
854 {
|
855 se.gupta 1.52 try
856 {
857 AcceptLanguageListContainer cntr = request->operationContext.get(AcceptLanguageListContainer::NAME);
|
858 david.dillard 1.55 }catch(const Exception &)
|
859 se.gupta 1.52 {
|
860 kumpf 1.74 request->operationContext.insert(AcceptLanguageListContainer(AcceptLanguageList()));
|
861 se.gupta 1.52 }
862
863 if (_indicationServiceQueueId == PEG_NOT_FOUND)
|
864 kumpf 1.39 {
865 Array<Uint32> serviceIds;
866
867 providerManagerService->find_services(
868 PEGASUS_QUEUENAME_INDICATIONSERVICE, 0, 0, &serviceIds);
869 PEGASUS_ASSERT(serviceIds.size() != 0);
870
871 _indicationServiceQueueId = serviceIds[0];
872 }
873
874 request->queueIds = QueueIdStack(
875 _indicationServiceQueueId, providerManagerService->getQueueId());
876
877 AsyncLegacyOperationStart * asyncRequest =
878 new AsyncLegacyOperationStart(
879 providerManagerService->get_next_xid(),
880 0,
881 _indicationServiceQueueId,
882 request,
883 _indicationServiceQueueId);
884
885 kumpf 1.39 providerManagerService->SendForget(asyncRequest);
|
886 jim.wunderlich 1.69
887
888
889
890 #ifdef PEGASUS_INDICATIONS_Q_THRESHOLD
891
892 // See Comments in config.mak asociated with
893 // PEGASUS_INDICATIONS_Q_THRESHOLD
894 //
895 // if INDICATIONS_Q_STALL THRESHOLD is gt 0
896 // then if there are over INDICATIONS_Q_STALL_THRESHOLD
897 // indications in the queue
898 // then force this provider to sleep until the queue count
899 // is lower than INDICATIONS_Q_RESUME_THRESHOLD
900
901 static Mutex indicationThresholdReportedLock;
902 static Boolean indicationThresholdReported = false;
903
904 #define INDICATIONS_Q_STALL_THRESHOLD PEGASUS_INDICATIONS_Q_THRESHOLD
905 #define INDICATIONS_Q_RESUME_THRESHOLD (int)(PEGASUS_INDICATIONS_Q_THRESHOLD*.90)
906 #define INDICATIONS_Q_STALL_DURATION 250 // milli-seconds
907 jim.wunderlich 1.69
908 MessageQueue * indicationsQueue = MessageQueue::lookup(_indicationServiceQueueId);
909
910 if (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_STALL_THRESHOLD)
911 {
912 AutoMutex indicationThresholdReportedAutoMutex(indicationThresholdReportedLock);
913 if (!indicationThresholdReported)
914 {
915 indicationThresholdReported = true;
916 indicationThresholdReportedAutoMutex.unlock();
917
918 // make log entry to record que max exceeded
919
920 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
921 "Indication generation stalled: maximum queue count ($0) exceeded.",
922 INDICATIONS_Q_STALL_THRESHOLD);
923 }
924 else
925 {
926 indicationThresholdReportedAutoMutex.unlock();
927 }
928 jim.wunderlich 1.69
929 while (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_RESUME_THRESHOLD)
930 {
931 pegasus_sleep(INDICATIONS_Q_STALL_DURATION);
932 }
933
934 AutoMutex indicationThresholdReportedAutoMutex1(indicationThresholdReportedLock);
935 // indicationThresholdReportedLock.lock(pegasus_thread_self());
936 if(indicationThresholdReported)
937 {
938 indicationThresholdReported = false;
939 indicationThresholdReportedAutoMutex1.unlock();
940
941 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
942 "Indication generation resumed: current queue count = $0",
943 ((MessageQueueService *)indicationsQueue)->getIncomingCount() );
944
945 }
946 else
947 {
948 indicationThresholdReportedAutoMutex1.unlock();
949 jim.wunderlich 1.69 }
950 }
951 #endif /* INDICATIONS_Q_STALL_THRESHOLD */
952
|
953 chip 1.1 }
954
|
955 a.arora 1.37 PEGASUS_NAMESPACE_END
|