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