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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2