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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2