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