1 s.kodali 1.1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // 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 //
10 // 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 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 s.kodali 1.1 // 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 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "BasicProviderManagerRouter.h"
33
34 #include <Pegasus/Common/Config.h>
35 #include <Pegasus/Common/OperationContextInternal.h>
36 #include <Pegasus/Common/CIMMessage.h>
37 #include <Pegasus/Common/Tracer.h>
38 #include <Pegasus/Common/Logger.h>
39 #include <Pegasus/Common/FileSystem.h>
40 #include <Pegasus/Config/ConfigManager.h>
41 #include <Pegasus/ProviderManagerRouter/ProviderManagerModule.h>
42 #include <Pegasus/ProviderManager2/ProviderManager.h>
43 s.kodali 1.1
44
45 PEGASUS_NAMESPACE_BEGIN
46
47
48 class ProviderManagerContainer
49 {
50 public:
51
52 ProviderManagerContainer(
53 const String& physicalName,
54 const String& logicalName,
55 const String& interfaceName,
56 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
57 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
58 Boolean subscriptionInitComplete)
59 : _manager(0)
60 {
61 #if defined (PEGASUS_OS_VMS)
62 String provDir = ConfigManager::getInstance()->
63 getCurrentValue("providerDir");
64 s.kodali 1.1 _physicalName = ConfigManager::getHomedPath(provDir) + "/" +
65 FileSystem::buildLibraryFileName(physicalName);
66 #else
67 _physicalName = physicalName; // providerMgrPath comes with full path
68 //_physicalName = ConfigManager::getHomedPath(PEGASUS_DEST_LIB_DIR) +
69 // String("/") + FileSystem::buildLibraryFileName(physicalName);
70 #endif
71
72 _logicalName = logicalName;
73 _interfaceName = interfaceName;
74
75 _module.reset(new ProviderManagerModule(_physicalName));
76 Boolean moduleLoaded = _module->load();
77
78 if (moduleLoaded)
79 {
80 _manager = _module->getProviderManager(_logicalName);
81 }
82 else
83 {
84 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
85 s.kodali 1.1 "ProviderManagerModule load failed.");
86 }
87
88 if (_manager == 0)
89 {
90 MessageLoaderParms parms(
91 "ProviderManager.BasicProviderManagerRouter."
92 "PROVIDERMANAGER_LOAD_FAILED",
93 "Failed to load the Provider Manager for interface "
94 "type \"$0\" from library \"$1\".",
95 _interfaceName, _physicalName);
96 Logger::put_l(
97 Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
98 parms);
99 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms);
100 }
101
102 _manager->setIndicationCallback(indicationCallback);
103 _manager->setResponseChunkCallback(responseChunkCallback);
104
105 _manager->setSubscriptionInitComplete (subscriptionInitComplete);
106 s.kodali 1.1 }
107
108 ProviderManagerContainer(
109 const String& interfaceName,
110 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
111 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
112 Boolean subscriptionInitComplete,
113 ProviderManager* manager)
114 :
115 _interfaceName(interfaceName),
116 _manager(manager),
117 _module(0)
118 {
119 _manager->setIndicationCallback(indicationCallback);
120 _manager->setResponseChunkCallback(responseChunkCallback);
121 _manager->setSubscriptionInitComplete(subscriptionInitComplete);
122 }
123
124 ~ProviderManagerContainer()
125 {
126 delete _manager;
127 s.kodali 1.1
128 if (_module.get())
129 _module->unload();
130 }
131
132 ProviderManager* getProviderManager()
133 {
134 return _manager;
135 }
136
137 const String& getInterfaceName() const
138 {
139 return _interfaceName;
140 }
141
142
143 private:
144
145 ProviderManagerContainer();
146 ProviderManagerContainer& operator=(const ProviderManagerContainer&);
147 ProviderManagerContainer(const ProviderManagerContainer&);
148 s.kodali 1.1
149 String _physicalName;
150 String _logicalName;
151 String _interfaceName;
152 ProviderManager* _manager;
153 AutoPtr<ProviderManagerModule> _module;
154 };
155
156 PEGASUS_INDICATION_CALLBACK_T
157 BasicProviderManagerRouter::_indicationCallback = 0;
158
159 PEGASUS_RESPONSE_CHUNK_CALLBACK_T
160 BasicProviderManagerRouter::_responseChunkCallback = 0;
161
162 ProviderManager*
163 (*BasicProviderManagerRouter::_createDefaultProviderManagerCallback)() = 0;
164
165 BasicProviderManagerRouter::BasicProviderManagerRouter(
166 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
167 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
168 ProviderManager* (*createDefaultProviderManagerCallback)())
169 s.kodali 1.1 {
170 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
171 "BasicProviderManagerRouter::BasicProviderManagerRouter");
172
173 _indicationCallback = indicationCallback;
174 _responseChunkCallback = responseChunkCallback;
175 _subscriptionInitComplete = false;
176 _createDefaultProviderManagerCallback =
177 createDefaultProviderManagerCallback;
178
179 PEG_METHOD_EXIT();
180 }
181
182 BasicProviderManagerRouter::~BasicProviderManagerRouter()
183 {
184 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
185 "BasicProviderManagerRouter::~BasicProviderManagerRouter");
186 /* Clean up the provider managers */
187 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
188 {
189 ProviderManagerContainer* pmc=_providerManagerTable[i];
190 s.kodali 1.1 delete pmc;
191 }
192 PEG_METHOD_EXIT();
193 }
194
195 Message* BasicProviderManagerRouter::processMessage(Message * message)
196 {
197 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
198 "BasicProviderManagerRouter::processMessage");
199
200 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
201 PEGASUS_ASSERT(request != 0);
202
203 Message* response = 0;
204 Boolean remoteNameSpaceRequest=false;
205 Boolean loadProviderManager=true;
206
207 //
208 // Retrieve the ProviderManager routing information
209 //
210
211 s.kodali 1.1 CIMInstance providerModule;
212
213 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
214 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
215 {
216 // Provider information is in OperationContext
217 ProviderIdContainer pidc = (ProviderIdContainer)
218 request->operationContext.get(ProviderIdContainer::NAME);
219 providerModule = pidc.getModule();
220 remoteNameSpaceRequest=pidc.isRemoteNameSpace();
221 }
222 else if (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0)
223 {
224 // Provider information is in CIMIndicationRequestMessage
225 CIMIndicationRequestMessage* indReq =
226 dynamic_cast<CIMIndicationRequestMessage*>(request);
227 ProviderIdContainer pidc =
228 indReq->operationContext.get(ProviderIdContainer::NAME);
229 providerModule = pidc.getModule();
230 }
231 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
232 s.kodali 1.1 {
233 // Provider information is in CIMEnableModuleRequestMessage
234 CIMEnableModuleRequestMessage* emReq =
235 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
236 providerModule = emReq->providerModule;
237 // Do not try to load the provider manager module if not already loaded.
238 loadProviderManager=false;
239 }
240 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
241 {
242 // Provider information is in CIMDisableModuleRequestMessage
243 CIMDisableModuleRequestMessage* dmReq =
244 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
245 providerModule = dmReq->providerModule;
246 // Do not try to load the provider manager module if not already loaded.
247 loadProviderManager=false;
248 }
249 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
250 (request->getType() ==
251 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
252 (request->getType() ==
253 s.kodali 1.1 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE) ||
254 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
255 {
256 // This operation is not provider-specific
257 }
258 else
259 {
260 // Error: Unrecognized message type.
261 PEGASUS_ASSERT(0);
262 CIMResponseMessage* resp = request->buildResponse();
263 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
264 "Unknown message type.");
265 response = resp;
266 }
267
268 //
269 // Forward the request to the appropriate ProviderManager(s)
270 //
271
272 if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
273 (request->getType() ==
274 s.kodali 1.1 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
275 (request->getType() ==
276 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE))
277 {
278 if (request->getType() ==
279 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE)
280 {
281 _subscriptionInitComplete = false;
282 }
283 else
284 {
285 _subscriptionInitComplete = true;
286 }
287
288 // Send CIMStopAllProvidersRequestMessage or
289 // CIMIndicationServiceDisabledRequestMessage or
290 // CIMSubscriptionInitCompleteRequestMessage to all ProviderManagers
291 ReadLock tableLock(_providerManagerTableLock);
292 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
293 {
294 ProviderManagerContainer* pmc=_providerManagerTable[i];
295 s.kodali 1.1 Message* resp = pmc->getProviderManager()->processMessage(request);
296 delete resp;
297 }
298
299 response = request->buildResponse();
300 }
301 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
302 {
303 // Do not need to forward this request to in-process provider
304 // managers
305 response = request->buildResponse();
306 }
307 else
308 {
309 // Retrieve the provider interface type
310 String interfaceType;
311 CIMValue itValue = providerModule.getProperty(
312 providerModule.findProperty("InterfaceType")).getValue();
313 itValue.get(interfaceType);
314 // Get providerManager path
315 String provMgrPath;
316 s.kodali 1.1 if (request->operationContext.contains(ProviderIdContainer::NAME))
317 {
318 ProviderIdContainer pidc = (ProviderIdContainer)
319 request->operationContext.get(ProviderIdContainer::NAME);
320 provMgrPath = pidc.getProvMgrPath();
321 }
322
323 ProviderManager* pm = 0;
324 try
325 {
326 // Look up the appropriate ProviderManager by InterfaceType
327
328 pm = _getProviderManager(
329 interfaceType,
330 provMgrPath,
331 loadProviderManager);
332 }
333 catch (const CIMException& e)
334 {
335 CIMResponseMessage *cimResponse = request->buildResponse();
336 cimResponse->cimException = e;
337 s.kodali 1.1 response = cimResponse;
338 }
339
340 // Incase of CIMEnableModuleRequestMessage or
341 // CIMDisableModuleRequestMessage, there must be not necessarily
342 // a running provider manager. This is not an error.
343 // This means there is no provider to enable or disable.
344 if (0 == pm)
345 {
346 if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
347 {
348 CIMEnableModuleResponseMessage* emResponse =
349 dynamic_cast<CIMEnableModuleResponseMessage*>(
350 request->buildResponse());
351 emResponse->operationalStatus.append(
352 CIM_MSE_OPSTATUS_VALUE_OK);
353 response = emResponse;
354 }
355 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
356 {
357 CIMDisableModuleResponseMessage* dmResponse =
358 s.kodali 1.1 dynamic_cast<CIMDisableModuleResponseMessage*>(
359 request->buildResponse());
360 dmResponse->operationalStatus.append(
361 CIM_MSE_OPSTATUS_VALUE_STOPPED);
362 response = dmResponse;
363 }
364 else
365 {
366 CIMResponseMessage* resp = request->buildResponse();
367 resp->cimException =
368 PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
369 "There is no Provider Manager for interfaceType '" +
370 interfaceType + ". The request message type is '" +
371 String(MessageTypeToString(request->getType())) + "'");
372
373 PEG_TRACE((TRC_PROVIDERMANAGER,Tracer::LEVEL1,"%s",
374 (const char*)resp->cimException.getMessage().getCString()));
375
376 response = resp;
377 }
378 }
379 s.kodali 1.1 else
380 {
381 if ( remoteNameSpaceRequest && !pm->supportsRemoteNameSpaces())
382 {
383 CIMResponseMessage* resp = request->buildResponse();
384 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
385 "Remote Namespace operations not supported for interface type "
386 + interfaceType);
387 response = resp;
388 }
389 else
390 {
391 response = pm->processMessage(request);
392 }
393 }
394 }
395
396 PEG_METHOD_EXIT();
397 return response;
398 }
399
400 s.kodali 1.1 // ATTN: May need to add interfaceVersion parameter to further constrain lookup
401 ProviderManager* BasicProviderManagerRouter::_getProviderManager(
402 const String& interfaceType,
403 const String& providerManagerPath,
404 Boolean loadProviderManager)
405 {
406 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
407 "BasicProviderManagerRouter::_getProviderManager");
408
409 //
410 // Search for this InterfaceType in the table of loaded ProviderManagers
411 //
412 {
413 ReadLock tableLock(_providerManagerTableLock);
414
415 ProviderManager* pm = _lookupProviderManager(interfaceType);
416 if (pm)
417 {
418 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
419 "Provider Manager for interfaceType '%s' already loaded.",
420 (const char*)interfaceType.getCString()));
421 s.kodali 1.1 PEG_METHOD_EXIT();
422 return pm;
423 }
424 }
425
426 //
427 // If requested, do not load the ProviderManger.
428 //
429 if (!loadProviderManager)
430 {
431 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
432 "Requested not to load the Provider Manager "
433 "for interfaceType '%s'.",
434 (const char*)interfaceType.getCString()));
435 PEG_METHOD_EXIT();
436 return 0;
437 }
438
439 //
440 // Load the ProviderManager for this InterfaceType and add it to the table
441 //
442 s.kodali 1.1 {
443 WriteLock tableLock(_providerManagerTableLock);
444
445 ProviderManager* pm = _lookupProviderManager(interfaceType);
446 if (pm)
447 {
448 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
449 "Provider Manager for interfaceType '%s' already loaded.",
450 (const char*)interfaceType.getCString()));
451 PEG_METHOD_EXIT();
452 return pm;
453 }
454
455 // The DefaultProviderManager is now statically linked rather than
456 // dynamically loaded. This code is no longer used but remains for
457 // reference purposes.
458
459 #if defined(PEGASUS_ENABLE_DEFAULT_PROVIDER_MANAGER)
460 if (interfaceType == "C++Default" &&
461 _createDefaultProviderManagerCallback)
462 {
463 s.kodali 1.1 pm = (*_createDefaultProviderManagerCallback)();
464 ProviderManagerContainer* pmc = new ProviderManagerContainer(
465 "C++Default",
466 _indicationCallback,
467 _responseChunkCallback,
468 _subscriptionInitComplete,
469 pm);
470 _providerManagerTable.append(pmc);
471 PEG_METHOD_EXIT();
472 return pmc->getProviderManager();
473 }
474 #endif
475
476 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
477 "Crating new Provider Manager for interfaceType '%s', "
478 "providerManagerPath '%s'.",
479 (const char*)interfaceType.getCString(),
480 (const char*)providerManagerPath.getCString()));
481
482 ProviderManagerContainer* pmc = new ProviderManagerContainer(
483 providerManagerPath,
484 s.kodali 1.1 interfaceType,
485 interfaceType,
486 _indicationCallback,
487 _responseChunkCallback,
488 _subscriptionInitComplete);
489 _providerManagerTable.append(pmc);
490 PEG_METHOD_EXIT();
491 return pmc->getProviderManager();
492 }
493
494 }
495
496 // NOTE: The caller must lock _providerManagerTableLock before calling this
497 // method.
498 ProviderManager* BasicProviderManagerRouter::_lookupProviderManager(
499 const String& interfaceType)
500 {
501 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
502 "BasicProviderManagerRouter::_lookupProviderManager");
503
504 //
505 s.kodali 1.1 // Search for this InterfaceType in the table of loaded ProviderManagers
506 //
507 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
508 {
509 if (interfaceType == _providerManagerTable[i]->getInterfaceName())
510 {
511 ProviderManagerContainer* pmc = _providerManagerTable[i];
512 PEG_METHOD_EXIT();
513 return pmc->getProviderManager();
514 }
515 }
516
517 // Not found
518 PEG_METHOD_EXIT();
519 return 0;
520 }
521
522 Boolean BasicProviderManagerRouter::hasActiveProviders()
523 {
524 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
525 "BasicProviderManagerRouter::hasActiveProviders");
526 s.kodali 1.1
527 ReadLock tableLock(_providerManagerTableLock);
528 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
529 {
530 ProviderManagerContainer* pmc = _providerManagerTable[i];
531 if (pmc->getProviderManager()->hasActiveProviders())
532 {
533 PEG_METHOD_EXIT();
534 return true;
535 }
536 }
537
538 PEG_METHOD_EXIT();
539 return false;
540 }
541
542 void BasicProviderManagerRouter::idleTimeCleanup()
543 {
544 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
545 "BasicProviderManagerRouter::idleTimeCleanup");
546
547 s.kodali 1.1 //
548 // Save pointers to the ProviderManagerContainers so we don't hold the
549 // _providerManagerTableLock while unloading idle providers
550 //
551 Array<ProviderManagerContainer*> pmcs;
552 {
553 ReadLock tableLock(_providerManagerTableLock);
554 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
555 {
556 pmcs.append(_providerManagerTable[i]);
557 }
558 }
559
560 //
561 // Unload idle providers in each of the active ProviderManagers
562 // _providerManagerTableLock while unloading idle providers
563 //
564 for (Uint32 i = 0; i < pmcs.size(); i++)
565 {
566 pmcs[i]->getProviderManager()->unloadIdleProviders();
567 }
568 s.kodali 1.1
569 PEG_METHOD_EXIT();
570 }
571
572 PEGASUS_NAMESPACE_END
|