1 s.kodali 1.1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 s.kodali 1.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/Signal.h>
33 #include <Pegasus/Common/Config.h>
34 #include <Pegasus/Common/Constants.h>
35 #include <Pegasus/Common/AutoPtr.h>
36 #include <Pegasus/Common/ArrayInternal.h>
37 #include <Pegasus/Common/CIMMessage.h>
38 #include <Pegasus/Common/OperationContextInternal.h>
39 #include <Pegasus/Common/System.h>
40 #include <Pegasus/Common/AnonymousPipe.h>
41 #include <Pegasus/Common/Tracer.h>
42 #include <Pegasus/Common/Logger.h>
43 s.kodali 1.1 #include <Pegasus/Common/Thread.h>
44 #include <Pegasus/Common/MessageQueueService.h>
45 #include <Pegasus/Config/ConfigManager.h>
46 #include <Pegasus/Common/Executor.h>
47 #include <Pegasus/Common/StringConversion.h>
48 #include <Pegasus/Common/SCMOClassCache.h>
49
50 #if defined (PEGASUS_OS_TYPE_WINDOWS)
51 # include <windows.h> // For CreateProcess()
52 #elif defined (PEGASUS_OS_VMS)
53 # include <perror.h>
54 # include <climsgdef.h>
55 # include <stdio.h>
56 # include <stdlib.h>
57 # include <string.h>
58 # include <processes.h>
59 # include <unixio.h>
60 #else
61 # include <unistd.h> // For fork(), exec(), and _exit()
62 # include <errno.h>
63 # include <sys/types.h>
64 s.kodali 1.1 # include <sys/resource.h>
65 # if defined(PEGASUS_HAS_SIGNALS)
66 # include <sys/wait.h>
67 # endif
68 #endif
69
70 #include "OOPProviderManagerRouter.h"
71
72 PEGASUS_USING_STD;
73
74 PEGASUS_NAMESPACE_BEGIN
75
76 static String _GROUP_PREFIX = "grp:";
77 static String _MODULE_PREFIX = "mod:";
78
79 static struct timeval deallocateWait = {300, 0};
80
81 // This calss is used to aggregate the responses sent when a single requests can
82 // result in many responses and these responses need to be aggregated before a
83 // response is sent back to the ProviderManageService.
84 class RespAggCounter
85 s.kodali 1.1 {
86 public:
87 RespAggCounter(Uint32 count):
88 _expectedResponseCount(count),
89 _receivedResponseCount(0)
90 {
91 }
92
93 Boolean isComplete(CIMException &e)
94 {
95 AutoMutex mtx(_mutex);
96 if (e.getCode() != CIM_ERR_SUCCESS)
97 {
98 _exception = e;
99 }
100 _receivedResponseCount++;
101 return _receivedResponseCount == _expectedResponseCount ;
102 }
103
104 CIMException getException()
105 {
106 s.kodali 1.1 return _exception;
107 }
108
109 private:
110 Mutex _mutex;
111 Uint32 _expectedResponseCount, _receivedResponseCount ;
112 CIMException _exception;
113 };
114
115
116 /////////////////////////////////////////////////////////////////////////////
117 // OutstandingRequestTable and OutstandingRequestEntry
118 /////////////////////////////////////////////////////////////////////////////
119
120 /**
121 An OutstandingRequestEntry represents a request message sent to a
122 Provider Agent for which no response has been received. The request
123 sender provides the message ID and a location for the response to be
124 returned. When a response matching the message ID is received, the
125 OutstandingRequestEntry is updated to indicate that the response
126 will arrive asynchronously. This entry will be deleted
127 s.kodali 1.1 when the response arrives. */
128 class OutstandingRequestEntry
129 {
130 public:
131 OutstandingRequestEntry(
132 String originalMessageId_,
133 CIMRequestMessage* requestMessage_,
134 CIMResponseMessage*& responseMessage_,
135 RespAggCounter* respAggregator_=NULL)
136 : originalMessageId(originalMessageId_),
137 requestMessage(requestMessage_),
138 responseMessage(responseMessage_),
139 respAggregator(respAggregator_)
140 {
141 }
142
143 /**
144 A unique value is substituted as the request messageId attribute to
145 allow responses to be definitively correllated with requests.
146 The original messageId value is stored here to avoid a race condition
147 between the processing of a response chunk and the resetting of the
148 s.kodali 1.1 original messageId in the request message.
149 */
150 String originalMessageId;
151 CIMRequestMessage* requestMessage;
152 CIMResponseMessage*& responseMessage;
153
154 // The aggregator object which aggregates the responses for requests
155 // like CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE etc.
156 RespAggCounter* respAggregator;
157 };
158
159 typedef HashTable<String, SharedPtr<OutstandingRequestEntry>, EqualFunc<String>,
160 HashFunc<String> > OutstandingRequestTable;
161
162 class RetryThreadParam{
163 public:
164 ProviderAgentContainer *pac;
165 Array<CIMRequestMessage *> retryRequestArray;
166 };
167
168
169 s.kodali 1.1 /////////////////////////////////////////////////////////////////////////////
170 // ProviderAgentContainer
171 /////////////////////////////////////////////////////////////////////////////
172
173 class ProviderAgentContainer
174 {
175 public:
176 ProviderAgentContainer(
|
177 s.kodali 1.3 Uint16 bitness,
|
178 s.kodali 1.1 const String & groupNameWithType,
179 const String & userName,
180 Uint16 userContext,
181 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
182 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
183 PEGASUS_PROVIDERMODULEGROUPFAIL_CALLBACK_T
184 providerModuleGroupFailCallback,
185 PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback,
186 Boolean subscriptionInitComplete,
187 ThreadPool * threadPool);
188
189 ~ProviderAgentContainer();
190
191 Boolean isInitialized();
192
193 String getGroupNameWithType() const;
194
195 CIMResponseMessage* processMessage(CIMRequestMessage* request,
196 RespAggCounter * respAggregator=NULL);
197
198 void unloadIdleProviders();
199 s.kodali 1.1
200 /**
201 Check if the pending responses in the _outstandingRequestTable
202 have active client connections. If not then create a response
203 to indicate that this client connection can be closed. The
204 entry for this request is also deleted from the
205 _outstandingRequestTable. This function is called at regular
206 intervals along with unloadIdleProviders
207 */
208 void cleanDisconnectedClientRequests();
|
209 venkat.puvvada 1.7 static void setAllProvidersStopped();
|
210 venkat.puvvada 1.9 void sendResponse(CIMResponseMessage *response);
|
211 s.kodali 1.1 private:
212 //
213 // Private methods
214 //
215
216 /** Unimplemented */
217 ProviderAgentContainer();
218 /** Unimplemented */
219 ProviderAgentContainer(const ProviderAgentContainer& pa);
220 /** Unimplemented */
221 ProviderAgentContainer& operator=(const ProviderAgentContainer& pa);
222
223 /**
224 Start a Provider Agent process and establish a pipe connection with it.
225 Note: The caller must lock the _agentMutex.
226 */
227 void _startAgentProcess();
228
229 /**
230 Send initialization data to the Provider Agent.
231 Note: The caller must lock the _agentMutex.
232 s.kodali 1.1 */
233 void _sendInitializationData();
234
235 /**
236 Initialize the ProviderAgentContainer if it is not already
237 initialized. Initialization includes starting the Provider Agent
238 process, establishing a pipe connection with it, and starting a
239 thread to read response messages from the Provider Agent.
240
241 Note: The caller must lock the _agentMutex.
242 */
243 void _initialize();
244
245 /**
246 Uninitialize the ProviderAgentContainer if it is initialized.
247 The connection is closed and outstanding requests are completed
248 with an error result.
249
250 @param cleanShutdown Indicates whether the provider agent process
251 exited cleanly. A value of true indicates that responses have been
252 sent for all requests that have been processed. A value of false
253 s.kodali 1.1 indicates that one or more requests may have been partially processed.
254 */
255 void _uninitialize(Boolean cleanShutdown);
256
257 /**
258 Performs the processMessage work, but does not retry on a transient
259 error.
260 */
261 CIMResponseMessage* _processMessage(CIMRequestMessage* request,
262 RespAggCounter *respAggregator);
263
264 /**
265 Read and process response messages from the Provider Agent until
266 the connection is closed.
267 */
268 void _processResponses();
269
270 void _sendResponse(CIMRequestMessage *request,
271 CIMResponseMessage *response);
272
273 static ThreadReturnType PEGASUS_THREAD_CDECL
274 s.kodali 1.1 _responseProcessor(void* arg);
275
276 /**
277 Process the ProvAgtGetScmoClassRequestMessage and sends the
278 requested SCMOClass back to the agent.
279 */
280 void _processGetSCMOClassRequest(
281 ProvAgtGetScmoClassRequestMessage* request);
282
283 /**
284 This function will fetch the bottom most queueid from the
285 QueueIdStack of the request message and check if the queue isActive().
286 */
287 Boolean _isClientActive(CIMRequestMessage *request_);
288
289 /**
290 This thread will retry the request if the provider goes down
291 before the request is processed.
292 */
293 static ThreadReturnType PEGASUS_THREAD_CDECL _retryRequestHandler(
294 void* arg) ;
295 s.kodali 1.1
296 //
297 // Private data
298 //
299
300 /**
301 The _agentMutex must be locked whenever writing to the Provider
302 Agent connection, accessing the _isInitialized flag, or changing
303 the Provider Agent state.
304 */
305 Mutex _agentMutex;
306
|
307 s.kodali 1.3 Uint16 _bitness;
308
|
309 s.kodali 1.1 /**
310 Name of the provider module or group served by this Provider Agent.
311 */
312 String _moduleOrGroupName;
313
314 /**
315 Name of the group with type(group or module indicator)
316 served by this Provider Agent.
317 */
318 String _groupNameWithType;
319
320 /**
321 The user context in which this Provider Agent operates.
322 */
323 String _userName;
324
325 /**
326 User Context setting of the provider module served by this Provider
327 Agent.
328 */
329 Uint16 _userContext;
330 s.kodali 1.1
331 /**
332 Callback function to which all generated indications are sent for
333 processing.
334 */
335 PEGASUS_INDICATION_CALLBACK_T _indicationCallback;
336
337 /**
338 Callback function to which response chunks are sent for processing.
339 */
340 PEGASUS_RESPONSE_CHUNK_CALLBACK_T _responseChunkCallback;
341
342 /**
343 Callback function to be called upon detection of failure of a
344 provider module.
345 */
346 PEGASUS_PROVIDERMODULEGROUPFAIL_CALLBACK_T _providerModuleGroupFailCallback;
347
348 /**
349 Callback function for async response.
350 */
351 s.kodali 1.1 PEGASUS_ASYNC_RESPONSE_CALLBACK_T _asyncResponseCallback;
352
353 /**
354 Indicates whether the Provider Agent is active.
355 */
356 Boolean _isInitialized;
357
358 /**
359 Pipe connection used to read responses from the Provider Agent.
360 */
361 AutoPtr<AnonymousPipe> _pipeFromAgent;
362 /**
363 Pipe connection used to write requests to the Provider Agent.
364 */
365 AutoPtr<AnonymousPipe> _pipeToAgent;
366
367 #if defined(PEGASUS_HAS_SIGNALS)
368 /**
369 Process ID of the active Provider Agent.
370 */
371 pid_t _pid;
372 s.kodali 1.1 #endif
373
374 /**
375 The _outstandingRequestTable holds an entry for each request that has
376 been sent to this Provider Agent for which no response has been
377 received. Entries are added (by the writing thread) when a request
378 is sent, and are removed (by the reading thread) when the response is
379 received (or when it is determined that no response is forthcoming).
380 */
381 OutstandingRequestTable _outstandingRequestTable;
382 /**
383 The _outstandingRequestTableMutex must be locked whenever reading or
384 updating the _outstandingRequestTable.
385 */
386 Mutex _outstandingRequestTableMutex;
387
388 /**
389 Holds the last provider module instance sent to the Provider Agent in
390 a ProviderIdContainer. Since the provider module instance rarely
391 changes, an optimization is used to send it only when it differs from
392 the last provider module instance sent.
393 s.kodali 1.1 */
394 CIMInstance _providerModuleCache;
395
396 /**
397 The number of Provider Agent processes that are currently initialized
398 (active).
399 */
400 static Uint32 _numProviderProcesses;
401
402 /**
403 The _numProviderProcessesMutex must be locked whenever reading or
404 updating the _numProviderProcesses count.
405 */
406 static Mutex _numProviderProcessesMutex;
407
408 /**
409 A value indicating that a request message has not been processed.
410 A CIMResponseMessage pointer with this value indicates that the
411 corresponding CIMRequestMessage has not been processed. This is
412 used to indicate that a provider agent exited without starting to
413 process the request, and that the request should be retried.
414 s.kodali 1.1 */
415 static CIMResponseMessage* _REQUEST_NOT_PROCESSED;
416
417 /**
418 Indicates whether the Indication Service has completed initialization.
419
420 For more information, please see the description of the
421 ProviderManagerRouter::_subscriptionInitComplete member variable.
422 */
423 Boolean _subscriptionInitComplete;
424
|
425 s.kodali 1.3
|
426 s.kodali 1.1 /**
427 OOPProviderManagerRouter ThreadPool pointer.
428 */
429 ThreadPool* _threadPool;
430
|
431 venkat.puvvada 1.7 static Boolean _allProvidersStopped;
|
432 s.kodali 1.1 };
433
434 Uint32 ProviderAgentContainer::_numProviderProcesses = 0;
435 Mutex ProviderAgentContainer::_numProviderProcessesMutex;
|
436 venkat.puvvada 1.7 Boolean ProviderAgentContainer::_allProvidersStopped = false;
|
437 s.kodali 1.1
438 // Set this to a value that no valid CIMResponseMessage* will have.
439 CIMResponseMessage* ProviderAgentContainer::_REQUEST_NOT_PROCESSED =
440 static_cast<CIMResponseMessage*>((void*)&_REQUEST_NOT_PROCESSED);
441
442 ProviderAgentContainer::ProviderAgentContainer(
|
443 s.kodali 1.3 Uint16 bitness,
|
444 s.kodali 1.1 const String & groupName,
445 const String & userName,
446 Uint16 userContext,
447 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
448 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
449 PEGASUS_PROVIDERMODULEGROUPFAIL_CALLBACK_T providerModuleGroupFailCallback,
450 PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback,
451 Boolean subscriptionInitComplete,
452 ThreadPool* threadPool)
453 :
|
454 s.kodali 1.3 _bitness(bitness),
|
455 s.kodali 1.1 _groupNameWithType(groupName),
456 _userName(userName),
457 _userContext(userContext),
458 _indicationCallback(indicationCallback),
459 _responseChunkCallback(responseChunkCallback),
460 _providerModuleGroupFailCallback(providerModuleGroupFailCallback),
461 _asyncResponseCallback(asyncResponseCallback),
462 _isInitialized(false),
463 _subscriptionInitComplete(subscriptionInitComplete),
464 _threadPool(threadPool)
465 {
466 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
467 "ProviderAgentContainer::ProviderAgentContainer");
468
469 // Remove prefixes "grp" and "mod" and get actual module or group name.
470 _moduleOrGroupName = _groupNameWithType.subString(4);
471
472 PEG_METHOD_EXIT();
473 }
474
475 ProviderAgentContainer::~ProviderAgentContainer()
476 s.kodali 1.1 {
477 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
478 "ProviderAgentContainer::~ProviderAgentContainer");
479
480 // Ensure the destructor does not throw an exception
481 try
482 {
483 if (isInitialized())
484 {
485 {
486 AutoMutex lock(_agentMutex);
487 // Check if the _pipeFromAgent is alive.
488 if( _pipeFromAgent.get() != 0 )
489 {
490 // Stop the responseProcessor thread by closing its
491 // connection.
492 _pipeFromAgent->closeReadHandle();
493 }
494 }
495
496 // Wait for the responseProcessor thread to exit
497 s.kodali 1.1 while (isInitialized())
498 {
499 Threads::yield();
500 }
501 }
502 }
503 catch (...)
504 {
505 }
506
507 PEG_METHOD_EXIT();
508 }
509
|
510 venkat.puvvada 1.7 void ProviderAgentContainer::setAllProvidersStopped()
511 {
512 _allProvidersStopped = true;
513 }
514
|
515 s.kodali 1.1 void ProviderAgentContainer::_startAgentProcess()
516 {
517 PEG_METHOD_ENTER(
518 TRC_PROVIDERMANAGER, "ProviderAgentContainer::_startAgentProcess");
519
520 // Start the provider agent.
521
522 int pid;
523 AnonymousPipe* readPipe;
524 AnonymousPipe* writePipe;
525 int status = Executor::startProviderAgent(
|
526 s.kodali 1.3 (unsigned short)_bitness,
|
527 s.kodali 1.1 (const char*)_moduleOrGroupName.getCString(),
528 ConfigManager::getPegasusHome(),
529 _userName,
530 pid,
531 readPipe,
532 writePipe);
533
534 if (status != 0)
535 {
536 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
537 "Executor::startProviderAgent() failed"));
538 PEG_METHOD_EXIT();
539 throw Exception(MessageLoaderParms(
540 "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
541 "Failed to start cimprovagt \"$0\".",
542 _moduleOrGroupName));
543 }
544
545 # if defined(PEGASUS_HAS_SIGNALS)
546 _pid = pid;
547 # endif
548 s.kodali 1.1
549 _pipeFromAgent.reset(readPipe);
550 _pipeToAgent.reset(writePipe);
551
552 PEG_METHOD_EXIT();
553 }
554
555 // Note: Caller must lock _agentMutex
556 void ProviderAgentContainer::_sendInitializationData()
557 {
558 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
559 "ProviderAgentContainer::_sendInitializationData");
560
561 //
562 // Gather config properties to pass to the Provider Agent
563 //
564 ConfigManager* configManager = ConfigManager::getInstance();
565 Array<Pair<String, String> > configProperties;
566
567 Array<String> configPropertyNames;
568 configManager->getAllPropertyNames(configPropertyNames, true);
569 s.kodali 1.1 for (Uint32 i = 0; i < configPropertyNames.size(); i++)
570 {
571 String configPropertyValue =
572 configManager->getCurrentValue(configPropertyNames[i]);
573 String configPropertyDefaultValue =
574 configManager->getDefaultValue(configPropertyNames[i]);
575 if (configPropertyValue != configPropertyDefaultValue)
576 {
577 configProperties.append(Pair<String, String>(
578 configPropertyNames[i], configPropertyValue));
579 }
580 }
581
582 //
583 // Create a Provider Agent initialization message
584 //
585 AutoPtr<CIMInitializeProviderAgentRequestMessage> request(
586 new CIMInitializeProviderAgentRequestMessage(
587 String("0"), // messageId
588 configManager->getPegasusHome(),
589 configProperties,
590 s.kodali 1.1 System::bindVerbose,
591 _subscriptionInitComplete,
592 QueueIdStack()));
593
594 //
595 // Write the initialization message to the pipe
596 //
597 AnonymousPipe::Status writeStatus =
598 _pipeToAgent->writeMessage(request.get());
599
600 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
601 {
602 PEG_METHOD_EXIT();
603 throw Exception(MessageLoaderParms(
604 "ProviderManager.OOPProviderManagerRouter."
605 "CIMPROVAGT_COMMUNICATION_FAILED",
606 "Failed to communicate with cimprovagt \"$0\".",
607 _moduleOrGroupName));
608 }
609
610 // Wait for a null response from the Provider Agent indicating it has
611 s.kodali 1.1 // initialized successfully.
612
613 CIMMessage* message;
614 AnonymousPipe::Status readStatus;
615 do
616 {
617 readStatus = _pipeFromAgent->readMessage(message);
618
619 } while (readStatus == AnonymousPipe::STATUS_INTERRUPT);
620
621 if (readStatus != AnonymousPipe::STATUS_SUCCESS)
622 {
623 PEG_METHOD_EXIT();
624 throw Exception(MessageLoaderParms(
625 "ProviderManager.OOPProviderManagerRouter."
626 "CIMPROVAGT_COMMUNICATION_FAILED",
627 "Failed to communicate with cimprovagt \"$0\".",
628 _moduleOrGroupName));
629 }
630
631 PEGASUS_ASSERT(message == 0);
632 s.kodali 1.1
633 PEG_METHOD_EXIT();
634 }
635
636 // Note: Caller must lock _agentMutex
637 void ProviderAgentContainer::_initialize()
638 {
639 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
640 "ProviderAgentContainer::_initialize");
641
642 if (_isInitialized)
643 {
644 PEGASUS_ASSERT(0);
645 PEG_METHOD_EXIT();
646 return;
647 }
648
649 //Get the current value of maxProviderProcesses
650 String maxProviderProcessesString = ConfigManager::getInstance()->
651 getCurrentValue("maxProviderProcesses");
652 Uint64 v;
653 s.kodali 1.1 StringConversion::decimalStringToUint64(
654 maxProviderProcessesString.getCString(),
655 v);
656 Uint32 maxProviderProcesses = (Uint32)v;
657
658 char* end = 0;
659
660 {
661 AutoMutex lock(_numProviderProcessesMutex);
662
663 if ((maxProviderProcesses != 0) &&
664 (_numProviderProcesses >= maxProviderProcesses))
665 {
666 throw PEGASUS_CIM_EXCEPTION(
667 CIM_ERR_FAILED,
668 MessageLoaderParms(
669 "ProviderManager.OOPProviderManagerRouter."
670 "MAX_PROVIDER_PROCESSES_REACHED",
671 "The maximum number of cimprovagt processes has been "
672 "reached."));
673 }
674 s.kodali 1.1 else
675 {
676 _numProviderProcesses++;
677 }
678 }
679
680 try
681 {
682 _startAgentProcess();
683 _isInitialized = true;
684 _sendInitializationData();
685
686 // Start a thread to read and process responses from the Provider Agent
687 ThreadStatus rtn = PEGASUS_THREAD_OK;
688 while ((rtn = MessageQueueService::get_thread_pool()->
689 allocate_and_awaken(this, _responseProcessor)) !=
690 PEGASUS_THREAD_OK)
691 {
692 if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
693 {
694 Threads::yield();
695 s.kodali 1.1 }
696 else
697 {
698 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
699 "Could not allocate thread to process responses from the "
700 "provider agent.");
701
702 throw Exception(MessageLoaderParms(
703 "ProviderManager.OOPProviderManagerRouter."
704 "CIMPROVAGT_THREAD_ALLOCATION_FAILED",
705 "Failed to allocate thread for cimprovagt \"$0\".",
706 _moduleOrGroupName));
707 }
708 }
709 }
710 catch (...)
711 {
712 // Closing the connection causes the agent process to exit
713 _pipeToAgent.reset();
714 _pipeFromAgent.reset();
715
716 s.kodali 1.1 #if defined(PEGASUS_HAS_SIGNALS)
717 if (_isInitialized)
718 {
719 // Harvest the status of the agent process to prevent a zombie
720 int status = Executor::reapProviderAgent(_pid);
721
722 if (status == -1)
723 {
724 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
725 "ProviderAgentContainer::_initialize(): "
726 "Executor::reapProviderAgent() failed"));
727 }
728 }
729 #endif
730
731 _isInitialized = false;
732
733 {
734 AutoMutex lock(_numProviderProcessesMutex);
735 _numProviderProcesses--;
736 }
737 s.kodali 1.1
738 PEG_METHOD_EXIT();
739 throw;
740 }
741
742 PEG_METHOD_EXIT();
743 }
744
745 Boolean ProviderAgentContainer::isInitialized()
746 {
747 AutoMutex lock(_agentMutex);
748 return _isInitialized;
749 }
750
751 void ProviderAgentContainer::_uninitialize(Boolean cleanShutdown)
752 {
753 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
754 "ProviderAgentContainer::_uninitialize");
755
756 #if defined(PEGASUS_HAS_SIGNALS)
757 pid_t pid = 0;
758 s.kodali 1.1 #endif
759
760 try
761 {
|
762 venkat.puvvada 1.8 CIMException cimException;
763 if (!cleanShutdown)
764 {
765 cimException = PEGASUS_CIM_EXCEPTION(
766 CIM_ERR_FAILED,
767 MessageLoaderParms(
768 "ProviderManager.OOPProviderManagerRouter."
769 "CIMPROVAGT_CONNECTION_LOST",
770 "Lost connection with cimprovagt \"$0\".",
771 _moduleOrGroupName));
772 }
773
|
774 s.kodali 1.1 AutoMutex lock(_agentMutex);
775
776 PEGASUS_ASSERT(_isInitialized);
777
778 // Close the connection with the Provider Agent
779 _pipeFromAgent.reset();
780 _pipeToAgent.reset();
781
782 _providerModuleCache = CIMInstance();
783
784 {
785 AutoMutex lock2(_numProviderProcessesMutex);
786 _numProviderProcesses--;
787 }
788
789 _isInitialized = false;
790
791 #if defined(PEGASUS_HAS_SIGNALS)
792 // Save the _pid so we can use it after we've released the _agentMutex
793 pid = _pid;
794 #endif
795 s.kodali 1.1
796 // In case of a clean shutdown requests which could not be processed are
797 // retried in a new thread.
798 Array<CIMRequestMessage *> retryReqArray;
799
800 //
801 // Complete with null responses all outstanding requests on this
802 // connection
803 //
804 {
805 AutoMutex tableLock(_outstandingRequestTableMutex);
806
807 for (OutstandingRequestTable::Iterator i =
808 _outstandingRequestTable.start();
809 i != 0; i++)
810 {
811 Boolean sendResponseNow = false;
812 CIMResponseMessage *response;
813
|
814 venkat.puvvada 1.8 MessageType msgType = i.value()->requestMessage->getType();
815
816 // Note: Whether this agent was shutdown cleanly or not,
817 // for the below requests wait until all responses are
818 // received.
819 if(msgType == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE ||
820 msgType == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE ||
821 msgType ==
822 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE ||
823 msgType ==
824 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE ||
825 msgType == CIM_ENABLE_MODULE_REQUEST_MESSAGE ||
826 msgType == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
|
827 s.kodali 1.1 {
|
828 venkat.puvvada 1.8 PEGASUS_ASSERT(i.value()->respAggregator);
829 if(i.value()->respAggregator->isComplete(cimException))
830 {
831 CIMException cimException;
832 sendResponseNow = true;
833
834 if (msgType == CIM_ENABLE_MODULE_REQUEST_MESSAGE ||
835 msgType == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
836 {
837 CIMException e =
838 i.value()->respAggregator->getException();
839 if (e.getCode() == CIM_ERR_SUCCESS)
840 {
841 retryReqArray.append(i.value()->requestMessage);
842 sendResponseNow = false;
843 }
844 else
845 {
846 cimException = e;
847 }
848 }
|
849 s.kodali 1.1
|
850 venkat.puvvada 1.8 if (sendResponseNow)
|
851 sahana.prabhakar 1.2 {
852 response =
853 i.value()->requestMessage->buildResponse();
854 response->messageId = i.value()->originalMessageId;
|
855 venkat.puvvada 1.8 response->cimException = cimException;
|
856 sahana.prabhakar 1.2 sendResponseNow = true;
857 }
|
858 venkat.puvvada 1.8 delete i.value()->respAggregator;
|
859 s.kodali 1.1 }
|
860 venkat.puvvada 1.8 }
861 else if (msgType == CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE)
862 {
863 response = i.value()->requestMessage->buildResponse();
864 response->messageId = i.value()->originalMessageId;
865 sendResponseNow = true;
866 }
867 else if (cleanShutdown)
868 {
869 // retry the request
870 retryReqArray.append(i.value()->requestMessage);
|
871 s.kodali 1.1 }
872 else
873 {
|
874 venkat.puvvada 1.8 // Requests with respAggregator set were already handled
875 // before.
876 PEGASUS_ASSERT(!i.value()->respAggregator);
|
877 s.kodali 1.1 response = i.value()->requestMessage->buildResponse();
|
878 venkat.puvvada 1.8 response->cimException = cimException;
|
879 s.kodali 1.1 sendResponseNow = true;
880 }
881
882 if(sendResponseNow)
883 {
884 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
885 "Completing messageId \"%s\" with a default response.",
886 (const char*)i.key().getCString()));
887
888 response->setComplete(true);
889 _asyncResponseCallback(
890 i.value()->requestMessage,
891 response);
892 }
893 }
894 _outstandingRequestTable.clear();
895 }
896
897 if(retryReqArray.size() > 0 )
898 {
899 ThreadStatus rtn = PEGASUS_THREAD_OK;
900 s.kodali 1.1 AutoPtr<RetryThreadParam> parms(new RetryThreadParam());
901 parms->pac = this;
902 parms->retryRequestArray = retryReqArray;
903
904 Boolean didRetry = true;
905
906 while((rtn = _threadPool->allocate_and_awaken(
907 (void*)parms.release(),
908 ProviderAgentContainer::_retryRequestHandler))
909 != PEGASUS_THREAD_OK)
910 {
911 if(rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
912 {
913 Threads::yield();
914 }
915 else
916 {
917 PEG_TRACE((TRC_PROVIDERMANAGER,
918 Tracer::LEVEL1,
919 "Could not allocate thread to retry "
920 "request in %s",
921 s.kodali 1.1 (const char *)_moduleOrGroupName. \
922 getCString()));
923 didRetry = false;
924 }
925 }
926
927 if(!didRetry)
928 {
929 for(Uint32 i=0; i<retryReqArray.size(); i++)
930 {
931 CIMResponseMessage *response =
932 retryReqArray[i]->buildResponse();
933 response->setComplete(true);
934 response->cimException =
935 PEGASUS_CIM_EXCEPTION(
936 CIM_ERR_FAILED,
937 MessageLoaderParms("ProviderManager."
938 "OOPProviderManagerRouter."
939 "REQUEST_RETRY_THREAD_"
940 "ALLOCATION_FAILED",
941 "Failed to allocate a thread to "
942 s.kodali 1.1 "retry a request in \"$0\".",
943 _moduleOrGroupName));
944
945 _asyncResponseCallback(
946 retryReqArray[i],
947 response);
948 }
949 }
950 }
951
952 //
953 // If not a clean shutdown, call the provider module failure callback
954 //
955 if (!cleanShutdown)
956 {
957 //
958 // Call the provider module failure callback to communicate
959 // the failure to the Provider Manager Service. The Provider
960 // Manager Service will inform the Indication Service.
961 //
962
963 s.kodali 1.1 // If this agent is servicing the group of modules, get all related
964 // provider module names.
965 Boolean isGroup = !String::compare(
966 _groupNameWithType, _GROUP_PREFIX, 4);
967
968 _providerModuleGroupFailCallback(
969 _moduleOrGroupName, _userName, _userContext, isGroup);
970 }
971 }
972 catch (...)
973 {
974 // We're uninitializing, so do not propagate the exception
975 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
976 "Ignoring _uninitialize() exception.");
977 }
978
979 #if defined(PEGASUS_HAS_SIGNALS)
980 // Harvest the status of the agent process to prevent a zombie. Do not
981 // hold the _agentMutex during this operation.
982
983 if ((pid != 0) && (Executor::reapProviderAgent(pid) == -1))
984 s.kodali 1.1 {
985 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL2,
986 "ProviderAgentContainer::_uninitialize(): "
987 "Executor::reapProviderAgent() failed."));
988 }
989 #endif
990
991 PEG_METHOD_EXIT();
992 }
993
994 String ProviderAgentContainer::getGroupNameWithType() const
995 {
996 return _groupNameWithType;
997 }
998
|
999 venkat.puvvada 1.9 void ProviderAgentContainer::sendResponse(CIMResponseMessage *response)
1000 {
|
1001 venkat.puvvada 1.10 AutoMutex lock(_agentMutex);
1002
1003 AnonymousPipe::Status writeStatus =
1004 _pipeToAgent->writeMessage(response);
1005 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1006 {
1007 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1008 "Failed to write message to pipe. writeStatus = %d.",
1009 writeStatus));
1010 }
|
1011 venkat.puvvada 1.11 delete response;
|
1012 venkat.puvvada 1.9 }
1013
|
1014 s.kodali 1.1 CIMResponseMessage* ProviderAgentContainer::processMessage(
1015 CIMRequestMessage* request,RespAggCounter* respAggregator)
1016 {
1017 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1018 "ProviderAgentContainer::processMessage");
1019
1020 CIMResponseMessage* response;
1021 MessageType msgType = request->getType();
1022
1023 do
1024 {
1025 response = _processMessage(request,respAggregator);
1026
1027 if (response == _REQUEST_NOT_PROCESSED)
1028 {
1029 // Check for request message types that should not be retried.
1030 if ((request->getType() ==
1031 CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1032 (request->getType() ==
1033 CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE) ||
1034 (request->getType() ==
1035 s.kodali 1.1 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1036 (request->getType() ==
1037 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE) ||
1038 (request->getType() ==
1039 CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE))
1040 {
1041 response = request->buildResponse();
1042 break;
1043 }
1044 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1045 {
1046 response = request->buildResponse();
1047 CIMDisableModuleResponseMessage* dmResponse =
1048 dynamic_cast<CIMDisableModuleResponseMessage*>(response);
1049 PEGASUS_ASSERT(dmResponse != 0);
1050
1051 Array<Uint16> operationalStatus;
1052 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1053 dmResponse->operationalStatus = operationalStatus;
1054 break;
1055 }
1056 s.kodali 1.1 }
1057 } while (response == _REQUEST_NOT_PROCESSED);
1058
1059 PEG_METHOD_EXIT();
1060 return response;
1061 }
1062
1063 CIMResponseMessage* ProviderAgentContainer::_processMessage(
1064 CIMRequestMessage* request, RespAggCounter *respAggregator)
1065 {
1066 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1067 "ProviderAgentContainer::_processMessage");
1068
1069 CIMResponseMessage* response;
1070 String originalMessageId = request->messageId;
1071
1072 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
1073 "ProviderAgentContainer, process message ID %s",
1074 (const char*)request->messageId.getCString()));
1075
1076 // These three variables are used for the provider module optimization.
1077 s.kodali 1.1 // See the _providerModuleCache member description for more information.
1078 AutoPtr<ProviderIdContainer> origProviderId;
1079 Boolean doProviderModuleOptimization = false;
1080 Boolean updateProviderModuleCache = false;
1081
1082 try
1083 {
1084 // The messageId attribute is used to correlate response messages
1085 // from the Provider Agent with request messages, so it is imperative
1086 // that the ID is unique for each request. The incoming ID cannot be
1087 // trusted to be unique, so we substitute a unique one. The memory
1088 // address of the request is used as the source of a unique piece of
1089 // data. (The message ID is only required to be unique while the
1090 // request is outstanding.)
1091 char messagePtrString[20];
1092 sprintf(messagePtrString, "%p", request);
1093 String uniqueMessageId = messagePtrString;
1094
1095 //
1096 // Set up the OutstandingRequestEntry for this request
1097 //
1098 s.kodali 1.1 SharedPtr<OutstandingRequestEntry> outstandingRequestEntry(
1099 new OutstandingRequestEntry(
1100 originalMessageId,
1101 request,
1102 response,
1103 respAggregator));
1104
1105 //
1106 // Lock the Provider Agent Container while initializing the
1107 // agent and writing the request to the connection
1108 //
1109 {
1110 AutoMutex lock(_agentMutex);
1111
|
1112 venkat.puvvada 1.7 // Don't process any other messages if _allProvidersStopped flag
1113 // is set. CIMServer hangs during the shutdown if the agent is
1114 // started to process a request after StopAllProviders request
1115 // has been processed. This scenario may happen if provider
1116 // generates indication during the shutdwon whose destination is
1117 // indication consumer provider running within cimserver.
1118 if (_allProvidersStopped &&
1119 request->getType() != CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1120 {
1121 //Note: l11n is not necessary, not propagated to client.
1122 CIMException e = CIMException(
1123 CIM_ERR_FAILED,
1124 "Request not processed, CIMServer shutting down");
1125 if (!respAggregator || respAggregator->isComplete(e))
1126 {
1127
1128 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1129 "Exception: %s",
1130 (const char*)e.getMessage().getCString()));
1131 response = request->buildResponse();
1132 delete respAggregator;
1133 venkat.puvvada 1.7 PEG_METHOD_EXIT();
1134 return response;
1135 }
1136 }
1137
|
1138 s.kodali 1.1 //
1139 // Initialize the Provider Agent, if necessary
1140 //
1141 if (!_isInitialized)
1142 {
1143 _initialize();
1144 }
1145
1146 //
1147 // Add an entry to the OutstandingRequestTable for this request
1148 //
1149 {
1150 AutoMutex tableLock(_outstandingRequestTableMutex);
1151
1152 _outstandingRequestTable.insert(
1153 uniqueMessageId, outstandingRequestEntry);
1154 }
1155
1156 // Get the provider module from the ProviderIdContainer to see if
1157 // we can optimize out the transmission of this instance to the
1158 // Provider Agent. (See the _providerModuleCache description.)
1159 s.kodali 1.1 if (request->operationContext.contains(ProviderIdContainer::NAME))
1160 {
1161 ProviderIdContainer pidc = request->operationContext.get(
1162 ProviderIdContainer::NAME);
1163 origProviderId.reset(new ProviderIdContainer(
1164 pidc.getModule(), pidc.getProvider(),
1165 pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
|
1166 venkat.puvvada 1.12 origProviderId->setProvMgrPath(pidc.getProvMgrPath());
|
1167 s.kodali 1.1 if (_providerModuleCache.isUninitialized() ||
1168 (!pidc.getModule().identical(_providerModuleCache)))
1169 {
1170 // We haven't sent this provider module instance to the
1171 // Provider Agent yet. Update our cache after we send it.
1172 updateProviderModuleCache = true;
1173 }
1174 else
1175 {
1176 // Replace the provider module in the ProviderIdContainer
1177 // with an uninitialized instance. We'll need to put the
1178 // original one back after the message is sent.
1179 ProviderIdContainer newpidc = ProviderIdContainer(
1180 CIMInstance(), pidc.getProvider(),
1181 pidc.isRemoteNameSpace(), pidc.getRemoteInfo());
1182 newpidc.setProvMgrPath(pidc.getProvMgrPath());
1183 request->operationContext.set(newpidc);
1184
1185 doProviderModuleOptimization = true;
1186 }
1187 }
1188 s.kodali 1.1
1189 //
1190 // Write the message to the pipe
1191 //
1192 try
1193 {
1194 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
1195 "Sending request to agent with messageId %s",
1196 (const char*)uniqueMessageId.getCString()));
1197
1198 request->messageId = uniqueMessageId;
1199 AnonymousPipe::Status writeStatus =
1200 _pipeToAgent->writeMessage(request);
1201 request->messageId = originalMessageId;
1202
1203 if (doProviderModuleOptimization)
1204 {
1205 request->operationContext.set(*origProviderId.get());
1206 }
1207
1208 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1209 s.kodali 1.1 {
1210 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1211 "Failed to write message to pipe. writeStatus = %d.",
1212 writeStatus));
1213
1214 request->messageId = originalMessageId;
1215
1216 if (doProviderModuleOptimization)
1217 {
1218 request->operationContext.set(*origProviderId.get());
1219 }
1220
1221 // Remove this OutstandingRequestTable entry
1222 {
1223 AutoMutex tableLock(_outstandingRequestTableMutex);
1224 Boolean removed =
1225 _outstandingRequestTable.remove(uniqueMessageId);
1226 PEGASUS_ASSERT(removed);
1227 }
1228
1229 // A response value of _REQUEST_NOT_PROCESSED indicates
1230 s.kodali 1.1 // that the request was not processed by the provider
1231 // agent, so it can be retried safely.
1232 PEG_METHOD_EXIT();
1233 return _REQUEST_NOT_PROCESSED;
1234 }
1235
1236 if (updateProviderModuleCache)
1237 {
1238 _providerModuleCache = origProviderId->getModule();
1239 }
1240
1241 response = request->buildResponse();
1242 response->isAsyncResponsePending = true;
1243 PEG_METHOD_EXIT();
1244
1245 return response;
1246 }
1247 catch (...)
1248 {
1249 request->messageId = originalMessageId;
1250
1251 s.kodali 1.1 if (doProviderModuleOptimization)
1252 {
1253 request->operationContext.set(*origProviderId.get());
1254 }
1255
1256 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1257 "Failed to write message to pipe.");
1258 // Remove the OutstandingRequestTable entry for this request
1259 {
1260 AutoMutex tableLock(_outstandingRequestTableMutex);
1261 Boolean removed =
1262 _outstandingRequestTable.remove(uniqueMessageId);
1263 PEGASUS_ASSERT(removed);
1264 }
1265 PEG_METHOD_EXIT();
1266 throw;
1267 }
1268 }
1269 }
1270 catch (CIMException& e)
1271 {
1272 s.kodali 1.1 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1273 "Caught CIMException: %s",
1274 (const char*)e.getMessage().getCString()));
1275 response = request->buildResponse();
1276 response->cimException = e;
1277 }
1278 catch (Exception& e)
1279 {
1280 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1281 "Caught Exception: %s",
1282 (const char*)e.getMessage().getCString()));
1283 response = request->buildResponse();
1284 response->cimException = PEGASUS_CIM_EXCEPTION(
1285 CIM_ERR_FAILED, e.getMessage());
1286 }
1287 catch (...)
1288 {
1289 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1290 "Caught unknown exception");
1291 response = request->buildResponse();
1292 response->cimException = PEGASUS_CIM_EXCEPTION(
1293 s.kodali 1.1 CIM_ERR_FAILED, String());
1294 }
1295
1296 response->messageId = originalMessageId;
1297 response->syncAttributes(request);
1298
1299 PEG_METHOD_EXIT();
1300 return response;
1301 }
1302
1303 void ProviderAgentContainer::unloadIdleProviders()
1304 {
1305 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1306 "ProviderAgentContainer::unloadIdleProviders");
1307
1308 AutoMutex lock(_agentMutex);
1309 if (_isInitialized)
1310 {
1311 // Send a "wake up" message to the Provider Agent.
1312 // Don't bother checking whether the operation is successful.
1313 Uint32 messageLength = 0;
1314 s.kodali 1.1 _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
1315 }
1316
1317 PEG_METHOD_EXIT();
1318 }
1319
1320 void ProviderAgentContainer::cleanDisconnectedClientRequests()
1321 {
1322 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1323 "ProviderAgentContainer::cleanDisconnectedClientRequests");
1324
1325 // Array to store the keys which need to be remvoed.
1326 Array<String> keys;
1327
1328 AutoMutex tableLock(_outstandingRequestTableMutex);
1329 for (OutstandingRequestTable::Iterator i = _outstandingRequestTable.start();
1330 i != 0; i++)
1331 {
1332 if(!_isClientActive(i.value()->requestMessage))
1333 {
1334 // create empty response and set isComplete to true.
1335 s.kodali 1.1 AutoPtr<CIMResponseMessage> response;
1336 SharedPtr<OutstandingRequestEntry> entry = i.value();
1337 response.reset(i.value()->requestMessage->buildResponse());
1338 response->setComplete(true);
1339 response->messageId = i.value()->originalMessageId;
1340 _asyncResponseCallback(
1341 i.value()->requestMessage,
1342 response.release());
1343 keys.append(i.key());
1344 }
1345 }
1346
1347 for(Uint32 j=0; j<keys.size();j++)
1348 {
1349 _outstandingRequestTable.remove(keys[j]);
1350 }
1351 PEG_METHOD_EXIT();
1352 }
1353
1354 void ProviderAgentContainer::_processGetSCMOClassRequest(
1355 ProvAgtGetScmoClassRequestMessage* request)
1356 s.kodali 1.1 {
1357 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1358 "ProviderAgentContainer::_processGetSCMOClassRequest");
1359
1360 AutoPtr<ProvAgtGetScmoClassResponseMessage> response(
1361 new ProvAgtGetScmoClassResponseMessage(
|
1362 venkat.puvvada 1.6 request->messageId,
|
1363 s.kodali 1.1 CIMException(),
1364 QueueIdStack(),
1365 SCMOClass("","")));
1366
1367 CString ns = request->nameSpace.getString().getCString();
1368 CString cn = request->className.getString().getCString();
1369
1370 delete request;
1371
1372 response->scmoClass = SCMOClassCache::getInstance()->getSCMOClass(
1373 ns,strlen(ns),
1374 cn,strlen(cn));
1375
1376 //
1377 // Lock the Provider Agent Container and
1378 // writing the response to the connection
1379 //
1380 {
1381
1382 AutoMutex lock(_agentMutex);
1383
1384 s.kodali 1.1 //
1385 // Write the message to the pipe
1386 //
1387 try
1388 {
1389
1390 AnonymousPipe::Status writeStatus =
1391 _pipeToAgent->writeMessage(response.get());
1392
1393 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1394 {
1395 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1396 "Failed to write message to pipe. writeStatus = %d.",
1397 writeStatus));
1398
1399 PEG_METHOD_EXIT();
1400 return;
1401 }
1402
1403 }
1404 catch (Exception & e)
1405 s.kodali 1.1 {
1406 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1407 "Exception: Failed to write message to pipe. Error: %s",
1408 (const char*)e.getMessage().getCString()));
1409 PEG_METHOD_EXIT();
1410 throw;
1411 }
1412 catch (...)
1413 {
1414
1415 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1416 "Unkonwn exception. Failed to write message to pipe.");
1417 PEG_METHOD_EXIT();
1418 throw;
1419 }
1420 }
1421
1422 PEG_METHOD_EXIT();
1423 return;
1424 }
1425
1426 s.kodali 1.1 Boolean ProviderAgentContainer::_isClientActive(CIMRequestMessage *request_)
1427 {
1428 MessageQueue *connectionMQ = MessageQueue::lookup(request_->queueIds[0]);
1429 return connectionMQ->isActive();
1430 }
1431
1432 // Note: This method should not throw an exception. It is used as a thread
1433 // entry point, and any exceptions thrown are ignored.
1434 ThreadReturnType PEGASUS_THREAD_CDECL
1435 ProviderAgentContainer::_retryRequestHandler(void* arg)
1436 {
1437 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1438 "ProviderAgentContainer::_retryRequestHandler");
1439
1440 PEGASUS_ASSERT(arg != 0);
1441 RetryThreadParam *threadParams=
1442 reinterpret_cast<RetryThreadParam *>(arg);
1443 Array<CIMRequestMessage *> retryRequests = threadParams->retryRequestArray;
1444
1445 try
1446 {
1447 s.kodali 1.1 for(Uint32 i=0; i<retryRequests.size(); i++)
1448 {
1449 threadParams->pac->processMessage(retryRequests[i]);
1450 }
1451 }
1452 catch(Exception &e)
1453 {
1454 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
1455 "Unexpected exception in _retryRequestHandler: %s",
1456 (const char*)e.getMessage().getCString()));
1457 }
1458 catch (...)
1459 {
1460 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
1461 "Unexpected exception in _retryRequestHandler.");
1462 }
1463 PEG_METHOD_EXIT();
1464
1465 return ThreadReturnType(0);
1466 }
1467
1468 s.kodali 1.1
1469 void ProviderAgentContainer::_processResponses()
1470 {
1471 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1472 "ProviderAgentContainer::_processResponses");
1473
1474 //
1475 // Process responses until the pipe is closed
1476 //
1477 while (1)
1478 {
1479 try
1480 {
1481 CIMMessage* message;
1482
1483 //
1484 // Read a response from the Provider Agent
1485 //
1486 AnonymousPipe::Status readStatus =
1487 _pipeFromAgent->readMessage(message);
1488
1489 s.kodali 1.1 // Ignore interrupts
1490 if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
1491 {
1492 continue;
1493 }
1494
1495 // Handle an error the same way as a closed connection
1496 if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
1497 (readStatus == AnonymousPipe::STATUS_CLOSED))
1498 {
1499 _uninitialize(false);
1500 return;
1501 }
1502
1503 // A null message indicates that the provider agent process has
1504 // finished its processing and is ready to exit.
1505 if (message == 0)
1506 {
1507 _uninitialize(true);
1508 return;
1509 }
1510 s.kodali 1.1
1511 if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
1512 {
1513 // Process an indication message
|
1514 venkat.puvvada 1.9 CIMProcessIndicationRequestMessage* request =
|
1515 s.kodali 1.1 reinterpret_cast<CIMProcessIndicationRequestMessage*>(
|
1516 venkat.puvvada 1.9 message);
1517 request->oopAgentName = getGroupNameWithType();
1518 _indicationCallback(request);
|
1519 s.kodali 1.1 }
1520 else if (message->getType()==PROVAGT_GET_SCMOCLASS_REQUEST_MESSAGE)
1521 {
1522
1523 _processGetSCMOClassRequest(
1524 reinterpret_cast<ProvAgtGetScmoClassRequestMessage*>(
1525 message));
1526 }
1527 else if (!message->isComplete())
1528 {
1529 // Process an incomplete response chunk
1530
1531 CIMResponseMessage* response;
1532 response = dynamic_cast<CIMResponseMessage*>(message);
1533 PEGASUS_ASSERT(response != 0);
1534
1535 Boolean foundEntry = false;
1536 // Get the OutstandingRequestEntry for this response chunk
1537 SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
1538 {
1539 AutoMutex tableLock(_outstandingRequestTableMutex);
1540 s.kodali 1.1 foundEntry = _outstandingRequestTable.lookup(
1541 response->messageId, _outstandingRequestEntry);
1542 }
1543
1544 if(foundEntry)
1545 {
1546 // Put the original message ID into the response
1547 response->messageId =
1548 _outstandingRequestEntry->originalMessageId;
1549
1550 // Call the response chunk callback to process the chunk
1551 // if the client connection is active.
1552 // No need to acquire _agentMutex since this a chunk
1553 // response callback. The request object will not be
1554 // deleted here.
1555 _responseChunkCallback(
1556 _outstandingRequestEntry->requestMessage, response);
1557 }
1558 }
1559 else
1560 {
1561 s.kodali 1.1 // Process a completed response
1562 CIMResponseMessage* response;
1563 response = dynamic_cast<CIMResponseMessage*>(message);
1564 PEGASUS_ASSERT(response != 0);
1565
1566 Boolean foundEntry = false;
1567 // Give the response to the waiting OutstandingRequestEntry
1568 SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
1569 {
1570 AutoMutex tableLock(_outstandingRequestTableMutex);
1571 foundEntry = _outstandingRequestTable.lookup(
1572 response->messageId, _outstandingRequestEntry);
1573
1574 if(foundEntry)
1575 {
1576 // Remove the completed request from the table
1577 Boolean removed = _outstandingRequestTable.remove( \
1578 response->messageId);
1579 PEGASUS_ASSERT(removed);
1580 }
1581
1582 s.kodali 1.1 }
1583
1584 if(foundEntry)
1585 {
1586 if(_outstandingRequestEntry->respAggregator == NULL)
1587 {
1588 response->messageId =
1589 _outstandingRequestEntry->originalMessageId;
1590
1591 _sendResponse(_outstandingRequestEntry->requestMessage,
1592 response);
1593 }
1594 else
1595 {
1596 if(_outstandingRequestEntry->respAggregator-> \
1597 isComplete(response->cimException))
1598 {
1599 response->messageId =
1600 _outstandingRequestEntry->originalMessageId;
1601
1602 _sendResponse(
1603 s.kodali 1.1 _outstandingRequestEntry->requestMessage,
1604 response);
1605
1606 // delete respAggregator pointer now
1607 delete _outstandingRequestEntry->respAggregator;
1608 }
1609 else
1610 {
1611 // this is not the last response for this request.
1612 // Its job is done and it can be deleted now.
1613 delete response;
1614 }
1615 }
1616 }
1617 else
1618 {
1619 PEG_TRACE((TRC_DISCARDED_DATA,Tracer::LEVEL4,
1620 "The response for message id %s arrived after the " \
1621 "client disconnected.",
1622 (const char *)response->messageId.getCString()));
1623 }
1624 s.kodali 1.1 }
1625 }
1626 catch (Exception& e)
1627 {
1628 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL2,
1629 "Ignoring exception: %s",
1630 (const char*)e.getMessage().getCString()));
1631 }
1632 catch (...)
1633 {
1634 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1635 "Ignoring exception");
1636 }
1637 }
1638 }
1639
1640 void ProviderAgentContainer::_sendResponse(CIMRequestMessage *request,
1641 CIMResponseMessage *response)
1642 {
1643 response->syncAttributes(request);
1644 {
1645 s.kodali 1.1 // acquire the _agentMutex to make sure that
1646 // _processMessage thread has finished
1647 // processing the request.
1648 AutoMutex agentLock(_agentMutex);
1649 }
1650
1651 // Call the asyncResponseCallback to process
1652 // the completed response.
1653 _asyncResponseCallback(
1654 request,
1655 response);
1656 }
1657
1658 ThreadReturnType PEGASUS_THREAD_CDECL
1659 ProviderAgentContainer::_responseProcessor(void* arg)
1660 {
1661 ProviderAgentContainer* pa =
1662 reinterpret_cast<ProviderAgentContainer*>(arg);
1663
1664 pa->_processResponses();
1665
1666 s.kodali 1.1 return ThreadReturnType(0);
1667 }
1668
1669 /////////////////////////////////////////////////////////////////////////////
1670 // OOPProviderManagerRouter
1671 /////////////////////////////////////////////////////////////////////////////
1672
1673 OOPProviderManagerRouter::OOPProviderManagerRouter(
1674 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
1675 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
1676 PEGASUS_PROVIDERMODULEGROUPFAIL_CALLBACK_T providerModuleGroupFailCallback,
1677 PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback)
1678 {
1679 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1680 "OOPProviderManagerRouter::OOPProviderManagerRouter");
1681
1682 _indicationCallback = indicationCallback;
1683 _responseChunkCallback = responseChunkCallback;
1684 _providerModuleGroupFailCallback = providerModuleGroupFailCallback;
1685 _asyncResponseCallback = asyncResponseCallback;
1686 _subscriptionInitComplete = false;
1687 s.kodali 1.1 _threadPool =
1688 new ThreadPool(0, "OOPProviderManagerRouter", 0, 0, deallocateWait);;
1689 PEG_METHOD_EXIT();
1690 }
1691
1692 OOPProviderManagerRouter::~OOPProviderManagerRouter()
1693 {
1694 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1695 "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1696
1697 try
1698 {
1699 // Clean up the ProviderAgentContainers
1700 AutoMutex lock(_providerAgentTableMutex);
1701 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1702 for (; i != 0; i++)
1703 {
1704 delete i.value();
1705 }
1706
1707 delete _threadPool;
1708 s.kodali 1.1 }
1709 catch (...) {}
1710
1711 PEG_METHOD_EXIT();
1712 }
1713
|
1714 venkat.puvvada 1.9 void OOPProviderManagerRouter::_handleIndicationDeliveryResponse(
1715 CIMResponseMessage *response)
1716 {
1717 if (response->getType() == CIM_PROCESS_INDICATION_RESPONSE_MESSAGE)
1718 {
1719 CIMProcessIndicationResponseMessage *rsp =
1720 (CIMProcessIndicationResponseMessage*)response;
1721
1722 // Look up the Provider Agents for this module
1723 Array<ProviderAgentContainer*> paArray =
1724 _lookupProviderAgents(rsp->oopAgentName);
1725
1726 for (Uint32 i = 0; i < paArray.size(); i++)
1727 {
1728 if (paArray[i]->isInitialized())
1729 {
1730 paArray[i]->sendResponse(response);
1731 }
1732 }
1733 return;
1734 }
1735 venkat.puvvada 1.9
1736 PEGASUS_ASSERT(false);
1737 }
1738
|
1739 s.kodali 1.1 Message* OOPProviderManagerRouter::processMessage(Message* message)
1740 {
1741 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1742 "OOPProviderManagerRouter::processMessage");
1743
|
1744 venkat.puvvada 1.9 if (message->getType() == CIM_PROCESS_INDICATION_RESPONSE_MESSAGE)
1745 {
1746 _handleIndicationDeliveryResponse((CIMResponseMessage*)message);
1747 return 0;
1748 }
1749
|
1750 s.kodali 1.1 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1751 PEGASUS_ASSERT(request != 0);
1752
1753 AutoPtr<CIMResponseMessage> response;
1754
1755 //
1756 // Get the provider information from the request
1757 //
1758 CIMInstance providerModule;
1759
1760 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1761 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1762 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1763 {
1764 // Provider information is in the OperationContext
1765 ProviderIdContainer pidc = (ProviderIdContainer)
1766 request->operationContext.get(ProviderIdContainer::NAME);
1767 providerModule = pidc.getModule();
1768 }
1769 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1770 {
1771 s.kodali 1.1 CIMEnableModuleRequestMessage* emReq =
1772 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1773 providerModule = emReq->providerModule;
1774 }
1775 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1776 {
1777 CIMDisableModuleRequestMessage* dmReq =
1778 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1779 providerModule = dmReq->providerModule;
1780 }
1781 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1782 (request->getType() ==
1783 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1784 (request->getType() ==
1785 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE) ||
1786 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1787 {
1788 // This operation is not provider-specific
1789 }
1790 else
1791 {
1792 s.kodali 1.1 // Unrecognized message type. This should never happen.
1793 PEGASUS_ASSERT(0);
1794 response.reset(request->buildResponse());
1795 response->cimException = PEGASUS_CIM_EXCEPTION(
1796 CIM_ERR_FAILED, "Unrecognized message type.");
1797 PEG_METHOD_EXIT();
1798 return response.release();
1799 }
1800
1801 //
1802 // Process the request message
1803 //
1804 if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1805 {
|
1806 venkat.puvvada 1.7 ProviderAgentContainer::setAllProvidersStopped();
|
1807 s.kodali 1.1 // Forward the CIMStopAllProvidersRequest to all providers
1808 response.reset(_forwardRequestToAllAgents(request));
1809
1810 // Note: Do not uninitialize the ProviderAgentContainers here.
1811 // Just let the selecting thread notice when the agent connections
1812 // are closed.
1813 }
1814 else if (request->getType () ==
1815 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1816 {
1817 _subscriptionInitComplete = true;
1818
1819 //
1820 // Forward the CIMSubscriptionInitCompleteRequestMessage to
1821 // all providers
1822 //
1823 response.reset (_forwardRequestToAllAgents (request));
1824 }
1825 else if (request->getType () ==
1826 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE)
1827 {
1828 s.kodali 1.1 _subscriptionInitComplete = false;
1829
1830 //
1831 // Forward the CIMIndicationServiceDisabledRequestMessage to
1832 // all providers
1833 //
1834 response.reset (_forwardRequestToAllAgents (request));
1835 }
1836 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1837 {
1838 CIMNotifyConfigChangeRequestMessage* notifyRequest =
1839 dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1840 PEGASUS_ASSERT(notifyRequest != 0);
1841
1842 if (notifyRequest->currentValueModified)
1843 {
1844 // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1845 response.reset(_forwardRequestToAllAgents(request));
1846 }
1847 else
1848 {
1849 s.kodali 1.1 // No need to notify provider agents about changes to planned value
1850 response.reset(request->buildResponse());
1851 }
1852 }
1853 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1854 {
1855 // Fan out the request to all Provider Agent processes for this module
1856
1857 // Retrieve the provider group name.
1858 String groupNameWithType;
1859 _getGroupNameWithType(providerModule, groupNameWithType);
1860
1861
1862 // Look up the Provider Agents for this module
1863 Array<ProviderAgentContainer*> paArray =
1864 _lookupProviderAgents(groupNameWithType);
1865
1866 Array<ProviderAgentContainer*> paInit;
1867
1868 for (Uint32 i=0; i<paArray.size(); i++)
1869 {
1870 s.kodali 1.1 //
1871 // Do not start up an agent process just to disable the module
1872 //
1873 if (paArray[i]->isInitialized())
1874 {
1875 paInit.append(paArray[i]);
1876 }
1877 }
1878
1879 if(paInit.size() > 0)
1880 {
1881 RespAggCounter *respAggregator =
1882 new RespAggCounter(paInit.size());
1883
1884 for (Uint32 i=0; i<paInit.size(); i++)
1885 {
1886 // Forward the request to the provider agent
1887 //
1888 response.reset(
1889 paInit[i]->processMessage(request,respAggregator));
1890
1891 s.kodali 1.1 // Note: Do not uninitialize the ProviderAgentContainer here
1892 // when a disable module operation is successful. Just let the
1893 // selecting thread notice when the agent connection is closed.
1894 }
1895 }
1896
1897 // Use a default response if no Provider Agents were called
1898 if (!response.get())
1899 {
1900 response.reset(request->buildResponse());
1901
1902 CIMDisableModuleResponseMessage* dmResponse =
1903 dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1904 PEGASUS_ASSERT(dmResponse != 0);
1905
1906 Array<Uint16> operationalStatus;
1907 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1908 dmResponse->operationalStatus = operationalStatus;
1909 }
1910 }
1911 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1912 s.kodali 1.1 {
1913 // Fan out the request to all Provider Agent processes for this module
1914
1915 // Retrieve the provider module group name.
1916 String groupNameWithType;
1917 _getGroupNameWithType(providerModule, groupNameWithType);
1918
1919 // Look up the Provider Agents for this module
1920 Array<ProviderAgentContainer*> paArray =
1921 _lookupProviderAgents(groupNameWithType);
1922
1923 // Create an array of initialized provider agents.
1924 Array<ProviderAgentContainer*> paInit;
1925
1926 // create an array of initialized provider agents.
1927 for (Uint32 i=0; i<paArray.size(); i++)
1928 {
1929 if (paArray[i]->isInitialized())
1930 {
1931 paInit.append(paArray[i]);
1932 }
1933 s.kodali 1.1 }
1934
1935 if(paInit.size() > 0 )
1936 {
1937 RespAggCounter *respAggregator =
1938 new RespAggCounter(paInit.size());
1939
1940 for (Uint32 i=0; i<paInit.size(); i++)
1941 {
1942 //
1943 // Forward the request to the provider agent
1944 //
1945 response.reset(
1946 paInit[i]->processMessage(request,respAggregator));
1947 }
1948 }
1949
1950 // Use a default response if no Provider Agents were called
1951 if (!response.get())
1952 {
1953 response.reset(request->buildResponse());
1954 s.kodali 1.1
1955 CIMEnableModuleResponseMessage* emResponse =
1956 dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1957 PEGASUS_ASSERT(emResponse != 0);
1958
1959 Array<Uint16> operationalStatus;
1960 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1961 emResponse->operationalStatus = operationalStatus;
1962 }
1963 }
1964 else
1965 {
1966 //
1967 // Look up the Provider Agent for this module instance and requesting
1968 // user
1969 //
1970 ProviderAgentContainer* pa = _lookupProviderAgent(providerModule,
1971 request);
1972 PEGASUS_ASSERT(pa != 0);
1973
1974 //
1975 s.kodali 1.1 // Forward the request to the provider agent
1976 //
1977 response.reset(pa->processMessage(request));
1978 }
1979
1980 PEG_METHOD_EXIT();
1981 return response.release();
1982 }
1983
1984 ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1985 const CIMInstance& providerModule,
1986 CIMRequestMessage* request)
1987 {
1988 // Retrieve the provider module group name
1989 String groupNameWithType;
1990 _getGroupNameWithType(providerModule, groupNameWithType);
1991
|
1992 venkat.puvvada 1.4 Uint16 bitness = PG_PROVMODULE_BITNESS_DEFAULT;
1993 Uint32 bIndex = providerModule.findProperty(
1994 PEGASUS_PROPERTYNAME_MODULE_BITNESS);
1995
1996 if (bIndex != PEG_NOT_FOUND)
1997 {
1998 CIMValue value =
1999 providerModule.getProperty(bIndex).getValue();
2000 if (!value.isNull())
2001 {
2002 value.get(bitness);
2003 }
2004 }
2005
|
2006 s.kodali 1.1 #if defined(PEGASUS_OS_ZOS)
2007 // For z/OS we don't start an extra provider agent for
2008 // each user, since the userid is switched at the thread
2009 // level. Therefore we set the userName to an empty String,
2010 // as it is used below to build the key for the provider
2011 // agent table
2012 String userName;
2013 Uint16 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
2014 #else
2015
2016 // Retrieve the provider user context configuration
2017 Uint16 userContext = 0;
2018 Uint32 pos = providerModule.findProperty(
2019 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
2020 if (pos != PEG_NOT_FOUND)
2021 {
2022 CIMValue userContextValue =
2023 providerModule.getProperty(pos).getValue();
2024 if (!userContextValue.isNull())
2025 {
2026 userContextValue.get(userContext);
2027 s.kodali 1.1 }
2028 }
2029
2030 if (userContext == 0)
2031 {
2032 // PASE has a default user context "QYCMCIMOM",
2033 // so we leave userContext unset here.
2034 #ifndef PEGASUS_OS_PASE
2035 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
2036 #endif
2037 }
2038
2039 String userName;
2040
2041 if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
2042 {
2043 if (request->operationContext.contains(IdentityContainer::NAME))
2044 {
2045 // User Name is in the OperationContext
2046 IdentityContainer ic = (IdentityContainer)
2047 request->operationContext.get(IdentityContainer::NAME);
2048 s.kodali 1.1 userName = ic.getUserName();
2049 }
2050 //else
2051 //{
2052 // If no IdentityContainer is present, default to the CIM
2053 // Server's user context
2054 //}
2055
2056 // If authentication is disabled, use the CIM Server's user context
2057 if (!userName.size())
2058 {
2059 userName = System::getEffectiveUserName();
2060 }
2061 }
2062 else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
2063 {
2064 // Retrieve the provider module designated user property value
2065 providerModule.getProperty(providerModule.findProperty(
2066 PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
2067 get(userName);
2068 }
2069 s.kodali 1.1 else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
2070 {
2071 userName = System::getEffectiveUserName();
2072 }
2073 #ifdef PEGASUS_OS_PASE // it might be unset user in PASE in this branch.
2074 else if (userContext == 0)
2075 {
2076 userName = "QYCMCIMOM";
2077 }
2078 #endif
2079 else // Privileged User
2080 {
2081 PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
2082 userName = System::getPrivilegedUserName();
2083 }
2084
2085 PEG_TRACE((
2086 TRC_PROVIDERMANAGER,
2087 Tracer::LEVEL4,
2088 "Group name with type = %s, User context = %hd, User name = %s",
2089 (const char*) groupNameWithType.getCString(),
2090 s.kodali 1.1 userContext,
2091 (const char*) userName.getCString()));
2092 #endif
2093
2094 ProviderAgentContainer* pa = 0;
2095
2096 #ifdef PEGASUS_OS_PASE
2097 String userUpper = userName;
2098 userUpper.toUpper();
2099 String key = groupNameWithType + ":" + userUpper;
2100 #else
2101 String key = groupNameWithType + ":" + userName;
2102 #endif
2103
2104 AutoMutex lock(_providerAgentTableMutex);
2105 if (!_providerAgentTable.lookup(key, pa))
2106 {
2107 pa = new ProviderAgentContainer(
|
2108 s.kodali 1.3 bitness,
|
2109 s.kodali 1.1 groupNameWithType, userName, userContext,
2110 _indicationCallback, _responseChunkCallback,
2111 _providerModuleGroupFailCallback,
2112 _asyncResponseCallback,
2113 _subscriptionInitComplete,
2114 _threadPool);
2115 _providerAgentTable.insert(key, pa);
2116 }
2117
2118 return pa;
2119 }
2120
2121 Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
2122 const String& groupNameWithType)
2123 {
2124 Array<ProviderAgentContainer*> paArray;
2125
2126 AutoMutex lock(_providerAgentTableMutex);
2127 for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
2128 {
2129 if (i.value()->getGroupNameWithType() == groupNameWithType)
2130 s.kodali 1.1 {
2131 paArray.append(i.value());
2132 }
2133 }
2134 return paArray;
2135 }
2136
2137 CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
2138 CIMRequestMessage* request)
2139 {
2140 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
2141 "OOPProviderManagerRouter::_forwardRequestToAllAgents");
2142
2143 // Get a list of the ProviderAgentContainers. We need our own array copy
2144 // because we cannot hold the _providerAgentTableMutex while calling
2145 // _ProviderAgentContainer::processMessage().
2146 Array<ProviderAgentContainer*> paContainerArray;
2147 {
2148 AutoMutex tableLock(_providerAgentTableMutex);
2149 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
2150 i != 0; i++)
2151 s.kodali 1.1 {
2152 if(i.value()->isInitialized())
2153 {
2154 paContainerArray.append(i.value());
2155 }
2156 }
2157 }
2158
2159 Boolean responsePending = false;
2160 CIMResponseMessage *response = request->buildResponse();
2161
2162 if(paContainerArray.size() > 0 )
2163 {
2164 RespAggCounter *respAggregator =
2165 new RespAggCounter(paContainerArray.size());
2166
2167 // Forward the request to each of the initialized provider agents
2168 for (Uint32 j = 0; j < paContainerArray.size(); j++)
2169 {
2170 ProviderAgentContainer* pa = paContainerArray[j];
2171
2172 s.kodali 1.1 // Note: The ProviderAgentContainer could become uninitialized
2173 // before _ProviderAgentContainer::processMessage() processes
2174 // this request. In this case, the Provider Agent process will
2175 // (unfortunately) be started to process this message.
2176 AutoPtr<CIMResponseMessage> response;
2177 response.reset(pa->processMessage(request,respAggregator));
2178 responsePending = true;
2179 }
2180
2181 response->isAsyncResponsePending = responsePending;
2182 }
2183
2184 PEG_METHOD_EXIT();
2185 return response;
2186 }
2187
2188 void OOPProviderManagerRouter::idleTimeCleanup()
2189 {
2190 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
2191 "OOPProviderManagerRouter::idleTimeCleanup");
2192
2193 s.kodali 1.1 // Get a list of the ProviderAgentContainers. We need our own array copy
2194 // because we cannot hold the _providerAgentTableMutex while calling
2195 // ProviderAgentContainer::unloadIdleProviders() &
2196 // ProviderAgentContainer::cleanDisconnectedClientRequests().
2197 Array<ProviderAgentContainer*> paContainerArray;
2198 {
2199 AutoMutex tableLock(_providerAgentTableMutex);
2200 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
2201 i != 0; i++)
2202 {
2203 paContainerArray.append(i.value());
2204 }
2205 }
2206
2207 // Iterate through the _providerAgentTable unloading idle providers
2208 for (Uint32 j = 0; j < paContainerArray.size(); j++)
2209 {
2210 paContainerArray[j]->unloadIdleProviders();
2211 }
2212
2213 // Iterate through the _providerAgentTable cleaning up disconnected clients.
2214 s.kodali 1.1 for (Uint32 k = 0; k < paContainerArray.size(); k++)
2215 {
2216 paContainerArray[k]->cleanDisconnectedClientRequests();
2217 }
2218
2219 PEG_METHOD_EXIT();
2220 }
2221
2222 void OOPProviderManagerRouter::_getGroupNameWithType(
2223 const CIMInstance &providerModule,
2224 String &groupNameWithType)
2225 {
2226 Uint32 idx = providerModule.findProperty(
2227 PEGASUS_PROPERTYNAME_MODULE_MODULEGROUPNAME);
2228
2229 String moduleName;
2230 String groupName;
2231
2232 if (idx != PEG_NOT_FOUND)
2233 {
2234 providerModule.getProperty(idx).getValue().get(groupName);
2235 s.kodali 1.1 }
2236
2237 // Note: If group name is not found, module name is used as group name.
2238 // prefixes "grp" and "mod" is used to distinguish between the provider
2239 // modules who have same group and module names.
2240 if (groupName.size())
2241 {
2242 groupNameWithType.assign(_GROUP_PREFIX);
2243 groupNameWithType.append(groupName);
2244 }
2245 else
2246 {
2247 _getProviderModuleName(providerModule, moduleName);
2248 groupNameWithType.assign(_MODULE_PREFIX);
2249 groupNameWithType.append(moduleName);
2250 }
2251 }
2252
2253 void OOPProviderManagerRouter::_getProviderModuleName(
2254 const CIMInstance & providerModule,
2255 String & moduleName)
2256 s.kodali 1.1 {
2257 CIMValue nameValue = providerModule.getProperty(
2258 providerModule.findProperty(PEGASUS_PROPERTYNAME_NAME)).getValue();
2259 nameValue.get(moduleName);
2260
2261 #if defined(PEGASUS_OS_ZOS)
2262 // Retrieve the providers shareAS flag, to see if it will share the
2263 // provider address space with other providers or requests its own
2264 // address space.
2265 Boolean shareAS = true;
2266 Uint32 saIndex = providerModule.findProperty("ShareAS");
2267 if (saIndex != PEG_NOT_FOUND)
2268 {
2269 CIMValue shareValue=providerModule.getProperty(saIndex).getValue();
2270 shareValue.get(shareAS);
2271 }
2272 if (shareAS == true)
2273 {
2274 moduleName.assign("SharedProviderAgent");
2275 }
2276 #endif
2277 s.kodali 1.1 return;
2278 }
2279
2280
2281 PEGASUS_NAMESPACE_END
|