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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2