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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2