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

   1 karl  1.7 //%2005////////////////////////////////////////////////////////////////////////
   2 kumpf 1.1 //
   3 karl  1.5 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6 kumpf 1.1 // IBM Corp.; EMC Corporation, The Open Group.
   7 karl  1.5 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9 karl  1.7 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11 kumpf 1.1 //
  12           // Permission is hereby granted, free of charge, to any person obtaining a copy
  13           // of this software and associated documentation files (the "Software"), to
  14           // deal in the Software without restriction, including without limitation the
  15           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  16           // sell copies of the Software, and to permit persons to whom the Software is
  17           // furnished to do so, subject to the following conditions:
  18 karl  1.5 // 
  19 kumpf 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  20           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  21           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  22           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  23           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  24           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  25           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27           //
  28           //==============================================================================
  29           //
  30           // Author: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
  31           //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
  32           //
  33 gs.keenan 1.8 // Modified By:	Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
  34 carolann.graves 1.14 //              Carol Ann Krug Graves, Hewlett-Packard Company
  35                      //                  (carolann_graves@hp.com)
  36 kumpf           1.1  //
  37                      //%/////////////////////////////////////////////////////////////////////////////
  38                      
  39                      #include <Pegasus/Common/Config.h>
  40                      #include <Pegasus/Common/Constants.h>
  41                      #include <Pegasus/Common/AutoPtr.h>
  42                      #include <Pegasus/Common/ArrayInternal.h>
  43                      #include <Pegasus/Common/CIMMessage.h>
  44                      #include <Pegasus/Common/CIMMessageSerializer.h>
  45                      #include <Pegasus/Common/CIMMessageDeserializer.h>
  46                      #include <Pegasus/Common/OperationContextInternal.h>
  47                      #include <Pegasus/Common/System.h>
  48                      #include <Pegasus/Common/AnonymousPipe.h>
  49                      #include <Pegasus/Common/Tracer.h>
  50                      #include <Pegasus/Common/Logger.h>
  51                      #include <Pegasus/Common/Thread.h>
  52                      #include <Pegasus/Common/MessageQueueService.h>
  53                      #include <Pegasus/Config/ConfigManager.h>
  54                      
  55                      #if defined (PEGASUS_OS_TYPE_WINDOWS)
  56 gs.keenan       1.8  # include <windows.h>  // For CreateProcess()
  57                      #elif defined (PEGASUS_OS_OS400)
  58                      # include <unistd.cleinc>
  59                      #elif defined (PEGASUS_OS_VMS)
  60                      # include <perror.h>
  61                      # include <climsgdef.h>
  62                      # include <stdio.h>
  63                      # include <stdlib.h>
  64                      # include <string.h>
  65                      # include <processes.h>
  66                      # include <unixio.h>
  67 kumpf           1.1  #else
  68 gs.keenan       1.8  # include <unistd.h>  // For fork(), exec(), and _exit()
  69                      # include <errno.h>
  70 kumpf           1.1  #endif
  71                      
  72                      #include "OOPProviderManagerRouter.h"
  73                      
  74                      PEGASUS_USING_STD;
  75                      
  76                      PEGASUS_NAMESPACE_BEGIN
  77                      
  78                      /////////////////////////////////////////////////////////////////////////////
  79                      // OutstandingRequestTable and OutstandingRequestEntry
  80                      /////////////////////////////////////////////////////////////////////////////
  81                      
  82                      /**
  83                          An OutstandingRequestEntry represents a request message sent to a
  84                          Provider Agent for which no response has been received.  The request
  85                          sender provides the message ID and a location for the response to be
  86                          returned, and then waits on the semaphore.  When a response matching
  87                          the message ID is received, it is placed into the specified location
  88                          and the semaphore is signaled.
  89                       */
  90                      class OutstandingRequestEntry
  91 kumpf           1.1  {
  92                      public:
  93                          OutstandingRequestEntry(
  94                              String messageId_,
  95                              CIMResponseMessage*& responseMessage_,
  96                              Semaphore* responseReady_)
  97                              : messageId(messageId_),
  98                                responseMessage(responseMessage_),
  99                                responseReady(responseReady_)
 100                          {
 101                          }
 102                      
 103                          String messageId;
 104                          CIMResponseMessage*& responseMessage;
 105                          Semaphore* responseReady;
 106                      };
 107                      
 108                      typedef HashTable<String, OutstandingRequestEntry*, EqualFunc<String>,
 109                          HashFunc<String> > OutstandingRequestTable;
 110                      
 111                      
 112 kumpf           1.1  /////////////////////////////////////////////////////////////////////////////
 113                      // ProviderAgentContainer
 114                      /////////////////////////////////////////////////////////////////////////////
 115                      
 116                      class ProviderAgentContainer
 117                      {
 118                      public:
 119                          ProviderAgentContainer(
 120                              const String & moduleName,
 121 kumpf           1.6          const String & userName,
 122 carolann.graves 1.14         PEGASUS_INDICATION_CALLBACK indicationCallback,
 123                              Boolean subscriptionInitComplete);
 124 kumpf           1.1  
 125                          ~ProviderAgentContainer();
 126                      
 127                          Boolean isInitialized();
 128                      
 129 kumpf           1.6      String getModuleName() const;
 130                      
 131 kumpf           1.1      CIMResponseMessage* processMessage(CIMRequestMessage* request);
 132                          void unloadIdleProviders();
 133                      
 134                      private:
 135                          //
 136                          // Private methods
 137                          //
 138                      
 139                          /** Unimplemented */
 140                          ProviderAgentContainer();
 141                          /** Unimplemented */
 142                          ProviderAgentContainer(const ProviderAgentContainer& pa);
 143                          /** Unimplemented */
 144                          ProviderAgentContainer& operator=(const ProviderAgentContainer& pa);
 145                      
 146                          /**
 147                              Start a Provider Agent process and establish a pipe connection with it.
 148                              Note: The caller must lock the _agentMutex.
 149                           */
 150                          void _startAgentProcess();
 151                      
 152 kumpf           1.1      /**
 153                              Send initialization data to the Provider Agent.
 154                              Note: The caller must lock the _agentMutex.
 155                           */
 156                          void _sendInitializationData();
 157                      
 158                          /**
 159                              Initialize the ProviderAgentContainer if it is not already
 160                              initialized.  Initialization includes starting the Provider Agent
 161                              process, establishing a pipe connection with it, and starting a
 162                              thread to read response messages from the Provider Agent.
 163                      
 164                              Note: The caller must lock the _agentMutex.
 165                           */
 166                          void _initialize();
 167                      
 168                          /**
 169                              Uninitialize the ProviderAgentContainer if it is initialized.
 170                              The connection is closed and outstanding requests are completed
 171                              with an error result.
 172                      
 173 kumpf           1.1          Note: The caller must lock the _agentMutex.
 174                           */
 175                          void _uninitialize();
 176                      
 177                          /**
 178                              Read and process response messages from the Provider Agent until
 179                              the connection is closed.
 180                           */
 181                          void _processResponses();
 182                          static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
 183                              _responseProcessor(void* arg);
 184                      
 185                          //
 186                          // Private data
 187                          //
 188                      
 189                          /**
 190                              The _agentMutex must be locked whenever writing to the Provider
 191                              Agent connection, accessing the _isInitialized flag, or changing
 192                              the Provider Agent state.
 193                           */
 194 kumpf           1.1      Mutex _agentMutex;
 195                      
 196                          /**
 197                              Name of the provider module served by this Provider Agent.
 198                           */
 199                          String _moduleName;
 200                      
 201                          /**
 202 kumpf           1.6          The user context in which this Provider Agent operates.
 203                           */
 204                          String _userName;
 205                      
 206                          /**
 207 kumpf           1.1          Callback function to which all generated indications are sent for
 208                              processing.
 209                           */
 210                          PEGASUS_INDICATION_CALLBACK _indicationCallback;
 211                      
 212                          /**
 213                              Indicates whether the Provider Agent is active.
 214                           */
 215                          Boolean _isInitialized;
 216                      
 217                          /**
 218                              Pipe connection used to read responses from the Provider Agent.
 219                           */
 220                          AutoPtr<AnonymousPipe> _pipeFromAgent;
 221                          /**
 222                              Pipe connection used to write requests to the Provider Agent.
 223                           */
 224                          AutoPtr<AnonymousPipe> _pipeToAgent;
 225                      
 226                          /**
 227                              The _outstandingRequestTable holds an entry for each request that has
 228 kumpf           1.1          been sent to this Provider Agent for which no response has been
 229                              received.  Entries are added (by the writing thread) when a request
 230                              is sent, and are removed (by the reading thread) when the response is
 231                              received (or when it is determined that no response is forthcoming).
 232                           */
 233                          OutstandingRequestTable _outstandingRequestTable;
 234                          /**
 235                              The _outstandingRequestTableMutex must be locked whenever reading or
 236                              updating the _outstandingRequestTable.
 237                           */
 238                          Mutex _outstandingRequestTableMutex;
 239 kumpf           1.2  
 240                          /**
 241                              Holds the last provider module instance sent to the Provider Agent in
 242                              a ProviderIdContainer.  Since the provider module instance rarely
 243                              changes, an optimization is used to send it only when it differs from
 244                              the last provider module instance sent.
 245                           */
 246                          CIMInstance _providerModuleCache;
 247 kumpf           1.6  
 248                          /**
 249                              The number of Provider Agent processes that are currently initialized
 250                              (active).
 251                          */
 252                          static Uint32 _numProviderProcesses;
 253                      
 254                          /**
 255                              The _numProviderProcessesMutex must be locked whenever reading or
 256                              updating the _numProviderProcesses count.
 257                          */
 258                          static Mutex _numProviderProcessesMutex;
 259                      
 260                          /**
 261                              The maximum number of Provider Agent processes that may be initialized
 262                              (active) at one time.
 263                          */
 264                          static Uint32 _maxProviderProcesses;
 265 carolann.graves 1.14 
 266                          /**
 267                              Indicates whether the Indication Service has completed initialization.
 268                      
 269                              For more information, please see the description of the
 270                              ProviderManagerRouter::_subscriptionInitComplete member variable.
 271                           */
 272                          Boolean _subscriptionInitComplete;
 273 kumpf           1.1  };
 274                      
 275 kumpf           1.6  Uint32 ProviderAgentContainer::_numProviderProcesses = 0;
 276                      Mutex ProviderAgentContainer::_numProviderProcessesMutex;
 277                      Uint32 ProviderAgentContainer::_maxProviderProcesses = PEG_NOT_FOUND;
 278                      
 279 kumpf           1.1  ProviderAgentContainer::ProviderAgentContainer(
 280                          const String & moduleName,
 281 kumpf           1.6      const String & userName,
 282 carolann.graves 1.14     PEGASUS_INDICATION_CALLBACK indicationCallback,
 283                          Boolean subscriptionInitComplete)
 284 kumpf           1.1      : _moduleName(moduleName),
 285 kumpf           1.6        _userName(userName),
 286 kumpf           1.1        _indicationCallback(indicationCallback),
 287 carolann.graves 1.14       _isInitialized(false),
 288                            _subscriptionInitComplete(subscriptionInitComplete)
 289 kumpf           1.1  {
 290                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 291                              "ProviderAgentContainer::ProviderAgentContainer");
 292                          PEG_METHOD_EXIT();
 293                      }
 294                      
 295                      ProviderAgentContainer::~ProviderAgentContainer()
 296                      {
 297                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 298                              "ProviderAgentContainer::~ProviderAgentContainer");
 299                      
 300                          // Ensure the destructor does not throw an exception
 301                          try
 302                          {
 303                              // Stop the responseProcessor thread by closing its connection
 304                              _pipeFromAgent->closeReadHandle();
 305                      
 306                              // Wait for the responseProcessor thread to exit
 307                              while (isInitialized())
 308                              {
 309                                  pegasus_yield();
 310 kumpf           1.1          }
 311                          }
 312                          catch (...)
 313                          {
 314                          }
 315                      
 316                          PEG_METHOD_EXIT();
 317                      }
 318                      
 319                      void ProviderAgentContainer::_startAgentProcess()
 320                      {
 321                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 322                              "ProviderAgentContainer::_startAgentProcess");
 323                      
 324                          AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe());
 325                          AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe());
 326                      
 327                          //
 328                          // Start a cimprovagt process for this provider module
 329                          //
 330                      
 331 kumpf           1.1  #if defined (PEGASUS_OS_TYPE_WINDOWS)
 332                          //
 333                          //  Set up members of the PROCESS_INFORMATION structure
 334                          //
 335                          PROCESS_INFORMATION piProcInfo;
 336                          ZeroMemory (&piProcInfo, sizeof (PROCESS_INFORMATION));
 337                      
 338                          //
 339                          //  Set up members of the STARTUPINFO structure
 340                          //
 341                          STARTUPINFO siStartInfo;
 342                          ZeroMemory (&siStartInfo, sizeof (STARTUPINFO));
 343                          siStartInfo.cb = sizeof (STARTUPINFO);
 344                      
 345                          //
 346                          //  Generate the command line
 347                          //
 348                          char cmdLine[2048];
 349                          char readHandle[32];
 350                          char writeHandle[32];
 351                          pipeToAgent->exportReadHandle(readHandle);
 352 kumpf           1.1      pipeFromAgent->exportWriteHandle(writeHandle);
 353                      
 354                          sprintf(cmdLine, "\"%s\" %s %s \"%s\"",
 355                              (const char*)ConfigManager::getHomedPath(
 356                                  PEGASUS_PROVIDER_AGENT_PROC_NAME).getCString(),
 357                              readHandle, writeHandle, (const char*)_moduleName.getCString());
 358                      
 359                          //
 360                          //  Create the child process
 361                          //
 362                          if (!CreateProcess (
 363                              NULL,          //
 364                              cmdLine,       //  command line
 365                              NULL,          //  process security attributes
 366                              NULL,          //  primary thread security attributes
 367                              TRUE,          //  handles are inherited
 368                              0,             //  creation flags
 369                              NULL,          //  use parent's environment
 370                              NULL,          //  use parent's current directory
 371                              &siStartInfo,  //  STARTUPINFO
 372                              &piProcInfo))  //  PROCESS_INFORMATION
 373 kumpf           1.1      {
 374                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 375                                  "CreateProcess() failed.  errno = %d.", GetLastError());
 376                              PEG_METHOD_EXIT();
 377                              throw Exception(MessageLoaderParms(
 378                                  "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
 379                                  "Failed to start cimprovagt \"$0\".",
 380                                  _moduleName));
 381                          }
 382                      
 383                          CloseHandle(piProcInfo.hProcess);
 384                          CloseHandle(piProcInfo.hThread);
 385 gs.keenan       1.8  
 386                      #elif defined (PEGASUS_OS_VMS)
 387                      
 388 gs.keenan       1.10     //
 389                          //  fork and exec the child process
 390                          //
 391                          int status;
 392 gs.keenan       1.8  
 393 gs.keenan       1.10     status = vfork ();
 394                          switch (status)
 395                          {
 396                            case 0:
 397                              try
 398 gs.keenan       1.8          {
 399 gs.keenan       1.10           //
 400                                // Execute the cimprovagt program
 401                                //
 402                                String agentCommandPath =
 403                                    ConfigManager::getHomedPath(PEGASUS_PROVIDER_AGENT_PROC_NAME);
 404                                CString agentCommandPathCString = agentCommandPath.getCString();
 405                      
 406                                char readHandle[32];
 407                                char writeHandle[32];
 408                                pipeToAgent->exportReadHandle(readHandle);
 409                                pipeFromAgent->exportWriteHandle(writeHandle);
 410                      
 411                                if ((status = execl(agentCommandPathCString, agentCommandPathCString,
 412                                    readHandle, writeHandle,
 413                                    (const char*)_moduleName.getCString(), (char*)0)) == -1);
 414                                {
 415                                  // If we're still here, there was an error
 416                                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 417                                      "execl() failed.  errno = %d.", errno);
 418                                  _exit(1);
 419                                }
 420 gs.keenan       1.10         }
 421                              catch (...)
 422                              {
 423                                // There's not much we can do here in no man's land
 424                                try
 425                                {
 426                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 427                                      "Caught exception before calling execl().");
 428                                }
 429                                catch (...) 
 430                                {
 431                                }
 432                               _exit(1);
 433                              }
 434                              PEG_METHOD_EXIT();
 435                              return;
 436                              break;
 437                      
 438                            case -1:
 439                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 440                                  "fork() failed.  errno = %d.", errno);
 441 gs.keenan       1.10         PEG_METHOD_EXIT();
 442                              throw Exception(MessageLoaderParms(
 443                                  "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
 444                                  "Failed to start cimprovagt \"$0\".",
 445                                  _moduleName));
 446                              break;
 447                      
 448                            default:
 449                              // Close our copies of the agent's ends of the pipes
 450                              pipeToAgent->closeReadHandle();
 451                              pipeFromAgent->closeWriteHandle();
 452 gs.keenan       1.8  
 453 gs.keenan       1.10         _pipeToAgent.reset(pipeToAgent.release());
 454                              _pipeFromAgent.reset(pipeFromAgent.release());
 455 gs.keenan       1.8  
 456 gs.keenan       1.10         PEG_METHOD_EXIT();
 457                          }
 458 chuck           1.16 #elif defined (PEGASUS_OS_OS400)
 459                      
 460                          //Out of provider support for OS400 goes here when needed.
 461                      
 462 kumpf           1.1  #else
 463                          pid_t pid = fork();
 464                          if (pid < 0)
 465                          {
 466                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 467                                  "fork() failed.  errno = %d.", errno);
 468                              PEG_METHOD_EXIT();
 469                              throw Exception(MessageLoaderParms(
 470                                  "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
 471                                  "Failed to start cimprovagt \"$0\".",
 472                                  _moduleName));
 473                          }
 474                          else if (pid == 0)
 475                          {
 476                              //
 477                              // Child side of the fork
 478                              //
 479                      
 480                              try
 481                              {
 482                                  // Close our copies of the parent's ends of the pipes
 483 kumpf           1.1              pipeToAgent->closeWriteHandle();
 484                                  pipeFromAgent->closeReadHandle();
 485                      
 486                                  //
 487                                  // Execute the cimprovagt program
 488                                  //
 489                                  String agentCommandPath =
 490                                      ConfigManager::getHomedPath(PEGASUS_PROVIDER_AGENT_PROC_NAME);
 491                                  CString agentCommandPathCString = agentCommandPath.getCString();
 492                      
 493                                  char readHandle[32];
 494                                  char writeHandle[32];
 495                                  pipeToAgent->exportReadHandle(readHandle);
 496                                  pipeFromAgent->exportWriteHandle(writeHandle);
 497                      
 498 kumpf           1.13 #ifndef PEGASUS_DISABLE_PROV_USERCTXT
 499 kumpf           1.6              // Set the user context of the Provider Agent process
 500                                  if (_userName != System::getEffectiveUserName())
 501                                  {
 502                                      if (!System::changeUserContext(_userName.getCString()))
 503                                      {
 504                                          Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 505                                              "System::changeUserContext() failed.  userName = %s.",
 506 kumpf           1.9                          (const char*)_userName.getCString());
 507 kumpf           1.6                      Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER,
 508                                              Logger::WARNING,
 509                                              "ProviderManager.OOPProviderManagerRouter."
 510                                                  "USER_CONTEXT_CHANGE_FAILED",
 511                                              "Unable to change user context to \"$0\".", _userName);
 512                                          _exit(1);
 513                                      }
 514                                  }
 515 kumpf           1.13 #endif
 516 kumpf           1.6  
 517 kumpf           1.1              execl(agentCommandPathCString, agentCommandPathCString,
 518                                      readHandle, writeHandle,
 519                                      (const char*)_moduleName.getCString(), (char*)0);
 520                      
 521                                  // If we're still here, there was an error
 522                                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 523                                      "execl() failed.  errno = %d.", errno);
 524                                  _exit(1);
 525                              }
 526                              catch (...)
 527                              {
 528                                  // There's not much we can do here in no man's land
 529                                  try
 530                                  {
 531                                      PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 532                                          "Caught exception before calling execl().");
 533                                  }
 534                                  catch (...) {}
 535                                  _exit(1);
 536                              }
 537                          }
 538 kumpf           1.1  #endif
 539                      
 540                          //
 541                          // CIM Server process
 542                          //
 543                      
 544                          // Close our copies of the agent's ends of the pipes
 545                          pipeToAgent->closeReadHandle();
 546                          pipeFromAgent->closeWriteHandle();
 547                      
 548                          _pipeToAgent.reset(pipeToAgent.release());
 549                          _pipeFromAgent.reset(pipeFromAgent.release());
 550                      
 551 gs.keenan       1.10     PEG_METHOD_EXIT();
 552 kumpf           1.1  }
 553                      
 554                      // Note: Caller must lock _agentMutex
 555                      void ProviderAgentContainer::_sendInitializationData()
 556                      {
 557                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 558                              "ProviderAgentContainer::_sendInitializationData");
 559                      
 560                          //
 561                          // Gather config properties to pass to the Provider Agent
 562                          //
 563                          ConfigManager* configManager = ConfigManager::getInstance();
 564                          Array<Pair<String, String> > configProperties;
 565                      
 566                          Array<String> configPropertyNames;
 567                          configManager->getAllPropertyNames(configPropertyNames, true);
 568                          for (Uint32 i = 0; i < configPropertyNames.size(); i++)
 569                          {
 570                              String configPropertyValue =
 571                                  configManager->getCurrentValue(configPropertyNames[i]);
 572                              String configPropertyDefaultValue =
 573 kumpf           1.1              configManager->getDefaultValue(configPropertyNames[i]);
 574                              if (configPropertyValue != configPropertyDefaultValue)
 575                              {
 576                                  configProperties.append(Pair<String, String>(
 577                                      configPropertyNames[i], configPropertyValue));
 578                              }
 579                          }
 580                      
 581                          //
 582                          // Create a Provider Agent initialization message
 583                          //
 584                          AutoPtr<CIMInitializeProviderAgentRequestMessage> request(
 585                              new CIMInitializeProviderAgentRequestMessage(
 586                                  String("0"),    // messageId
 587                                  configManager->getPegasusHome(),
 588                                  configProperties,
 589                                  System::bindVerbose,
 590 carolann.graves 1.14             _subscriptionInitComplete,
 591 kumpf           1.1              QueueIdStack()));
 592                      
 593                          //
 594                          // Write the initialization message to the pipe
 595                          //
 596                          AnonymousPipe::Status writeStatus =
 597                              _pipeToAgent->writeMessage(request.get());
 598                      
 599                          if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
 600                          {
 601                              PEG_METHOD_EXIT();
 602                              throw Exception(MessageLoaderParms(
 603                                  "ProviderManager.OOPProviderManagerRouter."
 604                                      "CIMPROVAGT_COMMUNICATION_FAILED",
 605                                  "Failed to communicate with cimprovagt \"$0\".",
 606                                  _moduleName));
 607                          }
 608                      
 609                          // Do not wait for a response from the Provider Agent.  (It isn't coming.)
 610                      
 611                          PEG_METHOD_EXIT();
 612 kumpf           1.1  }
 613                      
 614                      // Note: Caller must lock _agentMutex
 615                      void ProviderAgentContainer::_initialize()
 616                      {
 617                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 618                              "ProviderAgentContainer::_initialize");
 619                      
 620                          if (_isInitialized)
 621                          {
 622                              PEGASUS_ASSERT(0);
 623                              PEG_METHOD_EXIT();
 624                              return;
 625                          }
 626                      
 627 kumpf           1.6      if (_maxProviderProcesses == PEG_NOT_FOUND)
 628                          {
 629                              String maxProviderProcesses = ConfigManager::getInstance()->getCurrentValue("maxProviderProcesses");
 630                              CString maxProviderProcessesString = maxProviderProcesses.getCString();
 631                              char* end = 0;
 632                              _maxProviderProcesses = strtol(maxProviderProcessesString, &end, 10);
 633                          }
 634                      
 635                          {
 636                              AutoMutex lock(_numProviderProcessesMutex);
 637                              if ((_maxProviderProcesses != 0) &&
 638                                  (_numProviderProcesses >= _maxProviderProcesses))
 639                              {
 640                                  throw PEGASUS_CIM_EXCEPTION(
 641                                      CIM_ERR_FAILED,
 642                                      MessageLoaderParms(
 643                                          "ProviderManager.OOPProviderManagerRouter."
 644                                              "MAX_PROVIDER_PROCESSES_REACHED",
 645                                          "The maximum number of cimprovagt processes has been "
 646                                              "reached."));
 647                              }
 648 kumpf           1.6          else
 649                              {
 650                                  _numProviderProcesses++;
 651                              }
 652                          }
 653                      
 654 kumpf           1.1      try
 655                          {
 656                              _startAgentProcess();
 657                      
 658                              _sendInitializationData();
 659                      
 660                              _isInitialized = true;
 661                      
 662                              // Start a thread to read and process responses from the Provider Agent
 663                              while (!MessageQueueService::get_thread_pool()->allocate_and_awaken(
 664                                         this, _responseProcessor))
 665                              {
 666                                  pegasus_yield();
 667                              }
 668                          }
 669                          catch (...)
 670                          {
 671                              _isInitialized = false;
 672                              _pipeToAgent.reset();
 673                              _pipeFromAgent.reset();
 674 kumpf           1.6  
 675                              {
 676                                  AutoMutex lock(_numProviderProcessesMutex);
 677                                  _numProviderProcesses--;
 678                              }
 679                      
 680 kumpf           1.1          PEG_METHOD_EXIT();
 681                              throw;
 682                          }
 683                      
 684                          PEG_METHOD_EXIT();
 685                      }
 686                      
 687                      Boolean ProviderAgentContainer::isInitialized()
 688                      {
 689                          AutoMutex lock(_agentMutex);
 690                          return _isInitialized;
 691                      }
 692                      
 693                      // Note: Caller must lock _agentMutex
 694                      void ProviderAgentContainer::_uninitialize()
 695                      {
 696                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 697                              "ProviderAgentContainer::_uninitialize");
 698                      
 699                          if (!_isInitialized)
 700                          {
 701 kumpf           1.1          PEGASUS_ASSERT(0);
 702                              PEG_METHOD_EXIT();
 703                              return;
 704                          }
 705                      
 706                          try
 707                          {
 708                              // Close the connection with the Provider Agent
 709                              _pipeFromAgent.reset();
 710                              _pipeToAgent.reset();
 711                      
 712 kumpf           1.2          _providerModuleCache = CIMInstance();
 713                      
 714 kumpf           1.6          {
 715                                  AutoMutex lock(_numProviderProcessesMutex);
 716                                  _numProviderProcesses--;
 717                              }
 718                      
 719 kumpf           1.1          _isInitialized = false;
 720                      
 721                              //
 722                              // Complete with null responses all outstanding requests on this
 723                              // connection
 724                              //
 725                              {
 726                                  AutoMutex tableLock(_outstandingRequestTableMutex);
 727                      
 728                                  for (OutstandingRequestTable::Iterator i =
 729                                           _outstandingRequestTable.start();
 730                                       i != 0; i++)
 731                                  {
 732                                      PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 733                                          String("Completing messageId \"") + i.value()->messageId +
 734                                              "\" with a null response.");
 735                                      i.value()->responseMessage = 0;
 736                                      i.value()->responseReady->signal();
 737                                  }
 738                      
 739                                  _outstandingRequestTable.clear();
 740 kumpf           1.1          }
 741                          }
 742                          catch (...)
 743                          {
 744                              // We're uninitializing, so do not propagate the exception
 745                              PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 746                                  "Ignoring _uninitialize() exception.");
 747                          }
 748                      
 749                          PEG_METHOD_EXIT();
 750                      }
 751                      
 752 kumpf           1.6  String ProviderAgentContainer::getModuleName() const
 753                      {
 754                          return _moduleName;
 755                      }
 756                      
 757 kumpf           1.1  CIMResponseMessage* ProviderAgentContainer::processMessage(
 758                          CIMRequestMessage* request)
 759                      {
 760                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 761                              "ProviderAgentContainer::processMessage");
 762                      
 763                          CIMResponseMessage* response;
 764                          String originalMessageId = request->messageId;
 765                      
 766 kumpf           1.2      // These three variables are used for the provider module optimization.
 767                          // See the _providerModuleCache member description for more information.
 768                          AutoPtr<ProviderIdContainer> origProviderId;
 769                          Boolean doProviderModuleOptimization = false;
 770                          Boolean updateProviderModuleCache = false;
 771                      
 772 kumpf           1.1      try
 773                          {
 774                              // The messageId attribute is used to correlate response messages
 775                              // from the Provider Agent with request messages, so it is imperative
 776                              // that the ID is unique for each request.  The incoming ID cannot be
 777                              // trusted to be unique, so we substitute a unique one.  The memory
 778                              // address of the request is used as the source of a unique piece of
 779                              // data.  (The message ID is only required to be unique while the
 780                              // request is outstanding.)
 781                              char messagePtrString[20];
 782                              sprintf(messagePtrString, "%p", request);
 783                              String uniqueMessageId = messagePtrString;
 784                      
 785                              //
 786                              // Set up the OutstandingRequestEntry for this request
 787                              //
 788                              Semaphore waitSemaphore(0);
 789                              OutstandingRequestEntry outstandingRequestEntry(
 790                                  uniqueMessageId, response, &waitSemaphore);
 791                      
 792                              //
 793 kumpf           1.1          // Lock the Provider Agent Container while initializing the
 794                              // agent and writing the request to the connection
 795                              //
 796                              {
 797                                  AutoMutex lock(_agentMutex);
 798                      
 799                                  //
 800                                  // Initialize the Provider Agent, if necessary
 801                                  //
 802                                  if (!_isInitialized)
 803                                  {
 804                                      _initialize();
 805                                  }
 806                      
 807                                  //
 808                                  // Add an entry to the OutstandingRequestTable for this request
 809                                  //
 810                                  {
 811                                      AutoMutex tableLock(_outstandingRequestTableMutex);
 812                      
 813                                      _outstandingRequestTable.insert(
 814 kumpf           1.1                      uniqueMessageId, &outstandingRequestEntry);
 815                                  }
 816                      
 817 kumpf           1.2              // Get the provider module from the ProviderIdContainer to see if
 818                                  // we can optimize out the transmission of this instance to the
 819                                  // Provider Agent.  (See the _providerModuleCache description.)
 820                                  try
 821                                  {
 822                                      ProviderIdContainer pidc = request->operationContext.get(
 823                                          ProviderIdContainer::NAME);
 824                                      origProviderId.reset(new ProviderIdContainer(
 825                                          pidc.getModule(), pidc.getProvider(),
 826                                          pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
 827                                      if (_providerModuleCache.isUninitialized() ||
 828                                          (!pidc.getModule().identical(_providerModuleCache)))
 829                                      {
 830                                          // We haven't sent this provider module instance to the
 831                                          // Provider Agent yet.  Update our cache after we send it.
 832                                          updateProviderModuleCache = true;
 833                                      }
 834                                      else
 835                                      {
 836                                          // Replace the provider module in the ProviderIdContainer
 837                                          // with an uninitialized instance.  We'll need to put the
 838 kumpf           1.2                      // original one back after the message is sent.
 839                                          request->operationContext.set(ProviderIdContainer(
 840                                              CIMInstance(), pidc.getProvider(),
 841                                              pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
 842                                          doProviderModuleOptimization = true;
 843                                      }
 844                                  }
 845                                  catch (...)
 846                                  {
 847                                      // No ProviderIdContainer to optimize
 848                                  }
 849                      
 850 kumpf           1.1              //
 851                                  // Write the message to the pipe
 852                                  //
 853                                  try
 854                                  {
 855                                      PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL3,
 856                                          String("Sending request to agent with messageId ") +
 857                                              uniqueMessageId);
 858                      
 859                                      request->messageId = uniqueMessageId;
 860                                      AnonymousPipe::Status writeStatus =
 861                                          _pipeToAgent->writeMessage(request);
 862                                      request->messageId = originalMessageId;
 863                      
 864 kumpf           1.2                  if (doProviderModuleOptimization)
 865                                      {
 866                                          request->operationContext.set(*origProviderId.get());
 867                                      }
 868                      
 869 kumpf           1.1                  if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
 870                                      {
 871                                          Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 872                                              "Failed to write message to pipe.  writeStatus = %d.",
 873                                              writeStatus);
 874                                          throw Exception(MessageLoaderParms(
 875                                              "ProviderManager.OOPProviderManagerRouter."
 876                                                  "CIMPROVAGT_COMMUNICATION_FAILED",
 877                                              "Failed to communicate with cimprovagt \"$0\".",
 878                                              _moduleName));
 879                                      }
 880 kumpf           1.2  
 881                                      if (updateProviderModuleCache)
 882                                      {
 883                                          _providerModuleCache = origProviderId->getModule();
 884                                      }
 885 kumpf           1.1              }
 886                                  catch (...)
 887                                  {
 888                                      request->messageId = originalMessageId;
 889 kumpf           1.2  
 890                                      if (doProviderModuleOptimization)
 891                                      {
 892                                          request->operationContext.set(*origProviderId.get());
 893                                      }
 894                      
 895 kumpf           1.1                  Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 896                                          "Failed to write message to pipe.");
 897                                      // Remove the OutstandingRequestTable entry for this request
 898                                      {
 899                                          AutoMutex tableLock(_outstandingRequestTableMutex);
 900                                          Boolean removed =
 901                                              _outstandingRequestTable.remove(uniqueMessageId);
 902                                          PEGASUS_ASSERT(removed);
 903                                      }
 904                                      throw;
 905                                  }
 906                              }
 907                      
 908                              //
 909                              // Wait for the response
 910                              //
 911                              try
 912                              {
 913                                  // Must not hold _agentMutex while waiting for the response
 914                                  waitSemaphore.wait();
 915                              }
 916 kumpf           1.1          catch (...)
 917                              {
 918                                  // Remove the OutstandingRequestTable entry for this request
 919                                  {
 920                                      AutoMutex tableLock(_outstandingRequestTableMutex);
 921                                      Boolean removed =
 922                                          _outstandingRequestTable.remove(uniqueMessageId);
 923                                      PEGASUS_ASSERT(removed);
 924                                  }
 925                                  throw;
 926                              }
 927                      
 928                              // A null response is returned when an agent connection is closed
 929                              // while requests remain outstanding.
 930                              if (response == 0)
 931                              {
 932                                  response = request->buildResponse();
 933                                  response->cimException = PEGASUS_CIM_EXCEPTION(
 934                                      CIM_ERR_FAILED,
 935                                      MessageLoaderParms(
 936                                          "ProviderManager.OOPProviderManagerRouter."
 937 kumpf           1.1                          "CIMPROVAGT_CONNECTION_LOST",
 938                                          "Lost connection with cimprovagt \"$0\".",
 939                                          _moduleName));
 940                              }
 941                          }
 942                          catch (CIMException& e)
 943                          {
 944                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 945                                  String("Caught exception: ") + e.getMessage());
 946                              response = request->buildResponse();
 947                              response->cimException = e;
 948                          }
 949                          catch (Exception& e)
 950                          {
 951                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 952                                  String("Caught exception: ") + e.getMessage());
 953                              response = request->buildResponse();
 954                              response->cimException = PEGASUS_CIM_EXCEPTION(
 955                                  CIM_ERR_FAILED, e.getMessage());
 956                          }
 957                          catch (...)
 958 kumpf           1.1      {
 959                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 960                                  "Caught unknown exception");
 961                              response = request->buildResponse();
 962                              response->cimException = PEGASUS_CIM_EXCEPTION(
 963                                  CIM_ERR_FAILED, String::EMPTY);
 964                          }
 965                      
 966                          response->messageId = originalMessageId;
 967                      
 968                          PEG_METHOD_EXIT();
 969                          return response;
 970                      }
 971                      
 972                      void ProviderAgentContainer::unloadIdleProviders()
 973                      {
 974                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 975 carolann.graves 1.4          "ProviderAgentContainer::unloadIdleProviders");
 976 kumpf           1.1  
 977                          AutoMutex lock(_agentMutex);
 978                          if (_isInitialized)
 979                          {
 980                              // Send a "wake up" message to the Provider Agent.
 981                              // Don't bother checking whether the operation is successful.
 982                              Uint32 messageLength = 0;
 983                              _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
 984                          }
 985                      
 986                          PEG_METHOD_EXIT();
 987                      }
 988                      
 989                      void ProviderAgentContainer::_processResponses()
 990                      {
 991                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 992                              "ProviderAgentContainer::_processResponses");
 993                      
 994                          //
 995                          // Process responses until the pipe is closed
 996                          //
 997 kumpf           1.1      while (1)
 998                          {
 999                              try
1000                              {
1001                                  CIMMessage* message;
1002                      
1003                                  //
1004                                  // Read a response from the Provider Agent
1005                                  //
1006                                  AnonymousPipe::Status readStatus =
1007                                      _pipeFromAgent->readMessage(message);
1008                      
1009                                  // Ignore interrupts
1010                                  if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
1011                                  {
1012                                      continue;
1013                                  }
1014                      
1015                                  // Handle an error the same way as a closed connection
1016                                  if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
1017                                      (readStatus == AnonymousPipe::STATUS_CLOSED))
1018 kumpf           1.1              {
1019                                      AutoMutex lock(_agentMutex);
1020                                      _uninitialize();
1021                                      return;
1022                                  }
1023                      
1024                                  if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
1025                                  {
1026                                      // Forward indications to the indication callback
1027                                      _indicationCallback(
1028                                          reinterpret_cast<CIMProcessIndicationRequestMessage*>(
1029                                              message));
1030                                  }
1031                                  else
1032                                  {
1033                                      CIMResponseMessage* response;
1034                                      response = dynamic_cast<CIMResponseMessage*>(message);
1035                                      PEGASUS_ASSERT(response != 0);
1036                      
1037                                      // Give the response to the waiting OutstandingRequestEntry
1038                                      OutstandingRequestEntry* _outstandingRequestEntry = 0;
1039 kumpf           1.1                  {
1040                                          AutoMutex tableLock(_outstandingRequestTableMutex);
1041                                          Boolean foundEntry = _outstandingRequestTable.lookup(
1042                                              response->messageId, _outstandingRequestEntry);
1043                                          PEGASUS_ASSERT(foundEntry);
1044                      
1045                                          // Remove the completed request from the table
1046                                          Boolean removed =
1047                                              _outstandingRequestTable.remove(response->messageId);
1048                                          PEGASUS_ASSERT(removed);
1049                                      }
1050                      
1051                                      _outstandingRequestEntry->responseMessage = response;
1052                                      _outstandingRequestEntry->responseReady->signal();
1053                                  }
1054                              }
1055                              catch (Exception& e)
1056                              {
1057                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1058                                      String("Ignoring exception: ") + e.getMessage());
1059                              }
1060 kumpf           1.1          catch (...)
1061                              {
1062                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1063                                      "Ignoring exception");
1064                              }
1065                          }
1066                      
1067                      }
1068                      
1069                      PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
1070                      ProviderAgentContainer::_responseProcessor(void* arg)
1071                      {
1072                          ProviderAgentContainer* pa =
1073                              reinterpret_cast<ProviderAgentContainer*>(arg);
1074                      
1075                          pa->_processResponses();
1076                      
1077                          return(PEGASUS_THREAD_RETURN(0));
1078                      }
1079                      
1080                      /////////////////////////////////////////////////////////////////////////////
1081 kumpf           1.1  // OOPProviderManagerRouter
1082                      /////////////////////////////////////////////////////////////////////////////
1083                      
1084                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1085                          PEGASUS_INDICATION_CALLBACK indicationCallback)
1086                      {
1087                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1088                              "OOPProviderManagerRouter::OOPProviderManagerRouter");
1089                      
1090                          _indicationCallback = indicationCallback;
1091 carolann.graves 1.14     _subscriptionInitComplete = false;
1092 kumpf           1.1  
1093                          PEG_METHOD_EXIT();
1094                      }
1095                      
1096                      OOPProviderManagerRouter::~OOPProviderManagerRouter()
1097                      {
1098                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1099                              "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1100                      
1101                          try
1102                          {
1103                              // Clean up the ProviderAgentContainers
1104                              AutoMutex lock(_providerAgentTableMutex);
1105                              ProviderAgentTable::Iterator i = _providerAgentTable.start();
1106                              for(; i != 0; i++)
1107                              {
1108                                  delete i.value();
1109                              }
1110                          }
1111                          catch (...) {}
1112                      
1113 kumpf           1.1      PEG_METHOD_EXIT();
1114                      }
1115                      
1116                      // Private, unimplemented constructor
1117                      OOPProviderManagerRouter::OOPProviderManagerRouter()
1118                      {
1119                      }
1120                      
1121                      // Private, unimplemented constructor
1122                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1123                          const OOPProviderManagerRouter&)
1124 david.dillard   1.3      : ProviderManagerRouter(*this)
1125 kumpf           1.1  {
1126                      }
1127                      
1128                      // Private, unimplemented assignment operator
1129                      OOPProviderManagerRouter& OOPProviderManagerRouter::operator=(
1130                          const OOPProviderManagerRouter&)
1131                      {
1132                          return *this;
1133                      }
1134                      
1135                      Message* OOPProviderManagerRouter::processMessage(Message* message)
1136                      {
1137                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1138                              "OOPProviderManagerRouter::processMessage");
1139                      
1140                          CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1141                          PEGASUS_ASSERT(request != 0);
1142                      
1143                          AutoPtr<CIMResponseMessage> response;
1144                      
1145                          //
1146 kumpf           1.1      // Get the provider information from the request
1147                          //
1148                          CIMInstance providerModule;
1149                      
1150                          if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1151                              (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1152                              (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1153                          {
1154                              // Provider information is in the OperationContext
1155                              ProviderIdContainer pidc = (ProviderIdContainer)
1156                                  request->operationContext.get(ProviderIdContainer::NAME);
1157                              providerModule = pidc.getModule();
1158                          }
1159                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1160                          {
1161                              CIMEnableModuleRequestMessage* emReq =
1162                                  dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1163                              providerModule = emReq->providerModule;
1164                          }
1165                          else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1166                          {
1167 kumpf           1.1          CIMDisableModuleRequestMessage* dmReq =
1168                                  dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1169                              providerModule = dmReq->providerModule;
1170                          }
1171                          else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1172 carolann.graves 1.14              (request->getType() ==
1173                                       CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1174 kumpf           1.1               (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1175                          {
1176                              // This operation is not provider-specific
1177                          }
1178                          else
1179                          {
1180                              // Unrecognized message type.  This should never happen.
1181                              PEGASUS_ASSERT(0);
1182                              response.reset(request->buildResponse());
1183                              response->cimException = PEGASUS_CIM_EXCEPTION(
1184                                  CIM_ERR_FAILED, "Unrecognized message type.");
1185                              PEG_METHOD_EXIT();
1186                              return response.release();
1187                          }
1188                      
1189                          //
1190                          // Process the request message
1191                          //
1192                          if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1193                          {
1194                              // Forward the CIMStopAllProvidersRequest to all providers
1195 kumpf           1.1          response.reset(_forwardRequestToAllAgents(request));
1196                      
1197                              // Note: Do not uninitialize the ProviderAgentContainers here.
1198                              // Just let the selecting thread notice when the agent connections
1199                              // are closed.
1200                          }
1201 carolann.graves 1.14     else if (request->getType () == 
1202                              CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1203                          {
1204                              _subscriptionInitComplete = true;
1205                      
1206                              //
1207                              //  Forward the CIMSubscriptionInitCompleteRequestMessage to 
1208                              //  all providers
1209                              //
1210                              response.reset (_forwardRequestToAllAgents (request));
1211                          }
1212 kumpf           1.1      else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1213                          {
1214                              CIMNotifyConfigChangeRequestMessage* notifyRequest =
1215                                  dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1216                              PEGASUS_ASSERT(notifyRequest != 0);
1217                      
1218                              if (notifyRequest->currentValueModified)
1219                              {
1220                                  // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1221                                  response.reset(_forwardRequestToAllAgents(request));
1222                              }
1223                              else
1224                              {
1225                                  // No need to notify provider agents about changes to planned value
1226                                  response.reset(request->buildResponse());
1227                              }
1228                          }
1229 kumpf           1.6      else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1230 kumpf           1.1      {
1231 kumpf           1.6          // Fan out the request to all Provider Agent processes for this module
1232                      
1233 kumpf           1.1          // Retrieve the provider module name
1234                              String moduleName;
1235                              CIMValue nameValue = providerModule.getProperty(
1236                                  providerModule.findProperty("Name")).getValue();
1237                              nameValue.get(moduleName);
1238                      
1239 kumpf           1.6          // Look up the Provider Agents for this module
1240                              Array<ProviderAgentContainer*> paArray =
1241                                  _lookupProviderAgents(moduleName);
1242 kumpf           1.1  
1243 kumpf           1.6          for (Uint32 i=0; i<paArray.size(); i++)
1244 kumpf           1.1          {
1245                                  //
1246                                  // Do not start up an agent process just to disable the module
1247                                  //
1248 kumpf           1.6              if (paArray[i]->isInitialized())
1249                                  {
1250                                      //
1251                                      // Forward the request to the provider agent
1252                                      //
1253                                      response.reset(paArray[i]->processMessage(request));
1254                      
1255                                      // Note: Do not uninitialize the ProviderAgentContainer here
1256                                      // when a disable module operation is successful.  Just let the
1257                                      // selecting thread notice when the agent connection is closed.
1258                      
1259                                      // Determine the success of the disable module operation
1260                                      CIMDisableModuleResponseMessage* dmResponse =
1261                                          dynamic_cast<CIMDisableModuleResponseMessage*>(
1262                                              response.get());
1263                                      PEGASUS_ASSERT(dmResponse != 0);
1264                      
1265                                      Boolean isStopped = false;
1266                                      for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1267                                      {
1268                                          if (dmResponse->operationalStatus[i] ==
1269 kumpf           1.6                          CIM_MSE_OPSTATUS_VALUE_STOPPED)
1270                                          {
1271                                              isStopped = true;
1272                                              break;
1273                                          }
1274                                      }
1275                      
1276                                      // If the operation is unsuccessful, stop and return the error
1277                                      if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1278                                          !isStopped)
1279                                      {
1280                                          break;
1281                                      }
1282                                  }
1283                              }
1284                      
1285                              // Use a default response if no Provider Agents were called
1286                              if (!response.get())
1287                              {
1288 kumpf           1.1              response.reset(request->buildResponse());
1289                      
1290                                  CIMDisableModuleResponseMessage* dmResponse =
1291                                      dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1292                                  PEGASUS_ASSERT(dmResponse != 0);
1293                      
1294                                  Array<Uint16> operationalStatus;
1295                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1296                                  dmResponse->operationalStatus = operationalStatus;
1297                              }
1298 kumpf           1.6      }
1299                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1300                          {
1301                              // Fan out the request to all Provider Agent processes for this module
1302                      
1303                              // Retrieve the provider module name
1304                              String moduleName;
1305                              CIMValue nameValue = providerModule.getProperty(
1306                                  providerModule.findProperty("Name")).getValue();
1307                              nameValue.get(moduleName);
1308                      
1309                              // Look up the Provider Agents for this module
1310                              Array<ProviderAgentContainer*> paArray =
1311                                  _lookupProviderAgents(moduleName);
1312                      
1313                              for (Uint32 i=0; i<paArray.size(); i++)
1314 kumpf           1.1          {
1315                                  //
1316                                  // Do not start up an agent process just to enable the module
1317                                  //
1318 kumpf           1.6              if (paArray[i]->isInitialized())
1319                                  {
1320                                      //
1321                                      // Forward the request to the provider agent
1322                                      //
1323                                      response.reset(paArray[i]->processMessage(request));
1324                      
1325                                      // Determine the success of the enable module operation
1326                                      CIMEnableModuleResponseMessage* emResponse =
1327                                          dynamic_cast<CIMEnableModuleResponseMessage*>(
1328                                              response.get());
1329                                      PEGASUS_ASSERT(emResponse != 0);
1330                      
1331                                      Boolean isOk = false;
1332                                      for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1333                                      {
1334                                          if (emResponse->operationalStatus[i] ==
1335                                              CIM_MSE_OPSTATUS_VALUE_OK)
1336                                          {
1337                                              isOk = true;
1338                                              break;
1339 kumpf           1.6                      }
1340                                      }
1341                      
1342                                      // If the operation is unsuccessful, stop and return the error
1343                                      if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1344                                          !isOk)
1345                                      {
1346                                          break;
1347                                      }
1348                                  }
1349                              }
1350                      
1351                              // Use a default response if no Provider Agents were called
1352                              if (!response.get())
1353                              {
1354 kumpf           1.1              response.reset(request->buildResponse());
1355                      
1356                                  CIMEnableModuleResponseMessage* emResponse =
1357                                      dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1358                                  PEGASUS_ASSERT(emResponse != 0);
1359                      
1360                                  Array<Uint16> operationalStatus;
1361                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1362                                  emResponse->operationalStatus = operationalStatus;
1363                              }
1364 kumpf           1.6      }
1365                          else
1366                          {
1367                              // Retrieve the provider module name
1368                              String moduleName;
1369                              CIMValue nameValue = providerModule.getProperty(
1370                                  providerModule.findProperty("Name")).getValue();
1371                              nameValue.get(moduleName);
1372                      
1373                              // Retrieve the provider user context configuration
1374                              Uint16 userContext = 0;
1375                              Uint32 pos = providerModule.findProperty(
1376                                  PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1377                              if (pos != PEG_NOT_FOUND)
1378                              {
1379 kumpf           1.12             CIMValue userContextValue =
1380                                      providerModule.getProperty(pos).getValue();
1381                                  if (!userContextValue.isNull())
1382                                  {
1383                                      userContextValue.get(userContext);
1384                                  }
1385 kumpf           1.6          }
1386                      
1387                              if (userContext == 0)
1388                              {
1389                                  userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED;
1390                              }
1391                      
1392                              String userName;
1393                      
1394                              if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
1395 kumpf           1.1          {
1396 kumpf           1.6              try
1397                                  {
1398                                      // User Name is in the OperationContext
1399                                      IdentityContainer ic = (IdentityContainer)
1400                                          request->operationContext.get(IdentityContainer::NAME);
1401                                      userName = ic.getUserName();
1402                                  }
1403                                  catch (Exception& e)
1404                                  {
1405                                      // If no IdentityContainer is present, default to the CIM
1406                                      // Server's user context
1407                                  }
1408 kumpf           1.1  
1409 kumpf           1.6              // If authentication is disabled, use the CIM Server's user context
1410                                  if (!userName.size())
1411                                  {
1412                                      userName = System::getEffectiveUserName();
1413                                  }
1414                              }
1415                              else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1416                              {
1417                                  // Retrieve the provider module name
1418                                  providerModule.getProperty(providerModule.findProperty(
1419                                      PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1420                                      get(userName);
1421                              }
1422                              else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1423                              {
1424                                  userName = System::getEffectiveUserName();
1425                              }
1426                              else    // Privileged User
1427                              {
1428                                  PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1429                                  userName = System::getPrivilegedUserName();
1430 kumpf           1.1          }
1431 kumpf           1.6  
1432                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1433                                  "Module name = " + moduleName);
1434                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1435                                  "User context = %hd.", userContext);
1436                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1437                                  "User name = " + userName);
1438                      
1439                              // Look up the Provider Agent for this module and user
1440                              ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName);
1441                              PEGASUS_ASSERT(pa != 0);
1442                      
1443                              //
1444                              // Forward the request to the provider agent
1445                              //
1446                              response.reset(pa->processMessage(request));
1447 kumpf           1.1      }
1448                      
1449                          response->syncAttributes(request);
1450                      
1451                          PEG_METHOD_EXIT();
1452                          return response.release();
1453                      }
1454                      
1455                      ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1456 kumpf           1.6      const String& moduleName,
1457                          const String& userName)
1458 kumpf           1.1  {
1459                          ProviderAgentContainer* pa = 0;
1460 kumpf           1.6      String key = moduleName + ":" + userName;
1461 kumpf           1.1  
1462                          AutoMutex lock(_providerAgentTableMutex);
1463 kumpf           1.6      if (!_providerAgentTable.lookup(key, pa))
1464 kumpf           1.1      {
1465 kumpf           1.6          pa = new ProviderAgentContainer(
1466 carolann.graves 1.14             moduleName, userName, _indicationCallback,
1467                                  _subscriptionInitComplete);
1468 kumpf           1.6          _providerAgentTable.insert(key, pa);
1469 kumpf           1.1      }
1470                          return pa;
1471                      }
1472                      
1473 kumpf           1.6  Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1474                          const String& moduleName)
1475                      {
1476                          Array<ProviderAgentContainer*> paArray;
1477                      
1478                          AutoMutex lock(_providerAgentTableMutex);
1479                          for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1480                          {
1481                              if (i.value()->getModuleName() == moduleName)
1482                              {
1483                                  paArray.append(i.value());
1484                              }
1485                          }
1486                          return paArray;
1487                      }
1488                      
1489 kumpf           1.1  CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1490                          CIMRequestMessage* request)
1491                      {
1492                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1493                              "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1494                      
1495                          // Get a list of the ProviderAgentContainers.  We need our own array copy
1496                          // because we cannot hold the _providerAgentTableMutex while calling
1497                          // _ProviderAgentContainer::processMessage().
1498                          Array<ProviderAgentContainer*> paContainerArray;
1499                          {
1500                              AutoMutex tableLock(_providerAgentTableMutex);
1501                              for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1502                                   i != 0; i++)
1503                              {
1504                                  paContainerArray.append(i.value());
1505                              }
1506                          }
1507                      
1508                          CIMException responseException;
1509                      
1510 kumpf           1.1      // Forward the request to each of the initialized provider agents
1511                          for (Uint32 j = 0; j < paContainerArray.size(); j++)
1512                          {
1513                              ProviderAgentContainer* pa = paContainerArray[j];
1514                              if (pa->isInitialized())
1515                              {
1516                                  // Note: The ProviderAgentContainer could become uninitialized
1517                                  // before _ProviderAgentContainer::processMessage() processes
1518                                  // this request.  In this case, the Provider Agent process will
1519                                  // (unfortunately) be started to process this message.
1520                                  AutoPtr<CIMResponseMessage> response;
1521                                  response.reset(pa->processMessage(request));
1522                                  if (response.get() != 0)
1523                                  {
1524                                      // If the operation failed, save the exception data
1525                                      if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1526                                          (responseException.getCode() == CIM_ERR_SUCCESS))
1527                                      {
1528                                          responseException = response->cimException;
1529                                      }
1530                                  }
1531 kumpf           1.1          }
1532                          }
1533                      
1534                          CIMResponseMessage* response = request->buildResponse();
1535                          response->cimException = responseException;
1536                      
1537                          PEG_METHOD_EXIT();
1538                          return response;
1539                      }
1540                      
1541                      Boolean OOPProviderManagerRouter::hasActiveProviders()
1542                      {
1543                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1544                              "OOPProviderManagerRouter::hasActiveProviders");
1545                      
1546                          // Iterate through the _providerAgentTable looking for initialized agents
1547                          AutoMutex lock(_providerAgentTableMutex);
1548                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1549                          for(; i != 0; i++)
1550                          {
1551                              if (i.value()->isInitialized())
1552 kumpf           1.1          {
1553                                  PEG_METHOD_EXIT();
1554                                  return true;
1555                              }
1556                          }
1557                      
1558                          // No initialized Provider Agents were found
1559                          PEG_METHOD_EXIT();
1560                          return false;
1561                      }
1562                      
1563                      void OOPProviderManagerRouter::unloadIdleProviders()
1564                      {
1565                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1566                              "OOPProviderManagerRouter::unloadIdleProviders");
1567                      
1568                          // Iterate through the _providerAgentTable unloading idle providers
1569                          AutoMutex lock(_providerAgentTableMutex);
1570                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1571                          for(; i != 0; i++)
1572                          {
1573 kumpf           1.1          i.value()->unloadIdleProviders();
1574                          }
1575                      
1576                          PEG_METHOD_EXIT();
1577                      }
1578                      
1579                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2