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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2