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 karl 1.4.2.1 static void setAllProvidersStopped();
210 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 karl 1.4.2.1 static Boolean _allProvidersStopped;
|
432 s.kodali 1.1 };
433
434 Uint32 ProviderAgentContainer::_numProviderProcesses = 0;
435 Mutex ProviderAgentContainer::_numProviderProcessesMutex;
|
436 karl 1.4.2.1 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 karl 1.4.2.1 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 karl 1.4.2.1 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 karl 1.4.2.1 MessageType msgType = i.value()->requestMessage->getType();
|
815 s.kodali 1.1
|
816 karl 1.4.2.1 // 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 {
828 PEGASUS_ASSERT(i.value()->respAggregator);
829 if(i.value()->respAggregator->isComplete(cimException))
|
830 s.kodali 1.1 {
|
831 karl 1.4.2.1 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
850 if (sendResponseNow)
|
851 sahana.prabhakar 1.2 {
852 response =
853 i.value()->requestMessage->buildResponse();
854 response->messageId = i.value()->originalMessageId;
|
855 karl 1.4.2.1 response->cimException = cimException;
|
856 sahana.prabhakar 1.2 sendResponseNow = true;
857 }
|
858 karl 1.4.2.1 delete i.value()->respAggregator;
|
859 s.kodali 1.1 }
860 }
|
861 karl 1.4.2.1 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 }
|
872 s.kodali 1.1 else
873 {
|
874 karl 1.4.2.1 // 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 karl 1.4.2.1 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 karl 1.4.2.1 void ProviderAgentContainer::sendResponse(CIMResponseMessage *response)
1000 {
1001 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 delete response;
1012 }
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 karl 1.4.2.1 // 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 karl 1.4.2.1 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 if (_providerModuleCache.isUninitialized() ||
1167 (!pidc.getModule().identical(_providerModuleCache)))
1168 {
1169 // We haven't sent this provider module instance to the
1170 // Provider Agent yet. Update our cache after we send it.
1171 updateProviderModuleCache = true;
1172 }
1173 else
1174 {
1175 // Replace the provider module in the ProviderIdContainer
1176 // with an uninitialized instance. We'll need to put the
1177 // original one back after the message is sent.
1178 ProviderIdContainer newpidc = ProviderIdContainer(
1179 CIMInstance(), pidc.getProvider(),
1180 s.kodali 1.1 pidc.isRemoteNameSpace(), pidc.getRemoteInfo());
1181 newpidc.setProvMgrPath(pidc.getProvMgrPath());
1182 request->operationContext.set(newpidc);
1183
1184 doProviderModuleOptimization = true;
1185 }
1186 }
1187
1188 //
1189 // Write the message to the pipe
1190 //
1191 try
1192 {
1193 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL3,
1194 "Sending request to agent with messageId %s",
1195 (const char*)uniqueMessageId.getCString()));
1196
1197 request->messageId = uniqueMessageId;
1198 AnonymousPipe::Status writeStatus =
1199 _pipeToAgent->writeMessage(request);
1200 request->messageId = originalMessageId;
1201 s.kodali 1.1
1202 if (doProviderModuleOptimization)
1203 {
1204 request->operationContext.set(*origProviderId.get());
1205 }
1206
1207 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1208 {
1209 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1210 "Failed to write message to pipe. writeStatus = %d.",
1211 writeStatus));
1212
1213 request->messageId = originalMessageId;
1214
1215 if (doProviderModuleOptimization)
1216 {
1217 request->operationContext.set(*origProviderId.get());
1218 }
1219
1220 // Remove this OutstandingRequestTable entry
1221 {
1222 s.kodali 1.1 AutoMutex tableLock(_outstandingRequestTableMutex);
1223 Boolean removed =
1224 _outstandingRequestTable.remove(uniqueMessageId);
1225 PEGASUS_ASSERT(removed);
1226 }
1227
1228 // A response value of _REQUEST_NOT_PROCESSED indicates
1229 // that the request was not processed by the provider
1230 // agent, so it can be retried safely.
1231 PEG_METHOD_EXIT();
1232 return _REQUEST_NOT_PROCESSED;
1233 }
1234
1235 if (updateProviderModuleCache)
1236 {
1237 _providerModuleCache = origProviderId->getModule();
1238 }
1239
1240 response = request->buildResponse();
1241 response->isAsyncResponsePending = true;
1242 PEG_METHOD_EXIT();
1243 s.kodali 1.1
1244 return response;
1245 }
1246 catch (...)
1247 {
1248 request->messageId = originalMessageId;
1249
1250 if (doProviderModuleOptimization)
1251 {
1252 request->operationContext.set(*origProviderId.get());
1253 }
1254
1255 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1256 "Failed to write message to pipe.");
1257 // Remove the OutstandingRequestTable entry for this request
1258 {
1259 AutoMutex tableLock(_outstandingRequestTableMutex);
1260 Boolean removed =
1261 _outstandingRequestTable.remove(uniqueMessageId);
1262 PEGASUS_ASSERT(removed);
1263 }
1264 s.kodali 1.1 PEG_METHOD_EXIT();
1265 throw;
1266 }
1267 }
1268 }
1269 catch (CIMException& e)
1270 {
1271 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1272 "Caught CIMException: %s",
1273 (const char*)e.getMessage().getCString()));
1274 response = request->buildResponse();
1275 response->cimException = e;
1276 }
1277 catch (Exception& e)
1278 {
1279 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1280 "Caught Exception: %s",
1281 (const char*)e.getMessage().getCString()));
1282 response = request->buildResponse();
1283 response->cimException = PEGASUS_CIM_EXCEPTION(
1284 CIM_ERR_FAILED, e.getMessage());
1285 s.kodali 1.1 }
1286 catch (...)
1287 {
1288 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1289 "Caught unknown exception");
1290 response = request->buildResponse();
1291 response->cimException = PEGASUS_CIM_EXCEPTION(
1292 CIM_ERR_FAILED, String());
1293 }
1294
1295 response->messageId = originalMessageId;
1296 response->syncAttributes(request);
1297
1298 PEG_METHOD_EXIT();
1299 return response;
1300 }
1301
1302 void ProviderAgentContainer::unloadIdleProviders()
1303 {
1304 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1305 "ProviderAgentContainer::unloadIdleProviders");
1306 s.kodali 1.1
1307 AutoMutex lock(_agentMutex);
1308 if (_isInitialized)
1309 {
1310 // Send a "wake up" message to the Provider Agent.
1311 // Don't bother checking whether the operation is successful.
1312 Uint32 messageLength = 0;
1313 _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
1314 }
1315
1316 PEG_METHOD_EXIT();
1317 }
1318
1319 void ProviderAgentContainer::cleanDisconnectedClientRequests()
1320 {
1321 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1322 "ProviderAgentContainer::cleanDisconnectedClientRequests");
1323
1324 // Array to store the keys which need to be remvoed.
1325 Array<String> keys;
1326
1327 s.kodali 1.1 AutoMutex tableLock(_outstandingRequestTableMutex);
1328 for (OutstandingRequestTable::Iterator i = _outstandingRequestTable.start();
1329 i != 0; i++)
1330 {
1331 if(!_isClientActive(i.value()->requestMessage))
1332 {
1333 // create empty response and set isComplete to true.
1334 AutoPtr<CIMResponseMessage> response;
1335 SharedPtr<OutstandingRequestEntry> entry = i.value();
1336 response.reset(i.value()->requestMessage->buildResponse());
1337 response->setComplete(true);
1338 response->messageId = i.value()->originalMessageId;
1339 _asyncResponseCallback(
1340 i.value()->requestMessage,
1341 response.release());
1342 keys.append(i.key());
1343 }
1344 }
1345
1346 for(Uint32 j=0; j<keys.size();j++)
1347 {
1348 s.kodali 1.1 _outstandingRequestTable.remove(keys[j]);
1349 }
1350 PEG_METHOD_EXIT();
1351 }
1352
1353 void ProviderAgentContainer::_processGetSCMOClassRequest(
1354 ProvAgtGetScmoClassRequestMessage* request)
1355 {
1356 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1357 "ProviderAgentContainer::_processGetSCMOClassRequest");
1358
1359 AutoPtr<ProvAgtGetScmoClassResponseMessage> response(
1360 new ProvAgtGetScmoClassResponseMessage(
|
1361 karl 1.4.2.1 request->messageId,
|
1362 s.kodali 1.1 CIMException(),
1363 QueueIdStack(),
1364 SCMOClass("","")));
1365
1366 CString ns = request->nameSpace.getString().getCString();
1367 CString cn = request->className.getString().getCString();
1368
1369 delete request;
1370
1371 response->scmoClass = SCMOClassCache::getInstance()->getSCMOClass(
1372 ns,strlen(ns),
1373 cn,strlen(cn));
1374
1375 //
1376 // Lock the Provider Agent Container and
1377 // writing the response to the connection
1378 //
1379 {
1380
1381 AutoMutex lock(_agentMutex);
1382
1383 s.kodali 1.1 //
1384 // Write the message to the pipe
1385 //
1386 try
1387 {
1388
1389 AnonymousPipe::Status writeStatus =
1390 _pipeToAgent->writeMessage(response.get());
1391
1392 if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1393 {
1394 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1395 "Failed to write message to pipe. writeStatus = %d.",
1396 writeStatus));
1397
1398 PEG_METHOD_EXIT();
1399 return;
1400 }
1401
1402 }
1403 catch (Exception & e)
1404 s.kodali 1.1 {
1405 PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1406 "Exception: Failed to write message to pipe. Error: %s",
1407 (const char*)e.getMessage().getCString()));
1408 PEG_METHOD_EXIT();
1409 throw;
1410 }
1411 catch (...)
1412 {
1413
1414 PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL1,
1415 "Unkonwn exception. Failed to write message to pipe.");
1416 PEG_METHOD_EXIT();
1417 throw;
1418 }
1419 }
1420
1421 PEG_METHOD_EXIT();
1422 return;
1423 }
1424
1425 s.kodali 1.1 Boolean ProviderAgentContainer::_isClientActive(CIMRequestMessage *request_)
1426 {
1427 MessageQueue *connectionMQ = MessageQueue::lookup(request_->queueIds[0]);
1428 return connectionMQ->isActive();
1429 }
1430
1431 // Note: This method should not throw an exception. It is used as a thread
1432 // entry point, and any exceptions thrown are ignored.
1433 ThreadReturnType PEGASUS_THREAD_CDECL
1434 ProviderAgentContainer::_retryRequestHandler(void* arg)
1435 {
1436 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1437 "ProviderAgentContainer::_retryRequestHandler");
1438
1439 PEGASUS_ASSERT(arg != 0);
1440 RetryThreadParam *threadParams=
1441 reinterpret_cast<RetryThreadParam *>(arg);
1442 Array<CIMRequestMessage *> retryRequests = threadParams->retryRequestArray;
1443
1444 try
1445 {
1446 s.kodali 1.1 for(Uint32 i=0; i<retryRequests.size(); i++)
1447 {
1448 threadParams->pac->processMessage(retryRequests[i]);
1449 }
1450 }
1451 catch(Exception &e)
1452 {
1453 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
1454 "Unexpected exception in _retryRequestHandler: %s",
1455 (const char*)e.getMessage().getCString()));
1456 }
1457 catch (...)
1458 {
1459 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
1460 "Unexpected exception in _retryRequestHandler.");
1461 }
1462 PEG_METHOD_EXIT();
1463
1464 return ThreadReturnType(0);
1465 }
1466
1467 s.kodali 1.1
1468 void ProviderAgentContainer::_processResponses()
1469 {
1470 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1471 "ProviderAgentContainer::_processResponses");
1472
1473 //
1474 // Process responses until the pipe is closed
1475 //
1476 while (1)
1477 {
1478 try
1479 {
1480 CIMMessage* message;
1481
1482 //
1483 // Read a response from the Provider Agent
1484 //
1485 AnonymousPipe::Status readStatus =
1486 _pipeFromAgent->readMessage(message);
1487
1488 s.kodali 1.1 // Ignore interrupts
1489 if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
1490 {
1491 continue;
1492 }
1493
1494 // Handle an error the same way as a closed connection
1495 if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
1496 (readStatus == AnonymousPipe::STATUS_CLOSED))
1497 {
1498 _uninitialize(false);
1499 return;
1500 }
1501
1502 // A null message indicates that the provider agent process has
1503 // finished its processing and is ready to exit.
1504 if (message == 0)
1505 {
1506 _uninitialize(true);
1507 return;
1508 }
1509 s.kodali 1.1
1510 if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
1511 {
1512 // Process an indication message
|
1513 karl 1.4.2.1 CIMProcessIndicationRequestMessage* request =
|
1514 s.kodali 1.1 reinterpret_cast<CIMProcessIndicationRequestMessage*>(
|
1515 karl 1.4.2.1 message);
1516 request->oopAgentName = getGroupNameWithType();
1517 _indicationCallback(request);
|
1518 s.kodali 1.1 }
1519 else if (message->getType()==PROVAGT_GET_SCMOCLASS_REQUEST_MESSAGE)
1520 {
1521
1522 _processGetSCMOClassRequest(
1523 reinterpret_cast<ProvAgtGetScmoClassRequestMessage*>(
1524 message));
1525 }
1526 else if (!message->isComplete())
1527 {
1528 // Process an incomplete response chunk
1529
1530 CIMResponseMessage* response;
1531 response = dynamic_cast<CIMResponseMessage*>(message);
1532 PEGASUS_ASSERT(response != 0);
1533
1534 Boolean foundEntry = false;
1535 // Get the OutstandingRequestEntry for this response chunk
1536 SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
1537 {
1538 AutoMutex tableLock(_outstandingRequestTableMutex);
1539 s.kodali 1.1 foundEntry = _outstandingRequestTable.lookup(
1540 response->messageId, _outstandingRequestEntry);
1541 }
1542
1543 if(foundEntry)
1544 {
1545 // Put the original message ID into the response
1546 response->messageId =
1547 _outstandingRequestEntry->originalMessageId;
1548
1549 // Call the response chunk callback to process the chunk
1550 // if the client connection is active.
1551 // No need to acquire _agentMutex since this a chunk
1552 // response callback. The request object will not be
1553 // deleted here.
1554 _responseChunkCallback(
1555 _outstandingRequestEntry->requestMessage, response);
1556 }
1557 }
1558 else
1559 {
1560 s.kodali 1.1 // Process a completed response
1561 CIMResponseMessage* response;
1562 response = dynamic_cast<CIMResponseMessage*>(message);
1563 PEGASUS_ASSERT(response != 0);
1564
1565 Boolean foundEntry = false;
1566 // Give the response to the waiting OutstandingRequestEntry
1567 SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
1568 {
1569 AutoMutex tableLock(_outstandingRequestTableMutex);
1570 foundEntry = _outstandingRequestTable.lookup(
1571 response->messageId, _outstandingRequestEntry);
1572
1573 if(foundEntry)
1574 {
1575 // Remove the completed request from the table
1576 Boolean removed = _outstandingRequestTable.remove( \
1577 response->messageId);
1578 PEGASUS_ASSERT(removed);
1579 }
1580
1581 s.kodali 1.1 }
1582
1583 if(foundEntry)
1584 {
1585 if(_outstandingRequestEntry->respAggregator == NULL)
1586 {
1587 response->messageId =
1588 _outstandingRequestEntry->originalMessageId;
1589
1590 _sendResponse(_outstandingRequestEntry->requestMessage,
1591 response);
1592 }
1593 else
1594 {
1595 if(_outstandingRequestEntry->respAggregator-> \
1596 isComplete(response->cimException))
1597 {
1598 response->messageId =
1599 _outstandingRequestEntry->originalMessageId;
1600
1601 _sendResponse(
1602 s.kodali 1.1 _outstandingRequestEntry->requestMessage,
1603 response);
1604
1605 // delete respAggregator pointer now
1606 delete _outstandingRequestEntry->respAggregator;
1607 }
1608 else
1609 {
1610 // this is not the last response for this request.
1611 // Its job is done and it can be deleted now.
1612 delete response;
1613 }
1614 }
1615 }
1616 else
1617 {
1618 PEG_TRACE((TRC_DISCARDED_DATA,Tracer::LEVEL4,
1619 "The response for message id %s arrived after the " \
1620 "client disconnected.",
1621 (const char *)response->messageId.getCString()));
1622 }
1623 s.kodali 1.1 }
1624 }
1625 catch (Exception& e)
1626 {
1627 PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL2,
1628 "Ignoring exception: %s",
1629 (const char*)e.getMessage().getCString()));
1630 }
1631 catch (...)
1632 {
1633 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1634 "Ignoring exception");
1635 }
1636 }
1637 }
1638
1639 void ProviderAgentContainer::_sendResponse(CIMRequestMessage *request,
1640 CIMResponseMessage *response)
1641 {
1642 response->syncAttributes(request);
1643 {
1644 s.kodali 1.1 // acquire the _agentMutex to make sure that
1645 // _processMessage thread has finished
1646 // processing the request.
1647 AutoMutex agentLock(_agentMutex);
1648 }
1649
1650 // Call the asyncResponseCallback to process
1651 // the completed response.
1652 _asyncResponseCallback(
1653 request,
1654 response);
1655 }
1656
1657 ThreadReturnType PEGASUS_THREAD_CDECL
1658 ProviderAgentContainer::_responseProcessor(void* arg)
1659 {
1660 ProviderAgentContainer* pa =
1661 reinterpret_cast<ProviderAgentContainer*>(arg);
1662
1663 pa->_processResponses();
1664
1665 s.kodali 1.1 return ThreadReturnType(0);
1666 }
1667
1668 /////////////////////////////////////////////////////////////////////////////
1669 // OOPProviderManagerRouter
1670 /////////////////////////////////////////////////////////////////////////////
1671
1672 OOPProviderManagerRouter::OOPProviderManagerRouter(
1673 PEGASUS_INDICATION_CALLBACK_T indicationCallback,
1674 PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
1675 PEGASUS_PROVIDERMODULEGROUPFAIL_CALLBACK_T providerModuleGroupFailCallback,
1676 PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback)
1677 {
1678 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1679 "OOPProviderManagerRouter::OOPProviderManagerRouter");
1680
1681 _indicationCallback = indicationCallback;
1682 _responseChunkCallback = responseChunkCallback;
1683 _providerModuleGroupFailCallback = providerModuleGroupFailCallback;
1684 _asyncResponseCallback = asyncResponseCallback;
1685 _subscriptionInitComplete = false;
1686 s.kodali 1.1 _threadPool =
1687 new ThreadPool(0, "OOPProviderManagerRouter", 0, 0, deallocateWait);;
1688 PEG_METHOD_EXIT();
1689 }
1690
1691 OOPProviderManagerRouter::~OOPProviderManagerRouter()
1692 {
1693 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1694 "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1695
1696 try
1697 {
1698 // Clean up the ProviderAgentContainers
1699 AutoMutex lock(_providerAgentTableMutex);
1700 ProviderAgentTable::Iterator i = _providerAgentTable.start();
1701 for (; i != 0; i++)
1702 {
1703 delete i.value();
1704 }
1705
1706 delete _threadPool;
1707 s.kodali 1.1 }
1708 catch (...) {}
1709
1710 PEG_METHOD_EXIT();
1711 }
1712
|
1713 karl 1.4.2.1 void OOPProviderManagerRouter::_handleIndicationDeliveryResponse(
1714 CIMResponseMessage *response)
1715 {
1716 if (response->getType() == CIM_PROCESS_INDICATION_RESPONSE_MESSAGE)
1717 {
1718 CIMProcessIndicationResponseMessage *rsp =
1719 (CIMProcessIndicationResponseMessage*)response;
1720
1721 // Look up the Provider Agents for this module
1722 Array<ProviderAgentContainer*> paArray =
1723 _lookupProviderAgents(rsp->oopAgentName);
1724
1725 for (Uint32 i = 0; i < paArray.size(); i++)
1726 {
1727 if (paArray[i]->isInitialized())
1728 {
1729 paArray[i]->sendResponse(response);
1730 }
1731 }
1732 return;
1733 }
1734 karl 1.4.2.1
1735 PEGASUS_ASSERT(false);
1736 }
1737
|
1738 s.kodali 1.1 Message* OOPProviderManagerRouter::processMessage(Message* message)
1739 {
1740 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1741 "OOPProviderManagerRouter::processMessage");
1742
|
1743 karl 1.4.2.1 if (message->getType() == CIM_PROCESS_INDICATION_RESPONSE_MESSAGE)
1744 {
1745 _handleIndicationDeliveryResponse((CIMResponseMessage*)message);
1746 return 0;
1747 }
1748
|
1749 s.kodali 1.1 CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1750 PEGASUS_ASSERT(request != 0);
1751
1752 AutoPtr<CIMResponseMessage> response;
1753
1754 //
1755 // Get the provider information from the request
1756 //
1757 CIMInstance providerModule;
1758
1759 if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1760 (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1761 (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1762 {
1763 // Provider information is in the OperationContext
1764 ProviderIdContainer pidc = (ProviderIdContainer)
1765 request->operationContext.get(ProviderIdContainer::NAME);
1766 providerModule = pidc.getModule();
1767 }
1768 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1769 {
1770 s.kodali 1.1 CIMEnableModuleRequestMessage* emReq =
1771 dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1772 providerModule = emReq->providerModule;
1773 }
1774 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1775 {
1776 CIMDisableModuleRequestMessage* dmReq =
1777 dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1778 providerModule = dmReq->providerModule;
1779 }
1780 else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1781 (request->getType() ==
1782 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1783 (request->getType() ==
1784 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE) ||
1785 (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1786 {
1787 // This operation is not provider-specific
1788 }
1789 else
1790 {
1791 s.kodali 1.1 // Unrecognized message type. This should never happen.
1792 PEGASUS_ASSERT(0);
1793 response.reset(request->buildResponse());
1794 response->cimException = PEGASUS_CIM_EXCEPTION(
1795 CIM_ERR_FAILED, "Unrecognized message type.");
1796 PEG_METHOD_EXIT();
1797 return response.release();
1798 }
1799
1800 //
1801 // Process the request message
1802 //
1803 if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1804 {
|
1805 karl 1.4.2.1 ProviderAgentContainer::setAllProvidersStopped();
|
1806 s.kodali 1.1 // Forward the CIMStopAllProvidersRequest to all providers
1807 response.reset(_forwardRequestToAllAgents(request));
1808
1809 // Note: Do not uninitialize the ProviderAgentContainers here.
1810 // Just let the selecting thread notice when the agent connections
1811 // are closed.
1812 }
1813 else if (request->getType () ==
1814 CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1815 {
1816 _subscriptionInitComplete = true;
1817
1818 //
1819 // Forward the CIMSubscriptionInitCompleteRequestMessage to
1820 // all providers
1821 //
1822 response.reset (_forwardRequestToAllAgents (request));
1823 }
1824 else if (request->getType () ==
1825 CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE)
1826 {
1827 s.kodali 1.1 _subscriptionInitComplete = false;
1828
1829 //
1830 // Forward the CIMIndicationServiceDisabledRequestMessage to
1831 // all providers
1832 //
1833 response.reset (_forwardRequestToAllAgents (request));
1834 }
1835 else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1836 {
1837 CIMNotifyConfigChangeRequestMessage* notifyRequest =
1838 dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1839 PEGASUS_ASSERT(notifyRequest != 0);
1840
1841 if (notifyRequest->currentValueModified)
1842 {
1843 // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1844 response.reset(_forwardRequestToAllAgents(request));
1845 }
1846 else
1847 {
1848 s.kodali 1.1 // No need to notify provider agents about changes to planned value
1849 response.reset(request->buildResponse());
1850 }
1851 }
1852 else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1853 {
1854 // Fan out the request to all Provider Agent processes for this module
1855
1856 // Retrieve the provider group name.
1857 String groupNameWithType;
1858 _getGroupNameWithType(providerModule, groupNameWithType);
1859
1860
1861 // Look up the Provider Agents for this module
1862 Array<ProviderAgentContainer*> paArray =
1863 _lookupProviderAgents(groupNameWithType);
1864
1865 Array<ProviderAgentContainer*> paInit;
1866
1867 for (Uint32 i=0; i<paArray.size(); i++)
1868 {
1869 s.kodali 1.1 //
1870 // Do not start up an agent process just to disable the module
1871 //
1872 if (paArray[i]->isInitialized())
1873 {
1874 paInit.append(paArray[i]);
1875 }
1876 }
1877
1878 if(paInit.size() > 0)
1879 {
1880 RespAggCounter *respAggregator =
1881 new RespAggCounter(paInit.size());
1882
1883 for (Uint32 i=0; i<paInit.size(); i++)
1884 {
1885 // Forward the request to the provider agent
1886 //
1887 response.reset(
1888 paInit[i]->processMessage(request,respAggregator));
1889
1890 s.kodali 1.1 // Note: Do not uninitialize the ProviderAgentContainer here
1891 // when a disable module operation is successful. Just let the
1892 // selecting thread notice when the agent connection is closed.
1893 }
1894 }
1895
1896 // Use a default response if no Provider Agents were called
1897 if (!response.get())
1898 {
1899 response.reset(request->buildResponse());
1900
1901 CIMDisableModuleResponseMessage* dmResponse =
1902 dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1903 PEGASUS_ASSERT(dmResponse != 0);
1904
1905 Array<Uint16> operationalStatus;
1906 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1907 dmResponse->operationalStatus = operationalStatus;
1908 }
1909 }
1910 else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1911 s.kodali 1.1 {
1912 // Fan out the request to all Provider Agent processes for this module
1913
1914 // Retrieve the provider module group name.
1915 String groupNameWithType;
1916 _getGroupNameWithType(providerModule, groupNameWithType);
1917
1918 // Look up the Provider Agents for this module
1919 Array<ProviderAgentContainer*> paArray =
1920 _lookupProviderAgents(groupNameWithType);
1921
1922 // Create an array of initialized provider agents.
1923 Array<ProviderAgentContainer*> paInit;
1924
1925 // create an array of initialized provider agents.
1926 for (Uint32 i=0; i<paArray.size(); i++)
1927 {
1928 if (paArray[i]->isInitialized())
1929 {
1930 paInit.append(paArray[i]);
1931 }
1932 s.kodali 1.1 }
1933
1934 if(paInit.size() > 0 )
1935 {
1936 RespAggCounter *respAggregator =
1937 new RespAggCounter(paInit.size());
1938
1939 for (Uint32 i=0; i<paInit.size(); i++)
1940 {
1941 //
1942 // Forward the request to the provider agent
1943 //
1944 response.reset(
1945 paInit[i]->processMessage(request,respAggregator));
1946 }
1947 }
1948
1949 // Use a default response if no Provider Agents were called
1950 if (!response.get())
1951 {
1952 response.reset(request->buildResponse());
1953 s.kodali 1.1
1954 CIMEnableModuleResponseMessage* emResponse =
1955 dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1956 PEGASUS_ASSERT(emResponse != 0);
1957
1958 Array<Uint16> operationalStatus;
1959 operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1960 emResponse->operationalStatus = operationalStatus;
1961 }
1962 }
1963 else
1964 {
1965 //
1966 // Look up the Provider Agent for this module instance and requesting
1967 // user
1968 //
1969 ProviderAgentContainer* pa = _lookupProviderAgent(providerModule,
1970 request);
1971 PEGASUS_ASSERT(pa != 0);
1972
1973 //
1974 s.kodali 1.1 // Forward the request to the provider agent
1975 //
1976 response.reset(pa->processMessage(request));
1977 }
1978
1979 PEG_METHOD_EXIT();
1980 return response.release();
1981 }
1982
1983 ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1984 const CIMInstance& providerModule,
1985 CIMRequestMessage* request)
1986 {
1987 // Retrieve the provider module group name
1988 String groupNameWithType;
1989 _getGroupNameWithType(providerModule, groupNameWithType);
1990
|
1991 venkat.puvvada 1.4 Uint16 bitness = PG_PROVMODULE_BITNESS_DEFAULT;
1992 Uint32 bIndex = providerModule.findProperty(
1993 PEGASUS_PROPERTYNAME_MODULE_BITNESS);
1994
1995 if (bIndex != PEG_NOT_FOUND)
1996 {
1997 CIMValue value =
1998 providerModule.getProperty(bIndex).getValue();
1999 if (!value.isNull())
2000 {
2001 value.get(bitness);
2002 }
2003 }
2004
|
2005 s.kodali 1.1 #if defined(PEGASUS_OS_ZOS)
2006 // For z/OS we don't start an extra provider agent for
2007 // each user, since the userid is switched at the thread
2008 // level. Therefore we set the userName to an empty String,
2009 // as it is used below to build the key for the provider
2010 // agent table
2011 String userName;
2012 Uint16 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
2013 #else
2014
2015 // Retrieve the provider user context configuration
2016 Uint16 userContext = 0;
2017 Uint32 pos = providerModule.findProperty(
2018 PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
2019 if (pos != PEG_NOT_FOUND)
2020 {
2021 CIMValue userContextValue =
2022 providerModule.getProperty(pos).getValue();
2023 if (!userContextValue.isNull())
2024 {
2025 userContextValue.get(userContext);
2026 s.kodali 1.1 }
2027 }
2028
2029 if (userContext == 0)
2030 {
2031 // PASE has a default user context "QYCMCIMOM",
2032 // so we leave userContext unset here.
2033 #ifndef PEGASUS_OS_PASE
2034 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
2035 #endif
2036 }
2037
2038 String userName;
2039
2040 if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
2041 {
2042 if (request->operationContext.contains(IdentityContainer::NAME))
2043 {
2044 // User Name is in the OperationContext
2045 IdentityContainer ic = (IdentityContainer)
2046 request->operationContext.get(IdentityContainer::NAME);
2047 s.kodali 1.1 userName = ic.getUserName();
2048 }
2049 //else
2050 //{
2051 // If no IdentityContainer is present, default to the CIM
2052 // Server's user context
2053 //}
2054
2055 // If authentication is disabled, use the CIM Server's user context
2056 if (!userName.size())
2057 {
2058 userName = System::getEffectiveUserName();
2059 }
2060 }
2061 else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
2062 {
2063 // Retrieve the provider module designated user property value
2064 providerModule.getProperty(providerModule.findProperty(
2065 PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
2066 get(userName);
2067 }
2068 s.kodali 1.1 else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
2069 {
2070 userName = System::getEffectiveUserName();
2071 }
2072 #ifdef PEGASUS_OS_PASE // it might be unset user in PASE in this branch.
2073 else if (userContext == 0)
2074 {
2075 userName = "QYCMCIMOM";
2076 }
2077 #endif
2078 else // Privileged User
2079 {
2080 PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
2081 userName = System::getPrivilegedUserName();
2082 }
2083
2084 PEG_TRACE((
2085 TRC_PROVIDERMANAGER,
2086 Tracer::LEVEL4,
2087 "Group name with type = %s, User context = %hd, User name = %s",
2088 (const char*) groupNameWithType.getCString(),
2089 s.kodali 1.1 userContext,
2090 (const char*) userName.getCString()));
2091 #endif
2092
2093 ProviderAgentContainer* pa = 0;
2094
2095 #ifdef PEGASUS_OS_PASE
2096 String userUpper = userName;
2097 userUpper.toUpper();
2098 String key = groupNameWithType + ":" + userUpper;
2099 #else
2100 String key = groupNameWithType + ":" + userName;
2101 #endif
2102
2103 AutoMutex lock(_providerAgentTableMutex);
2104 if (!_providerAgentTable.lookup(key, pa))
2105 {
2106 pa = new ProviderAgentContainer(
|
2107 s.kodali 1.3 bitness,
|
2108 s.kodali 1.1 groupNameWithType, userName, userContext,
2109 _indicationCallback, _responseChunkCallback,
2110 _providerModuleGroupFailCallback,
2111 _asyncResponseCallback,
2112 _subscriptionInitComplete,
2113 _threadPool);
2114 _providerAgentTable.insert(key, pa);
2115 }
2116
2117 return pa;
2118 }
2119
2120 Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
2121 const String& groupNameWithType)
2122 {
2123 Array<ProviderAgentContainer*> paArray;
2124
2125 AutoMutex lock(_providerAgentTableMutex);
2126 for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
2127 {
2128 if (i.value()->getGroupNameWithType() == groupNameWithType)
2129 s.kodali 1.1 {
2130 paArray.append(i.value());
2131 }
2132 }
2133 return paArray;
2134 }
2135
2136 CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
2137 CIMRequestMessage* request)
2138 {
2139 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
2140 "OOPProviderManagerRouter::_forwardRequestToAllAgents");
2141
2142 // Get a list of the ProviderAgentContainers. We need our own array copy
2143 // because we cannot hold the _providerAgentTableMutex while calling
2144 // _ProviderAgentContainer::processMessage().
2145 Array<ProviderAgentContainer*> paContainerArray;
2146 {
2147 AutoMutex tableLock(_providerAgentTableMutex);
2148 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
2149 i != 0; i++)
2150 s.kodali 1.1 {
2151 if(i.value()->isInitialized())
2152 {
2153 paContainerArray.append(i.value());
2154 }
2155 }
2156 }
2157
2158 Boolean responsePending = false;
2159 CIMResponseMessage *response = request->buildResponse();
2160
2161 if(paContainerArray.size() > 0 )
2162 {
2163 RespAggCounter *respAggregator =
2164 new RespAggCounter(paContainerArray.size());
2165
2166 // Forward the request to each of the initialized provider agents
2167 for (Uint32 j = 0; j < paContainerArray.size(); j++)
2168 {
2169 ProviderAgentContainer* pa = paContainerArray[j];
2170
2171 s.kodali 1.1 // Note: The ProviderAgentContainer could become uninitialized
2172 // before _ProviderAgentContainer::processMessage() processes
2173 // this request. In this case, the Provider Agent process will
2174 // (unfortunately) be started to process this message.
2175 AutoPtr<CIMResponseMessage> response;
2176 response.reset(pa->processMessage(request,respAggregator));
2177 responsePending = true;
2178 }
2179
2180 response->isAsyncResponsePending = responsePending;
2181 }
2182
2183 PEG_METHOD_EXIT();
2184 return response;
2185 }
2186
2187 void OOPProviderManagerRouter::idleTimeCleanup()
2188 {
2189 PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
2190 "OOPProviderManagerRouter::idleTimeCleanup");
2191
2192 s.kodali 1.1 // Get a list of the ProviderAgentContainers. We need our own array copy
2193 // because we cannot hold the _providerAgentTableMutex while calling
2194 // ProviderAgentContainer::unloadIdleProviders() &
2195 // ProviderAgentContainer::cleanDisconnectedClientRequests().
2196 Array<ProviderAgentContainer*> paContainerArray;
2197 {
2198 AutoMutex tableLock(_providerAgentTableMutex);
2199 for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
2200 i != 0; i++)
2201 {
2202 paContainerArray.append(i.value());
2203 }
2204 }
2205
2206 // Iterate through the _providerAgentTable unloading idle providers
2207 for (Uint32 j = 0; j < paContainerArray.size(); j++)
2208 {
2209 paContainerArray[j]->unloadIdleProviders();
2210 }
2211
2212 // Iterate through the _providerAgentTable cleaning up disconnected clients.
2213 s.kodali 1.1 for (Uint32 k = 0; k < paContainerArray.size(); k++)
2214 {
2215 paContainerArray[k]->cleanDisconnectedClientRequests();
2216 }
2217
2218 PEG_METHOD_EXIT();
2219 }
2220
2221 void OOPProviderManagerRouter::_getGroupNameWithType(
2222 const CIMInstance &providerModule,
2223 String &groupNameWithType)
2224 {
2225 Uint32 idx = providerModule.findProperty(
2226 PEGASUS_PROPERTYNAME_MODULE_MODULEGROUPNAME);
2227
2228 String moduleName;
2229 String groupName;
2230
2231 if (idx != PEG_NOT_FOUND)
2232 {
2233 providerModule.getProperty(idx).getValue().get(groupName);
2234 s.kodali 1.1 }
2235
2236 // Note: If group name is not found, module name is used as group name.
2237 // prefixes "grp" and "mod" is used to distinguish between the provider
2238 // modules who have same group and module names.
2239 if (groupName.size())
2240 {
2241 groupNameWithType.assign(_GROUP_PREFIX);
2242 groupNameWithType.append(groupName);
2243 }
2244 else
2245 {
2246 _getProviderModuleName(providerModule, moduleName);
2247 groupNameWithType.assign(_MODULE_PREFIX);
2248 groupNameWithType.append(moduleName);
2249 }
2250 }
2251
2252 void OOPProviderManagerRouter::_getProviderModuleName(
2253 const CIMInstance & providerModule,
2254 String & moduleName)
2255 s.kodali 1.1 {
2256 CIMValue nameValue = providerModule.getProperty(
2257 providerModule.findProperty(PEGASUS_PROPERTYNAME_NAME)).getValue();
2258 nameValue.get(moduleName);
2259
2260 #if defined(PEGASUS_OS_ZOS)
2261 // Retrieve the providers shareAS flag, to see if it will share the
2262 // provider address space with other providers or requests its own
2263 // address space.
2264 Boolean shareAS = true;
2265 Uint32 saIndex = providerModule.findProperty("ShareAS");
2266 if (saIndex != PEG_NOT_FOUND)
2267 {
2268 CIMValue shareValue=providerModule.getProperty(saIndex).getValue();
2269 shareValue.get(shareAS);
2270 }
2271 if (shareAS == true)
2272 {
2273 moduleName.assign("SharedProviderAgent");
2274 }
2275 #endif
2276 s.kodali 1.1 return;
2277 }
2278
2279
2280 PEGASUS_NAMESPACE_END
|