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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2