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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2