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 // A request class to hold the provider info passed to the
54 // 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 karl 1.93.2.1 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 initializeError = true;
595 }
|
596 chip 1.1
|
597 kumpf 1.72 // The cleanup code executed when an exception occurs was previously
598 // included in the catch block above. Unloading the provider module
599 // from inside the catch block resulted in a crash when an exception
600 // was thrown from a provider's initialize() method. The issue is that
601 // when an exception is thrown, the program maintains internal
602 // pointers related to the code that threw the exception. In the case
603 // of an exception thrown from a provider during the initialize()
604 // method, those pointers point into the provider library, so when
605 // the DefaultProviderManager unloads the library, the pointers into
606 // the library that the program was holding are invalid.
|
607 chip 1.1
|
608 kumpf 1.72 if (initializeError == true)
609 {
|
610 kumpf 1.76 // Allow the provider to clean up
611 provider->terminate();
612
|
613 kumpf 1.72 // delete the cimom handle
614 delete cimomHandle;
|
615 marek 1.64
|
616 kumpf 1.72 provider->setProvider(0);
|
617 chip 1.1
|
618 kumpf 1.72 // unload provider module
619 module->unloadModule();
620 }
|
621 chip 1.1
|
622 kumpf 1.72 provider->status.setInitialized(!initializeError);
|
623 chip 1.1
624 PEG_METHOD_EXIT();
|
625 kumpf 1.71 return provider;
|
626 chip 1.1 }
627
|
628 kumpf 1.71 ProviderModule* DefaultProviderManager::_lookupModule(
629 const String& moduleFileName)
|
630 chip 1.1 {
|
631 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
632 "DefaultProviderManager::_lookupModule");
|
633 chip 1.1
|
634 kumpf 1.72 // lock the providerTable mutex
635 AutoMutex lock(_providerTableMutex);
636
|
637 kumpf 1.71 // look up provider module in cache
638 ProviderModule* module = 0;
|
639 chip 1.1
|
640 kumpf 1.71 if (_modules.lookup(moduleFileName, module))
641 {
642 // found provider module in cache
|
643 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
644 "Found Provider Module %s in Provider Manager Cache",
645 (const char*)moduleFileName.getCString()));
|
646 kumpf 1.71 }
647 else
|
648 chip 1.1 {
|
649 kumpf 1.71 // provider module not found in cache, create provider module
|
650 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
651 "Creating Provider Module %s",
652 (const char*)moduleFileName.getCString()));
|
653 chip 1.1
|
654 kumpf 1.71 module = new ProviderModule(moduleFileName);
|
655 marek 1.64
|
656 kumpf 1.71 // insert provider module in module table
657 _modules.insert(moduleFileName, module);
|
658 chip 1.1 }
659
660 PEG_METHOD_EXIT();
|
661 kumpf 1.71 return module;
|
662 chip 1.1 }
663
|
664 kumpf 1.71 Boolean DefaultProviderManager::hasActiveProviders()
|
665 chip 1.1 {
|
666 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
667 "DefaultProviderManager::hasActiveProviders");
|
668 schuur 1.12
669 try
670 {
|
671 kumpf 1.71 AutoMutex lock(_providerTableMutex);
|
672 marek 1.79 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
673 "Number of providers in _providers table = %d", _providers.size()));
|
674 marek 1.64
|
675 kumpf 1.71 // Iterate through the _providers table looking for an active provider
676 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
677 {
678 if (i.value()->status.isInitialized())
679 {
680 PEG_METHOD_EXIT();
681 return true;
682 }
683 }
684 }
685 catch (...)
686 {
687 // Unexpected exception; do not assume that no providers are loaded
|
688 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
689 kumpf 1.71 "Unexpected Exception in hasActiveProviders.");
690 PEG_METHOD_EXIT();
691 return true;
|
692 schuur 1.12 }
|
693 chip 1.1
|
694 kumpf 1.71 // No active providers were found in the _providers table
|
695 chip 1.1 PEG_METHOD_EXIT();
|
696 kumpf 1.71 return false;
|
697 chip 1.1 }
698
|
699 kumpf 1.71 void DefaultProviderManager::unloadIdleProviders()
|
700 chip 1.1 {
|
701 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
|
702 kumpf 1.72 "DefaultProviderManager::unloadIdleProviders");
|
703 kumpf 1.71
|
704 kumpf 1.75 try
|
705 kumpf 1.71 {
|
706 kumpf 1.75 struct timeval now;
707 Time::gettimeofday(&now);
|
708 chip 1.1
|
709 kumpf 1.72 // Make a copy of the table so it is not locked during provider calls
710 Array<ProviderMessageHandler*> providerList;
|
711 kumpf 1.71 {
|
712 kumpf 1.72 AutoMutex lock(_providerTableMutex);
|
713 chip 1.2
|
714 kumpf 1.72 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
|
715 kumpf 1.71 {
|
716 kumpf 1.72 providerList.append(i.value());
|
717 kumpf 1.71 }
|
718 kumpf 1.72 }
|
719 se.gupta 1.34
|
720 kumpf 1.72 for (Uint32 i = 0; i < providerList.size(); i++)
721 {
722 ProviderMessageHandler* provider = providerList[i];
|
723 marek 1.64
|
724 kumpf 1.72 AutoMutex lock(provider->status.getStatusMutex());
|
725 kumpf 1.66
|
726 kumpf 1.72 if (!provider->status.isInitialized())
|
727 kumpf 1.71 {
728 continue;
729 }
|
730 chip 1.1
|
731 kumpf 1.72 struct timeval providerTime = {0, 0};
732 provider->status.getLastOperationEndTime(&providerTime);
|
733 kumpf 1.71
|
734 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
735 "provider->status.isIdle() returns: %s",
736 (const char*)CIMValue(provider->status.isIdle())
737 .toString().getCString()));
|
738 marek 1.64
|
739 kumpf 1.72 if (provider->status.isIdle() &&
|
740 r.kieninger 1.82 ((now.tv_sec - providerTime.tv_sec) >
741 ((Sint32)PEGASUS_PROVIDER_IDLE_TIMEOUT_SECONDS)))
|
742 kumpf 1.71 {
|
743 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
744 "Unloading idle provider: %s",
745 (const char*)provider->getName().getCString()));
|
746 kumpf 1.72 _unloadProvider(provider);
|
747 kumpf 1.71 }
748 }
749 }
750 catch (...)
|
751 chip 1.1 {
|
752 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
|
753 kumpf 1.71 "Caught unexpected exception in unloadIdleProviders.");
|
754 chip 1.1 }
755
756 PEG_METHOD_EXIT();
757 }
758
|
759 kumpf 1.71 void DefaultProviderManager::_shutdownAllProviders()
|
760 chip 1.1 {
|
761 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
762 "DefaultProviderManager::_shutdownAllProviders");
|
763 chip 1.1
|
764 sahana.prabhakar 1.93 AutoMutex lock(_providerTableMutex);
765 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
766 "providers in cache = %d", _providers.size()));
767
768 //create an array of UnloadProviderRequest requests one per
769 //provider to process shutdown of providers simultaneously.
770 Array<AsyncRequestExecutor::AsyncRequestMsg*> ProviderRequests;
771 for (ProviderTable::Iterator i = _providers.start(); i != 0; i++)
|
772 chip 1.1 {
|
773 sahana.prabhakar 1.93 AutoMutex lock(i.value()->status.getStatusMutex());
774 if(i.value()->status.isInitialized())
775 {
776 ProviderRequests.append(
777 new UnloadProviderRequest(i.value()));
778 }
779 }
|
780 chip 1.2
|
781 sahana.prabhakar 1.93 //run the stop request on all providers on multiple threads using
782 //the request executor. This will invoke _asyncRequestCallback() on a
783 //seperate thread for each provider which in turn will unload that
784 //provider.
785
786 CIMException exception =
787 AsyncRequestExecutor(&_asyncRequestCallback,this).executeRequests(
788 ProviderRequests);
|
789 kumpf 1.72
|
790 sahana.prabhakar 1.93 if(exception.getCode() != CIM_ERR_SUCCESS)
|
791 karl 1.93.2.1 {
|
792 marek 1.85 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
|
793 kumpf 1.71 "Unexpected Exception in _shutdownAllProviders().");
|
794 karl 1.93.2.1 }
|
795 chip 1.1
796 PEG_METHOD_EXIT();
797 }
798
|
799 dmitry.mikulin 1.80 Sint16 DefaultProviderManager::_disableProvider(
800 const String& moduleName,
801 const String& providerName)
|
802 chip 1.1 {
|
803 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
804 "DefaultProviderManager::_disableProvider");
|
805 chip 1.1
|
806 dmitry.mikulin 1.80 ProviderMessageHandler* pr = _lookupProvider(moduleName, providerName);
|
807 kumpf 1.71 if (!pr->status.isInitialized())
808 {
|
809 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL2,
810 "Provider %s is not loaded",
811 (const char*)providerName.getCString()));
|
812 kumpf 1.71 PEG_METHOD_EXIT();
813 return 1;
814 }
|
815 chip 1.1
|
816 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,"Disable Provider %s",
817 (const char*)pr->getName().getCString()));
|
818 kumpf 1.71 //
819 // Check to see if there are pending requests. If there are pending
820 // requests and the disable timeout has not expired, loop and wait one
821 // second until either there is no pending requests or until timeout
822 // expires.
823 //
824 Uint32 waitTime = PROVIDER_DISABLE_TIMEOUT;
|
825 kumpf 1.72 while ((pr->status.numCurrentOperations() > 0) && (waitTime > 0))
|
826 kumpf 1.71 {
827 Threads::sleep(1000);
828 waitTime = waitTime - 1;
829 }
|
830 chip 1.1
|
831 kumpf 1.71 // There are still pending requests, do not disable
|
832 kumpf 1.72 if (pr->status.numCurrentOperations() > 0)
|
833 kumpf 1.71 {
|
834 marek 1.79 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
835 kumpf 1.71 "Disable failed since there are pending requests.");
836 PEG_METHOD_EXIT();
837 return 0;
838 }
|
839 chip 1.1
840 try
841 {
|
842 kumpf 1.72 AutoMutex lock(pr->status.getStatusMutex());
|
843 chip 1.1
|
844 kumpf 1.71 if (pr->status.isInitialized())
845 {
|
846 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
847 "Unloading Provider %s",
848 (const char*)pr->getName().getCString()));
|
849 kumpf 1.71 _unloadProvider(pr);
850 }
851 }
852 catch (...)
853 {
|
854 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL2,
855 "Unload provider failed %s",
856 (const char*)pr->getName().getCString()));
|
857 kumpf 1.71 PEG_METHOD_EXIT();
858 return -1;
|
859 chip 1.1 }
860
861 PEG_METHOD_EXIT();
|
862 kumpf 1.71 return 1;
|
863 chip 1.1 }
864
|
865 kumpf 1.71 void DefaultProviderManager::_unloadProvider(ProviderMessageHandler* provider)
|
866 chip 1.1 {
|
867 kumpf 1.71 //
|
868 kumpf 1.72 // NOTE: It is the caller's responsibility to make sure that the
869 // provider->status.getStatusMutex() mutex is locked before calling
870 // this method.
|
871 kumpf 1.71 //
|
872 kumpf 1.72
|
873 kumpf 1.71 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
874 "DefaultProviderManager::_unloadProvider");
|
875 chip 1.1
|
876 kumpf 1.72 if (provider->status.numCurrentOperations() > 0)
|
877 chip 1.1 {
|
878 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
879 "Provider cannot be unloaded due to pending operations: %s",
880 (const char*)provider->getName().getCString()));
|
881 chip 1.1 }
|
882 kumpf 1.71 else
|
883 chip 1.1 {
|
884 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
885 "Terminating Provider %s",
886 (const char*)provider->getName().getCString()));
|
887 chip 1.1
|
888 kumpf 1.72 provider->terminate();
|
889 chip 1.1
|
890 kumpf 1.72 // unload provider module
891 PEGASUS_ASSERT(provider->status.getModule() != 0);
|
892 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
893 "Unloading provider module: %s",
894 (const char*)provider->getName().getCString()));
|
895 kumpf 1.72 provider->status.getModule()->unloadModule();
|
896 chip 1.1
|
897 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER,Tracer::LEVEL3,
898 "DefaultProviderManager: Unloaded provider %s",
899 (const char*)provider->getName().getCString()));
|
900 kumpf 1.71
|
901 kumpf 1.72 // NOTE: The "delete provider->status.getCIMOMHandle()" operation
902 // was moved to be called after the unloadModule() call above
|
903 kumpf 1.71 // as part of a fix for bugzilla 3669. For some providers
904 // run out-of-process on Windows platforms (i.e. running
905 // the cimserver with the forceProviderProcesses config option
906 // set to "true"), deleting the provider's CIMOMHandle before
907 // unloading the provider library caused the unload mechanism
908 // to deadlock, making that provider unavailable and preventing
909 // the cimserver from shutting down. It should NOT be moved back
910 // above the unloadModule() call. See bugzilla 3669 for details.
|
911 kumpf 1.72
|
912 kumpf 1.71 // delete the cimom handle
|
913 thilo.boehm 1.87 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
914 "Destroying provider's CIMOMHandle: %s",
915 (const char*)provider->getName().getCString()));
|
916 kumpf 1.72 delete provider->status.getCIMOMHandle();
|
917 marek 1.64
|
918 kumpf 1.71 // set provider status to uninitialized
|
919 kumpf 1.72 provider->status.setInitialized(false);
|
920 chip 1.1 }
921
922 PEG_METHOD_EXIT();
|
923 carolann.graves 1.49 }
924
|
925 mike 1.63 ProviderManager* DefaultProviderManager::createDefaultProviderManagerCallback()
926 {
927 return new DefaultProviderManager();
928 }
929
|
930 sahana.prabhakar 1.93 //async request handler method invoked on a seperate thread per provider
931 //through the async request executor.
932 CIMException DefaultProviderManager::_asyncRequestCallback(
933 void *callbackPtr,
934 AsyncRequestExecutor::AsyncRequestMsg* request)
935 {
936 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
937 "DefaultProviderManager::_asyncRequestCallback");
938
939 CIMException responseException;
940
941 //extract the parameters
942 UnloadProviderRequest* my_request =
943 dynamic_cast<UnloadProviderRequest*>(request);
944 if(my_request != NULL)
945 {
946 PEGASUS_ASSERT(0 != callbackPtr);
947
948 DefaultProviderManager *dpmPtr =
949 static_cast<DefaultProviderManager*>(callbackPtr);
950
951 sahana.prabhakar 1.93 ProviderMessageHandler* provider =
952 dynamic_cast<ProviderMessageHandler*>(my_request->_provider);
953 try
954 {
955 AutoMutex lock(provider->status.getStatusMutex());
956 //unload the provider
957 if (provider->status.isInitialized())
958 {
959 dpmPtr->_unloadProvider(provider);
960 }
961 else
962 {
963 PEGASUS_ASSERT(0);
964 }
965 }
966 catch (CIMException& e)
967 {
968 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"CIMException: %s",
969 (const char*)e.getMessage().getCString()));
970 responseException = e;
971 }
972 sahana.prabhakar 1.93 catch (Exception& e)
973 {
974 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,"Exception: %s",
975 (const char*)e.getMessage().getCString()));
976 responseException = CIMException(CIM_ERR_FAILED, e.getMessage());
977 }
978 catch (PEGASUS_STD(exception)& e)
979 {
980 responseException = CIMException(CIM_ERR_FAILED, e.what());
981 }
982 catch (...)
983 {
984 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
985 "Exception: Unknown");
986 responseException = PEGASUS_CIM_EXCEPTION(
987 CIM_ERR_FAILED, "Unknown error.");
988 }
989 }
990
991 // delete the UnloadProviderRequest.
992 delete request;
993 sahana.prabhakar 1.93
994 PEG_METHOD_EXIT();
995 return responseException;
996 }
997
|
998 kumpf 1.26 PEGASUS_NAMESPACE_END
|
999 kumpf 1.74
1000 PEGASUS_USING_PEGASUS;
1001
1002 // This entry point is not needed because the DefaultProviderManager is created
1003 // using DefaultProviderManager::createDefaultProviderManagerCallback().
1004 #if 0
1005 extern "C" PEGASUS_EXPORT ProviderManager* PegasusCreateProviderManager(
1006 const String& providerManagerName)
1007 {
1008 if (String::equalNoCase(providerManagerName, "Default"))
1009 {
1010 return new DefaultProviderManager();
1011 }
1012
1013 return 0;
1014 }
1015 #endif
|