1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // 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 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
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 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 kumpf 1.1 // 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 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "ProviderManagerService.h"
35
36 #include <Pegasus/Common/Config.h>
37 #include <Pegasus/Common/PegasusVersion.h>
38 #include <Pegasus/Common/Constants.h>
39 #include <Pegasus/Common/CIMMessage.h>
40 #include <Pegasus/Common/Thread.h>
41 #include <Pegasus/Common/Tracer.h>
42 #include <Pegasus/Common/Logger.h>
43 kumpf 1.1 #include <Pegasus/Common/AutoPtr.h>
44 #include <Pegasus/Common/Constants.h>
45 #include <Pegasus/Common/StatisticalData.h>
46
47 #include <Pegasus/Config/ConfigManager.h>
48
49 #include <Pegasus/ProviderManagerService/BasicProviderManagerRouter.h>
50 #include <Pegasus/ProviderManagerService/OOPProviderManagerRouter.h>
51
|
52 marek 1.2 #ifdef PEGASUS_ZOS_SECURITY
53 // This include file will not be provided in the OpenGroup CVS for now.
54 // Do NOT try to include it in your compile
55 #include <Pegasus/ProviderManager2/ProviderManagerzOS_inline.h>
56 #endif
57
|
58 kumpf 1.1 PEGASUS_NAMESPACE_BEGIN
59
60 inline Boolean _isSupportedRequestType(const Message * message)
61 {
62 // ATTN: needs implementation
63
64 // for now, assume all requests are valid
65
66 return(true);
67 }
68
69 inline Boolean _isSupportedResponseType(const Message * message)
70 {
71 // ATTN: needs implementation
72
73 // for now, assume all responses are invalid
74
75 return(false);
76 }
77
78 ProviderManagerService* ProviderManagerService::providerManagerService=NULL;
79 kumpf 1.1 Uint32 ProviderManagerService::_indicationServiceQueueId = PEG_NOT_FOUND;
80
81 ProviderManagerService::ProviderManagerService(
82 ProviderRegistrationManager * providerRegistrationManager,
83 CIMRepository * repository,
84 ProviderManager* (*createDefaultProviderManagerCallback)())
85 : MessageQueueService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP)
86 {
87 providerManagerService=this;
88 _repository=repository;
89
90 _providerRegistrationManager = providerRegistrationManager;
91
92 _unloadIdleProvidersBusy = 0;
93
94 _basicProviderManagerRouter = 0;
95 _oopProviderManagerRouter = 0;
96
97 // Determine which ProviderManagerRouter(s) to use
98
99 _forceProviderProcesses = ConfigManager::parseBooleanValue(
100 kumpf 1.1 ConfigManager::getInstance()->getCurrentValue(
101 "forceProviderProcesses"));
102
103 #ifdef PEGASUS_DISABLE_PROV_USERCTXT
104 if (_forceProviderProcesses)
105 {
106 _oopProviderManagerRouter = new OOPProviderManagerRouter(
107 indicationCallback, responseChunkCallback,
108 providerModuleFailureCallback);
109 }
110 else
111 {
112 _basicProviderManagerRouter = new BasicProviderManagerRouter(
113 indicationCallback, responseChunkCallback,
114 createDefaultProviderManagerCallback);
115 }
116 #else
117 _oopProviderManagerRouter = new OOPProviderManagerRouter(
118 indicationCallback, responseChunkCallback,
119 providerModuleFailureCallback);
120
121 kumpf 1.1 if (!_forceProviderProcesses)
122 {
123 _basicProviderManagerRouter = new BasicProviderManagerRouter(
124 indicationCallback, responseChunkCallback,
125 createDefaultProviderManagerCallback);
126 }
127 #endif
128 }
129
130 ProviderManagerService::~ProviderManagerService(void)
131 {
132 delete _basicProviderManagerRouter;
133 delete _oopProviderManagerRouter;
134 providerManagerService=NULL;
135 }
136
137 Boolean ProviderManagerService::messageOK(const Message * message)
138 {
139 PEGASUS_ASSERT(message != 0);
140
141 if(_isSupportedRequestType(message))
142 kumpf 1.1 {
143 return(MessageQueueService::messageOK(message));
144 }
145
146 return(false);
147 }
148
149 void ProviderManagerService::handleEnqueue(void)
150 {
151 Message * message = dequeue();
152
153 handleEnqueue(message);
154 }
155
156 void ProviderManagerService::handleEnqueue(Message * message)
157 {
158 PEGASUS_ASSERT(message != 0);
159
160 AsyncLegacyOperationStart * asyncRequest;
161
162 if(message->_async != NULL)
163 kumpf 1.1 {
164 asyncRequest = static_cast<AsyncLegacyOperationStart *>(message->_async);
165 }
166 else
167 {
168 asyncRequest = new AsyncLegacyOperationStart(
169 0,
170 this->getQueueId(),
171 message,
172 this->getQueueId());
173 }
174
175 _handle_async_request(asyncRequest);
176 }
177
178 void ProviderManagerService::_handle_async_request(AsyncRequest * request)
179 {
180 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
181 "ProviderManagerService::_handle_async_request");
182
183 PEGASUS_ASSERT((request != 0) && (request->op != 0));
184 kumpf 1.1
185 if(request->getType() == async_messages::ASYNC_LEGACY_OP_START)
186 {
187 request->op->processing();
188
189 _incomingQueue.insert_back(request->op);
190 ThreadStatus rtn = PEGASUS_THREAD_OK;
191 while (( rtn =_thread_pool->allocate_and_awaken(
192 (void *)this, ProviderManagerService::handleCimOperation)) != PEGASUS_THREAD_OK)
193 {
194 if (rtn==PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
195 Threads::yield();
196 else
197 {
198 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
199 "Not enough threads to service provider manager." );
200
201 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
202 "Could not allocate thread for %s.",
203 getQueueName());
204 break;
205 kumpf 1.1 }
206 }
207 }
208 else
209 {
210 // pass all other operations to the default handler
211 MessageQueueService::_handle_async_request(request);
212 }
213
214 PEG_METHOD_EXIT();
215
216 return;
217 }
218
219 // Note: This method should not throw an exception. It is used as a thread
220 // entry point, and any exceptions thrown are ignored.
221 ThreadReturnType PEGASUS_THREAD_CDECL
222 ProviderManagerService::handleCimOperation(void* arg)
223 {
224 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
225 "ProviderManagerService::handleCimOperation");
226 kumpf 1.1
227 PEGASUS_ASSERT(arg != 0);
228
229 // get the service from argument
230 ProviderManagerService* service =
231 reinterpret_cast<ProviderManagerService *>(arg);
232 PEGASUS_ASSERT(service != 0);
233
234 try
235 {
236 if (service->_incomingQueue.size() == 0)
237 {
238 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
239 "ProviderManagerService::handleCimOperation() called with no "
240 "op node in queue");
241
242 PEG_METHOD_EXIT();
243 return(ThreadReturnType(1));
244 }
245
246 AsyncOpNode* op = service->_incomingQueue.remove_front();
247 kumpf 1.1 PEGASUS_ASSERT(op != 0);
248 PEGASUS_ASSERT(op->_request.get() != 0);
249
250 AsyncRequest* request =
251 static_cast<AsyncRequest*>(op->_request.get());
252
253 if ((request == 0) ||
254 (request->getType() != async_messages::ASYNC_LEGACY_OP_START))
255 {
256 // reply with NAK
257 PEG_METHOD_EXIT();
258 return(ThreadReturnType(0));
259 }
260
261 Message* legacy =
262 static_cast<AsyncLegacyOperationStart *>(request)->get_action();
263
264 if(_isSupportedRequestType(legacy))
265 {
266 AutoPtr<Message> xmessage(legacy);
267
268 kumpf 1.1 // Set the client's requested language into this service thread.
269 // This will allow functions in this service to return messages
270 // in the correct language.
271 CIMMessage* msg = dynamic_cast<CIMMessage *>(legacy);
272
273 if (msg != 0)
274 {
275 AcceptLanguageList* langs = new AcceptLanguageList(
276 ((AcceptLanguageListContainer)msg->operationContext.get(
277 AcceptLanguageListContainer::NAME)).getLanguages());
278 Thread::setLanguages(langs);
279 }
280 else
281 {
282 Thread::clearLanguages();
283 }
284
285 service->handleCimRequest(op, legacy);
286 }
287 }
288 catch (const Exception& e)
289 kumpf 1.1 {
290 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
291 "Unexpected exception in handleCimOperation: " + e.getMessage());
292 }
293 catch (...)
294 {
295 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
296 "Unexpected exception in handleCimOperation.");
297 }
298
299 PEG_METHOD_EXIT();
300
301 return(ThreadReturnType(0));
302 }
303
304 void ProviderManagerService::handleCimRequest(
305 AsyncOpNode * op,
306 Message * message)
307 {
308 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
309 "ProviderManagerService::handleCimRequest");
310 kumpf 1.1
311 CIMRequestMessage * request = dynamic_cast<CIMRequestMessage *>(message);
312 PEGASUS_ASSERT(request != 0);
313
314 // get request from op node
315 AsyncRequest * async = static_cast<AsyncRequest *>(op->_request.get());
316 PEGASUS_ASSERT(async != 0);
317
318 Message * response = 0;
319 Boolean consumerLookupFailed = false;
320
321 if (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
322 {
323 //
324 // Get a ProviderIdContainer for ExportIndicationRequestMessage.
325 // Note: This can be removed when the CIMExportRequestDispatcher
326 // is updated to add the ProviderIdContainer to the message.
327 //
328 CIMInstance providerModule;
329 CIMInstance provider;
330 const CIMExportIndicationRequestMessage* expRequest =
331 kumpf 1.1 dynamic_cast<const CIMExportIndicationRequestMessage*>(request);
332 if (_providerRegistrationManager->lookupIndicationConsumer(
333 expRequest->destinationPath, provider, providerModule))
334 {
335 request->operationContext.insert(
336 ProviderIdContainer(providerModule, provider));
337 }
338 else
339 {
340 consumerLookupFailed = true;
341 }
342 }
343
344 if (consumerLookupFailed)
345 {
346 CIMResponseMessage* cimResponse = request->buildResponse();
347 cimResponse->cimException = PEGASUS_CIM_EXCEPTION(
348 CIM_ERR_NOT_SUPPORTED, String::EMPTY);
349 response = cimResponse;
350 }
351 else if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
352 kumpf 1.1 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
353 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE) ||
354 (request->getType() == CIM_INITIALIZE_PROVIDER_REQUEST_MESSAGE))
355 {
356 // Handle CIMOperationRequestMessage, CIMExportIndicationRequestMessage,
357 // CIMIndicationRequestMessage, and CIMInitializeProviderRequestMessage.
358 // (These should be blocked when the provider module is disabled.)
359
360 //
361 // Get the provider module instance to check for a disabled module
362 //
363 CIMInstance providerModule;
364
365 // The provider ID container is added to the OperationContext
366 // by the CIMOperationRequestDispatcher for all CIM operation
367 // requests to providers, so it does not need to be added again.
368 // CIMInitializeProviderRequestMessage also has a provider ID
369 // container.
370 ProviderIdContainer pidc =
371 request->operationContext.get(ProviderIdContainer::NAME);
372 providerModule = pidc.getModule();
373 kumpf 1.1
374 //
375 // Check if the target provider is disabled
376 //
377 Boolean moduleDisabled = false;
378 Uint32 pos = providerModule.findProperty(CIMName("OperationalStatus"));
379 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
380 Array<Uint16> operationalStatus;
381 providerModule.getProperty(pos).getValue().get(operationalStatus);
382
383 for(Uint32 i = 0; i < operationalStatus.size(); i++)
384 {
385 if ((operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPED) ||
386 (operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPING))
387 {
388 moduleDisabled = true;
389 break;
390 }
391 }
392
393 if (moduleDisabled)
394 kumpf 1.1 {
395 //
396 // Send a "provider blocked" response
397 //
398 CIMResponseMessage* cimResponse = request->buildResponse();
399 cimResponse->cimException = PEGASUS_CIM_EXCEPTION_L(
|
400 kumpf 1.5 CIM_ERR_NOT_SUPPORTED,
|
401 kumpf 1.1 MessageLoaderParms(
402 "ProviderManager.ProviderManagerService.PROVIDER_BLOCKED",
403 "provider blocked."));
404 response = cimResponse;
405 }
406 else
407 {
408 //
409 // Forward the request to the appropriate ProviderManagerRouter
410 //
411 response = _processMessage(request);
412 }
413 }
414 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
415 {
416 // Handle CIMEnableModuleRequestMessage
417 CIMEnableModuleRequestMessage * emReq =
418 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
419
420 CIMInstance providerModule = emReq->providerModule;
421
422 kumpf 1.1 try
423 {
424 // Forward the request to the ProviderManager
425 response = _processMessage(request);
426
427 // If successful, update provider module status to OK
428 // ATTN: Use CIMEnableModuleResponseMessage operationalStatus?
429 CIMEnableModuleResponseMessage * emResp =
430 dynamic_cast<CIMEnableModuleResponseMessage*>(response);
431 if (emResp->cimException.getCode() == CIM_ERR_SUCCESS)
432 {
433 //
434 // On a successful enable, remove Stopped status and
435 // append OK status
436 //
437 Array<Uint16> removeStatus;
438 Array<Uint16> appendStatus;
439 removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPED);
440 appendStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
441 _updateProviderModuleStatus(
442 providerModule, removeStatus, appendStatus);
443 kumpf 1.1 }
444 }
445 catch (Exception& e)
446 {
447 // Get the OperationalStatus property from the provider module
448 Array<Uint16> operationalStatus;
449 CIMValue itValue = emReq->providerModule.getProperty(
450 emReq->providerModule.findProperty("OperationalStatus"))
451 .getValue();
452 itValue.get(operationalStatus);
453
454 delete response;
455
456 CIMEnableModuleResponseMessage* emResp =
457 dynamic_cast<CIMEnableModuleResponseMessage*>(
458 request->buildResponse());
459 emResp->operationalStatus = operationalStatus;
460 emResp->cimException =
461 CIMException(CIM_ERR_FAILED, e.getMessage());
462 response = emResp;
463 }
464 kumpf 1.1 }
465 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
466 {
467 // Handle CIMDisableModuleRequestMessage
468 CIMDisableModuleRequestMessage * dmReq =
469 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
470
471 CIMInstance providerModule = dmReq->providerModule;
472 Boolean updateModuleStatus = !dmReq->disableProviderOnly;
473
474 try
475 {
476 //
477 // On issuing a disable request, append Stopping status
478 // Do not remove existing status
479 //
480 if (updateModuleStatus)
481 {
482 Array<Uint16> removeStatus;
483 Array<Uint16> appendStatus;
484 appendStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
485 kumpf 1.1 _updateProviderModuleStatus(
486 providerModule, removeStatus, appendStatus);
487 }
488
489 // Forward the request to the ProviderManager
490 response = _processMessage(request);
491
492 // Update provider module status based on success or failure
493 if (updateModuleStatus)
494 {
495 CIMDisableModuleResponseMessage * dmResp =
496 dynamic_cast<CIMDisableModuleResponseMessage*>(response);
497 if (dmResp->cimException.getCode() != CIM_ERR_SUCCESS)
498 {
499 //
500 // On an unsuccessful disable, remove Stopping status
501 //
502 Array<Uint16> removeStatus;
503 Array<Uint16> appendStatus;
504 removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
505 _updateProviderModuleStatus(
506 kumpf 1.1 providerModule, removeStatus, appendStatus);
507 }
508 else
509 {
510 // Disable may or may not have been successful,
511 // depending on whether there are outstanding requests.
512 // Remove Stopping status
513 // Append status, if any, from disable module response
514 Array<Uint16> removeStatus;
515 Array<Uint16> appendStatus;
516 removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
517 if (dmResp->operationalStatus.size() > 0)
518 {
519 //
520 // On a successful disable, remove an OK or a Degraded
521 // status, if present
522 //
523 if (dmResp->operationalStatus[
524 dmResp->operationalStatus.size()-1] ==
525 CIM_MSE_OPSTATUS_VALUE_STOPPED)
526 {
527 kumpf 1.1 removeStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
528 removeStatus.append
529 (CIM_MSE_OPSTATUS_VALUE_DEGRADED);
530 }
531 appendStatus.append (dmResp->operationalStatus[
532 dmResp->operationalStatus.size()-1]);
533 }
534 _updateProviderModuleStatus(
535 providerModule, removeStatus, appendStatus);
536 }
537 }
538 }
539 catch (Exception& e)
540 {
541 // Get the OperationalStatus property from the provider module
542 Array<Uint16> operationalStatus;
543 CIMValue itValue = dmReq->providerModule.getProperty(
544 dmReq->providerModule.findProperty("OperationalStatus"))
545 .getValue();
546 itValue.get(operationalStatus);
547
548 kumpf 1.1 delete response;
549
550 CIMDisableModuleResponseMessage* dmResp =
551 dynamic_cast<CIMDisableModuleResponseMessage*>(
552 request->buildResponse());
553 dmResp->operationalStatus = operationalStatus;
554 dmResp->cimException =
555 CIMException(CIM_ERR_FAILED, e.getMessage());
556 response = dmResp;
557 }
558 }
559 else
560 {
561 response = _processMessage(request);
562 }
563
564 AsyncLegacyOperationResult * async_result =
565 new AsyncLegacyOperationResult(
566 op,
567 response);
568
569 kumpf 1.1 _complete_op_node(op, ASYNC_OPSTATE_COMPLETE, 0, 0);
570
571 PEG_METHOD_EXIT();
572 }
573
574 void ProviderManagerService::responseChunkCallback(
575 CIMRequestMessage* request,
576 CIMResponseMessage* response)
577 {
578 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
579 "ProviderManagerService::responseChunkCallback");
580
581 try
582 {
583 // only incomplete messages are processed because the caller ends up
584 // sending the complete() stage
585 PEGASUS_ASSERT(response->isComplete() == false);
586
587 AsyncLegacyOperationStart *requestAsync =
588 dynamic_cast<AsyncLegacyOperationStart *>(request->_async);
589 PEGASUS_ASSERT(requestAsync);
590 kumpf 1.1 AsyncOpNode *op = requestAsync->op;
591 PEGASUS_ASSERT(op);
592 PEGASUS_ASSERT(!response->_async);
593 response->_async = new AsyncLegacyOperationResult(
594 op, response);
595
596 // set the destination
597 op->_op_dest = op->_callback_response_q;
598
599 MessageQueueService *service =
600 dynamic_cast<MessageQueueService *>(op->_callback_response_q);
601
602 PEGASUS_ASSERT(service);
603
604 // the last chunk MUST be sent last, so use execute the callback
605 // not all chunks are going through the dispatcher's chunk
606 // resequencer, so this must be a synchronous call here
607 // After the call is done, response and asyncResponse are now invalid
608 // as they have been sent and deleted externally
609
610 op->_async_callback(op, service, op->_callback_ptr);
611 kumpf 1.1 }
612 catch(Exception &e)
613 {
614 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
615 "Exception in ProviderManagerService::responseChunkCallback: " +
616 e.getMessage() + ". Chunk not delivered.");
617 }
618 catch(...)
619 {
620 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
621 "Exception in ProviderManagerService::responseChunkCallback. "
622 "Chunk not delivered.");
623 }
624
625 PEG_METHOD_EXIT();
626 }
627
628 Message* ProviderManagerService::_processMessage(CIMRequestMessage* request)
629 {
630 Message* response = 0;
631
632 kumpf 1.1 if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
633 (request->getType() ==
634 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
635 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
636 {
637 if (_basicProviderManagerRouter)
638 {
639 response = _basicProviderManagerRouter->processMessage(request);
640 }
641
642 if (_oopProviderManagerRouter)
643 {
644 // Note: These responses do not contain interesting data, so just
645 // use the last one.
646 delete response;
647
648 response = _oopProviderManagerRouter->processMessage(request);
649 }
650 }
651 else
652 {
653 kumpf 1.1 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 #ifdef PEGASUS_ZOS_SECURITY
673 if (request->getType() != CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
674 kumpf 1.1 {
675 // this is a z/OS only function
676 // the function checks user authorization
677 // based on CIM operation versus provider profile
678 // Input: request and Provider ID Container
679 //Return: failure: a response message for the client
680 // success: NULL
681 response = checkSAFProviderProfile(request, pidc);
682 if (response != NULL)
683 {
684 return response;
685 }
686 }
687 #endif
688 }
689
690 Uint16 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
691 Uint32 pos = providerModule.findProperty(
692 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
693 if (pos != PEG_NOT_FOUND)
694 {
695 kumpf 1.1 providerModule.getProperty(pos).getValue().get(userContext);
696 }
697
698 // Forward the request to the appropriate ProviderManagerRouter, based
699 // on the CIM Server configuration and the UserContext setting.
700
701 if (_forceProviderProcesses
702 #ifndef PEGASUS_DISABLE_PROV_USERCTXT
703 || (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
704 || (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
705 || ((userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED) &&
706 !System::isPrivilegedUser(System::getEffectiveUserName()))
707 #endif
708 )
709 {
710 response = _oopProviderManagerRouter->processMessage(request);
711 }
712 else
713 {
714 response = _basicProviderManagerRouter->processMessage(request);
715 }
716 kumpf 1.1 }
717
718 return response;
719 }
720
721 void ProviderManagerService::unloadIdleProviders()
722 {
723 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
724 "ProviderManagerService::unloadIdleProviders");
|
725 kumpf 1.3
|
726 kumpf 1.1 // Ensure that only one _unloadIdleProvidersHandler thread runs at a time
727 _unloadIdleProvidersBusy++;
|
728 kumpf 1.3 if (_unloadIdleProvidersBusy.get() != 1)
|
729 kumpf 1.1 {
|
730 kumpf 1.3 _unloadIdleProvidersBusy--;
731 PEG_METHOD_EXIT();
732 return;
|
733 kumpf 1.1 }
|
734 kumpf 1.3
735 //
736 // Start an idle provider unload thread
737 //
738
739 if (_thread_pool->allocate_and_awaken((void*)this,
740 ProviderManagerService::_unloadIdleProvidersHandler) !=
741 PEGASUS_THREAD_OK)
|
742 kumpf 1.1 {
743 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
744 "Not enough threads to unload idle providers.");
745
746 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
747 "Could not allocate thread for %s to unload idle providers.",
748 getQueueName());
|
749 kumpf 1.3
750 // If we fail to allocate a thread, don't retry now.
751 _unloadIdleProvidersBusy--;
752 PEG_METHOD_EXIT();
753 return;
|
754 kumpf 1.1 }
|
755 kumpf 1.3
756 // Note: _unloadIdleProvidersBusy is decremented in
757 // _unloadIdleProvidersHandler
758
|
759 kumpf 1.1 PEG_METHOD_EXIT();
760 }
761
762 ThreadReturnType PEGASUS_THREAD_CDECL
763 ProviderManagerService::_unloadIdleProvidersHandler(void* arg) throw()
764 {
|
765 kumpf 1.3 ProviderManagerService* myself =
766 reinterpret_cast<ProviderManagerService*>(arg);
767
|
768 kumpf 1.1 try
769 {
770 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
|
771 kumpf 1.3 "ProviderManagerService::_unloadIdleProvidersHandler");
|
772 kumpf 1.1
773 if (myself->_basicProviderManagerRouter)
774 {
775 try
776 {
777 myself->_basicProviderManagerRouter->unloadIdleProviders();
778 }
779 catch (...)
780 {
781 // Ignore errors
782 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
783 "Unexpected exception from "
784 "BasicProviderManagerRouter::_unloadIdleProviders");
785 }
786 }
787
788 if (myself->_oopProviderManagerRouter)
789 {
790 try
791 {
792 myself->_oopProviderManagerRouter->unloadIdleProviders();
793 kumpf 1.1 }
794 catch (...)
795 {
796 // Ignore errors
797 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
798 "Unexpected exception from "
799 "OOPProviderManagerRouter::_unloadIdleProviders");
800 }
801 }
802
803 myself->_unloadIdleProvidersBusy--;
804 PEG_METHOD_EXIT();
805 }
806 catch (...)
807 {
808 // Ignore errors
809 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
810 "Unexpected exception in _unloadIdleProvidersHandler");
|
811 kumpf 1.3
812 myself->_unloadIdleProvidersBusy--;
|
813 kumpf 1.1 }
814
815 return(ThreadReturnType(0));
816 }
817
818 // Updates the providerModule instance and the ProviderRegistrationManager
819 //
820 // This method is used to update the provider module status when the module is
821 // disabled or enabled. If a Degraded status has been set (appended) to the
822 // OperationalStatus, it is cleared (removed) when the module is disabled or
823 // enabled.
824 //
825 void ProviderManagerService::_updateProviderModuleStatus(
826 CIMInstance& providerModule,
827 const Array<Uint16>& removeStatus,
828 const Array<Uint16>& appendStatus)
829 {
830 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
831 "ProviderManagerService::_updateProviderModuleStatus");
832
833 Array<Uint16> operationalStatus;
834 kumpf 1.1 String providerModuleName;
835
836 Uint32 pos = providerModule.findProperty(CIMName("Name"));
837 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
838 providerModule.getProperty(pos).getValue().get(providerModuleName);
839
840 //
841 // get operational status
842 //
843 pos = providerModule.findProperty(CIMName("OperationalStatus"));
844 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
845 CIMProperty operationalStatusProperty = providerModule.getProperty(pos);
846
847 if (_providerRegistrationManager->updateProviderModuleStatus(
848 providerModuleName, removeStatus, appendStatus, operationalStatus) ==
849 false)
850 {
851 throw PEGASUS_CIM_EXCEPTION_L(
852 CIM_ERR_FAILED,
853 MessageLoaderParms(
854 "ProviderManager.ProviderManagerService."
855 kumpf 1.1 "SET_MODULE_STATUS_FAILED",
856 "set module status failed."));
857 }
858
859 operationalStatusProperty.setValue(CIMValue(operationalStatus));
860
861 PEG_METHOD_EXIT();
862 }
863
864 void ProviderManagerService::indicationCallback(
865 CIMProcessIndicationRequestMessage* request)
866 {
867 if(request->operationContext.contains(AcceptLanguageListContainer::NAME))
868 {
869 AcceptLanguageListContainer cntr = request->operationContext.get(AcceptLanguageListContainer::NAME);
870 }
871 else
872 {
873 request->operationContext.insert(AcceptLanguageListContainer(AcceptLanguageList()));
874 }
875
876 kumpf 1.1 if (_indicationServiceQueueId == PEG_NOT_FOUND)
877 {
878 Array<Uint32> serviceIds;
879
880 providerManagerService->find_services(
881 PEGASUS_QUEUENAME_INDICATIONSERVICE, 0, 0, &serviceIds);
882 PEGASUS_ASSERT(serviceIds.size() != 0);
883
884 _indicationServiceQueueId = serviceIds[0];
885 }
886
887 request->queueIds = QueueIdStack(
888 _indicationServiceQueueId, providerManagerService->getQueueId());
889
890 AsyncLegacyOperationStart * asyncRequest =
891 new AsyncLegacyOperationStart(
892 0,
893 _indicationServiceQueueId,
894 request,
895 _indicationServiceQueueId);
896
897 kumpf 1.1 providerManagerService->SendForget(asyncRequest);
898
899
900
901
902 #ifdef PEGASUS_INDICATIONS_Q_THRESHOLD
903
904 // See Comments in config.mak asociated with
905 // PEGASUS_INDICATIONS_Q_THRESHOLD
906 //
907 // if INDICATIONS_Q_STALL THRESHOLD is gt 0
908 // then if there are over INDICATIONS_Q_STALL_THRESHOLD
909 // indications in the queue
910 // then force this provider to sleep until the queue count
911 // is lower than INDICATIONS_Q_RESUME_THRESHOLD
912
913 static Mutex indicationThresholdReportedLock;
914 static Boolean indicationThresholdReported = false;
915
916 #define INDICATIONS_Q_STALL_THRESHOLD PEGASUS_INDICATIONS_Q_THRESHOLD
917 #define INDICATIONS_Q_RESUME_THRESHOLD (int)(PEGASUS_INDICATIONS_Q_THRESHOLD*.90)
918 kumpf 1.1 #define INDICATIONS_Q_STALL_DURATION 250 // milli-seconds
919
920 MessageQueue * indicationsQueue = MessageQueue::lookup(_indicationServiceQueueId);
921
922 if (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_STALL_THRESHOLD)
923 {
924 AutoMutex indicationThresholdReportedAutoMutex(indicationThresholdReportedLock);
925 if (!indicationThresholdReported)
926 {
927 indicationThresholdReported = true;
928 indicationThresholdReportedAutoMutex.unlock();
929
930 // make log entry to record que max exceeded
931
932 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
933 "Indication generation stalled: maximum queue count ($0) exceeded.",
934 INDICATIONS_Q_STALL_THRESHOLD);
935 }
936 else
937 {
938 indicationThresholdReportedAutoMutex.unlock();
939 kumpf 1.1 }
940
941 while (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_RESUME_THRESHOLD)
942 {
943 Threads::sleep(INDICATIONS_Q_STALL_DURATION);
944 }
945
946 AutoMutex indicationThresholdReportedAutoMutex1(indicationThresholdReportedLock);
947 // indicationThresholdReportedLock.lock();
948 if(indicationThresholdReported)
949 {
950 indicationThresholdReported = false;
951 indicationThresholdReportedAutoMutex1.unlock();
952
953 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
954 "Indication generation resumed: current queue count = $0",
955 ((MessageQueueService *)indicationsQueue)->getIncomingCount() );
956
957 }
958 else
959 {
960 kumpf 1.1 indicationThresholdReportedAutoMutex1.unlock();
961 }
962 }
963 #endif /* INDICATIONS_Q_STALL_THRESHOLD */
964
965 }
966
967 void ProviderManagerService::providerModuleFailureCallback
968 (const String & moduleName,
969 const String & userName,
970 Uint16 userContext)
971 {
972 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
973 "ProviderManagerService::providerModuleFailureCallback");
974
975 if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
976 {
977 Logger::put_l (
978 Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
979 "ProviderManager.OOPProviderManagerRouter."
980 "OOP_PROVIDER_MODULE_USER_CTXT_FAILURE_DETECTED",
981 kumpf 1.1 "A failure was detected in provider module $0 with"
982 " user context $1.",
983 moduleName, userName);
984 }
985 else // not requestor context
986 {
987 Logger::put_l (
988 Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
989 "ProviderManager.OOPProviderManagerRouter."
990 "OOP_PROVIDER_MODULE_FAILURE_DETECTED",
991 "A failure was detected in provider module $0.",
992 moduleName);
993 }
994
995 //
996 // Create Notify Provider Fail request message
997 //
998 CIMNotifyProviderFailRequestMessage * request =
999 new CIMNotifyProviderFailRequestMessage
1000 (XmlWriter::getNextMessageId (),
1001 moduleName,
1002 kumpf 1.1 userName,
1003 QueueIdStack ());
1004
1005 //
1006 // Send Notify Provider Fail request message to Indication Service
1007 //
1008 if (_indicationServiceQueueId == PEG_NOT_FOUND)
1009 {
1010 Array <Uint32> serviceIds;
1011
1012 providerManagerService->find_services
1013 (PEGASUS_QUEUENAME_INDICATIONSERVICE, 0, 0, &serviceIds);
1014 PEGASUS_ASSERT (serviceIds.size () != 0);
1015
1016 _indicationServiceQueueId = serviceIds [0];
1017 }
1018
1019 request->queueIds = QueueIdStack
1020 (_indicationServiceQueueId, providerManagerService->getQueueId ());
1021
1022 AsyncLegacyOperationStart * asyncRequest = new AsyncLegacyOperationStart(
1023 kumpf 1.1 0,
1024 _indicationServiceQueueId,
1025 request,
1026 _indicationServiceQueueId);
1027
1028 AutoPtr <AsyncReply> asyncReply
1029 (providerManagerService->SendWait (asyncRequest));
1030
1031 AutoPtr <CIMNotifyProviderFailResponseMessage> response
1032 (reinterpret_cast <CIMNotifyProviderFailResponseMessage *>
1033 ((dynamic_cast <AsyncLegacyOperationResult *>
1034 (asyncReply.get ()))->get_result ()));
1035
1036 if (response->cimException.getCode () != CIM_ERR_SUCCESS)
1037 {
1038 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
1039 "Unexpected exception in providerModuleFailureCallback: " +
1040 response->cimException.getMessage ());
1041 }
1042 else
1043 {
1044 kumpf 1.1 //
1045 // Successful response
1046 // Examine result to see if any subscriptions were affected
1047 //
1048 if (response->numSubscriptionsAffected > 0)
1049 {
1050 //
1051 // Subscriptions were affected
1052 // Update the provider module status to Degraded
1053 //
1054 try
1055 {
1056 CIMInstance providerModule;
1057 CIMKeyBinding keyBinding(
1058 _PROPERTY_PROVIDERMODULE_NAME,
1059 moduleName,
1060 CIMKeyBinding::STRING);
1061 Array<CIMKeyBinding> kbArray;
1062 kbArray.append(keyBinding);
1063 CIMObjectPath modulePath("", PEGASUS_NAMESPACENAME_INTEROP,
1064 PEGASUS_CLASSNAME_PROVIDERMODULE, kbArray);
1065 kumpf 1.1 providerModule =
1066 providerManagerService->_providerRegistrationManager->
1067 getInstance(
1068 modulePath, false, false, CIMPropertyList());
1069
1070 Array<Uint16> removeStatus;
1071 Array<Uint16> appendStatus;
1072 removeStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1073 appendStatus.append(CIM_MSE_OPSTATUS_VALUE_DEGRADED);
1074 providerManagerService->_updateProviderModuleStatus(
1075 providerModule, removeStatus, appendStatus);
1076 }
1077 catch (const Exception & e)
1078 {
1079 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1080 "Failed to update provider module status: " +
1081 e.getMessage());
1082 }
1083
1084 //
1085 // Log a warning message since subscriptions were affected
1086 kumpf 1.1 //
1087 Logger::put_l (
1088 Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
1089 "ProviderManager.OOPProviderManagerRouter."
1090 "OOP_PROVIDER_MODULE_SUBSCRIPTIONS_AFFECTED",
1091 "The generation of indications by providers in module $0 "
1092 "may be affected. To ensure these providers are serving "
1093 "active subscriptions, disable and then re-enable this "
1094 "module using the cimprovider command.",
1095 moduleName);
1096 }
1097 }
1098
1099 PEG_METHOD_EXIT();
1100 }
1101
1102 PEGASUS_NAMESPACE_END
|