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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2