(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 a.dunfey        1.31             if(request->operationContext.contains(ProviderIdContainer::NAME))
1089 kumpf           1.2              {
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                                          // original one back after the message is sent.
1107                                          request->operationContext.set(ProviderIdContainer(
1108                                              CIMInstance(), pidc.getProvider(),
1109                                              pidc.isRemoteNameSpace(), pidc.getRemoteInfo()));
1110 kumpf           1.2                      doProviderModuleOptimization = true;
1111                                      }
1112                                  }
1113                      
1114 kumpf           1.1              //
1115                                  // Write the message to the pipe
1116                                  //
1117                                  try
1118                                  {
1119                                      PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL3,
1120                                          String("Sending request to agent with messageId ") +
1121                                              uniqueMessageId);
1122                      
1123                                      request->messageId = uniqueMessageId;
1124                                      AnonymousPipe::Status writeStatus =
1125                                          _pipeToAgent->writeMessage(request);
1126                                      request->messageId = originalMessageId;
1127                      
1128 kumpf           1.2                  if (doProviderModuleOptimization)
1129                                      {
1130                                          request->operationContext.set(*origProviderId.get());
1131                                      }
1132                      
1133 kumpf           1.1                  if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
1134                                      {
1135                                          Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1136                                              "Failed to write message to pipe.  writeStatus = %d.",
1137                                              writeStatus);
1138 kumpf           1.25 
1139                                          request->messageId = originalMessageId;
1140                      
1141                                          if (doProviderModuleOptimization)
1142                                          {
1143                                              request->operationContext.set(*origProviderId.get());
1144                                          }
1145                      
1146                                          // Remove this OutstandingRequestTable entry
1147                                          {
1148                                              AutoMutex tableLock(_outstandingRequestTableMutex);
1149                                              Boolean removed =
1150                                                  _outstandingRequestTable.remove(uniqueMessageId);
1151                                              PEGASUS_ASSERT(removed);
1152                                          }
1153                      
1154                                          // A response value of _REQUEST_NOT_PROCESSED indicates
1155                                          // that the request was not processed by the provider
1156                                          // agent, so it can be retried safely.
1157                                          PEG_METHOD_EXIT();
1158                                          return _REQUEST_NOT_PROCESSED;
1159 kumpf           1.1                  }
1160 kumpf           1.2  
1161                                      if (updateProviderModuleCache)
1162                                      {
1163                                          _providerModuleCache = origProviderId->getModule();
1164                                      }
1165 kumpf           1.1              }
1166                                  catch (...)
1167                                  {
1168                                      request->messageId = originalMessageId;
1169 kumpf           1.2  
1170                                      if (doProviderModuleOptimization)
1171                                      {
1172                                          request->operationContext.set(*origProviderId.get());
1173                                      }
1174                      
1175 kumpf           1.1                  Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1176                                          "Failed to write message to pipe.");
1177                                      // Remove the OutstandingRequestTable entry for this request
1178                                      {
1179                                          AutoMutex tableLock(_outstandingRequestTableMutex);
1180                                          Boolean removed =
1181                                              _outstandingRequestTable.remove(uniqueMessageId);
1182                                          PEGASUS_ASSERT(removed);
1183                                      }
1184 kumpf           1.25                 PEG_METHOD_EXIT();
1185 kumpf           1.1                  throw;
1186                                  }
1187                              }
1188                      
1189                              //
1190                              // Wait for the response
1191                              //
1192                              try
1193                              {
1194                                  // Must not hold _agentMutex while waiting for the response
1195                                  waitSemaphore.wait();
1196                              }
1197                              catch (...)
1198                              {
1199                                  // Remove the OutstandingRequestTable entry for this request
1200                                  {
1201                                      AutoMutex tableLock(_outstandingRequestTableMutex);
1202                                      Boolean removed =
1203                                          _outstandingRequestTable.remove(uniqueMessageId);
1204                                      PEGASUS_ASSERT(removed);
1205                                  }
1206 kumpf           1.25             PEG_METHOD_EXIT();
1207 kumpf           1.1              throw;
1208                              }
1209                      
1210 kumpf           1.22         // A response value of _REQUEST_NOT_PROCESSED indicates that the
1211                              // provider agent process was terminating when the request was sent.
1212                              // The request was not processed by the provider agent, so it can be 
1213                              // retried safely.
1214                              if (response == _REQUEST_NOT_PROCESSED)
1215                              {
1216 kumpf           1.25             PEG_METHOD_EXIT();
1217 kumpf           1.22             return response;
1218                              }
1219                      
1220 kumpf           1.1          // A null response is returned when an agent connection is closed
1221                              // while requests remain outstanding.
1222                              if (response == 0)
1223                              {
1224                                  response = request->buildResponse();
1225                                  response->cimException = PEGASUS_CIM_EXCEPTION(
1226                                      CIM_ERR_FAILED,
1227                                      MessageLoaderParms(
1228                                          "ProviderManager.OOPProviderManagerRouter."
1229                                              "CIMPROVAGT_CONNECTION_LOST",
1230                                          "Lost connection with cimprovagt \"$0\".",
1231                                          _moduleName));
1232                              }
1233                          }
1234                          catch (CIMException& e)
1235                          {
1236                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1237                                  String("Caught exception: ") + e.getMessage());
1238                              response = request->buildResponse();
1239                              response->cimException = e;
1240                          }
1241 kumpf           1.1      catch (Exception& e)
1242                          {
1243                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1244                                  String("Caught exception: ") + e.getMessage());
1245                              response = request->buildResponse();
1246                              response->cimException = PEGASUS_CIM_EXCEPTION(
1247                                  CIM_ERR_FAILED, e.getMessage());
1248                          }
1249                          catch (...)
1250                          {
1251                              PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
1252                                  "Caught unknown exception");
1253                              response = request->buildResponse();
1254                              response->cimException = PEGASUS_CIM_EXCEPTION(
1255                                  CIM_ERR_FAILED, String::EMPTY);
1256                          }
1257                      
1258                          response->messageId = originalMessageId;
1259                      
1260                          PEG_METHOD_EXIT();
1261                          return response;
1262 kumpf           1.1  }
1263                      
1264                      void ProviderAgentContainer::unloadIdleProviders()
1265                      {
1266                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1267 carolann.graves 1.4          "ProviderAgentContainer::unloadIdleProviders");
1268 kumpf           1.1  
1269                          AutoMutex lock(_agentMutex);
1270                          if (_isInitialized)
1271                          {
1272                              // Send a "wake up" message to the Provider Agent.
1273                              // Don't bother checking whether the operation is successful.
1274                              Uint32 messageLength = 0;
1275                              _pipeToAgent->writeBuffer((const char*)&messageLength, sizeof(Uint32));
1276                          }
1277                      
1278                          PEG_METHOD_EXIT();
1279                      }
1280                      
1281                      void ProviderAgentContainer::_processResponses()
1282                      {
1283                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1284                              "ProviderAgentContainer::_processResponses");
1285                      
1286                          //
1287                          // Process responses until the pipe is closed
1288                          //
1289 kumpf           1.1      while (1)
1290                          {
1291                              try
1292                              {
1293                                  CIMMessage* message;
1294                      
1295                                  //
1296                                  // Read a response from the Provider Agent
1297                                  //
1298                                  AnonymousPipe::Status readStatus =
1299                                      _pipeFromAgent->readMessage(message);
1300                      
1301                                  // Ignore interrupts
1302                                  if (readStatus == AnonymousPipe::STATUS_INTERRUPT)
1303                                  {
1304                                      continue;
1305                                  }
1306                      
1307                                  // Handle an error the same way as a closed connection
1308                                  if ((readStatus == AnonymousPipe::STATUS_ERROR) ||
1309                                      (readStatus == AnonymousPipe::STATUS_CLOSED))
1310 kumpf           1.1              {
1311                                      AutoMutex lock(_agentMutex);
1312 kumpf           1.22                 _uninitialize(false);
1313                                      return;
1314                                  }
1315                      
1316                                  // A null message indicates that the provider agent process has
1317                                  // finished its processing and is ready to exit.
1318                                  if (message == 0)
1319                                  {
1320                                      AutoMutex lock(_agentMutex);
1321                                      _uninitialize(true);
1322 kumpf           1.1                  return;
1323                                  }
1324                      
1325                                  if (message->getType() == CIM_PROCESS_INDICATION_REQUEST_MESSAGE)
1326                                  {
1327                                      // Forward indications to the indication callback
1328                                      _indicationCallback(
1329                                          reinterpret_cast<CIMProcessIndicationRequestMessage*>(
1330                                              message));
1331                                  }
1332 kumpf           1.26             else if (!message->isComplete())
1333                                  {
1334                                      CIMResponseMessage* response;
1335                                      response = dynamic_cast<CIMResponseMessage*>(message);
1336                                      PEGASUS_ASSERT(response != 0);
1337                      
1338                                      // Get the OutstandingRequestEntry for this response chunk
1339                                      OutstandingRequestEntry* _outstandingRequestEntry = 0;
1340                                      {
1341                                          AutoMutex tableLock(_outstandingRequestTableMutex);
1342                                          Boolean foundEntry = _outstandingRequestTable.lookup(
1343                                              response->messageId, _outstandingRequestEntry);
1344                                          PEGASUS_ASSERT(foundEntry);
1345                                      }
1346                      
1347                                      // Put the original message ID into the response
1348                                      response->messageId =
1349 kumpf           1.30                     _outstandingRequestEntry->originalMessageId;
1350 kumpf           1.26 
1351                                      // Call the response chunk callback to process the chunk
1352                                      _responseChunkCallback(
1353                                          _outstandingRequestEntry->requestMessage, response);
1354                                  }
1355 kumpf           1.1              else
1356                                  {
1357                                      CIMResponseMessage* response;
1358                                      response = dynamic_cast<CIMResponseMessage*>(message);
1359                                      PEGASUS_ASSERT(response != 0);
1360                      
1361                                      // Give the response to the waiting OutstandingRequestEntry
1362                                      OutstandingRequestEntry* _outstandingRequestEntry = 0;
1363                                      {
1364                                          AutoMutex tableLock(_outstandingRequestTableMutex);
1365                                          Boolean foundEntry = _outstandingRequestTable.lookup(
1366                                              response->messageId, _outstandingRequestEntry);
1367                                          PEGASUS_ASSERT(foundEntry);
1368                      
1369                                          // Remove the completed request from the table
1370                                          Boolean removed =
1371                                              _outstandingRequestTable.remove(response->messageId);
1372                                          PEGASUS_ASSERT(removed);
1373                                      }
1374                      
1375                                      _outstandingRequestEntry->responseMessage = response;
1376 kumpf           1.1                  _outstandingRequestEntry->responseReady->signal();
1377                                  }
1378                              }
1379                              catch (Exception& e)
1380                              {
1381                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1382                                      String("Ignoring exception: ") + e.getMessage());
1383                              }
1384                              catch (...)
1385                              {
1386                                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1387                                      "Ignoring exception");
1388                              }
1389                          }
1390                      
1391                      }
1392                      
1393                      PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL
1394                      ProviderAgentContainer::_responseProcessor(void* arg)
1395                      {
1396                          ProviderAgentContainer* pa =
1397 kumpf           1.1          reinterpret_cast<ProviderAgentContainer*>(arg);
1398                      
1399                          pa->_processResponses();
1400                      
1401                          return(PEGASUS_THREAD_RETURN(0));
1402                      }
1403                      
1404                      /////////////////////////////////////////////////////////////////////////////
1405                      // OOPProviderManagerRouter
1406                      /////////////////////////////////////////////////////////////////////////////
1407                      
1408                      OOPProviderManagerRouter::OOPProviderManagerRouter(
1409 kumpf           1.26     PEGASUS_INDICATION_CALLBACK_T indicationCallback,
1410 carolann.graves 1.29     PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
1411                          PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback)
1412 kumpf           1.1  {
1413                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1414                              "OOPProviderManagerRouter::OOPProviderManagerRouter");
1415                      
1416                          _indicationCallback = indicationCallback;
1417 kumpf           1.26     _responseChunkCallback = responseChunkCallback;
1418 carolann.graves 1.29     _providerModuleFailCallback = providerModuleFailCallback;
1419 carolann.graves 1.14     _subscriptionInitComplete = false;
1420 kumpf           1.1  
1421                          PEG_METHOD_EXIT();
1422                      }
1423                      
1424                      OOPProviderManagerRouter::~OOPProviderManagerRouter()
1425                      {
1426                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1427                              "OOPProviderManagerRouter::~OOPProviderManagerRouter");
1428                      
1429                          try
1430                          {
1431                              // Clean up the ProviderAgentContainers
1432                              AutoMutex lock(_providerAgentTableMutex);
1433                              ProviderAgentTable::Iterator i = _providerAgentTable.start();
1434                              for(; i != 0; i++)
1435                              {
1436                                  delete i.value();
1437                              }
1438                          }
1439                          catch (...) {}
1440                      
1441 kumpf           1.1      PEG_METHOD_EXIT();
1442                      }
1443                      
1444                      Message* OOPProviderManagerRouter::processMessage(Message* message)
1445                      {
1446                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1447                              "OOPProviderManagerRouter::processMessage");
1448                      
1449                          CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
1450                          PEGASUS_ASSERT(request != 0);
1451                      
1452                          AutoPtr<CIMResponseMessage> response;
1453                      
1454                          //
1455                          // Get the provider information from the request
1456                          //
1457                          CIMInstance providerModule;
1458                      
1459                          if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
1460                              (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
1461                              (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
1462 kumpf           1.1      {
1463                              // Provider information is in the OperationContext
1464                              ProviderIdContainer pidc = (ProviderIdContainer)
1465                                  request->operationContext.get(ProviderIdContainer::NAME);
1466                              providerModule = pidc.getModule();
1467                          }
1468                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1469                          {
1470                              CIMEnableModuleRequestMessage* emReq =
1471                                  dynamic_cast<CIMEnableModuleRequestMessage*>(request);
1472                              providerModule = emReq->providerModule;
1473                          }
1474                          else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1475                          {
1476                              CIMDisableModuleRequestMessage* dmReq =
1477                                  dynamic_cast<CIMDisableModuleRequestMessage*>(request);
1478                              providerModule = dmReq->providerModule;
1479                          }
1480                          else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
1481 carolann.graves 1.14              (request->getType() ==
1482                                       CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
1483 kumpf           1.1               (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
1484                          {
1485                              // This operation is not provider-specific
1486                          }
1487                          else
1488                          {
1489                              // Unrecognized message type.  This should never happen.
1490                              PEGASUS_ASSERT(0);
1491                              response.reset(request->buildResponse());
1492                              response->cimException = PEGASUS_CIM_EXCEPTION(
1493                                  CIM_ERR_FAILED, "Unrecognized message type.");
1494                              PEG_METHOD_EXIT();
1495                              return response.release();
1496                          }
1497                      
1498                          //
1499                          // Process the request message
1500                          //
1501                          if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
1502                          {
1503                              // Forward the CIMStopAllProvidersRequest to all providers
1504 kumpf           1.1          response.reset(_forwardRequestToAllAgents(request));
1505                      
1506                              // Note: Do not uninitialize the ProviderAgentContainers here.
1507                              // Just let the selecting thread notice when the agent connections
1508                              // are closed.
1509                          }
1510 carolann.graves 1.14     else if (request->getType () == 
1511                              CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
1512                          {
1513                              _subscriptionInitComplete = true;
1514                      
1515                              //
1516                              //  Forward the CIMSubscriptionInitCompleteRequestMessage to 
1517                              //  all providers
1518                              //
1519                              response.reset (_forwardRequestToAllAgents (request));
1520                          }
1521 kumpf           1.1      else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
1522                          {
1523                              CIMNotifyConfigChangeRequestMessage* notifyRequest =
1524                                  dynamic_cast<CIMNotifyConfigChangeRequestMessage*>(request);
1525                              PEGASUS_ASSERT(notifyRequest != 0);
1526                      
1527                              if (notifyRequest->currentValueModified)
1528                              {
1529                                  // Forward the CIMNotifyConfigChangeRequestMessage to all providers
1530                                  response.reset(_forwardRequestToAllAgents(request));
1531                              }
1532                              else
1533                              {
1534                                  // No need to notify provider agents about changes to planned value
1535                                  response.reset(request->buildResponse());
1536                              }
1537                          }
1538 kumpf           1.6      else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
1539 kumpf           1.1      {
1540 kumpf           1.6          // Fan out the request to all Provider Agent processes for this module
1541                      
1542 kumpf           1.1          // Retrieve the provider module name
1543                              String moduleName;
1544                              CIMValue nameValue = providerModule.getProperty(
1545                                  providerModule.findProperty("Name")).getValue();
1546                              nameValue.get(moduleName);
1547                      
1548 kumpf           1.6          // Look up the Provider Agents for this module
1549                              Array<ProviderAgentContainer*> paArray =
1550                                  _lookupProviderAgents(moduleName);
1551 kumpf           1.1  
1552 kumpf           1.6          for (Uint32 i=0; i<paArray.size(); i++)
1553 kumpf           1.1          {
1554                                  //
1555                                  // Do not start up an agent process just to disable the module
1556                                  //
1557 kumpf           1.6              if (paArray[i]->isInitialized())
1558                                  {
1559                                      //
1560                                      // Forward the request to the provider agent
1561                                      //
1562                                      response.reset(paArray[i]->processMessage(request));
1563                      
1564                                      // Note: Do not uninitialize the ProviderAgentContainer here
1565                                      // when a disable module operation is successful.  Just let the
1566                                      // selecting thread notice when the agent connection is closed.
1567                      
1568                                      // Determine the success of the disable module operation
1569                                      CIMDisableModuleResponseMessage* dmResponse =
1570                                          dynamic_cast<CIMDisableModuleResponseMessage*>(
1571                                              response.get());
1572                                      PEGASUS_ASSERT(dmResponse != 0);
1573                      
1574                                      Boolean isStopped = false;
1575                                      for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++)
1576                                      {
1577                                          if (dmResponse->operationalStatus[i] ==
1578 kumpf           1.6                          CIM_MSE_OPSTATUS_VALUE_STOPPED)
1579                                          {
1580                                              isStopped = true;
1581                                              break;
1582                                          }
1583                                      }
1584                      
1585                                      // If the operation is unsuccessful, stop and return the error
1586                                      if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1587                                          !isStopped)
1588                                      {
1589                                          break;
1590                                      }
1591                                  }
1592                              }
1593                      
1594                              // Use a default response if no Provider Agents were called
1595                              if (!response.get())
1596                              {
1597 kumpf           1.1              response.reset(request->buildResponse());
1598                      
1599                                  CIMDisableModuleResponseMessage* dmResponse =
1600                                      dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
1601                                  PEGASUS_ASSERT(dmResponse != 0);
1602                      
1603                                  Array<Uint16> operationalStatus;
1604                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED);
1605                                  dmResponse->operationalStatus = operationalStatus;
1606                              }
1607 kumpf           1.6      }
1608                          else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
1609                          {
1610                              // Fan out the request to all Provider Agent processes for this module
1611                      
1612                              // Retrieve the provider module name
1613                              String moduleName;
1614                              CIMValue nameValue = providerModule.getProperty(
1615                                  providerModule.findProperty("Name")).getValue();
1616                              nameValue.get(moduleName);
1617                      
1618                              // Look up the Provider Agents for this module
1619                              Array<ProviderAgentContainer*> paArray =
1620                                  _lookupProviderAgents(moduleName);
1621                      
1622                              for (Uint32 i=0; i<paArray.size(); i++)
1623 kumpf           1.1          {
1624                                  //
1625                                  // Do not start up an agent process just to enable the module
1626                                  //
1627 kumpf           1.6              if (paArray[i]->isInitialized())
1628                                  {
1629                                      //
1630                                      // Forward the request to the provider agent
1631                                      //
1632                                      response.reset(paArray[i]->processMessage(request));
1633                      
1634                                      // Determine the success of the enable module operation
1635                                      CIMEnableModuleResponseMessage* emResponse =
1636                                          dynamic_cast<CIMEnableModuleResponseMessage*>(
1637                                              response.get());
1638                                      PEGASUS_ASSERT(emResponse != 0);
1639                      
1640                                      Boolean isOk = false;
1641                                      for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++)
1642                                      {
1643                                          if (emResponse->operationalStatus[i] ==
1644                                              CIM_MSE_OPSTATUS_VALUE_OK)
1645                                          {
1646                                              isOk = true;
1647                                              break;
1648 kumpf           1.6                      }
1649                                      }
1650                      
1651                                      // If the operation is unsuccessful, stop and return the error
1652                                      if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) ||
1653                                          !isOk)
1654                                      {
1655                                          break;
1656                                      }
1657                                  }
1658                              }
1659                      
1660                              // Use a default response if no Provider Agents were called
1661                              if (!response.get())
1662                              {
1663 kumpf           1.1              response.reset(request->buildResponse());
1664                      
1665                                  CIMEnableModuleResponseMessage* emResponse =
1666                                      dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
1667                                  PEGASUS_ASSERT(emResponse != 0);
1668                      
1669                                  Array<Uint16> operationalStatus;
1670                                  operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1671                                  emResponse->operationalStatus = operationalStatus;
1672                              }
1673 kumpf           1.6      }
1674                          else
1675                          {
1676 carolann.graves 1.29         //
1677                              // Look up the Provider Agent for this module instance and requesting
1678                              // user
1679                              //
1680                              ProviderAgentContainer* pa = _lookupProviderAgent(providerModule,
1681                                  request);
1682                              PEGASUS_ASSERT(pa != 0);
1683                      
1684                              //
1685                              // Forward the request to the provider agent
1686                              //
1687                              response.reset(pa->processMessage(request));
1688                          }
1689                      
1690                          response->syncAttributes(request);
1691                      
1692                          PEG_METHOD_EXIT();
1693                          return response.release();
1694                      }
1695                      
1696                      ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent(
1697 carolann.graves 1.29     const CIMInstance& providerModule,
1698                          CIMRequestMessage* request)
1699                      {
1700                          // Retrieve the provider module name
1701                          String moduleName;
1702                          CIMValue nameValue = providerModule.getProperty(
1703                              providerModule.findProperty("Name")).getValue();
1704                          nameValue.get(moduleName);
1705 kumpf           1.6  
1706 carolann.graves 1.29     // Retrieve the provider user context configuration
1707                          Uint16 userContext = 0;
1708                          Uint32 pos = providerModule.findProperty(
1709                              PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
1710                          if (pos != PEG_NOT_FOUND)
1711                          {
1712                              CIMValue userContextValue =
1713                                  providerModule.getProperty(pos).getValue();
1714                              if (!userContextValue.isNull())
1715 kumpf           1.6          {
1716 carolann.graves 1.29             userContextValue.get(userContext);
1717 kumpf           1.6          }
1718 carolann.graves 1.29     }
1719 kumpf           1.6  
1720 carolann.graves 1.29     if (userContext == 0)
1721                          {
1722                              userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
1723                          }
1724 kumpf           1.6  
1725 carolann.graves 1.29     String userName;
1726 kumpf           1.6  
1727 carolann.graves 1.29     if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
1728                          {
1729 a.dunfey        1.31         if(request->operationContext.contains(IdentityContainer::NAME))
1730 kumpf           1.1          {
1731 carolann.graves 1.29             // User Name is in the OperationContext
1732                                  IdentityContainer ic = (IdentityContainer)
1733                                      request->operationContext.get(IdentityContainer::NAME);
1734                                  userName = ic.getUserName();
1735 kumpf           1.6          }
1736 a.dunfey        1.31         //else
1737                              //{
1738                              //    If no IdentityContainer is present, default to the CIM
1739                              //    Server's user context
1740                              //}
1741 carolann.graves 1.29 
1742                              // If authentication is disabled, use the CIM Server's user context
1743                              if (!userName.size())
1744 kumpf           1.6          {
1745                                  userName = System::getEffectiveUserName();
1746                              }
1747 carolann.graves 1.29     }
1748                          else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
1749                          {
1750                              // Retrieve the provider module designated user property value
1751                              providerModule.getProperty(providerModule.findProperty(
1752                                  PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue().
1753                                  get(userName);
1754                          }
1755                          else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER)
1756                          {
1757                              userName = System::getEffectiveUserName();
1758                          }
1759                          else    // Privileged User
1760                          {
1761                              PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED);
1762                              userName = System::getPrivilegedUserName();
1763 kumpf           1.1      }
1764                      
1765 carolann.graves 1.29     PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1766                              "Module name = " + moduleName);
1767                          Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1768                              "User context = %hd.", userContext);
1769                          PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4,
1770                              "User name = " + userName);
1771 kumpf           1.1  
1772                          ProviderAgentContainer* pa = 0;
1773 kumpf           1.6      String key = moduleName + ":" + userName;
1774 kumpf           1.1  
1775                          AutoMutex lock(_providerAgentTableMutex);
1776 kumpf           1.6      if (!_providerAgentTable.lookup(key, pa))
1777 kumpf           1.1      {
1778 kumpf           1.6          pa = new ProviderAgentContainer(
1779 carolann.graves 1.29             moduleName, userName, userContext,
1780                                  _indicationCallback, _responseChunkCallback,
1781                                  _providerModuleFailCallback,
1782 carolann.graves 1.14             _subscriptionInitComplete);
1783 kumpf           1.6          _providerAgentTable.insert(key, pa);
1784 kumpf           1.1      }
1785                          return pa;
1786                      }
1787                      
1788 kumpf           1.6  Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents(
1789                          const String& moduleName)
1790                      {
1791                          Array<ProviderAgentContainer*> paArray;
1792                      
1793                          AutoMutex lock(_providerAgentTableMutex);
1794                          for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++)
1795                          {
1796                              if (i.value()->getModuleName() == moduleName)
1797                              {
1798                                  paArray.append(i.value());
1799                              }
1800                          }
1801                          return paArray;
1802                      }
1803                      
1804 kumpf           1.1  CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents(
1805                          CIMRequestMessage* request)
1806                      {
1807                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1808                              "OOPProviderManagerRouter::_forwardRequestToAllAgents");
1809                      
1810                          // Get a list of the ProviderAgentContainers.  We need our own array copy
1811                          // because we cannot hold the _providerAgentTableMutex while calling
1812                          // _ProviderAgentContainer::processMessage().
1813                          Array<ProviderAgentContainer*> paContainerArray;
1814                          {
1815                              AutoMutex tableLock(_providerAgentTableMutex);
1816                              for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
1817                                   i != 0; i++)
1818                              {
1819                                  paContainerArray.append(i.value());
1820                              }
1821                          }
1822                      
1823                          CIMException responseException;
1824                      
1825 kumpf           1.1      // Forward the request to each of the initialized provider agents
1826                          for (Uint32 j = 0; j < paContainerArray.size(); j++)
1827                          {
1828                              ProviderAgentContainer* pa = paContainerArray[j];
1829                              if (pa->isInitialized())
1830                              {
1831                                  // Note: The ProviderAgentContainer could become uninitialized
1832                                  // before _ProviderAgentContainer::processMessage() processes
1833                                  // this request.  In this case, the Provider Agent process will
1834                                  // (unfortunately) be started to process this message.
1835                                  AutoPtr<CIMResponseMessage> response;
1836                                  response.reset(pa->processMessage(request));
1837                                  if (response.get() != 0)
1838                                  {
1839                                      // If the operation failed, save the exception data
1840                                      if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
1841                                          (responseException.getCode() == CIM_ERR_SUCCESS))
1842                                      {
1843                                          responseException = response->cimException;
1844                                      }
1845                                  }
1846 kumpf           1.1          }
1847                          }
1848                      
1849                          CIMResponseMessage* response = request->buildResponse();
1850                          response->cimException = responseException;
1851                      
1852                          PEG_METHOD_EXIT();
1853                          return response;
1854                      }
1855                      
1856                      Boolean OOPProviderManagerRouter::hasActiveProviders()
1857                      {
1858                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1859                              "OOPProviderManagerRouter::hasActiveProviders");
1860                      
1861                          // Iterate through the _providerAgentTable looking for initialized agents
1862                          AutoMutex lock(_providerAgentTableMutex);
1863                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1864                          for(; i != 0; i++)
1865                          {
1866                              if (i.value()->isInitialized())
1867 kumpf           1.1          {
1868                                  PEG_METHOD_EXIT();
1869                                  return true;
1870                              }
1871                          }
1872                      
1873                          // No initialized Provider Agents were found
1874                          PEG_METHOD_EXIT();
1875                          return false;
1876                      }
1877                      
1878                      void OOPProviderManagerRouter::unloadIdleProviders()
1879                      {
1880                          PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
1881                              "OOPProviderManagerRouter::unloadIdleProviders");
1882                      
1883                          // Iterate through the _providerAgentTable unloading idle providers
1884                          AutoMutex lock(_providerAgentTableMutex);
1885                          ProviderAgentTable::Iterator i = _providerAgentTable.start();
1886                          for(; i != 0; i++)
1887                          {
1888 kumpf           1.1          i.value()->unloadIdleProviders();
1889                          }
1890                      
1891                          PEG_METHOD_EXIT();
1892                      }
1893                      
1894                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2