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