(file) Return to OOPProviderManagerRouter.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / ProviderManagerRouter

   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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2