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