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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2