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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2