1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "BasicProviderManagerRouter.h"
35
36 #include <Pegasus/Common/Config.h>
37 #include <Pegasus/Common/OperationContextInternal.h>
38 #include <Pegasus/Common/CIMMessage.h>
39 #include <Pegasus/Common/Tracer.h>
40 #include <Pegasus/Common/Logger.h>
41 #include <Pegasus/Common/FileSystem.h>
42 #include <Pegasus/Config/ConfigManager.h>
43 kumpf 1.1 #include <Pegasus/ProviderManagerService/ProviderManagerModule.h>
44 #include <Pegasus/ProviderManager2/ProviderManager.h>
45
46 // ProviderManager library names. Should these be defined elsewhere?
47 #if defined(PEGASUS_OS_OS400)
48 # define LIBRARY_NAME_DEFAULTPM "QSYS/QYCMPMDE00"
49 # define LIBRARY_NAME_CMPIPM "QSYS/QYCMCMPIPM"
50 # define LIBRARY_NAME_JMPIPM "QSYS/QYCMJMPIPM"
51 #else
52 # define LIBRARY_NAME_CMPIPM "CMPIProviderManager"
53 # define LIBRARY_NAME_JMPIPM "JMPIProviderManager"
54 #endif
55
56 PEGASUS_NAMESPACE_BEGIN
57
58 class ProviderManagerContainer
59 {
60 public:
61
62 ProviderManagerContainer(
63 const String& physicalName,
64 kumpf 1.1 const String& logicalName,
65 const String& interfaceName,
66 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
67 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
68 Boolean subscriptionInitComplete)
69 : _manager(0)
70 {
71 #if defined (PEGASUS_OS_VMS)
|
72 kumpf 1.3 _physicalName =
73 ConfigManager::getInstance()->getCurrentValue("providerDir") +
74 String("/") + FileSystem::buildLibraryFileName(physicalName) +
75 String(".exe");
|
76 kumpf 1.1 #elif defined (PEGASUS_OS_OS400)
77 _physicalName = physicalName;
78 #else
79 _physicalName = ConfigManager::getHomedPath(PEGASUS_DEST_LIB_DIR) +
80 String("/") + FileSystem::buildLibraryFileName(physicalName);
81 #endif
82
83 _logicalName = logicalName;
84 _interfaceName = interfaceName;
85
86 _module.reset(new ProviderManagerModule(_physicalName));
87 Boolean moduleLoaded = _module->load();
88
89 if (moduleLoaded)
90 {
91 _manager = _module->getProviderManager(_logicalName);
92 }
93 else
94 {
95 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
96 "ProviderManagerModule load failed.");
97 kumpf 1.1 }
98
99 if (_manager == 0)
100 {
101 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
102 "Failed to load ProviderManager \"" + _physicalName + "\".");
103
104 Logger::put_l(
105 Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
106 "ProviderManager.BasicProviderManagerRouter."
107 "PROVIDERMANAGER_LOAD_FAILED",
108 "Failed to load the Provider Manager for interface type \"$0\""
109 " from library \"$1\".",
110 _interfaceName, _physicalName);
111
112 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms(
113 "ProviderManager.BasicProviderManagerRouter."
114 "PROVIDERMANAGER_LOAD_FAILED",
115 "Failed to load the Provider Manager for interface type \"$0\""
116 " from library \"$1\".",
117 _interfaceName, _physicalName));
118 kumpf 1.1 }
119
120 _manager->setIndicationCallback(indicationCallback);
121 _manager->setResponseChunkCallback(responseChunkCallback);
122
123 _manager->setSubscriptionInitComplete (subscriptionInitComplete);
124 }
125
126 ProviderManagerContainer(
127 const String& interfaceName,
128 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
129 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
130 Boolean subscriptionInitComplete,
|
131 kumpf 1.3 ProviderManager* manager)
132 :
133 _interfaceName(interfaceName),
134 _manager(manager),
135 _module(0)
|
136 kumpf 1.1 {
137 _manager->setIndicationCallback(indicationCallback);
138 _manager->setResponseChunkCallback(responseChunkCallback);
139 _manager->setSubscriptionInitComplete(subscriptionInitComplete);
140 }
141
142 ~ProviderManagerContainer()
143 {
144 delete _manager;
145
|
146 kumpf 1.3 if (_module.get())
147 _module->unload();
|
148 kumpf 1.1 }
149
150 ProviderManager* getProviderManager()
151 {
152 return _manager;
153 }
154
155 const String& getInterfaceName() const
156 {
157 return _interfaceName;
158 }
159
160
161 private:
162
163 ProviderManagerContainer();
164 ProviderManagerContainer& operator=(const ProviderManagerContainer&);
165 ProviderManagerContainer(const ProviderManagerContainer&);
166
167 String _physicalName;
168 String _logicalName;
169 kumpf 1.1 String _interfaceName;
170 ProviderManager* _manager;
171 AutoPtr<ProviderManagerModule> _module;
172 };
173
174 PEGASUS_INDICATION_CALLBACK_T
175 BasicProviderManagerRouter::_indicationCallback = 0;
176
177 PEGASUS_RESPONSE_CHUNK_CALLBACK_T
178 BasicProviderManagerRouter::_responseChunkCallback = 0;
179
|
180 kumpf 1.3 ProviderManager*
|
181 kumpf 1.1 (*BasicProviderManagerRouter::_createDefaultProviderManagerCallback)() = 0;
182
183 BasicProviderManagerRouter::BasicProviderManagerRouter(
184 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
185 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
186 ProviderManager* (*createDefaultProviderManagerCallback)())
187 {
188 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
189 "BasicProviderManagerRouter::BasicProviderManagerRouter");
190
191 _indicationCallback = indicationCallback;
192 _responseChunkCallback = responseChunkCallback;
193 _subscriptionInitComplete = false;
|
194 kumpf 1.3 _createDefaultProviderManagerCallback =
195 createDefaultProviderManagerCallback;
|
196 kumpf 1.1
197 PEG_METHOD_EXIT();
198 }
199
200 BasicProviderManagerRouter::~BasicProviderManagerRouter()
201 {
202 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
203 "BasicProviderManagerRouter::~BasicProviderManagerRouter");
204 /* Clean up the provider managers */
205 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
206 {
207 ProviderManagerContainer* pmc=_providerManagerTable[i];
208 delete pmc;
209 }
210 PEG_METHOD_EXIT();
211 }
212
213 Message* BasicProviderManagerRouter::processMessage(Message * message)
214 {
215 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
216 "BasicProviderManagerRouter::processMessage");
217 kumpf 1.1
218 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
219 PEGASUS_ASSERT(request != 0);
220
221 Message* response = 0;
222 Boolean remoteNameSpaceRequest=false;
223
224 //
225 // Retrieve the ProviderManager routing information
226 //
227
228 CIMInstance providerModule;
229
230 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
231 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE) ||
232 (request->getType() == CIM_INITIALIZE_PROVIDER_REQUEST_MESSAGE))
233 {
234 // Provider information is in OperationContext
235 ProviderIdContainer pidc = (ProviderIdContainer)
236 request->operationContext.get(ProviderIdContainer::NAME);
237 providerModule = pidc.getModule();
238 kumpf 1.1 remoteNameSpaceRequest=pidc.isRemoteNameSpace();
239 }
240 else if (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0)
241 {
242 // Provider information is in CIMIndicationRequestMessage
243 CIMIndicationRequestMessage* indReq =
244 dynamic_cast<CIMIndicationRequestMessage*>(request);
|
245 kumpf 1.3 ProviderIdContainer pidc =
246 indReq->operationContext.get(ProviderIdContainer::NAME);
|
247 kumpf 1.1 providerModule = pidc.getModule();
248 }
249 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
250 {
251 // Provider information is in CIMEnableModuleRequestMessage
252 CIMEnableModuleRequestMessage* emReq =
253 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
254 providerModule = emReq->providerModule;
255 }
256 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
257 {
258 // Provider information is in CIMDisableModuleRequestMessage
259 CIMDisableModuleRequestMessage* dmReq =
260 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
261 providerModule = dmReq->providerModule;
262 }
263 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
264 (request->getType() ==
265 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
266 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
267 {
268 kumpf 1.1 // This operation is not provider-specific
269 }
270 else
271 {
272 // Error: Unrecognized message type.
273 PEGASUS_ASSERT(0);
274 CIMResponseMessage* resp = request->buildResponse();
275 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
276 "Unknown message type.");
277 response = resp;
278 }
279
280 //
281 // Forward the request to the appropriate ProviderManager(s)
282 //
283
284 if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
285 (request->getType() ==
286 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE))
287 {
288 _subscriptionInitComplete = true;
289 kumpf 1.1
290 // Send CIMStopAllProvidersRequestMessage or
291 // CIMSubscriptionInitCompleteRequestMessage to all ProviderManagers
292 ReadLock tableLock(_providerManagerTableLock);
293 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
294 {
295 ProviderManagerContainer* pmc=_providerManagerTable[i];
296 Message* resp = pmc->getProviderManager()->processMessage(request);
297 delete resp;
298 }
299
300 response = request->buildResponse();
301 }
|
302 kumpf 1.3 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
|
303 kumpf 1.1 {
304 // Do not need to forward this request to in-process provider
305 // managers
306 response = request->buildResponse();
307 }
308 else
309 {
310 // Retrieve the provider interface type
311 String interfaceType;
312 CIMValue itValue = providerModule.getProperty(
313 providerModule.findProperty("InterfaceType")).getValue();
314 itValue.get(interfaceType);
315
316 ProviderManager* pm = 0;
317 Boolean gotError = false;
318 try
319 {
320 // Look up the appropriate ProviderManager by InterfaceType
|
321 kumpf 1.2 pm = _getProviderManager(interfaceType);
|
322 kumpf 1.1 }
323 catch (const CIMException& e)
324 {
325 CIMResponseMessage* cimResponse = request->buildResponse();
326 cimResponse->cimException = e;
327 response = cimResponse;
328 gotError = true;
329 }
330
331 if (remoteNameSpaceRequest && !pm->supportsRemoteNameSpaces())
332 {
333 CIMResponseMessage* resp = request->buildResponse();
334 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
335 "Remote Namespace operations not supported for interface type "
336 + interfaceType);
337 response = resp;
338 gotError = true;
339 }
340
341 if (!gotError)
342 {
343 kumpf 1.1 response = pm->processMessage(request);
344 }
345 }
346
347 // preserve message key
348 // set HTTP method in response from request
349 // set closeConnect
350 ((CIMResponseMessage *)response)->syncAttributes(request);
351
352 PEG_METHOD_EXIT();
353 return response;
354 }
355
356 // ATTN: May need to add interfaceVersion parameter to further constrain lookup
|
357 kumpf 1.2 ProviderManager* BasicProviderManagerRouter::_getProviderManager(
|
358 kumpf 1.1 const String& interfaceType)
359 {
360 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
|
361 kumpf 1.2 "BasicProviderManagerRouter::_getProviderManager");
|
362 kumpf 1.1
363 //
364 // Search for this InterfaceType in the table of loaded ProviderManagers
365 //
366 {
367 ReadLock tableLock(_providerManagerTableLock);
368
|
369 kumpf 1.2 ProviderManager* pm = _lookupProviderManager(interfaceType);
370 if (pm)
|
371 kumpf 1.1 {
|
372 kumpf 1.2 PEG_METHOD_EXIT();
373 return pm;
|
374 kumpf 1.1 }
375 }
376
377 //
378 // Load the ProviderManager for this InterfaceType and add it to the table
379 //
380 {
381 WriteLock tableLock(_providerManagerTableLock);
382
|
383 kumpf 1.2 ProviderManager* pm = _lookupProviderManager(interfaceType);
384 if (pm)
385 {
386 PEG_METHOD_EXIT();
387 return pm;
388 }
389
|
390 kumpf 1.1 // ATTN: this section is a temporary solution to populate the list of
391 // enabled provider managers for a given distribution. It includes
392 // another temporary solution for converting a generic file name into
393 // a file name useable by each platform.
394
|
395 kumpf 1.3 // The DefaultProviderManager is now statically linked rather than
396 // dynamically loaded. This code is no longer used but remains for
397 // reference purposes.
|
398 kumpf 1.1
399 #if defined(PEGASUS_ENABLE_DEFAULT_PROVIDER_MANAGER)
|
400 kumpf 1.3 if (interfaceType == "C++Default" &&
401 _createDefaultProviderManagerCallback)
|
402 kumpf 1.1 {
|
403 kumpf 1.3 pm = (*_createDefaultProviderManagerCallback)();
|
404 kumpf 1.1 ProviderManagerContainer* pmc = new ProviderManagerContainer(
405 "C++Default",
406 _indicationCallback,
407 _responseChunkCallback,
408 _subscriptionInitComplete,
|
409 kumpf 1.3 pm);
|
410 kumpf 1.1 _providerManagerTable.append(pmc);
411 return pmc->getProviderManager();
412 }
413 #endif
414
415 #if defined(PEGASUS_ENABLE_CMPI_PROVIDER_MANAGER)
416 if (interfaceType == "CMPI")
417 {
418 ProviderManagerContainer* pmc = new ProviderManagerContainer(
419 LIBRARY_NAME_CMPIPM,
420 "CMPI",
421 "CMPI",
422 _indicationCallback,
423 _responseChunkCallback,
424 _subscriptionInitComplete);
425 _providerManagerTable.append(pmc);
426 return pmc->getProviderManager();
427 }
428 #endif
429
430 #if defined(PEGASUS_ENABLE_JMPI_PROVIDER_MANAGER)
431 kumpf 1.1 if ( interfaceType == "JMPI"
432 || interfaceType == "JMPIExperimental"
433 )
434 {
435 ProviderManagerContainer* pmc = new ProviderManagerContainer(
436 LIBRARY_NAME_JMPIPM,
437 interfaceType,
438 interfaceType,
439 _indicationCallback,
440 _responseChunkCallback,
441 _subscriptionInitComplete);
442 _providerManagerTable.append(pmc);
443 return pmc->getProviderManager();
444 }
445 #endif
446 // END TEMP SECTION
447 }
448
449 // Error: ProviderManager not found for the specified interface type
450 PEGASUS_ASSERT(0);
451 PEG_METHOD_EXIT();
452 kumpf 1.1 return 0;
453 }
454
|
455 kumpf 1.2 // NOTE: The caller must lock _providerManagerTableLock before calling this
456 // method.
457 ProviderManager* BasicProviderManagerRouter::_lookupProviderManager(
458 const String& interfaceType)
459 {
460 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
461 "BasicProviderManagerRouter::_lookupProviderManager");
462
463 //
464 // Search for this InterfaceType in the table of loaded ProviderManagers
465 //
466 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
467 {
468 if (interfaceType == _providerManagerTable[i]->getInterfaceName())
469 {
470 ProviderManagerContainer* pmc = _providerManagerTable[i];
471 PEG_METHOD_EXIT();
472 return pmc->getProviderManager();
473 }
474 }
475
476 kumpf 1.2 // Not found
477 PEG_METHOD_EXIT();
478 return 0;
479 }
480
|
481 kumpf 1.1 Boolean BasicProviderManagerRouter::hasActiveProviders()
482 {
483 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
484 "BasicProviderManagerRouter::hasActiveProviders");
485
486 ReadLock tableLock(_providerManagerTableLock);
|
487 kumpf 1.3 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
|
488 kumpf 1.1 {
489 ProviderManagerContainer* pmc = _providerManagerTable[i];
490 if (pmc->getProviderManager()->hasActiveProviders())
491 {
492 PEG_METHOD_EXIT();
493 return true;
494 }
495 }
496
497 PEG_METHOD_EXIT();
498 return false;
499 }
500
501 void BasicProviderManagerRouter::unloadIdleProviders()
502 {
503 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
504 "BasicProviderManagerRouter::unloadIdleProviders");
505
506 //
507 // Save pointers to the ProviderManagerContainers so we don't hold the
508 // _providerManagerTableLock while unloading idle providers
509 kumpf 1.1 //
510 Array<ProviderManagerContainer*> pmcs;
511 {
512 ReadLock tableLock(_providerManagerTableLock);
|
513 kumpf 1.3 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
|
514 kumpf 1.1 {
515 pmcs.append(_providerManagerTable[i]);
516 }
517 }
518
519 //
520 // Unload idle providers in each of the active ProviderManagers
521 // _providerManagerTableLock while unloading idle providers
522 //
523 for (Uint32 i = 0; i < pmcs.size(); i++)
524 {
525 pmcs[i]->getProviderManager()->unloadIdleProviders();
526 }
527
528 PEG_METHOD_EXIT();
529 }
530
531 PEGASUS_NAMESPACE_END
|