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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2