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