(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 kumpf           1.1  #else
 459                          pid_t pid = fork();
 460                          if (pid < 0)
 461                          {
 462                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 463                                  "fork() failed.  errno = %d.", errno);
 464                              PEG_METHOD_EXIT();
 465                              throw Exception(MessageLoaderParms(
 466                                  "ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED",
 467                                  "Failed to start cimprovagt \"$0\".",
 468                                  _moduleName));
 469                          }
 470                          else if (pid == 0)
 471                          {
 472                              //
 473                              // Child side of the fork
 474                              //
 475                      
 476                              try
 477                              {
 478                                  // Close our copies of the parent's ends of the pipes
 479 kumpf           1.1              pipeToAgent->closeWriteHandle();
 480                                  pipeFromAgent->closeReadHandle();
 481                      
 482                                  //
 483                                  // Execute the cimprovagt program
 484                                  //
 485                                  String agentCommandPath =
 486                                      ConfigManager::getHomedPath(PEGASUS_PROVIDER_AGENT_PROC_NAME);
 487                                  CString agentCommandPathCString = agentCommandPath.getCString();
 488                      
 489                                  char readHandle[32];
 490                                  char writeHandle[32];
 491                                  pipeToAgent->exportReadHandle(readHandle);
 492                                  pipeFromAgent->exportWriteHandle(writeHandle);
 493                      
 494 kumpf           1.13 #ifndef PEGASUS_DISABLE_PROV_USERCTXT
 495 kumpf           1.6              // Set the user context of the Provider Agent process
 496                                  if (_userName != System::getEffectiveUserName())
 497                                  {
 498                                      if (!System::changeUserContext(_userName.getCString()))
 499                                      {
 500                                          Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 501                                              "System::changeUserContext() failed.  userName = %s.",
 502 kumpf           1.9                          (const char*)_userName.getCString());
 503 kumpf           1.6                      Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER,
 504                                              Logger::WARNING,
 505                                              "ProviderManager.OOPProviderManagerRouter."
 506                                                  "USER_CONTEXT_CHANGE_FAILED",
 507                                              "Unable to change user context to \"$0\".", _userName);
 508                                          _exit(1);
 509                                      }
 510                                  }
 511 kumpf           1.13 #endif
 512 kumpf           1.6  
 513 kumpf           1.1              execl(agentCommandPathCString, agentCommandPathCString,
 514                                      readHandle, writeHandle,
 515                                      (const char*)_moduleName.getCString(), (char*)0);
 516                      
 517                                  // If we're still here, there was an error
 518                                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 519                                      "execl() failed.  errno = %d.", errno);
 520                                  _exit(1);
 521                              }
 522                              catch (...)
 523                              {
 524                                  // There's not much we can do here in no man's land
 525                                  try
 526                                  {
 527                                      PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 528                                          "Caught exception before calling execl().");
 529                                  }
 530                                  catch (...) {}
 531                                  _exit(1);
 532                              }
 533                          }
 534 kumpf           1.1  #endif
 535                      
 536                          //
 537                          // CIM Server process
 538                          //
 539                      
 540                          // Close our copies of the agent's ends of the pipes
 541                          pipeToAgent->closeReadHandle();
 542                          pipeFromAgent->closeWriteHandle();
 543                      
 544                          _pipeToAgent.reset(pipeToAgent.release());
 545                          _pipeFromAgent.reset(pipeFromAgent.release());
 546                      
 547 gs.keenan       1.10     PEG_METHOD_EXIT();
 548 kumpf           1.1  }
 549                      
 550                      // Note: Caller must lock _agentMutex
 551                      void ProviderAgentContainer::_sendInitializationData()
 552                      {
 553                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 554                              "ProviderAgentContainer::_sendInitializationData");
 555                      
 556                          //
 557                          // Gather config properties to pass to the Provider Agent
 558                          //
 559                          ConfigManager* configManager = ConfigManager::getInstance();
 560                          Array<Pair<String, String> > configProperties;
 561                      
 562                          Array<String> configPropertyNames;
 563                          configManager->getAllPropertyNames(configPropertyNames, true);
 564                          for (Uint32 i = 0; i < configPropertyNames.size(); i++)
 565                          {
 566                              String configPropertyValue =
 567                                  configManager->getCurrentValue(configPropertyNames[i]);
 568                              String configPropertyDefaultValue =
 569 kumpf           1.1              configManager->getDefaultValue(configPropertyNames[i]);
 570                              if (configPropertyValue != configPropertyDefaultValue)
 571                              {
 572                                  configProperties.append(Pair<String, String>(
 573                                      configPropertyNames[i], configPropertyValue));
 574                              }
 575                          }
 576                      
 577                          //
 578                          // Create a Provider Agent initialization message
 579                          //
 580                          AutoPtr<CIMInitializeProviderAgentRequestMessage> request(
 581                              new CIMInitializeProviderAgentRequestMessage(
 582                                  String("0"),    // messageId
 583                                  configManager->getPegasusHome(),
 584                                  configProperties,
 585                                  System::bindVerbose,
 586 carolann.graves 1.14             _subscriptionInitComplete,
 587 kumpf           1.1              QueueIdStack()));
 588                      
 589                          //
 590                          // Write the initialization message to the pipe
 591                          //
 592                          AnonymousPipe::Status writeStatus =
 593                              _pipeToAgent->writeMessage(request.get());
 594                      
 595                          if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
 596                          {
 597                              PEG_METHOD_EXIT();
 598                              throw Exception(MessageLoaderParms(
 599                                  "ProviderManager.OOPProviderManagerRouter."
 600                                      "CIMPROVAGT_COMMUNICATION_FAILED",
 601                                  "Failed to communicate with cimprovagt \"$0\".",
 602                                  _moduleName));
 603                          }
 604                      
 605                          // Do not wait for a response from the Provider Agent.  (It isn't coming.)
 606                      
 607                          PEG_METHOD_EXIT();
 608 kumpf           1.1  }
 609                      
 610                      // Note: Caller must lock _agentMutex
 611                      void ProviderAgentContainer::_initialize()
 612                      {
 613                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 614                              "ProviderAgentContainer::_initialize");
 615                      
 616                          if (_isInitialized)
 617                          {
 618                              PEGASUS_ASSERT(0);
 619                              PEG_METHOD_EXIT();
 620                              return;
 621                          }
 622                      
 623 kumpf           1.6      if (_maxProviderProcesses == PEG_NOT_FOUND)
 624                          {
 625                              String maxProviderProcesses = ConfigManager::getInstance()->getCurrentValue("maxProviderProcesses");
 626                              CString maxProviderProcessesString = maxProviderProcesses.getCString();
 627                              char* end = 0;
 628                              _maxProviderProcesses = strtol(maxProviderProcessesString, &end, 10);
 629                          }
 630                      
 631                          {
 632                              AutoMutex lock(_numProviderProcessesMutex);
 633                              if ((_maxProviderProcesses != 0) &&
 634                                  (_numProviderProcesses >= _maxProviderProcesses))
 635                              {
 636                                  throw PEGASUS_CIM_EXCEPTION(
 637                                      CIM_ERR_FAILED,
 638                                      MessageLoaderParms(
 639                                          "ProviderManager.OOPProviderManagerRouter."
 640                                              "MAX_PROVIDER_PROCESSES_REACHED",
 641                                          "The maximum number of cimprovagt processes has been "
 642                                              "reached."));
 643                              }
 644 kumpf           1.6          else
 645                              {
 646                                  _numProviderProcesses++;
 647                              }
 648                          }
 649                      
 650 kumpf           1.1      try
 651                          {
 652                              _startAgentProcess();
 653                      
 654                              _sendInitializationData();
 655                      
 656                              _isInitialized = true;
 657                      
 658                              // Start a thread to read and process responses from the Provider Agent
 659                              while (!MessageQueueService::get_thread_pool()->allocate_and_awaken(
 660                                         this, _responseProcessor))
 661                              {
 662                                  pegasus_yield();
 663                              }
 664                          }
 665                          catch (...)
 666                          {
 667                              _isInitialized = false;
 668                              _pipeToAgent.reset();
 669                              _pipeFromAgent.reset();
 670 kumpf           1.6  
 671                              {
 672                                  AutoMutex lock(_numProviderProcessesMutex);
 673                                  _numProviderProcesses--;
 674                              }
 675                      
 676 kumpf           1.1          PEG_METHOD_EXIT();
 677                              throw;
 678                          }
 679                      
 680                          PEG_METHOD_EXIT();
 681                      }
 682                      
 683                      Boolean ProviderAgentContainer::isInitialized()
 684                      {
 685                          AutoMutex lock(_agentMutex);
 686                          return _isInitialized;
 687                      }
 688                      
 689                      // Note: Caller must lock _agentMutex
 690                      void ProviderAgentContainer::_uninitialize()
 691                      {
 692                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 693                              "ProviderAgentContainer::_uninitialize");
 694                      
 695                          if (!_isInitialized)
 696                          {
 697 kumpf           1.1          PEGASUS_ASSERT(0);
 698                              PEG_METHOD_EXIT();
 699                              return;
 700                          }
 701                      
 702                          try
 703                          {
 704                              // Close the connection with the Provider Agent
 705                              _pipeFromAgent.reset();
 706                              _pipeToAgent.reset();
 707                      
 708 kumpf           1.2          _providerModuleCache = CIMInstance();
 709                      
 710 kumpf           1.6          {
 711                                  AutoMutex lock(_numProviderProcessesMutex);
 712                                  _numProviderProcesses--;
 713                              }
 714                      
 715 kumpf           1.1          _isInitialized = false;
 716                      
 717                              //
 718                              // Complete with null responses all outstanding requests on this
 719                              // connection
 720                              //
 721                              {
 722                                  AutoMutex tableLock(_outstandingRequestTableMutex);
 723                      
 724                                  for (OutstandingRequestTable::Iterator i =
 725                                           _outstandingRequestTable.start();
 726                                       i != 0; i++)
 727                                  {
 728                                      PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 729                                          String("Completing messageId \"") + i.value()->messageId +
 730                                              "\" with a null response.");
 731                                      i.value()->responseMessage = 0;
 732                                      i.value()->responseReady->signal();
 733                                  }
 734                      
 735                                  _outstandingRequestTable.clear();
 736 kumpf           1.1          }
 737                          }
 738                          catch (...)
 739                          {
 740                              // We're uninitializing, so do not propagate the exception
 741                              PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 742                                  "Ignoring _uninitialize() exception.");
 743                          }
 744                      
 745                          PEG_METHOD_EXIT();
 746                      }
 747                      
 748 kumpf           1.6  String ProviderAgentContainer::getModuleName() const
 749                      {
 750                          return _moduleName;
 751                      }
 752                      
 753 kumpf           1.1  CIMResponseMessage* ProviderAgentContainer::processMessage(
 754                          CIMRequestMessage* request)
 755                      {
 756                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 757                              "ProviderAgentContainer::processMessage");
 758                      
 759                          CIMResponseMessage* response;
 760                          String originalMessageId = request->messageId;
 761                      
 762 kumpf           1.2      // These three variables are used for the provider module optimization.
 763                          // See the _providerModuleCache member description for more information.
 764                          AutoPtr<ProviderIdContainer> origProviderId;
 765                          Boolean doProviderModuleOptimization = false;
 766                          Boolean updateProviderModuleCache = false;
 767                      
 768 kumpf           1.1      try
 769                          {
 770                              // The messageId attribute is used to correlate response messages
 771                              // from the Provider Agent with request messages, so it is imperative
 772                              // that the ID is unique for each request.  The incoming ID cannot be
 773                              // trusted to be unique, so we substitute a unique one.  The memory
 774                              // address of the request is used as the source of a unique piece of
 775                              // data.  (The message ID is only required to be unique while the
 776                              // request is outstanding.)
 777                              char messagePtrString[20];
 778                              sprintf(messagePtrString, "%p", request);
 779                              String uniqueMessageId = messagePtrString;
 780                      
 781                              //
 782                              // Set up the OutstandingRequestEntry for this request
 783                              //
 784                              Semaphore waitSemaphore(0);
 785                              OutstandingRequestEntry outstandingRequestEntry(
 786                                  uniqueMessageId, response, &waitSemaphore);
 787                      
 788                              //
 789 kumpf           1.1          // Lock the Provider Agent Container while initializing the
 790                              // agent and writing the request to the connection
 791                              //
 792                              {
 793                                  AutoMutex lock(_agentMutex);
 794                      
 795                                  //
 796                                  // Initialize the Provider Agent, if necessary
 797                                  //
 798                                  if (!_isInitialized)
 799                                  {
 800                                      _initialize();
 801                                  }
 802                      
 803                                  //
 804                                  // Add an entry to the OutstandingRequestTable for this request
 805                                  //
 806                                  {
 807                                      AutoMutex tableLock(_outstandingRequestTableMutex);
 808                      
 809                                      _outstandingRequestTable.insert(
 810 kumpf           1.1                      uniqueMessageId, &outstandingRequestEntry);
 811                                  }
 812                      
 813 kumpf           1.2              // Get the provider module from the ProviderIdContainer to see if
 814                                  // we can optimize out the transmission of this instance to the
 815                                  // Provider Agent.  (See the _providerModuleCache description.)
 816                                  try
 817                                  {
 818                                      ProviderIdContainer pidc = request->operationContext.get(
 819                                          ProviderIdContainer::NAME);
 820                                      origProviderId.reset(new ProviderIdContainer(
 821                                          pidc.getModule(), pidc.getProvider(),
 822                                          pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
 823                                      if (_providerModuleCache.isUninitialized() ||
 824                                          (!pidc.getModule().identical(_providerModuleCache)))
 825                                      {
 826                                          // We haven't sent this provider module instance to the
 827                                          // Provider Agent yet.  Update our cache after we send it.
 828                                          updateProviderModuleCache = true;
 829                                      }
 830                                      else
 831                                      {
 832                                          // Replace the provider module in the ProviderIdContainer
 833                                          // with an uninitialized instance.  We'll need to put the
 834 kumpf           1.2                      // original one back after the message is sent.
 835                                          request->operationContext.set(ProviderIdContainer(
 836                                              CIMInstance(), pidc.getProvider(),
 837                                              pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
 838                                          doProviderModuleOptimization = true;
 839                                      }
 840                                  }
 841                                  catch (...)
 842                                  {
 843                                      // No ProviderIdContainer to optimize
 844                                  }
 845                      
 846 kumpf           1.1              //
 847                                  // Write the message to the pipe
 848                                  //
 849                                  try
 850                                  {
 851                                      PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL3,
 852                                          String("Sending request to agent with messageId ") +
 853                                              uniqueMessageId);
 854                      
 855                                      request->messageId = uniqueMessageId;
 856                                      AnonymousPipe::Status writeStatus =
 857                                          _pipeToAgent->writeMessage(request);
 858                                      request->messageId = originalMessageId;
 859                      
 860 kumpf           1.2                  if (doProviderModuleOptimization)
 861                                      {
 862                                          request->operationContext.set(*origProviderId.get());
 863                                      }
 864                      
 865 kumpf           1.1                  if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
 866                                      {
 867                                          Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 868                                              "Failed to write message to pipe.  writeStatus = %d.",
 869                                              writeStatus);
 870                                          throw Exception(MessageLoaderParms(
 871                                              "ProviderManager.OOPProviderManagerRouter."
 872                                                  "CIMPROVAGT_COMMUNICATION_FAILED",
 873                                              "Failed to communicate with cimprovagt \"$0\".",
 874                                              _moduleName));
 875                                      }
 876 kumpf           1.2  
 877                                      if (updateProviderModuleCache)
 878                                      {
 879                                          _providerModuleCache = origProviderId->getModule();
 880                                      }
 881 kumpf           1.1              }
 882                                  catch (...)
 883                                  {
 884                                      request->messageId = originalMessageId;
 885 kumpf           1.2  
 886                                      if (doProviderModuleOptimization)
 887                                      {
 888                                          request->operationContext.set(*origProviderId.get());
 889                                      }
 890                      
 891 kumpf           1.1                  Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 892                                          "Failed to write message to pipe.");
 893                                      // Remove the OutstandingRequestTable entry for this request
 894                                      {
 895                                          AutoMutex tableLock(_outstandingRequestTableMutex);
 896                                          Boolean removed =
 897                                              _outstandingRequestTable.remove(uniqueMessageId);
 898                                          PEGASUS_ASSERT(removed);
 899                                      }
 900                                      throw;
 901                                  }
 902                              }
 903                      
 904                              //
 905                              // Wait for the response
 906                              //
 907                              try
 908                              {
 909                                  // Must not hold _agentMutex while waiting for the response
 910                                  waitSemaphore.wait();
 911                              }
 912 kumpf           1.1          catch (...)
 913                              {
 914                                  // Remove the OutstandingRequestTable entry for this request
 915                                  {
 916                                      AutoMutex tableLock(_outstandingRequestTableMutex);
 917                                      Boolean removed =
 918                                          _outstandingRequestTable.remove(uniqueMessageId);
 919                                      PEGASUS_ASSERT(removed);
 920                                  }
 921                                  throw;
 922                              }
 923                      
 924                              // A null response is returned when an agent connection is closed
 925                              // while requests remain outstanding.
 926                              if (response == 0)
 927                              {
 928                                  response = request->buildResponse();
 929                                  response->cimException = PEGASUS_CIM_EXCEPTION(
 930                                      CIM_ERR_FAILED,
 931                                      MessageLoaderParms(
 932                                          "ProviderManager.OOPProviderManagerRouter."
 933 kumpf           1.1                          "CIMPROVAGT_CONNECTION_LOST",
 934                                          "Lost connection with cimprovagt \"$0\".",
 935                                          _moduleName));
 936                              }
 937                          }
 938                          catch (CIMException& e)
 939                          {
 940                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 941                                  String("Caught exception: ") + e.getMessage());
 942                              response = request->buildResponse();
 943                              response->cimException = e;
 944                          }
 945                          catch (Exception& e)
 946                          {
 947                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 948                                  String("Caught exception: ") + e.getMessage());
 949                              response = request->buildResponse();
 950                              response->cimException = PEGASUS_CIM_EXCEPTION(
 951                                  CIM_ERR_FAILED, e.getMessage());
 952                          }
 953                          catch (...)
 954 kumpf           1.1      {
 955                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 956                                  "Caught unknown exception");
 957                              response = request->buildResponse();
 958                              response->cimException = PEGASUS_CIM_EXCEPTION(
 959                                  CIM_ERR_FAILED, String::EMPTY);
 960                          }
 961                      
 962                          response->messageId = originalMessageId;
 963                      
 964                          PEG_METHOD_EXIT();
 965                          return response;
 966                      }
 967                      
 968                      void ProviderAgentContainer::unloadIdleProviders()
 969                      {
 970                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 971 carolann.graves 1.4          "ProviderAgentContainer::unloadIdleProviders");
 972 kumpf           1.1  
 973                          AutoMutex lock(_agentMutex);
 974                          if (_isInitialized)
 975                          {
 976                              // Send a "wake up" message to the Provider Agent.
 977                              // Don't bother checking whether the operation is successful.
 978                              Uint32 messageLength = 0;
 979                              _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
 980                          }
 981                      
 982                          PEG_METHOD_EXIT();
 983                      }
 984                      
 985                      void ProviderAgentContainer::_processResponses()
 986                      {
 987                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 988                              "ProviderAgentContainer::_processResponses");
 989                      
 990                          //
 991                          // Process responses until the pipe is closed
 992                          //
 993 kumpf           1.1      while (1)
 994                          {
 995                              try
 996                              {
 997                                  CIMMessage* message;
 998                      
 999                                  //
1000                                  // Read a response from the Provider Agent
1001                                  //
1002                                  AnonymousPipe::Status readStatus =
1003                                      _pipeFromAgent->readMessage(message);
1004                      
1005                                  // Ignore interrupts
1006                                  if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
1007                                  {
1008                                      continue;
1009                                  }
1010                      
1011                                  // Handle an error the same way as a closed connection
1012                                  if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
1013                                      (readStatus == AnonymousPipe::STATUS_CLOSED))
1014 kumpf           1.1              {
1015                                      AutoMutex lock(_agentMutex);
1016                                      _uninitialize();
1017                                      return;
1018                                  }
1019                      
1020                                  if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
1021                                  {
1022                                      // Forward indications to the indication callback
1023                                      _indicationCallback(
1024                                          reinterpret_cast<CIMProcessIndicationRequestMessage*>(
1025                                              message));
1026                                  }
1027                                  else
1028                                  {
1029                                      CIMResponseMessage* response;
1030                                      response = dynamic_cast<CIMResponseMessage*>(message);
1031                                      PEGASUS_ASSERT(response != 0);
1032                      
1033                                      // Give the response to the waiting OutstandingRequestEntry
1034                                      OutstandingRequestEntry* _outstandingRequestEntry = 0;
1035 kumpf           1.1                  {
1036                                          AutoMutex tableLock(_outstandingRequestTableMutex);
1037                                          Boolean foundEntry = _outstandingRequestTable.lookup(
1038                                              response->messageId, _outstandingRequestEntry);
1039                                          PEGASUS_ASSERT(foundEntry);
1040                      
1041                                          // Remove the completed request from the table
1042                                          Boolean removed =
1043                                              _outstandingRequestTable.remove(response->messageId);
1044                                          PEGASUS_ASSERT(removed);
1045                                      }
1046                      
1047                                      _outstandingRequestEntry->responseMessage = response;
1048                                      _outstandingRequestEntry->responseReady->signal();
1049                                  }
1050                              }
1051                              catch (Exception& e)
1052                              {
1053                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1054                                      String("Ignoring exception: ") + e.getMessage());
1055                              }
1056 kumpf           1.1          catch (...)
1057                              {
1058                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1059                                      "Ignoring exception");
1060                              }
1061                          }
1062                      
1063                      }
1064                      
1065                      PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
1066                      ProviderAgentContainer::_responseProcessor(void* arg)
1067                      {
1068                          ProviderAgentContainer* pa =
1069                              reinterpret_cast<ProviderAgentContainer*>(arg);
1070                      
1071                          pa->_processResponses();
1072                      
1073                          return(PEGASUS_THREAD_RETURN(0));
1074                      }
1075                      
1076                      /////////////////////////////////////////////////////////////////////////////
1077 kumpf           1.1  // OOPProviderManagerRouter
1078                      /////////////////////////////////////////////////////////////////////////////
1079                      
1080                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1081                          PEGASUS_INDICATION_CALLBACK indicationCallback)
1082                      {
1083                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1084                              "OOPProviderManagerRouter::OOPProviderManagerRouter");
1085                      
1086                          _indicationCallback = indicationCallback;
1087 carolann.graves 1.14     _subscriptionInitComplete = false;
1088 kumpf           1.1  
1089                          PEG_METHOD_EXIT();
1090                      }
1091                      
1092                      OOPProviderManagerRouter::~OOPProviderManagerRouter()
1093                      {
1094                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1095                              "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1096                      
1097                          try
1098                          {
1099                              // Clean up the ProviderAgentContainers
1100                              AutoMutex lock(_providerAgentTableMutex);
1101                              ProviderAgentTable::Iterator i = _providerAgentTable.start();
1102                              for(; i != 0; i++)
1103                              {
1104                                  delete i.value();
1105                              }
1106                          }
1107                          catch (...) {}
1108                      
1109 kumpf           1.1      PEG_METHOD_EXIT();
1110                      }
1111                      
1112                      // Private, unimplemented constructor
1113                      OOPProviderManagerRouter::OOPProviderManagerRouter()
1114                      {
1115                      }
1116                      
1117                      // Private, unimplemented constructor
1118                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1119                          const OOPProviderManagerRouter&)
1120 david.dillard   1.3      : ProviderManagerRouter(*this)
1121 kumpf           1.1  {
1122                      }
1123                      
1124                      // Private, unimplemented assignment operator
1125                      OOPProviderManagerRouter& OOPProviderManagerRouter::operator=(
1126                          const OOPProviderManagerRouter&)
1127                      {
1128                          return *this;
1129                      }
1130                      
1131                      Message* OOPProviderManagerRouter::processMessage(Message* message)
1132                      {
1133                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1134                              "OOPProviderManagerRouter::processMessage");
1135                      
1136                          CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1137                          PEGASUS_ASSERT(request != 0);
1138                      
1139                          AutoPtr<CIMResponseMessage> response;
1140                      
1141                          //
1142 kumpf           1.1      // Get the provider information from the request
1143                          //
1144                          CIMInstance providerModule;
1145                      
1146                          if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1147                              (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1148                              (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1149                          {
1150                              // Provider information is in the OperationContext
1151                              ProviderIdContainer pidc = (ProviderIdContainer)
1152                                  request->operationContext.get(ProviderIdContainer::NAME);
1153                              providerModule = pidc.getModule();
1154                          }
1155                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1156                          {
1157                              CIMEnableModuleRequestMessage* emReq =
1158                                  dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1159                              providerModule = emReq->providerModule;
1160                          }
1161                          else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1162                          {
1163 kumpf           1.1          CIMDisableModuleRequestMessage* dmReq =
1164                                  dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1165                              providerModule = dmReq->providerModule;
1166                          }
1167                          else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1168 carolann.graves 1.14              (request->getType() ==
1169                                       CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1170 kumpf           1.1               (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1171                          {
1172                              // This operation is not provider-specific
1173                          }
1174                          else
1175                          {
1176                              // Unrecognized message type.  This should never happen.
1177                              PEGASUS_ASSERT(0);
1178                              response.reset(request->buildResponse());
1179                              response->cimException = PEGASUS_CIM_EXCEPTION(
1180                                  CIM_ERR_FAILED, "Unrecognized message type.");
1181                              PEG_METHOD_EXIT();
1182                              return response.release();
1183                          }
1184                      
1185                          //
1186                          // Process the request message
1187                          //
1188                          if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1189                          {
1190                              // Forward the CIMStopAllProvidersRequest to all providers
1191 kumpf           1.1          response.reset(_forwardRequestToAllAgents(request));
1192                      
1193                              // Note: Do not uninitialize the ProviderAgentContainers here.
1194                              // Just let the selecting thread notice when the agent connections
1195                              // are closed.
1196                          }
1197 carolann.graves 1.14     else if (request->getType () == 
1198                              CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1199                          {
1200                              _subscriptionInitComplete = true;
1201                      
1202                              //
1203                              //  Forward the CIMSubscriptionInitCompleteRequestMessage to 
1204                              //  all providers
1205                              //
1206                              response.reset (_forwardRequestToAllAgents (request));
1207                          }
1208 kumpf           1.1      else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1209                          {
1210                              CIMNotifyConfigChangeRequestMessage* notifyRequest =
1211                                  dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1212                              PEGASUS_ASSERT(notifyRequest != 0);
1213                      
1214                              if (notifyRequest->currentValueModified)
1215                              {
1216                                  // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1217                                  response.reset(_forwardRequestToAllAgents(request));
1218                              }
1219                              else
1220                              {
1221                                  // No need to notify provider agents about changes to planned value
1222                                  response.reset(request->buildResponse());
1223                              }
1224                          }
1225 kumpf           1.6      else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1226 kumpf           1.1      {
1227 kumpf           1.6          // Fan out the request to all Provider Agent processes for this module
1228                      
1229 kumpf           1.1          // Retrieve the provider module name
1230                              String moduleName;
1231                              CIMValue nameValue = providerModule.getProperty(
1232                                  providerModule.findProperty("Name")).getValue();
1233                              nameValue.get(moduleName);
1234                      
1235 kumpf           1.6          // Look up the Provider Agents for this module
1236                              Array<ProviderAgentContainer*> paArray =
1237                                  _lookupProviderAgents(moduleName);
1238 kumpf           1.1  
1239 kumpf           1.6          for (Uint32 i=0; i<paArray.size(); i++)
1240 kumpf           1.1          {
1241                                  //
1242                                  // Do not start up an agent process just to disable the module
1243                                  //
1244 kumpf           1.6              if (paArray[i]->isInitialized())
1245                                  {
1246                                      //
1247                                      // Forward the request to the provider agent
1248                                      //
1249                                      response.reset(paArray[i]->processMessage(request));
1250                      
1251                                      // Note: Do not uninitialize the ProviderAgentContainer here
1252                                      // when a disable module operation is successful.  Just let the
1253                                      // selecting thread notice when the agent connection is closed.
1254                      
1255                                      // Determine the success of the disable module operation
1256                                      CIMDisableModuleResponseMessage* dmResponse =
1257                                          dynamic_cast<CIMDisableModuleResponseMessage*>(
1258                                              response.get());
1259                                      PEGASUS_ASSERT(dmResponse != 0);
1260                      
1261                                      Boolean isStopped = false;
1262                                      for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1263                                      {
1264                                          if (dmResponse->operationalStatus[i] ==
1265 kumpf           1.6                          CIM_MSE_OPSTATUS_VALUE_STOPPED)
1266                                          {
1267                                              isStopped = true;
1268                                              break;
1269                                          }
1270                                      }
1271                      
1272                                      // If the operation is unsuccessful, stop and return the error
1273                                      if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1274                                          !isStopped)
1275                                      {
1276                                          break;
1277                                      }
1278                                  }
1279                              }
1280                      
1281                              // Use a default response if no Provider Agents were called
1282                              if (!response.get())
1283                              {
1284 kumpf           1.1              response.reset(request->buildResponse());
1285                      
1286                                  CIMDisableModuleResponseMessage* dmResponse =
1287                                      dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1288                                  PEGASUS_ASSERT(dmResponse != 0);
1289                      
1290                                  Array<Uint16> operationalStatus;
1291                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1292                                  dmResponse->operationalStatus = operationalStatus;
1293                              }
1294 kumpf           1.6      }
1295                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1296                          {
1297                              // Fan out the request to all Provider Agent processes for this module
1298                      
1299                              // Retrieve the provider module name
1300                              String moduleName;
1301                              CIMValue nameValue = providerModule.getProperty(
1302                                  providerModule.findProperty("Name")).getValue();
1303                              nameValue.get(moduleName);
1304                      
1305                              // Look up the Provider Agents for this module
1306                              Array<ProviderAgentContainer*> paArray =
1307                                  _lookupProviderAgents(moduleName);
1308                      
1309                              for (Uint32 i=0; i<paArray.size(); i++)
1310 kumpf           1.1          {
1311                                  //
1312                                  // Do not start up an agent process just to enable the module
1313                                  //
1314 kumpf           1.6              if (paArray[i]->isInitialized())
1315                                  {
1316                                      //
1317                                      // Forward the request to the provider agent
1318                                      //
1319                                      response.reset(paArray[i]->processMessage(request));
1320                      
1321                                      // Determine the success of the enable module operation
1322                                      CIMEnableModuleResponseMessage* emResponse =
1323                                          dynamic_cast<CIMEnableModuleResponseMessage*>(
1324                                              response.get());
1325                                      PEGASUS_ASSERT(emResponse != 0);
1326                      
1327                                      Boolean isOk = false;
1328                                      for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1329                                      {
1330                                          if (emResponse->operationalStatus[i] ==
1331                                              CIM_MSE_OPSTATUS_VALUE_OK)
1332                                          {
1333                                              isOk = true;
1334                                              break;
1335 kumpf           1.6                      }
1336                                      }
1337                      
1338                                      // If the operation is unsuccessful, stop and return the error
1339                                      if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1340                                          !isOk)
1341                                      {
1342                                          break;
1343                                      }
1344                                  }
1345                              }
1346                      
1347                              // Use a default response if no Provider Agents were called
1348                              if (!response.get())
1349                              {
1350 kumpf           1.1              response.reset(request->buildResponse());
1351                      
1352                                  CIMEnableModuleResponseMessage* emResponse =
1353                                      dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1354                                  PEGASUS_ASSERT(emResponse != 0);
1355                      
1356                                  Array<Uint16> operationalStatus;
1357                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1358                                  emResponse->operationalStatus = operationalStatus;
1359                              }
1360 kumpf           1.6      }
1361                          else
1362                          {
1363                              // Retrieve the provider module name
1364                              String moduleName;
1365                              CIMValue nameValue = providerModule.getProperty(
1366                                  providerModule.findProperty("Name")).getValue();
1367                              nameValue.get(moduleName);
1368                      
1369                              // Retrieve the provider user context configuration
1370                              Uint16 userContext = 0;
1371                              Uint32 pos = providerModule.findProperty(
1372                                  PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1373                              if (pos != PEG_NOT_FOUND)
1374                              {
1375 kumpf           1.12             CIMValue userContextValue =
1376                                      providerModule.getProperty(pos).getValue();
1377                                  if (!userContextValue.isNull())
1378                                  {
1379                                      userContextValue.get(userContext);
1380                                  }
1381 kumpf           1.6          }
1382                      
1383                              if (userContext == 0)
1384                              {
1385                                  userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED;
1386                              }
1387                      
1388                              String userName;
1389                      
1390                              if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
1391 kumpf           1.1          {
1392 kumpf           1.6              try
1393                                  {
1394                                      // User Name is in the OperationContext
1395                                      IdentityContainer ic = (IdentityContainer)
1396                                          request->operationContext.get(IdentityContainer::NAME);
1397                                      userName = ic.getUserName();
1398                                  }
1399                                  catch (Exception& e)
1400                                  {
1401                                      // If no IdentityContainer is present, default to the CIM
1402                                      // Server's user context
1403                                  }
1404 kumpf           1.1  
1405 kumpf           1.6              // If authentication is disabled, use the CIM Server's user context
1406                                  if (!userName.size())
1407                                  {
1408                                      userName = System::getEffectiveUserName();
1409                                  }
1410                              }
1411                              else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1412                              {
1413                                  // Retrieve the provider module name
1414                                  providerModule.getProperty(providerModule.findProperty(
1415                                      PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1416                                      get(userName);
1417                              }
1418                              else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1419                              {
1420                                  userName = System::getEffectiveUserName();
1421                              }
1422                              else    // Privileged User
1423                              {
1424                                  PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1425                                  userName = System::getPrivilegedUserName();
1426 kumpf           1.1          }
1427 kumpf           1.6  
1428                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1429                                  "Module name = " + moduleName);
1430                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1431                                  "User context = %hd.", userContext);
1432                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1433                                  "User name = " + userName);
1434                      
1435                              // Look up the Provider Agent for this module and user
1436                              ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName);
1437                              PEGASUS_ASSERT(pa != 0);
1438                      
1439                              //
1440                              // Forward the request to the provider agent
1441                              //
1442                              response.reset(pa->processMessage(request));
1443 kumpf           1.1      }
1444                      
1445                          response->syncAttributes(request);
1446                      
1447                          PEG_METHOD_EXIT();
1448                          return response.release();
1449                      }
1450                      
1451                      ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1452 kumpf           1.6      const String& moduleName,
1453                          const String& userName)
1454 kumpf           1.1  {
1455                          ProviderAgentContainer* pa = 0;
1456 kumpf           1.6      String key = moduleName + ":" + userName;
1457 kumpf           1.1  
1458                          AutoMutex lock(_providerAgentTableMutex);
1459 kumpf           1.6      if (!_providerAgentTable.lookup(key, pa))
1460 kumpf           1.1      {
1461 kumpf           1.6          pa = new ProviderAgentContainer(
1462 carolann.graves 1.14             moduleName, userName, _indicationCallback,
1463                                  _subscriptionInitComplete);
1464 kumpf           1.6          _providerAgentTable.insert(key, pa);
1465 kumpf           1.1      }
1466                          return pa;
1467                      }
1468                      
1469 kumpf           1.6  Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1470                          const String& moduleName)
1471                      {
1472                          Array<ProviderAgentContainer*> paArray;
1473                      
1474                          AutoMutex lock(_providerAgentTableMutex);
1475                          for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1476                          {
1477                              if (i.value()->getModuleName() == moduleName)
1478                              {
1479                                  paArray.append(i.value());
1480                              }
1481                          }
1482                          return paArray;
1483                      }
1484                      
1485 kumpf           1.1  CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1486                          CIMRequestMessage* request)
1487                      {
1488                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1489                              "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1490                      
1491                          // Get a list of the ProviderAgentContainers.  We need our own array copy
1492                          // because we cannot hold the _providerAgentTableMutex while calling
1493                          // _ProviderAgentContainer::processMessage().
1494                          Array<ProviderAgentContainer*> paContainerArray;
1495                          {
1496                              AutoMutex tableLock(_providerAgentTableMutex);
1497                              for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1498                                   i != 0; i++)
1499                              {
1500                                  paContainerArray.append(i.value());
1501                              }
1502                          }
1503                      
1504                          CIMException responseException;
1505                      
1506 kumpf           1.1      // Forward the request to each of the initialized provider agents
1507                          for (Uint32 j = 0; j < paContainerArray.size(); j++)
1508                          {
1509                              ProviderAgentContainer* pa = paContainerArray[j];
1510                              if (pa->isInitialized())
1511                              {
1512                                  // Note: The ProviderAgentContainer could become uninitialized
1513                                  // before _ProviderAgentContainer::processMessage() processes
1514                                  // this request.  In this case, the Provider Agent process will
1515                                  // (unfortunately) be started to process this message.
1516                                  AutoPtr<CIMResponseMessage> response;
1517                                  response.reset(pa->processMessage(request));
1518                                  if (response.get() != 0)
1519                                  {
1520                                      // If the operation failed, save the exception data
1521                                      if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1522                                          (responseException.getCode() == CIM_ERR_SUCCESS))
1523                                      {
1524                                          responseException = response->cimException;
1525                                      }
1526                                  }
1527 kumpf           1.1          }
1528                          }
1529                      
1530                          CIMResponseMessage* response = request->buildResponse();
1531                          response->cimException = responseException;
1532                      
1533                          PEG_METHOD_EXIT();
1534                          return response;
1535                      }
1536                      
1537                      Boolean OOPProviderManagerRouter::hasActiveProviders()
1538                      {
1539                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1540                              "OOPProviderManagerRouter::hasActiveProviders");
1541                      
1542                          // Iterate through the _providerAgentTable looking for initialized agents
1543                          AutoMutex lock(_providerAgentTableMutex);
1544                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1545                          for(; i != 0; i++)
1546                          {
1547                              if (i.value()->isInitialized())
1548 kumpf           1.1          {
1549                                  PEG_METHOD_EXIT();
1550                                  return true;
1551                              }
1552                          }
1553                      
1554                          // No initialized Provider Agents were found
1555                          PEG_METHOD_EXIT();
1556                          return false;
1557                      }
1558                      
1559                      void OOPProviderManagerRouter::unloadIdleProviders()
1560                      {
1561                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1562                              "OOPProviderManagerRouter::unloadIdleProviders");
1563                      
1564                          // Iterate through the _providerAgentTable unloading idle providers
1565                          AutoMutex lock(_providerAgentTableMutex);
1566                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1567                          for(; i != 0; i++)
1568                          {
1569 kumpf           1.1          i.value()->unloadIdleProviders();
1570                          }
1571                      
1572                          PEG_METHOD_EXIT();
1573                      }
1574                      
1575                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2