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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2