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