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