1 martin 1.89 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.90 //
|
3 martin 1.89 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.90 //
|
10 martin 1.89 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.90 //
|
17 martin 1.89 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.90 //
|
20 martin 1.89 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.90 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.89 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.90 //
|
28 martin 1.89 //////////////////////////////////////////////////////////////////////////
|
29 chip 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "DefaultProviderManager.h"
33
34 #include <Pegasus/Common/CIMMessage.h>
35 #include <Pegasus/Common/OperationContext.h>
|
36 kumpf 1.71 #include <Pegasus/Common/Time.h>
|
37 chip 1.1 #include <Pegasus/Common/Tracer.h>
38 #include <Pegasus/Common/StatisticalData.h>
39 #include <Pegasus/Common/Logger.h>
|
40 kumpf 1.71 #include <Pegasus/Common/MessageLoader.h>
|
41 kumpf 1.77 #include <Pegasus/Common/FileSystem.h>
|
42 kumpf 1.71 #include <Pegasus/Common/PegasusVersion.h>
|
43 kumpf 1.38 #include <Pegasus/Common/Constants.h>
|
44 chip 1.1
|
45 chuck 1.44 #include <Pegasus/Query/QueryExpression/QueryExpression.h>
|
46 schuur 1.12 #include <Pegasus/ProviderManager2/QueryExpressionFactory.h>
47
|
48 schuur 1.21 #include <Pegasus/ProviderManager2/OperationResponseHandler.h>
|
49 chip 1.1
|
50 kumpf 1.71 PEGASUS_NAMESPACE_BEGIN
51
|
52 sahana.prabhakar 1.93
|
53 karl 1.96 // A request class to hold the provider info passed to the
|
54 sahana.prabhakar 1.93 // AsyncRequestExecutor for processing on different threads.
55 class UnloadProviderRequest : public AsyncRequestExecutor::AsyncRequestMsg
56 {
57 public:
58 UnloadProviderRequest(ProviderMessageHandler* provider)
59 :_provider(provider) {}
60
61 public:
62 ProviderMessageHandler* _provider;
63 };
64
|
65 kumpf 1.71 //
66 // Default Provider Manager
67 //
68 DefaultProviderManager::DefaultProviderManager()
69 {
70 _subscriptionInitComplete = false;
|
71 kumpf 1.66 }
|
72 a.dunfey 1.58
|
73 kumpf 1.71 DefaultProviderManager::~DefaultProviderManager()
74 {
75 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
76 "DefaultProviderManager::~DefaultProviderManager");
|
77 a.dunfey 1.58
|
78 kumpf 1.71 _shutdownAllProviders();
|
79 chip 1.1
|
80 kumpf 1.71 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
|
81 chip 1.1 {
|
82 kumpf 1.71 ProviderMessageHandler* provider = i.value();
83 delete provider;
|
84 chip 1.1 }
85
|
86 kumpf 1.71 for (ModuleTable::Iterator j = _modules.start(); j != 0; j++)
|
87 chip 1.1 {
|
88 kumpf 1.71 ProviderModule* module = j.value();
89 delete module;
|
90 chip 1.1 }
91
|
92 kumpf 1.71 PEG_METHOD_EXIT();
|
93 chip 1.1 }
94
|
95 kumpf 1.73 Message* DefaultProviderManager::processMessage(Message* message)
|
96 chip 1.1 {
97 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
98 "DefaultProviderManager::processMessage()");
99
|
100 kumpf 1.73 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage*>(message);
101 PEGASUS_ASSERT(request != 0);
102
103 CIMResponseMessage* response = 0;
|
104 chip 1.1
|
105 kumpf 1.73 try
|
106 chip 1.1 {
|
107 kumpf 1.73 // pass the request message to a handler method based on message type
108 switch(request->getType())
109 {
110 case CIM_GET_INSTANCE_REQUEST_MESSAGE:
111 case CIM_ENUMERATE_INSTANCES_REQUEST_MESSAGE:
112 case CIM_ENUMERATE_INSTANCE_NAMES_REQUEST_MESSAGE:
113 case CIM_CREATE_INSTANCE_REQUEST_MESSAGE:
114 case CIM_MODIFY_INSTANCE_REQUEST_MESSAGE:
115 case CIM_DELETE_INSTANCE_REQUEST_MESSAGE:
116 case CIM_EXEC_QUERY_REQUEST_MESSAGE:
117 case CIM_ASSOCIATORS_REQUEST_MESSAGE:
118 case CIM_ASSOCIATOR_NAMES_REQUEST_MESSAGE:
119 case CIM_REFERENCES_REQUEST_MESSAGE:
120 case CIM_REFERENCE_NAMES_REQUEST_MESSAGE:
121 case CIM_GET_PROPERTY_REQUEST_MESSAGE:
122 case CIM_SET_PROPERTY_REQUEST_MESSAGE:
123 case CIM_INVOKE_METHOD_REQUEST_MESSAGE:
124 case CIM_CREATE_SUBSCRIPTION_REQUEST_MESSAGE:
125 case CIM_MODIFY_SUBSCRIPTION_REQUEST_MESSAGE:
126 case CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE:
127 case CIM_EXPORT_INDICATION_REQUEST_MESSAGE:
|
128 kumpf 1.71 {
|
129 kumpf 1.91 ProviderIdContainer providerId =
|
130 dmitry.mikulin 1.80 request->operationContext.get(ProviderIdContainer::NAME);
131
|
132 kumpf 1.71 // resolve provider name
|
133 dmitry.mikulin 1.80 ProviderName name = _resolveProviderName(providerId);
|
134 kumpf 1.71
135 // get cached or load new provider module
136 ProviderOperationCounter poc(
|
137 dmitry.mikulin 1.80 _getProvider(
|
138 kumpf 1.91 name.getPhysicalName(),
139 name.getModuleName(),
|
140 dmitry.mikulin 1.80 name.getLogicalName()));
|
141 chip 1.1
|
142 kumpf 1.73 response = poc.GetProvider().processMessage(request);
|
143 kumpf 1.71 break;
144 }
|
145 schuur 1.14
|
146 kumpf 1.73 case CIM_DISABLE_MODULE_REQUEST_MESSAGE:
147 response = _handleDisableModuleRequest(request);
148 break;
149
150 case CIM_ENABLE_MODULE_REQUEST_MESSAGE:
151 response = _handleEnableModuleRequest(request);
152 break;
|
153 chip 1.1
|
154 kumpf 1.73 case CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE:
155 // tell the provider manager to shutdown all the providers
156 _shutdownAllProviders();
157 response = request->buildResponse();
158 break;
|
159 chip 1.1
|
160 kumpf 1.73 case CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE:
161 response = _handleSubscriptionInitCompleteRequest(request);
162 break;
|
163 chip 1.1
|
164 venkat.puvvada 1.92 case CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE:
165 response = _handleIndicationServiceDisabledRequest(request);
166 break;
167
|
168 kumpf 1.73 default:
|
169 dl.meetei 1.95 PEGASUS_UNREACHABLE(PEGASUS_ASSERT(0);)
|
170 kumpf 1.73 break;
171 }
|
172 kumpf 1.30 }
|
173 kumpf 1.71 catch (CIMException& e)
|
174 kumpf 1.30 {
|
175 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"CIMException: %s",
176 (const char*)e.getMessage().getCString()));
|
177 kumpf 1.73 response = request->buildResponse();
|
178 kumpf 1.71 response->cimException = PEGASUS_CIM_EXCEPTION_LANG(
179 e.getContentLanguages(), e.getCode(), e.getMessage());
|
180 kumpf 1.30 }
|
181 kumpf 1.71 catch (Exception& e)
|
182 kumpf 1.30 {
|
183 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"Exception: %s",
184 (const char*)e.getMessage().getCString()));
|
185 kumpf 1.73 response = request->buildResponse();
|
186 kumpf 1.71 response->cimException = PEGASUS_CIM_EXCEPTION_LANG(
187 e.getContentLanguages(), CIM_ERR_FAILED, e.getMessage());
|
188 kumpf 1.30 }
|
189 kumpf 1.71 catch (...)
|
190 kumpf 1.30 {
|
191 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
192 kumpf 1.30 "Exception: Unknown");
|
193 kumpf 1.73 response = request->buildResponse();
|
194 kumpf 1.71 response->cimException = PEGASUS_CIM_EXCEPTION(
195 CIM_ERR_FAILED, "Unknown error.");
|
196 kumpf 1.30 }
197
198 PEG_METHOD_EXIT();
|
199 kumpf 1.71 return response;
|
200 kumpf 1.30 }
201
|
202 kumpf 1.73 CIMResponseMessage* DefaultProviderManager::_handleDisableModuleRequest(
203 CIMRequestMessage* message)
|
204 chip 1.1 {
|
205 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
206 "DefaultProviderManager::_handleDisableModuleRequest");
|
207 chip 1.1
|
208 kumpf 1.71 CIMDisableModuleRequestMessage* request =
209 dynamic_cast<CIMDisableModuleRequestMessage*>(message);
|
210 chip 1.1 PEGASUS_ASSERT(request != 0);
211
|
212 kumpf 1.71 Array<Uint16> operationalStatus;
213 CIMException cimException;
|
214 chip 1.1
215 try
216 {
|
217 kumpf 1.71 // get provider module name
218 String moduleName;
219 CIMInstance mInstance = request->providerModule;
|
220 marek 1.88 Uint32 pos = mInstance.findProperty(PEGASUS_PROPERTYNAME_NAME);
|
221 kumpf 1.71 PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
222 mInstance.getProperty(pos).getValue().get(moduleName);
|
223 chip 1.1
|
224 kumpf 1.71 //
225 // Unload providers
226 //
227 Array<CIMInstance> providerInstances = request->providers;
|
228 chip 1.1
|
229 kumpf 1.71 for (Uint32 i = 0, n = providerInstances.size(); i < n; i++)
230 {
231 String pName;
232 providerInstances[i].getProperty(
|
233 marek 1.88 providerInstances[i].findProperty(PEGASUS_PROPERTYNAME_NAME)).
|
234 kumpf 1.71 getValue().get(pName);
|
235 chip 1.1
|
236 dmitry.mikulin 1.80 Sint16 ret_value = _disableProvider(moduleName, pName);
|
237 chip 1.1
|
238 kumpf 1.71 if (ret_value == 0)
239 {
240 // disable failed since there are pending requests,
241 // stop trying to disable other providers in this module.
242 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
243 break;
244 }
245 else if (ret_value != 1) // Not success
246 {
247 // disable failed for other reason, throw exception
248 throw PEGASUS_CIM_EXCEPTION_L(
249 CIM_ERR_FAILED,
250 MessageLoaderParms(
251 "ProviderManager.ProviderManagerService."
252 "DISABLE_PROVIDER_FAILED",
253 "Failed to disable the provider."));
254 }
255 }
256 }
|
257 kumpf 1.78 catch (CIMException& e)
|
258 kumpf 1.71 {
|
259 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"CIMException: %s",
260 (const char*)e.getMessage().getCString()));
|
261 kumpf 1.71 cimException = e;
262 }
|
263 kumpf 1.78 catch (Exception& e)
|
264 kumpf 1.71 {
|
265 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"Exception: %s",
266 (const char*)e.getMessage().getCString()));
|
267 kumpf 1.71 cimException = CIMException(CIM_ERR_FAILED, e.getMessage());
268 }
269 catch (...)
270 {
|
271 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
272 kumpf 1.71 "Exception: Unknown");
273 cimException = PEGASUS_CIM_EXCEPTION_L(
274 CIM_ERR_FAILED,
275 MessageLoaderParms(
276 "ProviderManager.ProviderManagerService.UNKNOWN_ERROR",
277 "Unknown Error"));
278 }
|
279 chip 1.1
|
280 kumpf 1.71 if (cimException.getCode() == CIM_ERR_SUCCESS)
281 {
282 // Status is set to OK if a provider was busy
283 if (operationalStatus.size() == 0)
284 {
285 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
286 }
287 }
288 else
289 {
290 // If exception occurs, module is not stopped
291 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
292 }
|
293 marek 1.64
|
294 kumpf 1.71 CIMDisableModuleResponseMessage* response =
295 dynamic_cast<CIMDisableModuleResponseMessage*>(
296 request->buildResponse());
297 PEGASUS_ASSERT(response != 0);
|
298 chip 1.1
|
299 kumpf 1.71 response->operationalStatus = operationalStatus;
|
300 chip 1.1
|
301 kumpf 1.71 PEG_METHOD_EXIT();
|
302 chip 1.1
|
303 kumpf 1.71 return response;
|
304 chip 1.1 }
305
|
306 kumpf 1.73 CIMResponseMessage* DefaultProviderManager::_handleEnableModuleRequest(
307 CIMRequestMessage* message)
|
308 chip 1.1 {
|
309 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
310 "DefaultProviderManager::_handleEnableModuleRequest");
|
311 chip 1.1
|
312 kumpf 1.71 CIMEnableModuleRequestMessage* request =
313 dynamic_cast<CIMEnableModuleRequestMessage*>(message);
314 PEGASUS_ASSERT(request != 0);
|
315 chip 1.1
|
316 kumpf 1.71 Array<Uint16> operationalStatus;
317 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
|
318 chip 1.1
|
319 kumpf 1.71 CIMEnableModuleResponseMessage* response =
320 dynamic_cast<CIMEnableModuleResponseMessage*>(
|
321 kumpf 1.54 request->buildResponse());
|
322 chip 1.1 PEGASUS_ASSERT(response != 0);
323
|
324 kumpf 1.71 response->operationalStatus = operationalStatus;
|
325 chip 1.1
|
326 kumpf 1.71 PEG_METHOD_EXIT();
327 return response;
328 }
|
329 chip 1.1
|
330 venkat.puvvada 1.92
331 CIMResponseMessage*
332 DefaultProviderManager::_handleIndicationServiceDisabledRequest(
333 CIMRequestMessage* message)
334 {
335 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
336 "DefaultProviderManager::_handleIndicationServiceDisabledRequest");
337
338 CIMIndicationServiceDisabledRequestMessage* request =
339 dynamic_cast<CIMIndicationServiceDisabledRequestMessage*>(message);
340 PEGASUS_ASSERT(request != 0);
341
342 CIMIndicationServiceDisabledResponseMessage* response =
343 dynamic_cast<CIMIndicationServiceDisabledResponseMessage*>(
344 request->buildResponse());
345 PEGASUS_ASSERT(response != 0);
346
347 _subscriptionInitComplete = false;
348
349 // Make a copy of the table so it is not locked during the provider calls
350 Array<ProviderMessageHandler*> providerList;
351 venkat.puvvada 1.92 {
352 AutoMutex lock(_providerTableMutex);
353
354 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
355 {
356 providerList.append(i.value());
357 }
358 }
359
360 //
361 // Notify all providers that indication service is disabled
362 //
363 for (Uint32 j = 0; j < providerList.size(); j++)
364 {
365 AutoMutex lock(providerList[j]->status.getStatusMutex());
366
367 if (providerList[j]->status.isInitialized())
368 {
369 providerList[j]->indicationServiceDisabled();
370 }
371 }
372 venkat.puvvada 1.92
373 PEG_METHOD_EXIT();
374 return response;
375 }
376
|
377 kumpf 1.73 CIMResponseMessage*
378 DefaultProviderManager::_handleSubscriptionInitCompleteRequest(
379 CIMRequestMessage* message)
|
380 kumpf 1.71 {
381 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
382 "DefaultProviderManager::_handleSubscriptionInitCompleteRequest");
|
383 chip 1.1
|
384 kumpf 1.71 CIMSubscriptionInitCompleteRequestMessage* request =
385 dynamic_cast<CIMSubscriptionInitCompleteRequestMessage*>(message);
|
386 chip 1.1 PEGASUS_ASSERT(request != 0);
387
|
388 kumpf 1.71 CIMSubscriptionInitCompleteResponseMessage* response =
389 dynamic_cast<CIMSubscriptionInitCompleteResponseMessage*>(
|
390 kumpf 1.54 request->buildResponse());
|
391 chip 1.1 PEGASUS_ASSERT(response != 0);
392
|
393 kumpf 1.71 _subscriptionInitComplete = true;
|
394 chip 1.1
|
395 kumpf 1.71 // Make a copy of the table so it is not locked during the provider calls
396 Array<ProviderMessageHandler*> providerList;
|
397 chip 1.1 {
|
398 kumpf 1.71 AutoMutex lock(_providerTableMutex);
|
399 chip 1.1
|
400 kumpf 1.71 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
401 {
402 providerList.append(i.value());
403 }
404 }
|
405 chip 1.1
|
406 kumpf 1.71 //
407 // Notify all providers that subscription initialization is complete
408 //
409 for (Uint32 j = 0; j < providerList.size(); j++)
410 {
|
411 kumpf 1.72 AutoMutex lock(providerList[j]->status.getStatusMutex());
412
413 if (providerList[j]->status.isInitialized())
414 {
415 providerList[j]->subscriptionInitComplete();
416 }
|
417 kumpf 1.71 }
|
418 chip 1.1
|
419 kumpf 1.71 PEG_METHOD_EXIT();
420 return response;
421 }
|
422 chip 1.1
|
423 kumpf 1.71 ProviderName DefaultProviderManager::_resolveProviderName(
|
424 kumpf 1.78 const ProviderIdContainer& providerId)
|
425 kumpf 1.71 {
426 String providerName;
427 String fileName;
|
428 dmitry.mikulin 1.80 String moduleName;
|
429 kumpf 1.71 CIMValue genericValue;
|
430 se.gupta 1.34
|
431 dmitry.mikulin 1.80 genericValue = providerId.getModule().getProperty(
|
432 marek 1.88 providerId.getModule().findProperty(
433 PEGASUS_PROPERTYNAME_NAME)).getValue();
|
434 dmitry.mikulin 1.80 genericValue.get(moduleName);
435
|
436 kumpf 1.71 genericValue = providerId.getProvider().getProperty(
|
437 marek 1.88 providerId.getProvider().findProperty(
438 PEGASUS_PROPERTYNAME_NAME)).getValue();
|
439 kumpf 1.71 genericValue.get(providerName);
|
440 chip 1.1
|
441 kumpf 1.71 genericValue = providerId.getModule().getProperty(
442 providerId.getModule().findProperty("Location")).getValue();
443 genericValue.get(fileName);
|
444 marek 1.64
|
445 kumpf 1.77 String resolvedFileName = _resolvePhysicalName(fileName);
446
447 if (resolvedFileName == String::EMPTY)
448 {
449 // Provider library not found
450 throw Exception(MessageLoaderParms(
451 "ProviderManager.ProviderManagerService.PROVIDER_FILE_NOT_FOUND",
452 "File \"$0\" was not found for provider module \"$1\".",
453 FileSystem::buildLibraryFileName(fileName), moduleName));
454 }
455
|
456 dmitry.mikulin 1.80 return ProviderName(moduleName, providerName, resolvedFileName);
|
457 chip 1.1 }
458
|
459 kumpf 1.71 ProviderOperationCounter DefaultProviderManager::_getProvider(
460 const String& moduleFileName,
|
461 dmitry.mikulin 1.80 const String& moduleName,
|
462 kumpf 1.71 const String& providerName)
|
463 chip 1.1 {
|
464 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
465 "DefaultProviderManager::_getProvider");
|
466 chip 1.1
|
467 dmitry.mikulin 1.80 ProviderMessageHandler* pr = _lookupProvider(moduleName, providerName);
|
468 chip 1.1
|
469 kumpf 1.71 if (!pr->status.isInitialized())
470 {
471 _initProvider(pr, moduleFileName);
|
472 kumpf 1.72 }
473
474 AutoMutex lock(pr->status.getStatusMutex());
|
475 chip 1.1
|
476 kumpf 1.72 if (!pr->status.isInitialized())
477 {
478 PEG_METHOD_EXIT();
479 throw PEGASUS_CIM_EXCEPTION(
480 CIM_ERR_FAILED, "provider initialization failed");
|
481 kumpf 1.71 }
|
482 chip 1.1
|
483 kumpf 1.71 ProviderOperationCounter poc(pr);
|
484 chip 1.1
|
485 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,"Returning Provider %s",
486 (const char*)providerName.getCString()));
|
487 chip 1.1
|
488 kumpf 1.71 PEG_METHOD_EXIT();
489 return poc;
490 }
|
491 chip 1.1
|
492 kumpf 1.71 ProviderMessageHandler* DefaultProviderManager::_lookupProvider(
|
493 dmitry.mikulin 1.80 const String& moduleName,
|
494 kumpf 1.71 const String& providerName)
495 {
496 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
497 "DefaultProviderManager::_lookupProvider");
|
498 chip 1.1
|
499 kumpf 1.71 // lock the providerTable mutex
500 AutoMutex lock(_providerTableMutex);
|
501 chip 1.1
|
502 dmitry.mikulin 1.80 // Construct the lookup key. We need a compound key to differentiate
503 // providers with the same name from different modules. The size field is
504 // added to handle the unlikely case when moduleName+providerName
505 // produce identical strings but define different providers.
506 char buffer[12];
507 sprintf(buffer, "%u:", providerName.size());
508 const String key = buffer + moduleName + ":" + providerName;
509
|
510 kumpf 1.71 // look up provider in cache
511 ProviderMessageHandler* pr = 0;
|
512 dmitry.mikulin 1.80 if (_providers.lookup(key, pr))
|
513 kumpf 1.71 {
|
514 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
515 "Found Provider %s in Provider Manager Cache",
516 (const char*)providerName.getCString()));
|
517 kumpf 1.71 }
518 else
519 {
520 // create provider
521 pr = new ProviderMessageHandler(
|
522 kumpf 1.91 moduleName, providerName,
|
523 dmitry.mikulin 1.81 0, _indicationCallback, _responseChunkCallback,
|
524 kumpf 1.71 _subscriptionInitComplete);
|
525 chip 1.1
|
526 kumpf 1.71 // insert provider in provider table
|
527 dmitry.mikulin 1.80 _providers.insert(key, pr);
|
528 marek 1.64
|
529 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,"Created provider %s",
530 (const char*)pr->getName().getCString()));
|
531 chip 1.1 }
532
533 PEG_METHOD_EXIT();
|
534 kumpf 1.71 return pr;
|
535 chip 1.1 }
536
|
537 kumpf 1.71 ProviderMessageHandler* DefaultProviderManager::_initProvider(
538 ProviderMessageHandler* provider,
539 const String& moduleFileName)
|
540 chip 1.1 {
|
541 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
542 "DefaultProviderManager::_initProvider");
|
543 chip 1.1
|
544 kumpf 1.71 ProviderModule* module = 0;
545 CIMProvider* base;
|
546 chip 1.1
|
547 kumpf 1.72 // lookup provider module
548 module = _lookupModule(moduleFileName);
|
549 chip 1.1
|
550 kumpf 1.72 // lock the provider status mutex
551 AutoMutex lock(provider->status.getStatusMutex());
|
552 chip 1.1
|
553 kumpf 1.72 if (provider->status.isInitialized())
|
554 kumpf 1.71 {
|
555 kumpf 1.72 // Initialization is already complete
556 return provider;
557 }
|
558 chip 1.1
|
559 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
560 "Loading/Linking Provider Module %s",
561 (const char*)moduleFileName.getCString()));
|
562 chip 1.1
|
563 kumpf 1.72 // load the provider
564 try
565 {
566 base = module->load(provider->getName());
567 }
568 catch (...)
569 {
|
570 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
571 "Exception caught Loading/Linking Provider Module %s",
572 (const char*)moduleFileName.getCString()));
|
573 kumpf 1.72 PEG_METHOD_EXIT();
574 throw;
575 }
|
576 chip 1.1
|
577 kumpf 1.72 // initialize the provider
|
578 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL2, "Initializing Provider %s",
579 (const char*)provider->getName().getCString()));
|
580 chip 1.1
|
581 kumpf 1.78 CIMOMHandle* cimomHandle = new CIMOMHandle();
|
582 kumpf 1.72 provider->status.setCIMOMHandle(cimomHandle);
583 provider->status.setModule(module);
584 provider->setProvider(base);
|
585 chip 1.1
|
586 kumpf 1.72 Boolean initializeError = false;
|
587 chip 1.1
|
588 kumpf 1.72 try
589 {
590 provider->initialize(*cimomHandle);
591 }
592 catch (...)
593 {
|
594 karl 1.96 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
595 "Initialization Error. Provider %s",
596 (const char*)provider->getName().getCString()));
|
597 kumpf 1.72 initializeError = true;
598 }
|
599 chip 1.1
|
600 kumpf 1.72 // The cleanup code executed when an exception occurs was previously
601 // included in the catch block above. Unloading the provider module
602 // from inside the catch block resulted in a crash when an exception
603 // was thrown from a provider's initialize() method. The issue is that
604 // when an exception is thrown, the program maintains internal
605 // pointers related to the code that threw the exception. In the case
606 // of an exception thrown from a provider during the initialize()
607 // method, those pointers point into the provider library, so when
608 // the DefaultProviderManager unloads the library, the pointers into
609 // the library that the program was holding are invalid.
|
610 chip 1.1
|
611 kumpf 1.72 if (initializeError == true)
612 {
|
613 kumpf 1.76 // Allow the provider to clean up
614 provider->terminate();
615
|
616 kumpf 1.72 // delete the cimom handle
617 delete cimomHandle;
|
618 marek 1.64
|
619 kumpf 1.72 provider->setProvider(0);
|
620 chip 1.1
|
621 kumpf 1.72 // unload provider module
622 module->unloadModule();
623 }
|
624 chip 1.1
|
625 kumpf 1.72 provider->status.setInitialized(!initializeError);
|
626 chip 1.1
627 PEG_METHOD_EXIT();
|
628 kumpf 1.71 return provider;
|
629 chip 1.1 }
630
|
631 kumpf 1.71 ProviderModule* DefaultProviderManager::_lookupModule(
632 const String& moduleFileName)
|
633 chip 1.1 {
|
634 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
635 "DefaultProviderManager::_lookupModule");
|
636 chip 1.1
|
637 kumpf 1.72 // lock the providerTable mutex
638 AutoMutex lock(_providerTableMutex);
639
|
640 kumpf 1.71 // look up provider module in cache
641 ProviderModule* module = 0;
|
642 chip 1.1
|
643 kumpf 1.71 if (_modules.lookup(moduleFileName, module))
644 {
645 // found provider module in cache
|
646 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
647 "Found Provider Module %s in Provider Manager Cache",
648 (const char*)moduleFileName.getCString()));
|
649 kumpf 1.71 }
650 else
|
651 chip 1.1 {
|
652 kumpf 1.71 // provider module not found in cache, create provider module
|
653 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
654 "Creating Provider Module %s",
655 (const char*)moduleFileName.getCString()));
|
656 chip 1.1
|
657 kumpf 1.71 module = new ProviderModule(moduleFileName);
|
658 marek 1.64
|
659 kumpf 1.71 // insert provider module in module table
660 _modules.insert(moduleFileName, module);
|
661 chip 1.1 }
662
663 PEG_METHOD_EXIT();
|
664 kumpf 1.71 return module;
|
665 chip 1.1 }
666
|
667 kumpf 1.71 Boolean DefaultProviderManager::hasActiveProviders()
|
668 chip 1.1 {
|
669 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
670 "DefaultProviderManager::hasActiveProviders");
|
671 schuur 1.12
672 try
673 {
|
674 kumpf 1.71 AutoMutex lock(_providerTableMutex);
|
675 marek 1.79 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
676 "Number of providers in _providers table = %d", _providers.size()));
|
677 marek 1.64
|
678 kumpf 1.71 // Iterate through the _providers table looking for an active provider
679 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
680 {
681 if (i.value()->status.isInitialized())
682 {
683 PEG_METHOD_EXIT();
684 return true;
685 }
686 }
687 }
688 catch (...)
689 {
690 // Unexpected exception; do not assume that no providers are loaded
|
691 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
692 kumpf 1.71 "Unexpected Exception in hasActiveProviders.");
693 PEG_METHOD_EXIT();
694 return true;
|
695 schuur 1.12 }
|
696 chip 1.1
|
697 kumpf 1.71 // No active providers were found in the _providers table
|
698 chip 1.1 PEG_METHOD_EXIT();
|
699 kumpf 1.71 return false;
|
700 chip 1.1 }
701
|
702 kumpf 1.71 void DefaultProviderManager::unloadIdleProviders()
|
703 chip 1.1 {
|
704 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
|
705 kumpf 1.72 "DefaultProviderManager::unloadIdleProviders");
|
706 kumpf 1.71
|
707 kumpf 1.75 try
|
708 kumpf 1.71 {
|
709 kumpf 1.75 struct timeval now;
710 Time::gettimeofday(&now);
|
711 chip 1.1
|
712 kumpf 1.72 // Make a copy of the table so it is not locked during provider calls
713 Array<ProviderMessageHandler*> providerList;
|
714 kumpf 1.71 {
|
715 kumpf 1.72 AutoMutex lock(_providerTableMutex);
|
716 chip 1.2
|
717 kumpf 1.72 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
|
718 kumpf 1.71 {
|
719 kumpf 1.72 providerList.append(i.value());
|
720 kumpf 1.71 }
|
721 kumpf 1.72 }
|
722 se.gupta 1.34
|
723 kumpf 1.72 for (Uint32 i = 0; i < providerList.size(); i++)
724 {
725 ProviderMessageHandler* provider = providerList[i];
|
726 marek 1.64
|
727 kumpf 1.72 AutoMutex lock(provider->status.getStatusMutex());
|
728 kumpf 1.66
|
729 kumpf 1.72 if (!provider->status.isInitialized())
|
730 kumpf 1.71 {
731 continue;
732 }
|
733 chip 1.1
|
734 kumpf 1.72 struct timeval providerTime = {0, 0};
735 provider->status.getLastOperationEndTime(&providerTime);
|
736 kumpf 1.71
|
737 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
738 "provider->status.isIdle() returns: %s",
739 (const char*)CIMValue(provider->status.isIdle())
740 .toString().getCString()));
|
741 marek 1.64
|
742 kumpf 1.72 if (provider->status.isIdle() &&
|
743 r.kieninger 1.82 ((now.tv_sec - providerTime.tv_sec) >
744 ((Sint32)PEGASUS_PROVIDER_IDLE_TIMEOUT_SECONDS)))
|
745 kumpf 1.71 {
|
746 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
747 "Unloading idle provider: %s",
748 (const char*)provider->getName().getCString()));
|
749 kumpf 1.72 _unloadProvider(provider);
|
750 kumpf 1.71 }
751 }
752 }
753 catch (...)
|
754 chip 1.1 {
|
755 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
756 kumpf 1.71 "Caught unexpected exception in unloadIdleProviders.");
|
757 chip 1.1 }
758
759 PEG_METHOD_EXIT();
760 }
761
|
762 kumpf 1.71 void DefaultProviderManager::_shutdownAllProviders()
|
763 chip 1.1 {
|
764 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
765 "DefaultProviderManager::_shutdownAllProviders");
|
766 chip 1.1
|
767 sahana.prabhakar 1.93 AutoMutex lock(_providerTableMutex);
768 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
769 "providers in cache = %d", _providers.size()));
770
|
771 karl 1.96 //create an array of UnloadProviderRequest requests one per
|
772 sahana.prabhakar 1.93 //provider to process shutdown of providers simultaneously.
773 Array<AsyncRequestExecutor::AsyncRequestMsg*> ProviderRequests;
774 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
|
775 chip 1.1 {
|
776 sahana.prabhakar 1.93 AutoMutex lock(i.value()->status.getStatusMutex());
777 if(i.value()->status.isInitialized())
|
778 karl 1.96 {
|
779 sahana.prabhakar 1.93 ProviderRequests.append(
780 new UnloadProviderRequest(i.value()));
781 }
782 }
|
783 chip 1.2
|
784 sahana.prabhakar 1.93 //run the stop request on all providers on multiple threads using
785 //the request executor. This will invoke _asyncRequestCallback() on a
786 //seperate thread for each provider which in turn will unload that
787 //provider.
|
788 karl 1.96
|
789 sahana.prabhakar 1.93 CIMException exception =
790 AsyncRequestExecutor(&_asyncRequestCallback,this).executeRequests(
791 ProviderRequests);
|
792 kumpf 1.72
|
793 sahana.prabhakar 1.93 if(exception.getCode() != CIM_ERR_SUCCESS)
|
794 ashok.pathak 1.94 {
|
795 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
|
796 kumpf 1.71 "Unexpected Exception in _shutdownAllProviders().");
|
797 ashok.pathak 1.94 }
|
798 chip 1.1
799 PEG_METHOD_EXIT();
800 }
801
|
802 dmitry.mikulin 1.80 Sint16 DefaultProviderManager::_disableProvider(
803 const String& moduleName,
804 const String& providerName)
|
805 chip 1.1 {
|
806 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
807 "DefaultProviderManager::_disableProvider");
|
808 chip 1.1
|
809 dmitry.mikulin 1.80 ProviderMessageHandler* pr = _lookupProvider(moduleName, providerName);
|
810 kumpf 1.71 if (!pr->status.isInitialized())
811 {
|
812 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL2,
813 "Provider %s is not loaded",
814 (const char*)providerName.getCString()));
|
815 kumpf 1.71 PEG_METHOD_EXIT();
816 return 1;
817 }
|
818 chip 1.1
|
819 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,"Disable Provider %s",
820 (const char*)pr->getName().getCString()));
|
821 kumpf 1.71 //
822 // Check to see if there are pending requests. If there are pending
823 // requests and the disable timeout has not expired, loop and wait one
824 // second until either there is no pending requests or until timeout
825 // expires.
826 //
827 Uint32 waitTime = PROVIDER_DISABLE_TIMEOUT;
|
828 kumpf 1.72 while ((pr->status.numCurrentOperations() > 0) && (waitTime > 0))
|
829 kumpf 1.71 {
830 Threads::sleep(1000);
831 waitTime = waitTime - 1;
832 }
|
833 chip 1.1
|
834 kumpf 1.71 // There are still pending requests, do not disable
|
835 kumpf 1.72 if (pr->status.numCurrentOperations() > 0)
|
836 kumpf 1.71 {
|
837 marek 1.79 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
838 kumpf 1.71 "Disable failed since there are pending requests.");
839 PEG_METHOD_EXIT();
840 return 0;
841 }
|
842 chip 1.1
843 try
844 {
|
845 kumpf 1.72 AutoMutex lock(pr->status.getStatusMutex());
|
846 chip 1.1
|
847 kumpf 1.71 if (pr->status.isInitialized())
848 {
|
849 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
850 "Unloading Provider %s",
851 (const char*)pr->getName().getCString()));
|
852 kumpf 1.71 _unloadProvider(pr);
853 }
854 }
855 catch (...)
856 {
|
857 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL2,
858 "Unload provider failed %s",
859 (const char*)pr->getName().getCString()));
|
860 kumpf 1.71 PEG_METHOD_EXIT();
861 return -1;
|
862 chip 1.1 }
863
864 PEG_METHOD_EXIT();
|
865 kumpf 1.71 return 1;
|
866 chip 1.1 }
867
|
868 kumpf 1.71 void DefaultProviderManager::_unloadProvider(ProviderMessageHandler* provider)
|
869 chip 1.1 {
|
870 kumpf 1.71 //
|
871 kumpf 1.72 // NOTE: It is the caller's responsibility to make sure that the
872 // provider->status.getStatusMutex() mutex is locked before calling
873 // this method.
|
874 kumpf 1.71 //
|
875 kumpf 1.72
|
876 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
877 "DefaultProviderManager::_unloadProvider");
|
878 chip 1.1
|
879 kumpf 1.72 if (provider->status.numCurrentOperations() > 0)
|
880 chip 1.1 {
|
881 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
882 "Provider cannot be unloaded due to pending operations: %s",
883 (const char*)provider->getName().getCString()));
|
884 chip 1.1 }
|
885 kumpf 1.71 else
|
886 chip 1.1 {
|
887 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
888 "Terminating Provider %s",
889 (const char*)provider->getName().getCString()));
|
890 chip 1.1
|
891 kumpf 1.72 provider->terminate();
|
892 chip 1.1
|
893 kumpf 1.72 // unload provider module
894 PEGASUS_ASSERT(provider->status.getModule() != 0);
|
895 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
896 "Unloading provider module: %s",
897 (const char*)provider->getName().getCString()));
|
898 kumpf 1.72 provider->status.getModule()->unloadModule();
|
899 chip 1.1
|
900 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER,Tracer::LEVEL3,
901 "DefaultProviderManager: Unloaded provider %s",
902 (const char*)provider->getName().getCString()));
|
903 kumpf 1.71
|
904 kumpf 1.72 // NOTE: The "delete provider->status.getCIMOMHandle()" operation
905 // was moved to be called after the unloadModule() call above
|
906 kumpf 1.71 // as part of a fix for bugzilla 3669. For some providers
907 // run out-of-process on Windows platforms (i.e. running
908 // the cimserver with the forceProviderProcesses config option
909 // set to "true"), deleting the provider's CIMOMHandle before
910 // unloading the provider library caused the unload mechanism
911 // to deadlock, making that provider unavailable and preventing
912 // the cimserver from shutting down. It should NOT be moved back
913 // above the unloadModule() call. See bugzilla 3669 for details.
|
914 kumpf 1.72
|
915 kumpf 1.71 // delete the cimom handle
|
916 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
917 "Destroying provider's CIMOMHandle: %s",
918 (const char*)provider->getName().getCString()));
|
919 kumpf 1.72 delete provider->status.getCIMOMHandle();
|
920 marek 1.64
|
921 kumpf 1.71 // set provider status to uninitialized
|
922 kumpf 1.72 provider->status.setInitialized(false);
|
923 chip 1.1 }
924
925 PEG_METHOD_EXIT();
|
926 carolann.graves 1.49 }
927
|
928 mike 1.63 ProviderManager* DefaultProviderManager::createDefaultProviderManagerCallback()
929 {
930 return new DefaultProviderManager();
931 }
932
|
933 sahana.prabhakar 1.93 //async request handler method invoked on a seperate thread per provider
934 //through the async request executor.
935 CIMException DefaultProviderManager::_asyncRequestCallback(
936 void *callbackPtr,
937 AsyncRequestExecutor::AsyncRequestMsg* request)
938 {
939 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
940 "DefaultProviderManager::_asyncRequestCallback");
941
942 CIMException responseException;
943
944 //extract the parameters
945 UnloadProviderRequest* my_request =
946 dynamic_cast<UnloadProviderRequest*>(request);
947 if(my_request != NULL)
948 {
949 PEGASUS_ASSERT(0 != callbackPtr);
950
|
951 karl 1.96 DefaultProviderManager *dpmPtr =
|
952 sahana.prabhakar 1.93 static_cast<DefaultProviderManager*>(callbackPtr);
953
954 ProviderMessageHandler* provider =
955 dynamic_cast<ProviderMessageHandler*>(my_request->_provider);
|
956 karl 1.96 try
|
957 sahana.prabhakar 1.93 {
958 AutoMutex lock(provider->status.getStatusMutex());
959 //unload the provider
960 if (provider->status.isInitialized())
961 {
962 dpmPtr->_unloadProvider(provider);
963 }
964 else
965 {
966 PEGASUS_ASSERT(0);
967 }
968 }
969 catch (CIMException& e)
970 {
971 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"CIMException: %s",
972 (const char*)e.getMessage().getCString()));
973 responseException = e;
974 }
975 catch (Exception& e)
976 {
977 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"Exception: %s",
978 sahana.prabhakar 1.93 (const char*)e.getMessage().getCString()));
979 responseException = CIMException(CIM_ERR_FAILED, e.getMessage());
980 }
981 catch (PEGASUS_STD(exception)& e)
982 {
983 responseException = CIMException(CIM_ERR_FAILED, e.what());
984 }
985 catch (...)
986 {
987 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
988 "Exception: Unknown");
989 responseException = PEGASUS_CIM_EXCEPTION(
990 CIM_ERR_FAILED, "Unknown error.");
991 }
992 }
993
994 // delete the UnloadProviderRequest.
995 delete request;
|
996 karl 1.96
|
997 sahana.prabhakar 1.93 PEG_METHOD_EXIT();
998 return responseException;
999 }
1000
|
1001 kumpf 1.26 PEGASUS_NAMESPACE_END
|
1002 kumpf 1.74
1003 PEGASUS_USING_PEGASUS;
1004
1005 // This entry point is not needed because the DefaultProviderManager is created
1006 // using DefaultProviderManager::createDefaultProviderManagerCallback().
1007 #if 0
1008 extern "C" PEGASUS_EXPORT ProviderManager* PegasusCreateProviderManager(
1009 const String& providerManagerName)
1010 {
1011 if (String::equalNoCase(providerManagerName, "Default"))
1012 {
1013 return new DefaultProviderManager();
1014 }
1015
1016 return 0;
1017 }
1018 #endif
|