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