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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2