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 }
1064
1065 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
1066 ProviderAgentContainer::_responseProcessor(void* arg)
1067 {
1068 ProviderAgentContainer* pa =
1069 reinterpret_cast<ProviderAgentContainer*>(arg);
1070
1071 pa->_processResponses();
1072
1073 return(PEGASUS_THREAD_RETURN(0));
1074 }
1075
1076 /////////////////////////////////////////////////////////////////////////////
1077 kumpf 1.1 // OOPProviderManagerRouter
1078 /////////////////////////////////////////////////////////////////////////////
1079
1080 OOPProviderManagerRouter::OOPProviderManagerRouter(
1081 PEGASUS_INDICATION_CALLBACK indicationCallback)
1082 {
1083 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1084 "OOPProviderManagerRouter::OOPProviderManagerRouter");
1085
1086 _indicationCallback = indicationCallback;
|
1087 carolann.graves 1.14 _subscriptionInitComplete = false;
|
1088 kumpf 1.1
1089 PEG_METHOD_EXIT();
1090 }
1091
1092 OOPProviderManagerRouter::~OOPProviderManagerRouter()
1093 {
1094 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1095 "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1096
1097 try
1098 {
1099 // Clean up the ProviderAgentContainers
1100 AutoMutex lock(_providerAgentTableMutex);
1101 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1102 for(; i != 0; i++)
1103 {
1104 delete i.value();
1105 }
1106 }
1107 catch (...) {}
1108
1109 kumpf 1.1 PEG_METHOD_EXIT();
1110 }
1111
1112 // Private, unimplemented constructor
1113 OOPProviderManagerRouter::OOPProviderManagerRouter()
1114 {
1115 }
1116
1117 // Private, unimplemented constructor
1118 OOPProviderManagerRouter::OOPProviderManagerRouter(
1119 const OOPProviderManagerRouter&)
|
1120 david.dillard 1.3 : ProviderManagerRouter(*this)
|
1121 kumpf 1.1 {
1122 }
1123
1124 // Private, unimplemented assignment operator
1125 OOPProviderManagerRouter& OOPProviderManagerRouter::operator=(
1126 const OOPProviderManagerRouter&)
1127 {
1128 return *this;
1129 }
1130
1131 Message* OOPProviderManagerRouter::processMessage(Message* message)
1132 {
1133 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1134 "OOPProviderManagerRouter::processMessage");
1135
1136 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1137 PEGASUS_ASSERT(request != 0);
1138
1139 AutoPtr<CIMResponseMessage> response;
1140
1141 //
1142 kumpf 1.1 // Get the provider information from the request
1143 //
1144 CIMInstance providerModule;
1145
1146 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1147 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1148 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1149 {
1150 // Provider information is in the OperationContext
1151 ProviderIdContainer pidc = (ProviderIdContainer)
1152 request->operationContext.get(ProviderIdContainer::NAME);
1153 providerModule = pidc.getModule();
1154 }
1155 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1156 {
1157 CIMEnableModuleRequestMessage* emReq =
1158 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1159 providerModule = emReq->providerModule;
1160 }
1161 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1162 {
1163 kumpf 1.1 CIMDisableModuleRequestMessage* dmReq =
1164 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1165 providerModule = dmReq->providerModule;
1166 }
1167 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
|
1168 carolann.graves 1.14 (request->getType() ==
1169 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
|
1170 kumpf 1.1 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1171 {
1172 // This operation is not provider-specific
1173 }
1174 else
1175 {
1176 // Unrecognized message type. This should never happen.
1177 PEGASUS_ASSERT(0);
1178 response.reset(request->buildResponse());
1179 response->cimException = PEGASUS_CIM_EXCEPTION(
1180 CIM_ERR_FAILED, "Unrecognized message type.");
1181 PEG_METHOD_EXIT();
1182 return response.release();
1183 }
1184
1185 //
1186 // Process the request message
1187 //
1188 if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1189 {
1190 // Forward the CIMStopAllProvidersRequest to all providers
1191 kumpf 1.1 response.reset(_forwardRequestToAllAgents(request));
1192
1193 // Note: Do not uninitialize the ProviderAgentContainers here.
1194 // Just let the selecting thread notice when the agent connections
1195 // are closed.
1196 }
|
1197 carolann.graves 1.14 else if (request->getType () ==
1198 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1199 {
1200 _subscriptionInitComplete = true;
1201
1202 //
1203 // Forward the CIMSubscriptionInitCompleteRequestMessage to
1204 // all providers
1205 //
1206 response.reset (_forwardRequestToAllAgents (request));
1207 }
|
1208 kumpf 1.1 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1209 {
1210 CIMNotifyConfigChangeRequestMessage* notifyRequest =
1211 dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1212 PEGASUS_ASSERT(notifyRequest != 0);
1213
1214 if (notifyRequest->currentValueModified)
1215 {
1216 // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1217 response.reset(_forwardRequestToAllAgents(request));
1218 }
1219 else
1220 {
1221 // No need to notify provider agents about changes to planned value
1222 response.reset(request->buildResponse());
1223 }
1224 }
|
1225 kumpf 1.6 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
|
1226 kumpf 1.1 {
|
1227 kumpf 1.6 // Fan out the request to all Provider Agent processes for this module
1228
|
1229 kumpf 1.1 // Retrieve the provider module name
1230 String moduleName;
1231 CIMValue nameValue = providerModule.getProperty(
1232 providerModule.findProperty("Name")).getValue();
1233 nameValue.get(moduleName);
1234
|
1235 kumpf 1.6 // Look up the Provider Agents for this module
1236 Array<ProviderAgentContainer*> paArray =
1237 _lookupProviderAgents(moduleName);
|
1238 kumpf 1.1
|
1239 kumpf 1.6 for (Uint32 i=0; i<paArray.size(); i++)
|
1240 kumpf 1.1 {
1241 //
1242 // Do not start up an agent process just to disable the module
1243 //
|
1244 kumpf 1.6 if (paArray[i]->isInitialized())
1245 {
1246 //
1247 // Forward the request to the provider agent
1248 //
1249 response.reset(paArray[i]->processMessage(request));
1250
1251 // Note: Do not uninitialize the ProviderAgentContainer here
1252 // when a disable module operation is successful. Just let the
1253 // selecting thread notice when the agent connection is closed.
1254
1255 // Determine the success of the disable module operation
1256 CIMDisableModuleResponseMessage* dmResponse =
1257 dynamic_cast<CIMDisableModuleResponseMessage*>(
1258 response.get());
1259 PEGASUS_ASSERT(dmResponse != 0);
1260
1261 Boolean isStopped = false;
1262 for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1263 {
1264 if (dmResponse->operationalStatus[i] ==
1265 kumpf 1.6 CIM_MSE_OPSTATUS_VALUE_STOPPED)
1266 {
1267 isStopped = true;
1268 break;
1269 }
1270 }
1271
1272 // If the operation is unsuccessful, stop and return the error
1273 if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1274 !isStopped)
1275 {
1276 break;
1277 }
1278 }
1279 }
1280
1281 // Use a default response if no Provider Agents were called
1282 if (!response.get())
1283 {
|
1284 kumpf 1.1 response.reset(request->buildResponse());
1285
1286 CIMDisableModuleResponseMessage* dmResponse =
1287 dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1288 PEGASUS_ASSERT(dmResponse != 0);
1289
1290 Array<Uint16> operationalStatus;
1291 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1292 dmResponse->operationalStatus = operationalStatus;
1293 }
|
1294 kumpf 1.6 }
1295 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1296 {
1297 // Fan out the request to all Provider Agent processes for this module
1298
1299 // Retrieve the provider module name
1300 String moduleName;
1301 CIMValue nameValue = providerModule.getProperty(
1302 providerModule.findProperty("Name")).getValue();
1303 nameValue.get(moduleName);
1304
1305 // Look up the Provider Agents for this module
1306 Array<ProviderAgentContainer*> paArray =
1307 _lookupProviderAgents(moduleName);
1308
1309 for (Uint32 i=0; i<paArray.size(); i++)
|
1310 kumpf 1.1 {
1311 //
1312 // Do not start up an agent process just to enable the module
1313 //
|
1314 kumpf 1.6 if (paArray[i]->isInitialized())
1315 {
1316 //
1317 // Forward the request to the provider agent
1318 //
1319 response.reset(paArray[i]->processMessage(request));
1320
1321 // Determine the success of the enable module operation
1322 CIMEnableModuleResponseMessage* emResponse =
1323 dynamic_cast<CIMEnableModuleResponseMessage*>(
1324 response.get());
1325 PEGASUS_ASSERT(emResponse != 0);
1326
1327 Boolean isOk = false;
1328 for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1329 {
1330 if (emResponse->operationalStatus[i] ==
1331 CIM_MSE_OPSTATUS_VALUE_OK)
1332 {
1333 isOk = true;
1334 break;
1335 kumpf 1.6 }
1336 }
1337
1338 // If the operation is unsuccessful, stop and return the error
1339 if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1340 !isOk)
1341 {
1342 break;
1343 }
1344 }
1345 }
1346
1347 // Use a default response if no Provider Agents were called
1348 if (!response.get())
1349 {
|
1350 kumpf 1.1 response.reset(request->buildResponse());
1351
1352 CIMEnableModuleResponseMessage* emResponse =
1353 dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1354 PEGASUS_ASSERT(emResponse != 0);
1355
1356 Array<Uint16> operationalStatus;
1357 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1358 emResponse->operationalStatus = operationalStatus;
1359 }
|
1360 kumpf 1.6 }
1361 else
1362 {
1363 // Retrieve the provider module name
1364 String moduleName;
1365 CIMValue nameValue = providerModule.getProperty(
1366 providerModule.findProperty("Name")).getValue();
1367 nameValue.get(moduleName);
1368
1369 // Retrieve the provider user context configuration
1370 Uint16 userContext = 0;
1371 Uint32 pos = providerModule.findProperty(
1372 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1373 if (pos != PEG_NOT_FOUND)
1374 {
|
1375 kumpf 1.12 CIMValue userContextValue =
1376 providerModule.getProperty(pos).getValue();
1377 if (!userContextValue.isNull())
1378 {
1379 userContextValue.get(userContext);
1380 }
|
1381 kumpf 1.6 }
1382
1383 if (userContext == 0)
1384 {
1385 userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED;
1386 }
1387
1388 String userName;
1389
1390 if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
|
1391 kumpf 1.1 {
|
1392 kumpf 1.6 try
1393 {
1394 // User Name is in the OperationContext
1395 IdentityContainer ic = (IdentityContainer)
1396 request->operationContext.get(IdentityContainer::NAME);
1397 userName = ic.getUserName();
1398 }
1399 catch (Exception& e)
1400 {
1401 // If no IdentityContainer is present, default to the CIM
1402 // Server's user context
1403 }
|
1404 kumpf 1.1
|
1405 kumpf 1.6 // If authentication is disabled, use the CIM Server's user context
1406 if (!userName.size())
1407 {
1408 userName = System::getEffectiveUserName();
1409 }
1410 }
1411 else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1412 {
1413 // Retrieve the provider module name
1414 providerModule.getProperty(providerModule.findProperty(
1415 PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1416 get(userName);
1417 }
1418 else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1419 {
1420 userName = System::getEffectiveUserName();
1421 }
1422 else // Privileged User
1423 {
1424 PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1425 userName = System::getPrivilegedUserName();
|
1426 kumpf 1.1 }
|
1427 kumpf 1.6
1428 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1429 "Module name = " + moduleName);
1430 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1431 "User context = %hd.", userContext);
1432 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1433 "User name = " + userName);
1434
1435 // Look up the Provider Agent for this module and user
1436 ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName);
1437 PEGASUS_ASSERT(pa != 0);
1438
1439 //
1440 // Forward the request to the provider agent
1441 //
1442 response.reset(pa->processMessage(request));
|
1443 kumpf 1.1 }
1444
1445 response->syncAttributes(request);
1446
1447 PEG_METHOD_EXIT();
1448 return response.release();
1449 }
1450
1451 ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
|
1452 kumpf 1.6 const String& moduleName,
1453 const String& userName)
|
1454 kumpf 1.1 {
1455 ProviderAgentContainer* pa = 0;
|
1456 kumpf 1.6 String key = moduleName + ":" + userName;
|
1457 kumpf 1.1
1458 AutoMutex lock(_providerAgentTableMutex);
|
1459 kumpf 1.6 if (!_providerAgentTable.lookup(key, pa))
|
1460 kumpf 1.1 {
|
1461 kumpf 1.6 pa = new ProviderAgentContainer(
|
1462 carolann.graves 1.14 moduleName, userName, _indicationCallback,
1463 _subscriptionInitComplete);
|
1464 kumpf 1.6 _providerAgentTable.insert(key, pa);
|
1465 kumpf 1.1 }
1466 return pa;
1467 }
1468
|
1469 kumpf 1.6 Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1470 const String& moduleName)
1471 {
1472 Array<ProviderAgentContainer*> paArray;
1473
1474 AutoMutex lock(_providerAgentTableMutex);
1475 for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1476 {
1477 if (i.value()->getModuleName() == moduleName)
1478 {
1479 paArray.append(i.value());
1480 }
1481 }
1482 return paArray;
1483 }
1484
|
1485 kumpf 1.1 CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1486 CIMRequestMessage* request)
1487 {
1488 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1489 "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1490
1491 // Get a list of the ProviderAgentContainers. We need our own array copy
1492 // because we cannot hold the _providerAgentTableMutex while calling
1493 // _ProviderAgentContainer::processMessage().
1494 Array<ProviderAgentContainer*> paContainerArray;
1495 {
1496 AutoMutex tableLock(_providerAgentTableMutex);
1497 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1498 i != 0; i++)
1499 {
1500 paContainerArray.append(i.value());
1501 }
1502 }
1503
1504 CIMException responseException;
1505
1506 kumpf 1.1 // Forward the request to each of the initialized provider agents
1507 for (Uint32 j = 0; j < paContainerArray.size(); j++)
1508 {
1509 ProviderAgentContainer* pa = paContainerArray[j];
1510 if (pa->isInitialized())
1511 {
1512 // Note: The ProviderAgentContainer could become uninitialized
1513 // before _ProviderAgentContainer::processMessage() processes
1514 // this request. In this case, the Provider Agent process will
1515 // (unfortunately) be started to process this message.
1516 AutoPtr<CIMResponseMessage> response;
1517 response.reset(pa->processMessage(request));
1518 if (response.get() != 0)
1519 {
1520 // If the operation failed, save the exception data
1521 if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1522 (responseException.getCode() == CIM_ERR_SUCCESS))
1523 {
1524 responseException = response->cimException;
1525 }
1526 }
1527 kumpf 1.1 }
1528 }
1529
1530 CIMResponseMessage* response = request->buildResponse();
1531 response->cimException = responseException;
1532
1533 PEG_METHOD_EXIT();
1534 return response;
1535 }
1536
1537 Boolean OOPProviderManagerRouter::hasActiveProviders()
1538 {
1539 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1540 "OOPProviderManagerRouter::hasActiveProviders");
1541
1542 // Iterate through the _providerAgentTable looking for initialized agents
1543 AutoMutex lock(_providerAgentTableMutex);
1544 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1545 for(; i != 0; i++)
1546 {
1547 if (i.value()->isInitialized())
1548 kumpf 1.1 {
1549 PEG_METHOD_EXIT();
1550 return true;
1551 }
1552 }
1553
1554 // No initialized Provider Agents were found
1555 PEG_METHOD_EXIT();
1556 return false;
1557 }
1558
1559 void OOPProviderManagerRouter::unloadIdleProviders()
1560 {
1561 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1562 "OOPProviderManagerRouter::unloadIdleProviders");
1563
1564 // Iterate through the _providerAgentTable unloading idle providers
1565 AutoMutex lock(_providerAgentTableMutex);
1566 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1567 for(; i != 0; i++)
1568 {
1569 kumpf 1.1 i.value()->unloadIdleProviders();
1570 }
1571
1572 PEG_METHOD_EXIT();
1573 }
1574
1575 PEGASUS_NAMESPACE_END
|