1 karl 1.5 //%2004////////////////////////////////////////////////////////////////////////
|
2 kumpf 1.1 //
|
3 karl 1.5 // 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 kumpf 1.1 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.5 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 kumpf 1.1 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to
12 // deal in the Software without restriction, including without limitation the
13 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14 // sell copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
|
16 karl 1.5 //
|
17 kumpf 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
18 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
19 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26 //==============================================================================
27 //
28 // Author: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
29 // Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
30 //
31 // Modified By:
32 //
33 //%/////////////////////////////////////////////////////////////////////////////
34
35 #include <Pegasus/Common/Config.h>
36 #include <Pegasus/Common/Constants.h>
37 #include <Pegasus/Common/AutoPtr.h>
38 kumpf 1.1 #include <Pegasus/Common/ArrayInternal.h>
39 #include <Pegasus/Common/CIMMessage.h>
40 #include <Pegasus/Common/CIMMessageSerializer.h>
41 #include <Pegasus/Common/CIMMessageDeserializer.h>
42 #include <Pegasus/Common/OperationContextInternal.h>
43 #include <Pegasus/Common/System.h>
44 #include <Pegasus/Common/AnonymousPipe.h>
45 #include <Pegasus/Common/Tracer.h>
46 #include <Pegasus/Common/Logger.h>
47 #include <Pegasus/Common/Thread.h>
48 #include <Pegasus/Common/MessageQueueService.h>
49 #include <Pegasus/Config/ConfigManager.h>
50
51 #if defined (PEGASUS_OS_TYPE_WINDOWS)
52 #include <windows.h> // For CreateProcess()
53 #else
54 # if defined (PEGASUS_OS_OS400)
55 # include <unistd.cleinc>
56 # else
57 # include <unistd.h> // For fork(), exec(), and _exit()
58 # endif
59 kumpf 1.1 #include <errno.h>
60 #endif
61
62 #include "OOPProviderManagerRouter.h"
63
64 PEGASUS_USING_STD;
65
66 PEGASUS_NAMESPACE_BEGIN
67
68 /////////////////////////////////////////////////////////////////////////////
69 // OutstandingRequestTable and OutstandingRequestEntry
70 /////////////////////////////////////////////////////////////////////////////
71
72 /**
73 An OutstandingRequestEntry represents a request message sent to a
74 Provider Agent for which no response has been received. The request
75 sender provides the message ID and a location for the response to be
76 returned, and then waits on the semaphore. When a response matching
77 the message ID is received, it is placed into the specified location
78 and the semaphore is signaled.
79 */
80 kumpf 1.1 class OutstandingRequestEntry
81 {
82 public:
83 OutstandingRequestEntry(
84 String messageId_,
85 CIMResponseMessage*& responseMessage_,
86 Semaphore* responseReady_)
87 : messageId(messageId_),
88 responseMessage(responseMessage_),
89 responseReady(responseReady_)
90 {
91 }
92
93 String messageId;
94 CIMResponseMessage*& responseMessage;
95 Semaphore* responseReady;
96 };
97
98 typedef HashTable<String, OutstandingRequestEntry*, EqualFunc<String>,
99 HashFunc<String> > OutstandingRequestTable;
100
101 kumpf 1.1
102 /////////////////////////////////////////////////////////////////////////////
103 // ProviderAgentContainer
104 /////////////////////////////////////////////////////////////////////////////
105
106 class ProviderAgentContainer
107 {
108 public:
109 ProviderAgentContainer(
110 const String & moduleName,
|
111 kumpf 1.6 const String & userName,
|
112 kumpf 1.1 PEGASUS_INDICATION_CALLBACK indicationCallback);
113
114 ~ProviderAgentContainer();
115
116 Boolean isInitialized();
117
|
118 kumpf 1.6 String getModuleName() const;
119
|
120 kumpf 1.1 CIMResponseMessage* processMessage(CIMRequestMessage* request);
121 void unloadIdleProviders();
122
123 private:
124 //
125 // Private methods
126 //
127
128 /** Unimplemented */
129 ProviderAgentContainer();
130 /** Unimplemented */
131 ProviderAgentContainer(const ProviderAgentContainer& pa);
132 /** Unimplemented */
133 ProviderAgentContainer& operator=(const ProviderAgentContainer& pa);
134
135 /**
136 Start a Provider Agent process and establish a pipe connection with it.
137 Note: The caller must lock the _agentMutex.
138 */
139 void _startAgentProcess();
140
141 kumpf 1.1 /**
142 Send initialization data to the Provider Agent.
143 Note: The caller must lock the _agentMutex.
144 */
145 void _sendInitializationData();
146
147 /**
148 Initialize the ProviderAgentContainer if it is not already
149 initialized. Initialization includes starting the Provider Agent
150 process, establishing a pipe connection with it, and starting a
151 thread to read response messages from the Provider Agent.
152
153 Note: The caller must lock the _agentMutex.
154 */
155 void _initialize();
156
157 /**
158 Uninitialize the ProviderAgentContainer if it is initialized.
159 The connection is closed and outstanding requests are completed
160 with an error result.
161
162 kumpf 1.1 Note: The caller must lock the _agentMutex.
163 */
164 void _uninitialize();
165
166 /**
167 Read and process response messages from the Provider Agent until
168 the connection is closed.
169 */
170 void _processResponses();
171 static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
172 _responseProcessor(void* arg);
173
174 //
175 // Private data
176 //
177
178 /**
179 The _agentMutex must be locked whenever writing to the Provider
180 Agent connection, accessing the _isInitialized flag, or changing
181 the Provider Agent state.
182 */
183 kumpf 1.1 Mutex _agentMutex;
184
185 /**
186 Name of the provider module served by this Provider Agent.
187 */
188 String _moduleName;
189
190 /**
|
191 kumpf 1.6 The user context in which this Provider Agent operates.
192 */
193 String _userName;
194
195 /**
|
196 kumpf 1.1 Callback function to which all generated indications are sent for
197 processing.
198 */
199 PEGASUS_INDICATION_CALLBACK _indicationCallback;
200
201 /**
202 Indicates whether the Provider Agent is active.
203 */
204 Boolean _isInitialized;
205
206 /**
207 Pipe connection used to read responses from the Provider Agent.
208 */
209 AutoPtr<AnonymousPipe> _pipeFromAgent;
210 /**
211 Pipe connection used to write requests to the Provider Agent.
212 */
213 AutoPtr<AnonymousPipe> _pipeToAgent;
214
215 /**
216 The _outstandingRequestTable holds an entry for each request that has
217 kumpf 1.1 been sent to this Provider Agent for which no response has been
218 received. Entries are added (by the writing thread) when a request
219 is sent, and are removed (by the reading thread) when the response is
220 received (or when it is determined that no response is forthcoming).
221 */
222 OutstandingRequestTable _outstandingRequestTable;
223 /**
224 The _outstandingRequestTableMutex must be locked whenever reading or
225 updating the _outstandingRequestTable.
226 */
227 Mutex _outstandingRequestTableMutex;
|
228 kumpf 1.2
229 /**
230 Holds the last provider module instance sent to the Provider Agent in
231 a ProviderIdContainer. Since the provider module instance rarely
232 changes, an optimization is used to send it only when it differs from
233 the last provider module instance sent.
234 */
235 CIMInstance _providerModuleCache;
|
236 kumpf 1.6
237 /**
238 The number of Provider Agent processes that are currently initialized
239 (active).
240 */
241 static Uint32 _numProviderProcesses;
242
243 /**
244 The _numProviderProcessesMutex must be locked whenever reading or
245 updating the _numProviderProcesses count.
246 */
247 static Mutex _numProviderProcessesMutex;
248
249 /**
250 The maximum number of Provider Agent processes that may be initialized
251 (active) at one time.
252 */
253 static Uint32 _maxProviderProcesses;
|
254 kumpf 1.1 };
255
|
256 kumpf 1.6 Uint32 ProviderAgentContainer::_numProviderProcesses = 0;
257 Mutex ProviderAgentContainer::_numProviderProcessesMutex;
258 Uint32 ProviderAgentContainer::_maxProviderProcesses = PEG_NOT_FOUND;
259
|
260 kumpf 1.1 ProviderAgentContainer::ProviderAgentContainer(
261 const String & moduleName,
|
262 kumpf 1.6 const String & userName,
|
263 kumpf 1.1 PEGASUS_INDICATION_CALLBACK indicationCallback)
264 : _moduleName(moduleName),
|
265 kumpf 1.6 _userName(userName),
|
266 kumpf 1.1 _indicationCallback(indicationCallback),
267 _isInitialized(false)
268 {
269 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
270 "ProviderAgentContainer::ProviderAgentContainer");
271 PEG_METHOD_EXIT();
272 }
273
274 ProviderAgentContainer::~ProviderAgentContainer()
275 {
276 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
277 "ProviderAgentContainer::~ProviderAgentContainer");
278
279 // Ensure the destructor does not throw an exception
280 try
281 {
282 // Stop the responseProcessor thread by closing its connection
283 _pipeFromAgent->closeReadHandle();
284
285 // Wait for the responseProcessor thread to exit
286 while (isInitialized())
287 kumpf 1.1 {
288 pegasus_yield();
289 }
290 }
291 catch (...)
292 {
293 }
294
295 PEG_METHOD_EXIT();
296 }
297
298 void ProviderAgentContainer::_startAgentProcess()
299 {
300 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
301 "ProviderAgentContainer::_startAgentProcess");
302
303 AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe());
304 AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe());
305
306 //
307 // Start a cimprovagt process for this provider module
308 kumpf 1.1 //
309
310 #if defined (PEGASUS_OS_TYPE_WINDOWS)
311 //
312 // Set up members of the PROCESS_INFORMATION structure
313 //
314 PROCESS_INFORMATION piProcInfo;
315 ZeroMemory (&piProcInfo, sizeof (PROCESS_INFORMATION));
316
317 //
318 // Set up members of the STARTUPINFO structure
319 //
320 STARTUPINFO siStartInfo;
321 ZeroMemory (&siStartInfo, sizeof (STARTUPINFO));
322 siStartInfo.cb = sizeof (STARTUPINFO);
323
324 //
325 // Generate the command line
326 //
327 char cmdLine[2048];
328 char readHandle[32];
329 kumpf 1.1 char writeHandle[32];
330 pipeToAgent->exportReadHandle(readHandle);
331 pipeFromAgent->exportWriteHandle(writeHandle);
332
333 sprintf(cmdLine, "\"%s\" %s %s \"%s\"",
334 (const char*)ConfigManager::getHomedPath(
335 PEGASUS_PROVIDER_AGENT_PROC_NAME).getCString(),
336 readHandle, writeHandle, (const char*)_moduleName.getCString());
337
338 //
339 // Create the child process
340 //
341 if (!CreateProcess (
342 NULL, //
343 cmdLine, // command line
344 NULL, // process security attributes
345 NULL, // primary thread security attributes
346 TRUE, // handles are inherited
347 0, // creation flags
348 NULL, // use parent's environment
349 NULL, // use parent's current directory
350 kumpf 1.1 &siStartInfo, // STARTUPINFO
351 &piProcInfo)) // PROCESS_INFORMATION
352 {
353 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
354 "CreateProcess() failed. errno = %d.", GetLastError());
355 PEG_METHOD_EXIT();
356 throw Exception(MessageLoaderParms(
357 "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
358 "Failed to start cimprovagt \"$0\".",
359 _moduleName));
360 }
361
362 CloseHandle(piProcInfo.hProcess);
363 CloseHandle(piProcInfo.hThread);
364 #else
365 pid_t pid = fork();
366 if (pid < 0)
367 {
368 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
369 "fork() failed. errno = %d.", errno);
370 PEG_METHOD_EXIT();
371 kumpf 1.1 throw Exception(MessageLoaderParms(
372 "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
373 "Failed to start cimprovagt \"$0\".",
374 _moduleName));
375 }
376 else if (pid == 0)
377 {
378 //
379 // Child side of the fork
380 //
381
382 try
383 {
384 // Close our copies of the parent's ends of the pipes
385 pipeToAgent->closeWriteHandle();
386 pipeFromAgent->closeReadHandle();
387
388 //
389 // Execute the cimprovagt program
390 //
391 String agentCommandPath =
392 kumpf 1.1 ConfigManager::getHomedPath(PEGASUS_PROVIDER_AGENT_PROC_NAME);
393 CString agentCommandPathCString = agentCommandPath.getCString();
394
395 char readHandle[32];
396 char writeHandle[32];
397 pipeToAgent->exportReadHandle(readHandle);
398 pipeFromAgent->exportWriteHandle(writeHandle);
399
|
400 kumpf 1.6 // Set the user context of the Provider Agent process
401 if (_userName != System::getEffectiveUserName())
402 {
403 if (!System::changeUserContext(_userName.getCString()))
404 {
405 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
406 "System::changeUserContext() failed. userName = %s.",
407 _userName.getCString());
408 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER,
409 Logger::WARNING,
410 "ProviderManager.OOPProviderManagerRouter."
411 "USER_CONTEXT_CHANGE_FAILED",
412 "Unable to change user context to \"$0\".", _userName);
413 _exit(1);
414 }
415 }
416
|
417 kumpf 1.1 execl(agentCommandPathCString, agentCommandPathCString,
418 readHandle, writeHandle,
419 (const char*)_moduleName.getCString(), (char*)0);
420
421 // If we're still here, there was an error
422 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
423 "execl() failed. errno = %d.", errno);
424 _exit(1);
425 }
426 catch (...)
427 {
428 // There's not much we can do here in no man's land
429 try
430 {
431 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
432 "Caught exception before calling execl().");
433 }
434 catch (...) {}
435 _exit(1);
436 }
437 }
438 kumpf 1.1 #endif
439
440 //
441 // CIM Server process
442 //
443
444 // Close our copies of the agent's ends of the pipes
445 pipeToAgent->closeReadHandle();
446 pipeFromAgent->closeWriteHandle();
447
448 _pipeToAgent.reset(pipeToAgent.release());
449 _pipeFromAgent.reset(pipeFromAgent.release());
450
451 PEG_METHOD_EXIT();
452 }
453
454 // Note: Caller must lock _agentMutex
455 void ProviderAgentContainer::_sendInitializationData()
456 {
457 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
458 "ProviderAgentContainer::_sendInitializationData");
459 kumpf 1.1
460 //
461 // Gather config properties to pass to the Provider Agent
462 //
463 ConfigManager* configManager = ConfigManager::getInstance();
464 Array<Pair<String, String> > configProperties;
465
466 Array<String> configPropertyNames;
467 configManager->getAllPropertyNames(configPropertyNames, true);
468 for (Uint32 i = 0; i < configPropertyNames.size(); i++)
469 {
470 String configPropertyValue =
471 configManager->getCurrentValue(configPropertyNames[i]);
472 String configPropertyDefaultValue =
473 configManager->getDefaultValue(configPropertyNames[i]);
474 if (configPropertyValue != configPropertyDefaultValue)
475 {
476 configProperties.append(Pair<String, String>(
477 configPropertyNames[i], configPropertyValue));
478 }
479 }
480 kumpf 1.1
481 //
482 // Create a Provider Agent initialization message
483 //
484 AutoPtr<CIMInitializeProviderAgentRequestMessage> request(
485 new CIMInitializeProviderAgentRequestMessage(
486 String("0"), // messageId
487 configManager->getPegasusHome(),
488 configProperties,
489 System::bindVerbose,
490 QueueIdStack()));
491
492 //
493 // Write the initialization message to the pipe
494 //
495 AnonymousPipe::Status writeStatus =
496 _pipeToAgent->writeMessage(request.get());
497
498 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
499 {
500 PEG_METHOD_EXIT();
501 kumpf 1.1 throw Exception(MessageLoaderParms(
502 "ProviderManager.OOPProviderManagerRouter."
503 "CIMPROVAGT_COMMUNICATION_FAILED",
504 "Failed to communicate with cimprovagt \"$0\".",
505 _moduleName));
506 }
507
508 // Do not wait for a response from the Provider Agent. (It isn't coming.)
509
510 PEG_METHOD_EXIT();
511 }
512
513 // Note: Caller must lock _agentMutex
514 void ProviderAgentContainer::_initialize()
515 {
516 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
517 "ProviderAgentContainer::_initialize");
518
519 if (_isInitialized)
520 {
521 PEGASUS_ASSERT(0);
522 kumpf 1.1 PEG_METHOD_EXIT();
523 return;
524 }
525
|
526 kumpf 1.6 if (_maxProviderProcesses == PEG_NOT_FOUND)
527 {
528 String maxProviderProcesses = ConfigManager::getInstance()->getCurrentValue("maxProviderProcesses");
529 CString maxProviderProcessesString = maxProviderProcesses.getCString();
530 char* end = 0;
531 _maxProviderProcesses = strtol(maxProviderProcessesString, &end, 10);
532 }
533
534 {
535 AutoMutex lock(_numProviderProcessesMutex);
536 if ((_maxProviderProcesses != 0) &&
537 (_numProviderProcesses >= _maxProviderProcesses))
538 {
539 throw PEGASUS_CIM_EXCEPTION(
540 CIM_ERR_FAILED,
541 MessageLoaderParms(
542 "ProviderManager.OOPProviderManagerRouter."
543 "MAX_PROVIDER_PROCESSES_REACHED",
544 "The maximum number of cimprovagt processes has been "
545 "reached."));
546 }
547 kumpf 1.6 else
548 {
549 _numProviderProcesses++;
550 }
551 }
552
|
553 kumpf 1.1 try
554 {
555 _startAgentProcess();
556
557 _sendInitializationData();
558
559 _isInitialized = true;
560
561 // Start a thread to read and process responses from the Provider Agent
562 while (!MessageQueueService::get_thread_pool()->allocate_and_awaken(
563 this, _responseProcessor))
564 {
565 pegasus_yield();
566 }
567 }
568 catch (...)
569 {
570 _isInitialized = false;
571 _pipeToAgent.reset();
572 _pipeFromAgent.reset();
|
573 kumpf 1.6
574 {
575 AutoMutex lock(_numProviderProcessesMutex);
576 _numProviderProcesses--;
577 }
578
|
579 kumpf 1.1 PEG_METHOD_EXIT();
580 throw;
581 }
582
583 PEG_METHOD_EXIT();
584 }
585
586 Boolean ProviderAgentContainer::isInitialized()
587 {
588 AutoMutex lock(_agentMutex);
589 return _isInitialized;
590 }
591
592 // Note: Caller must lock _agentMutex
593 void ProviderAgentContainer::_uninitialize()
594 {
595 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
596 "ProviderAgentContainer::_uninitialize");
597
598 if (!_isInitialized)
599 {
600 kumpf 1.1 PEGASUS_ASSERT(0);
601 PEG_METHOD_EXIT();
602 return;
603 }
604
605 try
606 {
607 // Close the connection with the Provider Agent
608 _pipeFromAgent.reset();
609 _pipeToAgent.reset();
610
|
611 kumpf 1.2 _providerModuleCache = CIMInstance();
612
|
613 kumpf 1.6 {
614 AutoMutex lock(_numProviderProcessesMutex);
615 _numProviderProcesses--;
616 }
617
|
618 kumpf 1.1 _isInitialized = false;
619
620 //
621 // Complete with null responses all outstanding requests on this
622 // connection
623 //
624 {
625 AutoMutex tableLock(_outstandingRequestTableMutex);
626
627 for (OutstandingRequestTable::Iterator i =
628 _outstandingRequestTable.start();
629 i != 0; i++)
630 {
631 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
632 String("Completing messageId \"") + i.value()->messageId +
633 "\" with a null response.");
634 i.value()->responseMessage = 0;
635 i.value()->responseReady->signal();
636 }
637
638 _outstandingRequestTable.clear();
639 kumpf 1.1 }
640 }
641 catch (...)
642 {
643 // We're uninitializing, so do not propagate the exception
644 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
645 "Ignoring _uninitialize() exception.");
646 }
647
648 PEG_METHOD_EXIT();
649 }
650
|
651 kumpf 1.6 String ProviderAgentContainer::getModuleName() const
652 {
653 return _moduleName;
654 }
655
|
656 kumpf 1.1 CIMResponseMessage* ProviderAgentContainer::processMessage(
657 CIMRequestMessage* request)
658 {
659 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
660 "ProviderAgentContainer::processMessage");
661
662 CIMResponseMessage* response;
663 String originalMessageId = request->messageId;
664
|
665 kumpf 1.2 // These three variables are used for the provider module optimization.
666 // See the _providerModuleCache member description for more information.
667 AutoPtr<ProviderIdContainer> origProviderId;
668 Boolean doProviderModuleOptimization = false;
669 Boolean updateProviderModuleCache = false;
670
|
671 kumpf 1.1 try
672 {
673 // The messageId attribute is used to correlate response messages
674 // from the Provider Agent with request messages, so it is imperative
675 // that the ID is unique for each request. The incoming ID cannot be
676 // trusted to be unique, so we substitute a unique one. The memory
677 // address of the request is used as the source of a unique piece of
678 // data. (The message ID is only required to be unique while the
679 // request is outstanding.)
680 char messagePtrString[20];
681 sprintf(messagePtrString, "%p", request);
682 String uniqueMessageId = messagePtrString;
683
684 //
685 // Set up the OutstandingRequestEntry for this request
686 //
687 Semaphore waitSemaphore(0);
688 OutstandingRequestEntry outstandingRequestEntry(
689 uniqueMessageId, response, &waitSemaphore);
690
691 //
692 kumpf 1.1 // Lock the Provider Agent Container while initializing the
693 // agent and writing the request to the connection
694 //
695 {
696 AutoMutex lock(_agentMutex);
697
698 //
699 // Initialize the Provider Agent, if necessary
700 //
701 if (!_isInitialized)
702 {
703 _initialize();
704 }
705
706 //
707 // Add an entry to the OutstandingRequestTable for this request
708 //
709 {
710 AutoMutex tableLock(_outstandingRequestTableMutex);
711
712 _outstandingRequestTable.insert(
713 kumpf 1.1 uniqueMessageId, &outstandingRequestEntry);
714 }
715
|
716 kumpf 1.2 // Get the provider module from the ProviderIdContainer to see if
717 // we can optimize out the transmission of this instance to the
718 // Provider Agent. (See the _providerModuleCache description.)
719 try
720 {
721 ProviderIdContainer pidc = request->operationContext.get(
722 ProviderIdContainer::NAME);
723 origProviderId.reset(new ProviderIdContainer(
724 pidc.getModule(), pidc.getProvider(),
725 pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
726 if (_providerModuleCache.isUninitialized() ||
727 (!pidc.getModule().identical(_providerModuleCache)))
728 {
729 // We haven't sent this provider module instance to the
730 // Provider Agent yet. Update our cache after we send it.
731 updateProviderModuleCache = true;
732 }
733 else
734 {
735 // Replace the provider module in the ProviderIdContainer
736 // with an uninitialized instance. We'll need to put the
737 kumpf 1.2 // original one back after the message is sent.
738 request->operationContext.set(ProviderIdContainer(
739 CIMInstance(), pidc.getProvider(),
740 pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
741 doProviderModuleOptimization = true;
742 }
743 }
744 catch (...)
745 {
746 // No ProviderIdContainer to optimize
747 }
748
|
749 kumpf 1.1 //
750 // Write the message to the pipe
751 //
752 try
753 {
754 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL3,
755 String("Sending request to agent with messageId ") +
756 uniqueMessageId);
757
758 request->messageId = uniqueMessageId;
759 AnonymousPipe::Status writeStatus =
760 _pipeToAgent->writeMessage(request);
761 request->messageId = originalMessageId;
762
|
763 kumpf 1.2 if (doProviderModuleOptimization)
764 {
765 request->operationContext.set(*origProviderId.get());
766 }
767
|
768 kumpf 1.1 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
769 {
770 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
771 "Failed to write message to pipe. writeStatus = %d.",
772 writeStatus);
773 throw Exception(MessageLoaderParms(
774 "ProviderManager.OOPProviderManagerRouter."
775 "CIMPROVAGT_COMMUNICATION_FAILED",
776 "Failed to communicate with cimprovagt \"$0\".",
777 _moduleName));
778 }
|
779 kumpf 1.2
780 if (updateProviderModuleCache)
781 {
782 _providerModuleCache = origProviderId->getModule();
783 }
|
784 kumpf 1.1 }
785 catch (...)
786 {
787 request->messageId = originalMessageId;
|
788 kumpf 1.2
789 if (doProviderModuleOptimization)
790 {
791 request->operationContext.set(*origProviderId.get());
792 }
793
|
794 kumpf 1.1 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
795 "Failed to write message to pipe.");
796 // Remove the OutstandingRequestTable entry for this request
797 {
798 AutoMutex tableLock(_outstandingRequestTableMutex);
799 Boolean removed =
800 _outstandingRequestTable.remove(uniqueMessageId);
801 PEGASUS_ASSERT(removed);
802 }
803 throw;
804 }
805 }
806
807 //
808 // Wait for the response
809 //
810 try
811 {
812 // Must not hold _agentMutex while waiting for the response
813 waitSemaphore.wait();
814 }
815 kumpf 1.1 catch (...)
816 {
817 // Remove the OutstandingRequestTable entry for this request
818 {
819 AutoMutex tableLock(_outstandingRequestTableMutex);
820 Boolean removed =
821 _outstandingRequestTable.remove(uniqueMessageId);
822 PEGASUS_ASSERT(removed);
823 }
824 throw;
825 }
826
827 // A null response is returned when an agent connection is closed
828 // while requests remain outstanding.
829 if (response == 0)
830 {
831 response = request->buildResponse();
832 response->cimException = PEGASUS_CIM_EXCEPTION(
833 CIM_ERR_FAILED,
834 MessageLoaderParms(
835 "ProviderManager.OOPProviderManagerRouter."
836 kumpf 1.1 "CIMPROVAGT_CONNECTION_LOST",
837 "Lost connection with cimprovagt \"$0\".",
838 _moduleName));
839 }
840 }
841 catch (CIMException& e)
842 {
843 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
844 String("Caught exception: ") + e.getMessage());
845 response = request->buildResponse();
846 response->cimException = e;
847 }
848 catch (Exception& e)
849 {
850 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
851 String("Caught exception: ") + e.getMessage());
852 response = request->buildResponse();
853 response->cimException = PEGASUS_CIM_EXCEPTION(
854 CIM_ERR_FAILED, e.getMessage());
855 }
856 catch (...)
857 kumpf 1.1 {
858 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
859 "Caught unknown exception");
860 response = request->buildResponse();
861 response->cimException = PEGASUS_CIM_EXCEPTION(
862 CIM_ERR_FAILED, String::EMPTY);
863 }
864
865 response->messageId = originalMessageId;
866
867 PEG_METHOD_EXIT();
868 return response;
869 }
870
871 void ProviderAgentContainer::unloadIdleProviders()
872 {
873 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
|
874 carolann.graves 1.4 "ProviderAgentContainer::unloadIdleProviders");
|
875 kumpf 1.1
876 AutoMutex lock(_agentMutex);
877 if (_isInitialized)
878 {
879 // Send a "wake up" message to the Provider Agent.
880 // Don't bother checking whether the operation is successful.
881 Uint32 messageLength = 0;
882 _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
883 }
884
885 PEG_METHOD_EXIT();
886 }
887
888 void ProviderAgentContainer::_processResponses()
889 {
890 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
891 "ProviderAgentContainer::_processResponses");
892
893 //
894 // Process responses until the pipe is closed
895 //
896 kumpf 1.1 while (1)
897 {
898 try
899 {
900 CIMMessage* message;
901
902 //
903 // Read a response from the Provider Agent
904 //
905 AnonymousPipe::Status readStatus =
906 _pipeFromAgent->readMessage(message);
907
908 // Ignore interrupts
909 if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
910 {
911 continue;
912 }
913
914 // Handle an error the same way as a closed connection
915 if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
916 (readStatus == AnonymousPipe::STATUS_CLOSED))
917 kumpf 1.1 {
918 AutoMutex lock(_agentMutex);
919 _uninitialize();
920 return;
921 }
922
923 if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
924 {
925 // Forward indications to the indication callback
926 _indicationCallback(
927 reinterpret_cast<CIMProcessIndicationRequestMessage*>(
928 message));
929 }
930 else
931 {
932 CIMResponseMessage* response;
933 response = dynamic_cast<CIMResponseMessage*>(message);
934 PEGASUS_ASSERT(response != 0);
935
936 // Give the response to the waiting OutstandingRequestEntry
937 OutstandingRequestEntry* _outstandingRequestEntry = 0;
938 kumpf 1.1 {
939 AutoMutex tableLock(_outstandingRequestTableMutex);
940 Boolean foundEntry = _outstandingRequestTable.lookup(
941 response->messageId, _outstandingRequestEntry);
942 PEGASUS_ASSERT(foundEntry);
943
944 // Remove the completed request from the table
945 Boolean removed =
946 _outstandingRequestTable.remove(response->messageId);
947 PEGASUS_ASSERT(removed);
948 }
949
950 _outstandingRequestEntry->responseMessage = response;
951 _outstandingRequestEntry->responseReady->signal();
952 }
953 }
954 catch (Exception& e)
955 {
956 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
957 String("Ignoring exception: ") + e.getMessage());
958 }
959 kumpf 1.1 catch (...)
960 {
961 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
962 "Ignoring exception");
963 }
964 }
965
966 PEG_METHOD_EXIT();
967 }
968
969 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
970 ProviderAgentContainer::_responseProcessor(void* arg)
971 {
972 ProviderAgentContainer* pa =
973 reinterpret_cast<ProviderAgentContainer*>(arg);
974
975 pa->_processResponses();
976
977 return(PEGASUS_THREAD_RETURN(0));
978 }
979
980 kumpf 1.1 /////////////////////////////////////////////////////////////////////////////
981 // OOPProviderManagerRouter
982 /////////////////////////////////////////////////////////////////////////////
983
984 OOPProviderManagerRouter::OOPProviderManagerRouter(
985 PEGASUS_INDICATION_CALLBACK indicationCallback)
986 {
987 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
988 "OOPProviderManagerRouter::OOPProviderManagerRouter");
989
990 _indicationCallback = indicationCallback;
991
992 PEG_METHOD_EXIT();
993 }
994
995 OOPProviderManagerRouter::~OOPProviderManagerRouter()
996 {
997 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
998 "OOPProviderManagerRouter::~OOPProviderManagerRouter");
999
1000 try
1001 kumpf 1.1 {
1002 // Clean up the ProviderAgentContainers
1003 AutoMutex lock(_providerAgentTableMutex);
1004 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1005 for(; i != 0; i++)
1006 {
1007 delete i.value();
1008 }
1009 }
1010 catch (...) {}
1011
1012 PEG_METHOD_EXIT();
1013 }
1014
1015 // Private, unimplemented constructor
1016 OOPProviderManagerRouter::OOPProviderManagerRouter()
1017 {
1018 }
1019
1020 // Private, unimplemented constructor
1021 OOPProviderManagerRouter::OOPProviderManagerRouter(
1022 kumpf 1.1 const OOPProviderManagerRouter&)
|
1023 david.dillard 1.3 : ProviderManagerRouter(*this)
|
1024 kumpf 1.1 {
1025 }
1026
1027 // Private, unimplemented assignment operator
1028 OOPProviderManagerRouter& OOPProviderManagerRouter::operator=(
1029 const OOPProviderManagerRouter&)
1030 {
1031 return *this;
1032 }
1033
1034 Message* OOPProviderManagerRouter::processMessage(Message* message)
1035 {
1036 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1037 "OOPProviderManagerRouter::processMessage");
1038
1039 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1040 PEGASUS_ASSERT(request != 0);
1041
1042 AutoPtr<CIMResponseMessage> response;
1043
1044 //
1045 kumpf 1.1 // Get the provider information from the request
1046 //
1047 CIMInstance providerModule;
1048
1049 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1050 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1051 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1052 {
1053 // Provider information is in the OperationContext
1054 ProviderIdContainer pidc = (ProviderIdContainer)
1055 request->operationContext.get(ProviderIdContainer::NAME);
1056 providerModule = pidc.getModule();
1057 }
1058 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1059 {
1060 CIMEnableModuleRequestMessage* emReq =
1061 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1062 providerModule = emReq->providerModule;
1063 }
1064 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1065 {
1066 kumpf 1.1 CIMDisableModuleRequestMessage* dmReq =
1067 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1068 providerModule = dmReq->providerModule;
1069 }
1070 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1071 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1072 {
1073 // This operation is not provider-specific
1074 }
1075 else
1076 {
1077 // Unrecognized message type. This should never happen.
1078 PEGASUS_ASSERT(0);
1079 response.reset(request->buildResponse());
1080 response->cimException = PEGASUS_CIM_EXCEPTION(
1081 CIM_ERR_FAILED, "Unrecognized message type.");
1082 PEG_METHOD_EXIT();
1083 return response.release();
1084 }
1085
1086 //
1087 kumpf 1.1 // Process the request message
1088 //
1089 if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1090 {
1091 // Forward the CIMStopAllProvidersRequest to all providers
1092 response.reset(_forwardRequestToAllAgents(request));
1093
1094 // Note: Do not uninitialize the ProviderAgentContainers here.
1095 // Just let the selecting thread notice when the agent connections
1096 // are closed.
1097 }
1098 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1099 {
1100 CIMNotifyConfigChangeRequestMessage* notifyRequest =
1101 dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1102 PEGASUS_ASSERT(notifyRequest != 0);
1103
1104 if (notifyRequest->currentValueModified)
1105 {
1106 // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1107 response.reset(_forwardRequestToAllAgents(request));
1108 kumpf 1.1 }
1109 else
1110 {
1111 // No need to notify provider agents about changes to planned value
1112 response.reset(request->buildResponse());
1113 }
1114 }
|
1115 kumpf 1.6 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
|
1116 kumpf 1.1 {
|
1117 kumpf 1.6 // Fan out the request to all Provider Agent processes for this module
1118
|
1119 kumpf 1.1 // Retrieve the provider module name
1120 String moduleName;
1121 CIMValue nameValue = providerModule.getProperty(
1122 providerModule.findProperty("Name")).getValue();
1123 nameValue.get(moduleName);
1124
|
1125 kumpf 1.6 // Look up the Provider Agents for this module
1126 Array<ProviderAgentContainer*> paArray =
1127 _lookupProviderAgents(moduleName);
|
1128 kumpf 1.1
|
1129 kumpf 1.6 for (Uint32 i=0; i<paArray.size(); i++)
|
1130 kumpf 1.1 {
1131 //
1132 // Do not start up an agent process just to disable the module
1133 //
|
1134 kumpf 1.6 if (paArray[i]->isInitialized())
1135 {
1136 //
1137 // Forward the request to the provider agent
1138 //
1139 response.reset(paArray[i]->processMessage(request));
1140
1141 // Note: Do not uninitialize the ProviderAgentContainer here
1142 // when a disable module operation is successful. Just let the
1143 // selecting thread notice when the agent connection is closed.
1144
1145 // Determine the success of the disable module operation
1146 CIMDisableModuleResponseMessage* dmResponse =
1147 dynamic_cast<CIMDisableModuleResponseMessage*>(
1148 response.get());
1149 PEGASUS_ASSERT(dmResponse != 0);
1150
1151 Boolean isStopped = false;
1152 for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1153 {
1154 if (dmResponse->operationalStatus[i] ==
1155 kumpf 1.6 CIM_MSE_OPSTATUS_VALUE_STOPPED)
1156 {
1157 isStopped = true;
1158 break;
1159 }
1160 }
1161
1162 // If the operation is unsuccessful, stop and return the error
1163 if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1164 !isStopped)
1165 {
1166 break;
1167 }
1168 }
1169 }
1170
1171 // Use a default response if no Provider Agents were called
1172 if (!response.get())
1173 {
|
1174 kumpf 1.1 response.reset(request->buildResponse());
1175
1176 CIMDisableModuleResponseMessage* dmResponse =
1177 dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1178 PEGASUS_ASSERT(dmResponse != 0);
1179
1180 Array<Uint16> operationalStatus;
1181 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1182 dmResponse->operationalStatus = operationalStatus;
1183 }
|
1184 kumpf 1.6 }
1185 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1186 {
1187 // Fan out the request to all Provider Agent processes for this module
1188
1189 // Retrieve the provider module name
1190 String moduleName;
1191 CIMValue nameValue = providerModule.getProperty(
1192 providerModule.findProperty("Name")).getValue();
1193 nameValue.get(moduleName);
1194
1195 // Look up the Provider Agents for this module
1196 Array<ProviderAgentContainer*> paArray =
1197 _lookupProviderAgents(moduleName);
1198
1199 for (Uint32 i=0; i<paArray.size(); i++)
|
1200 kumpf 1.1 {
1201 //
1202 // Do not start up an agent process just to enable the module
1203 //
|
1204 kumpf 1.6 if (paArray[i]->isInitialized())
1205 {
1206 //
1207 // Forward the request to the provider agent
1208 //
1209 response.reset(paArray[i]->processMessage(request));
1210
1211 // Determine the success of the enable module operation
1212 CIMEnableModuleResponseMessage* emResponse =
1213 dynamic_cast<CIMEnableModuleResponseMessage*>(
1214 response.get());
1215 PEGASUS_ASSERT(emResponse != 0);
1216
1217 Boolean isOk = false;
1218 for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1219 {
1220 if (emResponse->operationalStatus[i] ==
1221 CIM_MSE_OPSTATUS_VALUE_OK)
1222 {
1223 isOk = true;
1224 break;
1225 kumpf 1.6 }
1226 }
1227
1228 // If the operation is unsuccessful, stop and return the error
1229 if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1230 !isOk)
1231 {
1232 break;
1233 }
1234 }
1235 }
1236
1237 // Use a default response if no Provider Agents were called
1238 if (!response.get())
1239 {
|
1240 kumpf 1.1 response.reset(request->buildResponse());
1241
1242 CIMEnableModuleResponseMessage* emResponse =
1243 dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1244 PEGASUS_ASSERT(emResponse != 0);
1245
1246 Array<Uint16> operationalStatus;
1247 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1248 emResponse->operationalStatus = operationalStatus;
1249 }
|
1250 kumpf 1.6 }
1251 else
1252 {
1253 // Retrieve the provider module name
1254 String moduleName;
1255 CIMValue nameValue = providerModule.getProperty(
1256 providerModule.findProperty("Name")).getValue();
1257 nameValue.get(moduleName);
1258
1259 // Retrieve the provider user context configuration
1260 Uint16 userContext = 0;
1261 Uint32 pos = providerModule.findProperty(
1262 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1263 if (pos != PEG_NOT_FOUND)
1264 {
1265 providerModule.getProperty(pos).getValue().get(userContext);
1266 }
1267
1268 if (userContext == 0)
1269 {
1270 userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED;
1271 kumpf 1.6 }
1272
1273 String userName;
1274
1275 if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
|
1276 kumpf 1.1 {
|
1277 kumpf 1.6 try
1278 {
1279 // User Name is in the OperationContext
1280 IdentityContainer ic = (IdentityContainer)
1281 request->operationContext.get(IdentityContainer::NAME);
1282 userName = ic.getUserName();
1283 }
1284 catch (Exception& e)
1285 {
1286 // If no IdentityContainer is present, default to the CIM
1287 // Server's user context
1288 }
|
1289 kumpf 1.1
|
1290 kumpf 1.6 // If authentication is disabled, use the CIM Server's user context
1291 if (!userName.size())
1292 {
1293 userName = System::getEffectiveUserName();
1294 }
1295 }
1296 else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1297 {
1298 // Retrieve the provider module name
1299 providerModule.getProperty(providerModule.findProperty(
1300 PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1301 get(userName);
1302 }
1303 else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1304 {
1305 userName = System::getEffectiveUserName();
1306 }
1307 else // Privileged User
1308 {
1309 PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1310 userName = System::getPrivilegedUserName();
|
1311 kumpf 1.1 }
|
1312 kumpf 1.6
1313 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1314 "Module name = " + moduleName);
1315 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1316 "User context = %hd.", userContext);
1317 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1318 "User name = " + userName);
1319
1320 // Look up the Provider Agent for this module and user
1321 ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName);
1322 PEGASUS_ASSERT(pa != 0);
1323
1324 //
1325 // Forward the request to the provider agent
1326 //
1327 response.reset(pa->processMessage(request));
|
1328 kumpf 1.1 }
1329
1330 response->syncAttributes(request);
1331
1332 PEG_METHOD_EXIT();
1333 return response.release();
1334 }
1335
1336 ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
|
1337 kumpf 1.6 const String& moduleName,
1338 const String& userName)
|
1339 kumpf 1.1 {
1340 ProviderAgentContainer* pa = 0;
|
1341 kumpf 1.6 String key = moduleName + ":" + userName;
|
1342 kumpf 1.1
1343 AutoMutex lock(_providerAgentTableMutex);
|
1344 kumpf 1.6 if (!_providerAgentTable.lookup(key, pa))
|
1345 kumpf 1.1 {
|
1346 kumpf 1.6 pa = new ProviderAgentContainer(
1347 moduleName, userName, _indicationCallback);
1348 _providerAgentTable.insert(key, pa);
|
1349 kumpf 1.1 }
1350 return pa;
1351 }
1352
|
1353 kumpf 1.6 Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1354 const String& moduleName)
1355 {
1356 Array<ProviderAgentContainer*> paArray;
1357
1358 AutoMutex lock(_providerAgentTableMutex);
1359 for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1360 {
1361 if (i.value()->getModuleName() == moduleName)
1362 {
1363 paArray.append(i.value());
1364 }
1365 }
1366 return paArray;
1367 }
1368
|
1369 kumpf 1.1 CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1370 CIMRequestMessage* request)
1371 {
1372 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1373 "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1374
1375 // Get a list of the ProviderAgentContainers. We need our own array copy
1376 // because we cannot hold the _providerAgentTableMutex while calling
1377 // _ProviderAgentContainer::processMessage().
1378 Array<ProviderAgentContainer*> paContainerArray;
1379 {
1380 AutoMutex tableLock(_providerAgentTableMutex);
1381 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1382 i != 0; i++)
1383 {
1384 paContainerArray.append(i.value());
1385 }
1386 }
1387
1388 CIMException responseException;
1389
1390 kumpf 1.1 // Forward the request to each of the initialized provider agents
1391 for (Uint32 j = 0; j < paContainerArray.size(); j++)
1392 {
1393 ProviderAgentContainer* pa = paContainerArray[j];
1394 if (pa->isInitialized())
1395 {
1396 // Note: The ProviderAgentContainer could become uninitialized
1397 // before _ProviderAgentContainer::processMessage() processes
1398 // this request. In this case, the Provider Agent process will
1399 // (unfortunately) be started to process this message.
1400 AutoPtr<CIMResponseMessage> response;
1401 response.reset(pa->processMessage(request));
1402 if (response.get() != 0)
1403 {
1404 // If the operation failed, save the exception data
1405 if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1406 (responseException.getCode() == CIM_ERR_SUCCESS))
1407 {
1408 responseException = response->cimException;
1409 }
1410 }
1411 kumpf 1.1 }
1412 }
1413
1414 CIMResponseMessage* response = request->buildResponse();
1415 response->cimException = responseException;
1416
1417 PEG_METHOD_EXIT();
1418 return response;
1419 }
1420
1421 Boolean OOPProviderManagerRouter::hasActiveProviders()
1422 {
1423 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1424 "OOPProviderManagerRouter::hasActiveProviders");
1425
1426 // Iterate through the _providerAgentTable looking for initialized agents
1427 AutoMutex lock(_providerAgentTableMutex);
1428 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1429 for(; i != 0; i++)
1430 {
1431 if (i.value()->isInitialized())
1432 kumpf 1.1 {
1433 PEG_METHOD_EXIT();
1434 return true;
1435 }
1436 }
1437
1438 // No initialized Provider Agents were found
1439 PEG_METHOD_EXIT();
1440 return false;
1441 }
1442
1443 void OOPProviderManagerRouter::unloadIdleProviders()
1444 {
1445 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1446 "OOPProviderManagerRouter::unloadIdleProviders");
1447
1448 // Iterate through the _providerAgentTable unloading idle providers
1449 AutoMutex lock(_providerAgentTableMutex);
1450 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1451 for(; i != 0; i++)
1452 {
1453 kumpf 1.1 i.value()->unloadIdleProviders();
1454 }
1455
1456 PEG_METHOD_EXIT();
1457 }
1458
1459 PEGASUS_NAMESPACE_END
|