(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                          PEG_METHOD_EXIT();
1064                      }
1065                      
1066                      PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
1067                      ProviderAgentContainer::_responseProcessor(void* arg)
1068                      {
1069                          ProviderAgentContainer* pa =
1070                              reinterpret_cast<ProviderAgentContainer*>(arg);
1071                      
1072                          pa->_processResponses();
1073                      
1074                          return(PEGASUS_THREAD_RETURN(0));
1075                      }
1076                      
1077 kumpf           1.1  /////////////////////////////////////////////////////////////////////////////
1078                      // OOPProviderManagerRouter
1079                      /////////////////////////////////////////////////////////////////////////////
1080                      
1081                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1082                          PEGASUS_INDICATION_CALLBACK indicationCallback)
1083                      {
1084                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1085                              "OOPProviderManagerRouter::OOPProviderManagerRouter");
1086                      
1087                          _indicationCallback = indicationCallback;
1088 carolann.graves 1.14     _subscriptionInitComplete = false;
1089 kumpf           1.1  
1090                          PEG_METHOD_EXIT();
1091                      }
1092                      
1093                      OOPProviderManagerRouter::~OOPProviderManagerRouter()
1094                      {
1095                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1096                              "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1097                      
1098                          try
1099                          {
1100                              // Clean up the ProviderAgentContainers
1101                              AutoMutex lock(_providerAgentTableMutex);
1102                              ProviderAgentTable::Iterator i = _providerAgentTable.start();
1103                              for(; i != 0; i++)
1104                              {
1105                                  delete i.value();
1106                              }
1107                          }
1108                          catch (...) {}
1109                      
1110 kumpf           1.1      PEG_METHOD_EXIT();
1111                      }
1112                      
1113                      // Private, unimplemented constructor
1114                      OOPProviderManagerRouter::OOPProviderManagerRouter()
1115                      {
1116                      }
1117                      
1118                      // Private, unimplemented constructor
1119                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1120                          const OOPProviderManagerRouter&)
1121 david.dillard   1.3      : ProviderManagerRouter(*this)
1122 kumpf           1.1  {
1123                      }
1124                      
1125                      // Private, unimplemented assignment operator
1126                      OOPProviderManagerRouter& OOPProviderManagerRouter::operator=(
1127                          const OOPProviderManagerRouter&)
1128                      {
1129                          return *this;
1130                      }
1131                      
1132                      Message* OOPProviderManagerRouter::processMessage(Message* message)
1133                      {
1134                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1135                              "OOPProviderManagerRouter::processMessage");
1136                      
1137                          CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1138                          PEGASUS_ASSERT(request != 0);
1139                      
1140                          AutoPtr<CIMResponseMessage> response;
1141                      
1142                          //
1143 kumpf           1.1      // Get the provider information from the request
1144                          //
1145                          CIMInstance providerModule;
1146                      
1147                          if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1148                              (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1149                              (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1150                          {
1151                              // Provider information is in the OperationContext
1152                              ProviderIdContainer pidc = (ProviderIdContainer)
1153                                  request->operationContext.get(ProviderIdContainer::NAME);
1154                              providerModule = pidc.getModule();
1155                          }
1156                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1157                          {
1158                              CIMEnableModuleRequestMessage* emReq =
1159                                  dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1160                              providerModule = emReq->providerModule;
1161                          }
1162                          else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1163                          {
1164 kumpf           1.1          CIMDisableModuleRequestMessage* dmReq =
1165                                  dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1166                              providerModule = dmReq->providerModule;
1167                          }
1168                          else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1169 carolann.graves 1.14              (request->getType() ==
1170                                       CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1171 kumpf           1.1               (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1172                          {
1173                              // This operation is not provider-specific
1174                          }
1175                          else
1176                          {
1177                              // Unrecognized message type.  This should never happen.
1178                              PEGASUS_ASSERT(0);
1179                              response.reset(request->buildResponse());
1180                              response->cimException = PEGASUS_CIM_EXCEPTION(
1181                                  CIM_ERR_FAILED, "Unrecognized message type.");
1182                              PEG_METHOD_EXIT();
1183                              return response.release();
1184                          }
1185                      
1186                          //
1187                          // Process the request message
1188                          //
1189                          if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1190                          {
1191                              // Forward the CIMStopAllProvidersRequest to all providers
1192 kumpf           1.1          response.reset(_forwardRequestToAllAgents(request));
1193                      
1194                              // Note: Do not uninitialize the ProviderAgentContainers here.
1195                              // Just let the selecting thread notice when the agent connections
1196                              // are closed.
1197                          }
1198 carolann.graves 1.14     else if (request->getType () == 
1199                              CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1200                          {
1201                              _subscriptionInitComplete = true;
1202                      
1203                              //
1204                              //  Forward the CIMSubscriptionInitCompleteRequestMessage to 
1205                              //  all providers
1206                              //
1207                              response.reset (_forwardRequestToAllAgents (request));
1208                          }
1209 kumpf           1.1      else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1210                          {
1211                              CIMNotifyConfigChangeRequestMessage* notifyRequest =
1212                                  dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1213                              PEGASUS_ASSERT(notifyRequest != 0);
1214                      
1215                              if (notifyRequest->currentValueModified)
1216                              {
1217                                  // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1218                                  response.reset(_forwardRequestToAllAgents(request));
1219                              }
1220                              else
1221                              {
1222                                  // No need to notify provider agents about changes to planned value
1223                                  response.reset(request->buildResponse());
1224                              }
1225                          }
1226 kumpf           1.6      else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1227 kumpf           1.1      {
1228 kumpf           1.6          // Fan out the request to all Provider Agent processes for this module
1229                      
1230 kumpf           1.1          // Retrieve the provider module name
1231                              String moduleName;
1232                              CIMValue nameValue = providerModule.getProperty(
1233                                  providerModule.findProperty("Name")).getValue();
1234                              nameValue.get(moduleName);
1235                      
1236 kumpf           1.6          // Look up the Provider Agents for this module
1237                              Array<ProviderAgentContainer*> paArray =
1238                                  _lookupProviderAgents(moduleName);
1239 kumpf           1.1  
1240 kumpf           1.6          for (Uint32 i=0; i<paArray.size(); i++)
1241 kumpf           1.1          {
1242                                  //
1243                                  // Do not start up an agent process just to disable the module
1244                                  //
1245 kumpf           1.6              if (paArray[i]->isInitialized())
1246                                  {
1247                                      //
1248                                      // Forward the request to the provider agent
1249                                      //
1250                                      response.reset(paArray[i]->processMessage(request));
1251                      
1252                                      // Note: Do not uninitialize the ProviderAgentContainer here
1253                                      // when a disable module operation is successful.  Just let the
1254                                      // selecting thread notice when the agent connection is closed.
1255                      
1256                                      // Determine the success of the disable module operation
1257                                      CIMDisableModuleResponseMessage* dmResponse =
1258                                          dynamic_cast<CIMDisableModuleResponseMessage*>(
1259                                              response.get());
1260                                      PEGASUS_ASSERT(dmResponse != 0);
1261                      
1262                                      Boolean isStopped = false;
1263                                      for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1264                                      {
1265                                          if (dmResponse->operationalStatus[i] ==
1266 kumpf           1.6                          CIM_MSE_OPSTATUS_VALUE_STOPPED)
1267                                          {
1268                                              isStopped = true;
1269                                              break;
1270                                          }
1271                                      }
1272                      
1273                                      // If the operation is unsuccessful, stop and return the error
1274                                      if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1275                                          !isStopped)
1276                                      {
1277                                          break;
1278                                      }
1279                                  }
1280                              }
1281                      
1282                              // Use a default response if no Provider Agents were called
1283                              if (!response.get())
1284                              {
1285 kumpf           1.1              response.reset(request->buildResponse());
1286                      
1287                                  CIMDisableModuleResponseMessage* dmResponse =
1288                                      dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1289                                  PEGASUS_ASSERT(dmResponse != 0);
1290                      
1291                                  Array<Uint16> operationalStatus;
1292                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1293                                  dmResponse->operationalStatus = operationalStatus;
1294                              }
1295 kumpf           1.6      }
1296                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1297                          {
1298                              // Fan out the request to all Provider Agent processes for this module
1299                      
1300                              // Retrieve the provider module name
1301                              String moduleName;
1302                              CIMValue nameValue = providerModule.getProperty(
1303                                  providerModule.findProperty("Name")).getValue();
1304                              nameValue.get(moduleName);
1305                      
1306                              // Look up the Provider Agents for this module
1307                              Array<ProviderAgentContainer*> paArray =
1308                                  _lookupProviderAgents(moduleName);
1309                      
1310                              for (Uint32 i=0; i<paArray.size(); i++)
1311 kumpf           1.1          {
1312                                  //
1313                                  // Do not start up an agent process just to enable the module
1314                                  //
1315 kumpf           1.6              if (paArray[i]->isInitialized())
1316                                  {
1317                                      //
1318                                      // Forward the request to the provider agent
1319                                      //
1320                                      response.reset(paArray[i]->processMessage(request));
1321                      
1322                                      // Determine the success of the enable module operation
1323                                      CIMEnableModuleResponseMessage* emResponse =
1324                                          dynamic_cast<CIMEnableModuleResponseMessage*>(
1325                                              response.get());
1326                                      PEGASUS_ASSERT(emResponse != 0);
1327                      
1328                                      Boolean isOk = false;
1329                                      for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1330                                      {
1331                                          if (emResponse->operationalStatus[i] ==
1332                                              CIM_MSE_OPSTATUS_VALUE_OK)
1333                                          {
1334                                              isOk = true;
1335                                              break;
1336 kumpf           1.6                      }
1337                                      }
1338                      
1339                                      // If the operation is unsuccessful, stop and return the error
1340                                      if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1341                                          !isOk)
1342                                      {
1343                                          break;
1344                                      }
1345                                  }
1346                              }
1347                      
1348                              // Use a default response if no Provider Agents were called
1349                              if (!response.get())
1350                              {
1351 kumpf           1.1              response.reset(request->buildResponse());
1352                      
1353                                  CIMEnableModuleResponseMessage* emResponse =
1354                                      dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1355                                  PEGASUS_ASSERT(emResponse != 0);
1356                      
1357                                  Array<Uint16> operationalStatus;
1358                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1359                                  emResponse->operationalStatus = operationalStatus;
1360                              }
1361 kumpf           1.6      }
1362                          else
1363                          {
1364                              // Retrieve the provider module name
1365                              String moduleName;
1366                              CIMValue nameValue = providerModule.getProperty(
1367                                  providerModule.findProperty("Name")).getValue();
1368                              nameValue.get(moduleName);
1369                      
1370                              // Retrieve the provider user context configuration
1371                              Uint16 userContext = 0;
1372                              Uint32 pos = providerModule.findProperty(
1373                                  PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1374                              if (pos != PEG_NOT_FOUND)
1375                              {
1376 kumpf           1.12             CIMValue userContextValue =
1377                                      providerModule.getProperty(pos).getValue();
1378                                  if (!userContextValue.isNull())
1379                                  {
1380                                      userContextValue.get(userContext);
1381                                  }
1382 kumpf           1.6          }
1383                      
1384                              if (userContext == 0)
1385                              {
1386                                  userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED;
1387                              }
1388                      
1389                              String userName;
1390                      
1391                              if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
1392 kumpf           1.1          {
1393 kumpf           1.6              try
1394                                  {
1395                                      // User Name is in the OperationContext
1396                                      IdentityContainer ic = (IdentityContainer)
1397                                          request->operationContext.get(IdentityContainer::NAME);
1398                                      userName = ic.getUserName();
1399                                  }
1400                                  catch (Exception& e)
1401                                  {
1402                                      // If no IdentityContainer is present, default to the CIM
1403                                      // Server's user context
1404                                  }
1405 kumpf           1.1  
1406 kumpf           1.6              // If authentication is disabled, use the CIM Server's user context
1407                                  if (!userName.size())
1408                                  {
1409                                      userName = System::getEffectiveUserName();
1410                                  }
1411                              }
1412                              else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1413                              {
1414                                  // Retrieve the provider module name
1415                                  providerModule.getProperty(providerModule.findProperty(
1416                                      PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1417                                      get(userName);
1418                              }
1419                              else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1420                              {
1421                                  userName = System::getEffectiveUserName();
1422                              }
1423                              else    // Privileged User
1424                              {
1425                                  PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1426                                  userName = System::getPrivilegedUserName();
1427 kumpf           1.1          }
1428 kumpf           1.6  
1429                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1430                                  "Module name = " + moduleName);
1431                              Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1432                                  "User context = %hd.", userContext);
1433                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1434                                  "User name = " + userName);
1435                      
1436                              // Look up the Provider Agent for this module and user
1437                              ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName);
1438                              PEGASUS_ASSERT(pa != 0);
1439                      
1440                              //
1441                              // Forward the request to the provider agent
1442                              //
1443                              response.reset(pa->processMessage(request));
1444 kumpf           1.1      }
1445                      
1446                          response->syncAttributes(request);
1447                      
1448                          PEG_METHOD_EXIT();
1449                          return response.release();
1450                      }
1451                      
1452                      ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1453 kumpf           1.6      const String& moduleName,
1454                          const String& userName)
1455 kumpf           1.1  {
1456                          ProviderAgentContainer* pa = 0;
1457 kumpf           1.6      String key = moduleName + ":" + userName;
1458 kumpf           1.1  
1459                          AutoMutex lock(_providerAgentTableMutex);
1460 kumpf           1.6      if (!_providerAgentTable.lookup(key, pa))
1461 kumpf           1.1      {
1462 kumpf           1.6          pa = new ProviderAgentContainer(
1463 carolann.graves 1.14             moduleName, userName, _indicationCallback,
1464                                  _subscriptionInitComplete);
1465 kumpf           1.6          _providerAgentTable.insert(key, pa);
1466 kumpf           1.1      }
1467                          return pa;
1468                      }
1469                      
1470 kumpf           1.6  Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1471                          const String& moduleName)
1472                      {
1473                          Array<ProviderAgentContainer*> paArray;
1474                      
1475                          AutoMutex lock(_providerAgentTableMutex);
1476                          for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1477                          {
1478                              if (i.value()->getModuleName() == moduleName)
1479                              {
1480                                  paArray.append(i.value());
1481                              }
1482                          }
1483                          return paArray;
1484                      }
1485                      
1486 kumpf           1.1  CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1487                          CIMRequestMessage* request)
1488                      {
1489                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1490                              "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1491                      
1492                          // Get a list of the ProviderAgentContainers.  We need our own array copy
1493                          // because we cannot hold the _providerAgentTableMutex while calling
1494                          // _ProviderAgentContainer::processMessage().
1495                          Array<ProviderAgentContainer*> paContainerArray;
1496                          {
1497                              AutoMutex tableLock(_providerAgentTableMutex);
1498                              for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1499                                   i != 0; i++)
1500                              {
1501                                  paContainerArray.append(i.value());
1502                              }
1503                          }
1504                      
1505                          CIMException responseException;
1506                      
1507 kumpf           1.1      // Forward the request to each of the initialized provider agents
1508                          for (Uint32 j = 0; j < paContainerArray.size(); j++)
1509                          {
1510                              ProviderAgentContainer* pa = paContainerArray[j];
1511                              if (pa->isInitialized())
1512                              {
1513                                  // Note: The ProviderAgentContainer could become uninitialized
1514                                  // before _ProviderAgentContainer::processMessage() processes
1515                                  // this request.  In this case, the Provider Agent process will
1516                                  // (unfortunately) be started to process this message.
1517                                  AutoPtr<CIMResponseMessage> response;
1518                                  response.reset(pa->processMessage(request));
1519                                  if (response.get() != 0)
1520                                  {
1521                                      // If the operation failed, save the exception data
1522                                      if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1523                                          (responseException.getCode() == CIM_ERR_SUCCESS))
1524                                      {
1525                                          responseException = response->cimException;
1526                                      }
1527                                  }
1528 kumpf           1.1          }
1529                          }
1530                      
1531                          CIMResponseMessage* response = request->buildResponse();
1532                          response->cimException = responseException;
1533                      
1534                          PEG_METHOD_EXIT();
1535                          return response;
1536                      }
1537                      
1538                      Boolean OOPProviderManagerRouter::hasActiveProviders()
1539                      {
1540                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1541                              "OOPProviderManagerRouter::hasActiveProviders");
1542                      
1543                          // Iterate through the _providerAgentTable looking for initialized agents
1544                          AutoMutex lock(_providerAgentTableMutex);
1545                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1546                          for(; i != 0; i++)
1547                          {
1548                              if (i.value()->isInitialized())
1549 kumpf           1.1          {
1550                                  PEG_METHOD_EXIT();
1551                                  return true;
1552                              }
1553                          }
1554                      
1555                          // No initialized Provider Agents were found
1556                          PEG_METHOD_EXIT();
1557                          return false;
1558                      }
1559                      
1560                      void OOPProviderManagerRouter::unloadIdleProviders()
1561                      {
1562                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1563                              "OOPProviderManagerRouter::unloadIdleProviders");
1564                      
1565                          // Iterate through the _providerAgentTable unloading idle providers
1566                          AutoMutex lock(_providerAgentTableMutex);
1567                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1568                          for(; i != 0; i++)
1569                          {
1570 kumpf           1.1          i.value()->unloadIdleProviders();
1571                          }
1572                      
1573                          PEG_METHOD_EXIT();
1574                      }
1575                      
1576                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2