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 _physicalName = ConfigManager::getInstance()->getCurrentValue("providerDir") +
73 String("/") + FileSystem::buildLibraryFileName(physicalName) + String(".exe");
74 #elif defined (PEGASUS_OS_OS400)
75 _physicalName = physicalName;
76 #else
77 _physicalName = ConfigManager::getHomedPath(PEGASUS_DEST_LIB_DIR) +
78 String("/") + FileSystem::buildLibraryFileName(physicalName);
79 #endif
80
81 _logicalName = logicalName;
82 _interfaceName = interfaceName;
83
84 _module.reset(new ProviderManagerModule(_physicalName));
85 kumpf 1.1 Boolean moduleLoaded = _module->load();
86
87 if (moduleLoaded)
88 {
89 _manager = _module->getProviderManager(_logicalName);
90 }
91 else
92 {
93 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
94 "ProviderManagerModule load failed.");
95 }
96
97 if (_manager == 0)
98 {
99 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
100 "Failed to load ProviderManager \"" + _physicalName + "\".");
101
102 Logger::put_l(
103 Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
104 "ProviderManager.BasicProviderManagerRouter."
105 "PROVIDERMANAGER_LOAD_FAILED",
106 kumpf 1.1 "Failed to load the Provider Manager for interface type \"$0\""
107 " from library \"$1\".",
108 _interfaceName, _physicalName);
109
110 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms(
111 "ProviderManager.BasicProviderManagerRouter."
112 "PROVIDERMANAGER_LOAD_FAILED",
113 "Failed to load the Provider Manager for interface type \"$0\""
114 " from library \"$1\".",
115 _interfaceName, _physicalName));
116 }
117
118 _manager->setIndicationCallback(indicationCallback);
119 _manager->setResponseChunkCallback(responseChunkCallback);
120
121 _manager->setSubscriptionInitComplete (subscriptionInitComplete);
122 }
123
124 ProviderManagerContainer(
125 const String& interfaceName,
126 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
127 kumpf 1.1 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
128 Boolean subscriptionInitComplete,
129 ProviderManager* manager)
130 :
131 _interfaceName(interfaceName),
132 _manager(manager),
133 _module(0)
134 {
135 _manager->setIndicationCallback(indicationCallback);
136 _manager->setResponseChunkCallback(responseChunkCallback);
137 _manager->setSubscriptionInitComplete(subscriptionInitComplete);
138 }
139
140 ~ProviderManagerContainer()
141 {
142 delete _manager;
143
144 if (_module.get())
145 _module->unload();
146 }
147
148 kumpf 1.1 ProviderManager* getProviderManager()
149 {
150 return _manager;
151 }
152
153 const String& getInterfaceName() const
154 {
155 return _interfaceName;
156 }
157
158
159 private:
160
161 ProviderManagerContainer();
162 ProviderManagerContainer& operator=(const ProviderManagerContainer&);
163 ProviderManagerContainer(const ProviderManagerContainer&);
164
165 String _physicalName;
166 String _logicalName;
167 String _interfaceName;
168 ProviderManager* _manager;
169 kumpf 1.1 AutoPtr<ProviderManagerModule> _module;
170 };
171
172 PEGASUS_INDICATION_CALLBACK_T
173 BasicProviderManagerRouter::_indicationCallback = 0;
174
175 PEGASUS_RESPONSE_CHUNK_CALLBACK_T
176 BasicProviderManagerRouter::_responseChunkCallback = 0;
177
178 ProviderManager*
179 (*BasicProviderManagerRouter::_createDefaultProviderManagerCallback)() = 0;
180
181 BasicProviderManagerRouter::BasicProviderManagerRouter(
182 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
183 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
184 ProviderManager* (*createDefaultProviderManagerCallback)())
185 {
186 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
187 "BasicProviderManagerRouter::BasicProviderManagerRouter");
188
189 _indicationCallback = indicationCallback;
190 kumpf 1.1 _responseChunkCallback = responseChunkCallback;
191 _subscriptionInitComplete = false;
192 _createDefaultProviderManagerCallback =
193 createDefaultProviderManagerCallback;
194
195 PEG_METHOD_EXIT();
196 }
197
198 BasicProviderManagerRouter::~BasicProviderManagerRouter()
199 {
200 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
201 "BasicProviderManagerRouter::~BasicProviderManagerRouter");
202 /* Clean up the provider managers */
203 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
204 {
205 ProviderManagerContainer* pmc=_providerManagerTable[i];
206 delete pmc;
207 }
208 PEG_METHOD_EXIT();
209 }
210
211 kumpf 1.1 Message* BasicProviderManagerRouter::processMessage(Message * message)
212 {
213 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
214 "BasicProviderManagerRouter::processMessage");
215
216 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
217 PEGASUS_ASSERT(request != 0);
218
219 Message* response = 0;
220 Boolean remoteNameSpaceRequest=false;
221
222 //
223 // Retrieve the ProviderManager routing information
224 //
225
226 CIMInstance providerModule;
227
228 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
229 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE) ||
230 (request->getType() == CIM_INITIALIZE_PROVIDER_REQUEST_MESSAGE))
231 {
232 kumpf 1.1 // Provider information is in OperationContext
233 ProviderIdContainer pidc = (ProviderIdContainer)
234 request->operationContext.get(ProviderIdContainer::NAME);
235 providerModule = pidc.getModule();
236 remoteNameSpaceRequest=pidc.isRemoteNameSpace();
237 }
238 else if (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0)
239 {
240 // Provider information is in CIMIndicationRequestMessage
241 CIMIndicationRequestMessage* indReq =
242 dynamic_cast<CIMIndicationRequestMessage*>(request);
243 ProviderIdContainer pidc = indReq->operationContext.get(ProviderIdContainer::NAME);
244 providerModule = pidc.getModule();
245 }
246 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
247 {
248 // Provider information is in CIMEnableModuleRequestMessage
249 CIMEnableModuleRequestMessage* emReq =
250 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
251 providerModule = emReq->providerModule;
252 }
253 kumpf 1.1 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
254 {
255 // Provider information is in CIMDisableModuleRequestMessage
256 CIMDisableModuleRequestMessage* dmReq =
257 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
258 providerModule = dmReq->providerModule;
259 }
260 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
261 (request->getType() ==
262 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
263 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
264 {
265 // This operation is not provider-specific
266 }
267 else
268 {
269 // Error: Unrecognized message type.
270 PEGASUS_ASSERT(0);
271 CIMResponseMessage* resp = request->buildResponse();
272 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
273 "Unknown message type.");
274 kumpf 1.1 response = resp;
275 }
276
277 //
278 // Forward the request to the appropriate ProviderManager(s)
279 //
280
281 if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
282 (request->getType() ==
283 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE))
284 {
285 _subscriptionInitComplete = true;
286
287 // Send CIMStopAllProvidersRequestMessage or
288 // CIMSubscriptionInitCompleteRequestMessage to all ProviderManagers
289 ReadLock tableLock(_providerManagerTableLock);
290 for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
291 {
292 ProviderManagerContainer* pmc=_providerManagerTable[i];
293 Message* resp = pmc->getProviderManager()->processMessage(request);
294 delete resp;
295 kumpf 1.1 }
296
297 response = request->buildResponse();
298 }
299 else if(request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
300 {
301 // Do not need to forward this request to in-process provider
302 // managers
303 response = request->buildResponse();
304 }
305 else
306 {
307 // Retrieve the provider interface type
308 String interfaceType;
309 CIMValue itValue = providerModule.getProperty(
310 providerModule.findProperty("InterfaceType")).getValue();
311 itValue.get(interfaceType);
312
313 ProviderManager* pm = 0;
314 Boolean gotError = false;
315 try
316 kumpf 1.1 {
317 // Look up the appropriate ProviderManager by InterfaceType
318 pm = _lookupProviderManager(interfaceType);
319 }
320 catch (const CIMException& e)
321 {
322 CIMResponseMessage* cimResponse = request->buildResponse();
323 cimResponse->cimException = e;
324 response = cimResponse;
325 gotError = true;
326 }
327
328 if (remoteNameSpaceRequest && !pm->supportsRemoteNameSpaces())
329 {
330 CIMResponseMessage* resp = request->buildResponse();
331 resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
332 "Remote Namespace operations not supported for interface type "
333 + interfaceType);
334 response = resp;
335 gotError = true;
336 }
337 kumpf 1.1
338 if (!gotError)
339 {
340 response = pm->processMessage(request);
341 }
342 }
343
344 // preserve message key
345 // set HTTP method in response from request
346 // set closeConnect
347 ((CIMResponseMessage *)response)->syncAttributes(request);
348
349 PEG_METHOD_EXIT();
350 return response;
351 }
352
353 // ATTN: May need to add interfaceVersion parameter to further constrain lookup
354 ProviderManager* BasicProviderManagerRouter::_lookupProviderManager(
355 const String& interfaceType)
356 {
357 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
358 kumpf 1.1 "BasicProviderManagerRouter::_lookupProviderManager");
359
360 //
361 // Search for this InterfaceType in the table of loaded ProviderManagers
362 //
363 {
364 ReadLock tableLock(_providerManagerTableLock);
365
366 // find provider manager for specified provider interface type
367 for(Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
368 {
369 if (interfaceType == _providerManagerTable[i]->getInterfaceName())
370 {
371 ProviderManagerContainer* pmc=_providerManagerTable[i];
372 PEG_METHOD_EXIT();
373 return pmc->getProviderManager();
374 }
375 }
376 }
377
378 //
379 kumpf 1.1 // Load the ProviderManager for this InterfaceType and add it to the table
380 //
381 {
382 WriteLock tableLock(_providerManagerTableLock);
383
384 // ATTN: this section is a temporary solution to populate the list of
385 // enabled provider managers for a given distribution. It includes
386 // another temporary solution for converting a generic file name into
387 // a file name useable by each platform.
388
389 // The DefaultProviderManager is now statically linked rather than
390 // dynamically loaded. This code is no longer used but remains for
391 // reference purposes.
392
393 #if defined(PEGASUS_ENABLE_DEFAULT_PROVIDER_MANAGER)
394 if (interfaceType == "C++Default" &&
395 _createDefaultProviderManagerCallback)
396 {
397 ProviderManager* pm = (*_createDefaultProviderManagerCallback)();
398 ProviderManagerContainer* pmc = new ProviderManagerContainer(
399 "C++Default",
400 kumpf 1.1 _indicationCallback,
401 _responseChunkCallback,
402 _subscriptionInitComplete,
403 pm);
404 _providerManagerTable.append(pmc);
405 return pmc->getProviderManager();
406 }
407 #endif
408
409 #if defined(PEGASUS_ENABLE_CMPI_PROVIDER_MANAGER)
410 if (interfaceType == "CMPI")
411 {
412 ProviderManagerContainer* pmc = new ProviderManagerContainer(
413 LIBRARY_NAME_CMPIPM,
414 "CMPI",
415 "CMPI",
416 _indicationCallback,
417 _responseChunkCallback,
418 _subscriptionInitComplete);
419 _providerManagerTable.append(pmc);
420 return pmc->getProviderManager();
421 kumpf 1.1 }
422 #endif
423
424 #if defined(PEGASUS_ENABLE_JMPI_PROVIDER_MANAGER)
425 if ( interfaceType == "JMPI"
426 || interfaceType == "JMPIExperimental"
427 )
428 {
429 ProviderManagerContainer* pmc = new ProviderManagerContainer(
430 LIBRARY_NAME_JMPIPM,
431 interfaceType,
432 interfaceType,
433 _indicationCallback,
434 _responseChunkCallback,
435 _subscriptionInitComplete);
436 _providerManagerTable.append(pmc);
437 return pmc->getProviderManager();
438 }
439 #endif
440 // END TEMP SECTION
441 }
442 kumpf 1.1
443 // Error: ProviderManager not found for the specified interface type
444 PEGASUS_ASSERT(0);
445 PEG_METHOD_EXIT();
446 return 0;
447 }
448
449 Boolean BasicProviderManagerRouter::hasActiveProviders()
450 {
451 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
452 "BasicProviderManagerRouter::hasActiveProviders");
453
454 ReadLock tableLock(_providerManagerTableLock);
455 for(Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
456 {
457 ProviderManagerContainer* pmc = _providerManagerTable[i];
458 if (pmc->getProviderManager()->hasActiveProviders())
459 {
460 PEG_METHOD_EXIT();
461 return true;
462 }
463 kumpf 1.1 }
464
465 PEG_METHOD_EXIT();
466 return false;
467 }
468
469 void BasicProviderManagerRouter::unloadIdleProviders()
470 {
471 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
472 "BasicProviderManagerRouter::unloadIdleProviders");
473
474 //
475 // Save pointers to the ProviderManagerContainers so we don't hold the
476 // _providerManagerTableLock while unloading idle providers
477 //
478 Array<ProviderManagerContainer*> pmcs;
479 {
480 ReadLock tableLock(_providerManagerTableLock);
481 for(Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
482 {
483 pmcs.append(_providerManagerTable[i]);
484 kumpf 1.1 }
485 }
486
487 //
488 // Unload idle providers in each of the active ProviderManagers
489 // _providerManagerTableLock while unloading idle providers
490 //
491 for (Uint32 i = 0; i < pmcs.size(); i++)
492 {
493 pmcs[i]->getProviderManager()->unloadIdleProviders();
494 }
495
496 PEG_METHOD_EXIT();
497 }
498
499 PEGASUS_NAMESPACE_END
|