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

   1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
   2           //
   3           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6           // IBM Corp.; EMC Corporation, The Open Group.
   7           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  12           // EMC Corporation; Symantec Corporation; The Open Group.
  13           //
  14           // Permission is hereby granted, free of charge, to any person obtaining a copy
  15           // of this software and associated documentation files (the "Software"), to
  16           // deal in the Software without restriction, including without limitation the
  17           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  18           // sell copies of the Software, and to permit persons to whom the Software is
  19           // furnished to do so, subject to the following conditions:
  20           // 
  21           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  23           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  24           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  26           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29           //
  30           //==============================================================================
  31           //
  32           //%/////////////////////////////////////////////////////////////////////////////
  33           
  34           #include "ProviderManagerService.h"
  35           
  36           #include <Pegasus/Common/Config.h>
  37           #include <Pegasus/Common/PegasusVersion.h>
  38           #include <Pegasus/Common/Constants.h>
  39           #include <Pegasus/Common/CIMMessage.h>
  40           #include <Pegasus/Common/Thread.h>
  41           #include <Pegasus/Common/Tracer.h>
  42           #include <Pegasus/Common/Logger.h>
  43 kumpf 1.1 #include <Pegasus/Common/AutoPtr.h>
  44           #include <Pegasus/Common/Constants.h>
  45           #include <Pegasus/Common/StatisticalData.h>
  46           
  47           #include <Pegasus/Config/ConfigManager.h>
  48           
  49           #include <Pegasus/ProviderManagerService/BasicProviderManagerRouter.h>
  50           #include <Pegasus/ProviderManagerService/OOPProviderManagerRouter.h>
  51           
  52 marek 1.2 #ifdef PEGASUS_ZOS_SECURITY
  53           // This include file will not be provided in the OpenGroup CVS for now.
  54           // Do NOT try to include it in your compile
  55           #include <Pegasus/ProviderManager2/ProviderManagerzOS_inline.h>
  56           #endif
  57           
  58 kumpf 1.1 PEGASUS_NAMESPACE_BEGIN
  59           
  60           inline Boolean _isSupportedRequestType(const Message * message)
  61           {
  62               // ATTN: needs implementation
  63           
  64               // for now, assume all requests are valid
  65           
  66               return(true);
  67           }
  68           
  69           inline Boolean _isSupportedResponseType(const Message * message)
  70           {
  71               // ATTN: needs implementation
  72           
  73               // for now, assume all responses are invalid
  74           
  75               return(false);
  76           }
  77           
  78           ProviderManagerService* ProviderManagerService::providerManagerService=NULL;
  79 kumpf 1.1 Uint32 ProviderManagerService::_indicationServiceQueueId = PEG_NOT_FOUND;
  80           
  81           ProviderManagerService::ProviderManagerService(
  82                   ProviderRegistrationManager * providerRegistrationManager,
  83                   CIMRepository * repository,
  84                   ProviderManager* (*createDefaultProviderManagerCallback)())
  85               : MessageQueueService(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP)
  86           {
  87               providerManagerService=this;
  88               _repository=repository;
  89           
  90               _providerRegistrationManager = providerRegistrationManager;
  91           
  92               _unloadIdleProvidersBusy = 0;
  93           
  94               _basicProviderManagerRouter = 0;
  95               _oopProviderManagerRouter = 0;
  96           
  97               // Determine which ProviderManagerRouter(s) to use
  98           
  99               _forceProviderProcesses = ConfigManager::parseBooleanValue(
 100 kumpf 1.1         ConfigManager::getInstance()->getCurrentValue(
 101                       "forceProviderProcesses"));
 102           
 103           #ifdef PEGASUS_DISABLE_PROV_USERCTXT
 104               if (_forceProviderProcesses)
 105               {
 106                   _oopProviderManagerRouter = new OOPProviderManagerRouter(
 107                       indicationCallback, responseChunkCallback,
 108                       providerModuleFailureCallback);
 109               }
 110               else
 111               {
 112                   _basicProviderManagerRouter = new BasicProviderManagerRouter(
 113                       indicationCallback, responseChunkCallback, 
 114                       createDefaultProviderManagerCallback);
 115               }
 116           #else
 117               _oopProviderManagerRouter = new OOPProviderManagerRouter(
 118                   indicationCallback, responseChunkCallback,
 119                   providerModuleFailureCallback);
 120           
 121 kumpf 1.1     if (!_forceProviderProcesses)
 122               {
 123                   _basicProviderManagerRouter = new BasicProviderManagerRouter(
 124                       indicationCallback, responseChunkCallback,
 125                       createDefaultProviderManagerCallback);
 126               }
 127           #endif
 128           }
 129           
 130           ProviderManagerService::~ProviderManagerService(void)
 131           {
 132               delete _basicProviderManagerRouter;
 133               delete _oopProviderManagerRouter;
 134               providerManagerService=NULL;
 135           }
 136           
 137           Boolean ProviderManagerService::messageOK(const Message * message)
 138           {
 139               PEGASUS_ASSERT(message != 0);
 140           
 141               if(_isSupportedRequestType(message))
 142 kumpf 1.1     {
 143                   return(MessageQueueService::messageOK(message));
 144               }
 145           
 146               return(false);
 147           }
 148           
 149           void ProviderManagerService::handleEnqueue(void)
 150           {
 151               Message * message = dequeue();
 152           
 153               handleEnqueue(message);
 154           }
 155           
 156           void ProviderManagerService::handleEnqueue(Message * message)
 157           {
 158               PEGASUS_ASSERT(message != 0);
 159           
 160               AsyncLegacyOperationStart * asyncRequest;
 161           
 162               if(message->_async != NULL)
 163 kumpf 1.1     {
 164                   asyncRequest = static_cast<AsyncLegacyOperationStart *>(message->_async);
 165               }
 166               else
 167               {
 168                   asyncRequest = new AsyncLegacyOperationStart(
 169                       0,
 170                       this->getQueueId(),
 171                       message,
 172                       this->getQueueId());
 173               }
 174           
 175               _handle_async_request(asyncRequest);
 176           }
 177           
 178           void ProviderManagerService::_handle_async_request(AsyncRequest * request)
 179           {
 180               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 181                   "ProviderManagerService::_handle_async_request");
 182           
 183               PEGASUS_ASSERT((request != 0) && (request->op != 0));
 184 kumpf 1.1 
 185               if(request->getType() == async_messages::ASYNC_LEGACY_OP_START)
 186               {
 187                   request->op->processing();
 188           
 189                   _incomingQueue.insert_back(request->op);
 190                   ThreadStatus rtn = PEGASUS_THREAD_OK;
 191                   while (( rtn =_thread_pool->allocate_and_awaken(
 192                                (void *)this, ProviderManagerService::handleCimOperation)) != PEGASUS_THREAD_OK)
 193                   {
 194                       if (rtn==PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
 195                           Threads::yield();
 196                       else
 197                       {
 198                           Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
 199                               "Not enough threads to service provider manager." );
 200           
 201                           Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 202                               "Could not allocate thread for %s.",
 203                               getQueueName());
 204                           break;
 205 kumpf 1.1            }
 206                   }
 207               }
 208               else
 209               {
 210                   // pass all other operations to the default handler
 211                   MessageQueueService::_handle_async_request(request);
 212               }
 213           
 214               PEG_METHOD_EXIT();
 215           
 216               return;
 217           }
 218           
 219           // Note: This method should not throw an exception.  It is used as a thread
 220           // entry point, and any exceptions thrown are ignored.
 221           ThreadReturnType PEGASUS_THREAD_CDECL
 222           ProviderManagerService::handleCimOperation(void* arg)
 223           {
 224               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 225                   "ProviderManagerService::handleCimOperation");
 226 kumpf 1.1 
 227               PEGASUS_ASSERT(arg != 0);
 228           
 229               // get the service from argument
 230               ProviderManagerService* service =
 231                   reinterpret_cast<ProviderManagerService *>(arg);
 232               PEGASUS_ASSERT(service != 0);
 233           
 234               try
 235               {
 236                   if (service->_incomingQueue.size() == 0)
 237                   {
 238                       PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 239                           "ProviderManagerService::handleCimOperation() called with no "
 240                               "op node in queue");
 241           
 242                       PEG_METHOD_EXIT();
 243                       return(ThreadReturnType(1));
 244                   }
 245           
 246                   AsyncOpNode* op = service->_incomingQueue.remove_front();
 247 kumpf 1.1         PEGASUS_ASSERT(op != 0);
 248                   PEGASUS_ASSERT(op->_request.get() != 0);
 249           
 250                   AsyncRequest* request =
 251                       static_cast<AsyncRequest*>(op->_request.get());
 252           
 253                   if ((request == 0) ||
 254                       (request->getType() != async_messages::ASYNC_LEGACY_OP_START))
 255                   {
 256                       // reply with NAK
 257                       PEG_METHOD_EXIT();
 258                       return(ThreadReturnType(0));
 259                   }
 260           
 261                   Message* legacy =
 262                       static_cast<AsyncLegacyOperationStart *>(request)->get_action();
 263           
 264                   if(_isSupportedRequestType(legacy))
 265                   {
 266                       AutoPtr<Message> xmessage(legacy);
 267           
 268 kumpf 1.1             // Set the client's requested language into this service thread.
 269                       // This will allow functions in this service to return messages
 270                       // in the correct language.
 271                       CIMMessage* msg = dynamic_cast<CIMMessage *>(legacy);
 272           
 273                       if (msg != 0)
 274                       {
 275                           AcceptLanguageList* langs = new AcceptLanguageList(
 276                               ((AcceptLanguageListContainer)msg->operationContext.get(
 277                                   AcceptLanguageListContainer::NAME)).getLanguages());
 278                           Thread::setLanguages(langs);
 279                       }
 280                       else
 281                       {
 282                           Thread::clearLanguages();
 283                       }
 284           
 285                       service->handleCimRequest(op, legacy);
 286                   }
 287               }
 288               catch (const Exception& e)
 289 kumpf 1.1     {
 290                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 291                       "Unexpected exception in handleCimOperation: " + e.getMessage());
 292               }
 293               catch (...)
 294               {
 295                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 296                       "Unexpected exception in handleCimOperation.");
 297               }
 298           
 299               PEG_METHOD_EXIT();
 300           
 301               return(ThreadReturnType(0));
 302           }
 303           
 304           void ProviderManagerService::handleCimRequest(
 305               AsyncOpNode * op,
 306               Message * message)
 307           {
 308               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 309                   "ProviderManagerService::handleCimRequest");
 310 kumpf 1.1 
 311               CIMRequestMessage * request = dynamic_cast<CIMRequestMessage *>(message);
 312               PEGASUS_ASSERT(request != 0);
 313           
 314               // get request from op node
 315               AsyncRequest * async = static_cast<AsyncRequest *>(op->_request.get());
 316               PEGASUS_ASSERT(async != 0);
 317           
 318               Message * response = 0;
 319               Boolean consumerLookupFailed = false;
 320           
 321               if (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
 322               {
 323                   //
 324                   // Get a ProviderIdContainer for ExportIndicationRequestMessage.
 325                   // Note: This can be removed when the CIMExportRequestDispatcher
 326                   // is updated to add the ProviderIdContainer to the message.
 327                   //
 328                   CIMInstance providerModule;
 329                   CIMInstance provider;
 330                   const CIMExportIndicationRequestMessage* expRequest =
 331 kumpf 1.1             dynamic_cast<const CIMExportIndicationRequestMessage*>(request);
 332                   if (_providerRegistrationManager->lookupIndicationConsumer(
 333                           expRequest->destinationPath, provider, providerModule))
 334                   {
 335                       request->operationContext.insert(
 336                           ProviderIdContainer(providerModule, provider));
 337                   }
 338                   else
 339                   {
 340                       consumerLookupFailed = true;
 341                   }
 342               }
 343           
 344               if (consumerLookupFailed)
 345               {
 346                   CIMResponseMessage* cimResponse = request->buildResponse();
 347                   cimResponse->cimException = PEGASUS_CIM_EXCEPTION(
 348                       CIM_ERR_NOT_SUPPORTED, String::EMPTY);
 349                   response = cimResponse;
 350               }
 351               else if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
 352 kumpf 1.1         (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0) ||
 353                   (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE) ||
 354                   (request->getType() == CIM_INITIALIZE_PROVIDER_REQUEST_MESSAGE))
 355               {
 356                   // Handle CIMOperationRequestMessage, CIMExportIndicationRequestMessage,
 357                   // CIMIndicationRequestMessage, and CIMInitializeProviderRequestMessage.
 358                   // (These should be blocked when the provider module is disabled.)
 359           
 360                   //
 361                   // Get the provider module instance to check for a disabled module
 362                   //
 363                   CIMInstance providerModule;
 364           
 365                   // The provider ID container is added to the OperationContext
 366                   // by the CIMOperationRequestDispatcher for all CIM operation
 367                   // requests to providers, so it does not need to be added again.
 368                   // CIMInitializeProviderRequestMessage also has a provider ID
 369                   // container.
 370                   ProviderIdContainer pidc =
 371                       request->operationContext.get(ProviderIdContainer::NAME);
 372                   providerModule = pidc.getModule();
 373 kumpf 1.1 
 374                   //
 375                   // Check if the target provider is disabled
 376                   //
 377                   Boolean moduleDisabled = false;
 378                   Uint32 pos = providerModule.findProperty(CIMName("OperationalStatus"));
 379                   PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
 380                   Array<Uint16> operationalStatus;
 381                   providerModule.getProperty(pos).getValue().get(operationalStatus);
 382           
 383                   for(Uint32 i = 0; i < operationalStatus.size(); i++)
 384                   {
 385                       if ((operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPED) ||
 386                           (operationalStatus[i] == CIM_MSE_OPSTATUS_VALUE_STOPPING))
 387                       {
 388                           moduleDisabled = true;
 389                           break;
 390                       }
 391                   }
 392           
 393                   if (moduleDisabled)
 394 kumpf 1.1         {
 395                       //
 396                       // Send a "provider blocked" response
 397                       //
 398                       CIMResponseMessage* cimResponse = request->buildResponse();
 399                       cimResponse->cimException = PEGASUS_CIM_EXCEPTION_L(
 400 kumpf 1.5                 CIM_ERR_NOT_SUPPORTED,
 401 kumpf 1.1                 MessageLoaderParms(
 402                               "ProviderManager.ProviderManagerService.PROVIDER_BLOCKED",
 403                               "provider blocked."));
 404                       response = cimResponse;
 405                   }
 406                   else
 407                   {
 408                       //
 409                       // Forward the request to the appropriate ProviderManagerRouter
 410                       //
 411                       response = _processMessage(request);
 412                   }
 413               }
 414               else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
 415               {
 416                   // Handle CIMEnableModuleRequestMessage
 417                   CIMEnableModuleRequestMessage * emReq =
 418                       dynamic_cast<CIMEnableModuleRequestMessage*>(request);
 419           
 420                   CIMInstance providerModule = emReq->providerModule;
 421           
 422 kumpf 1.1         try
 423                   {
 424                       // Forward the request to the ProviderManager
 425                       response = _processMessage(request);
 426           
 427                       // If successful, update provider module status to OK
 428                       // ATTN: Use CIMEnableModuleResponseMessage operationalStatus?
 429                       CIMEnableModuleResponseMessage * emResp =
 430                           dynamic_cast<CIMEnableModuleResponseMessage*>(response);
 431                       if (emResp->cimException.getCode() == CIM_ERR_SUCCESS)
 432                       {
 433                           //
 434                           //  On a successful enable, remove Stopped status and
 435                           //  append OK status
 436                           //
 437                           Array<Uint16> removeStatus;
 438                           Array<Uint16> appendStatus;
 439                           removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPED);
 440                           appendStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
 441                           _updateProviderModuleStatus(
 442                               providerModule, removeStatus, appendStatus);
 443 kumpf 1.1             }
 444                   }
 445                   catch (Exception& e)
 446                   {
 447                       // Get the OperationalStatus property from the provider module
 448                       Array<Uint16> operationalStatus;
 449                       CIMValue itValue = emReq->providerModule.getProperty(
 450                           emReq->providerModule.findProperty("OperationalStatus"))
 451                               .getValue();
 452                       itValue.get(operationalStatus);
 453           
 454                       delete response;
 455           
 456                       CIMEnableModuleResponseMessage* emResp =
 457                           dynamic_cast<CIMEnableModuleResponseMessage*>(
 458                               request->buildResponse());
 459                       emResp->operationalStatus = operationalStatus;
 460                       emResp->cimException =
 461                           CIMException(CIM_ERR_FAILED, e.getMessage());
 462                       response = emResp;
 463                   }
 464 kumpf 1.1     }
 465               else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
 466               {
 467                   // Handle CIMDisableModuleRequestMessage
 468                   CIMDisableModuleRequestMessage * dmReq =
 469                       dynamic_cast<CIMDisableModuleRequestMessage*>(request);
 470           
 471                   CIMInstance providerModule = dmReq->providerModule;
 472                   Boolean updateModuleStatus = !dmReq->disableProviderOnly;
 473           
 474                   try
 475                   {
 476                       //
 477                       //  On issuing a disable request, append Stopping status
 478                       //  Do not remove existing status
 479                       //
 480                       if (updateModuleStatus)
 481                       {
 482                           Array<Uint16> removeStatus;
 483                           Array<Uint16> appendStatus;
 484                           appendStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
 485 kumpf 1.1                 _updateProviderModuleStatus(
 486                               providerModule, removeStatus, appendStatus);
 487                       }
 488           
 489                       // Forward the request to the ProviderManager
 490                       response = _processMessage(request);
 491           
 492                       // Update provider module status based on success or failure
 493                       if (updateModuleStatus)
 494                       {
 495                           CIMDisableModuleResponseMessage * dmResp =
 496                               dynamic_cast<CIMDisableModuleResponseMessage*>(response);
 497                           if (dmResp->cimException.getCode() != CIM_ERR_SUCCESS)
 498                           {
 499                               //
 500                               //  On an unsuccessful disable, remove Stopping status
 501                               //
 502                               Array<Uint16> removeStatus;
 503                               Array<Uint16> appendStatus;
 504                               removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
 505                               _updateProviderModuleStatus(
 506 kumpf 1.1                         providerModule, removeStatus, appendStatus);
 507                           }
 508                           else
 509                           {
 510                               // Disable may or may not have been successful,
 511                               // depending on whether there are outstanding requests.
 512                               // Remove Stopping status
 513                               // Append status, if any, from disable module response
 514                               Array<Uint16> removeStatus;
 515                               Array<Uint16> appendStatus;
 516                               removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
 517                               if (dmResp->operationalStatus.size() > 0)
 518                               {
 519                                   //
 520                                   //  On a successful disable, remove an OK or a Degraded
 521                                   //  status, if present
 522                                   //
 523                                   if (dmResp->operationalStatus[
 524                                       dmResp->operationalStatus.size()-1] ==
 525                                       CIM_MSE_OPSTATUS_VALUE_STOPPED)
 526                                   {
 527 kumpf 1.1                             removeStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
 528                                       removeStatus.append
 529                                           (CIM_MSE_OPSTATUS_VALUE_DEGRADED);
 530                                   }
 531                                   appendStatus.append (dmResp->operationalStatus[
 532                                       dmResp->operationalStatus.size()-1]);
 533                               }
 534                               _updateProviderModuleStatus(
 535                                   providerModule, removeStatus, appendStatus);
 536                           }
 537                       }
 538                   }
 539                   catch (Exception& e)
 540                   {
 541                       // Get the OperationalStatus property from the provider module
 542                       Array<Uint16> operationalStatus;
 543                       CIMValue itValue = dmReq->providerModule.getProperty(
 544                           dmReq->providerModule.findProperty("OperationalStatus"))
 545                               .getValue();
 546                       itValue.get(operationalStatus);
 547           
 548 kumpf 1.1             delete response;
 549           
 550                       CIMDisableModuleResponseMessage* dmResp =
 551                           dynamic_cast<CIMDisableModuleResponseMessage*>(
 552                               request->buildResponse());
 553                       dmResp->operationalStatus = operationalStatus;
 554                       dmResp->cimException =
 555                           CIMException(CIM_ERR_FAILED, e.getMessage());
 556                       response = dmResp;
 557                   }
 558               }
 559               else
 560               {
 561                   response = _processMessage(request);
 562               }
 563           
 564               AsyncLegacyOperationResult * async_result =
 565                   new AsyncLegacyOperationResult(
 566                   op,
 567                   response);
 568           
 569 kumpf 1.1     _complete_op_node(op, ASYNC_OPSTATE_COMPLETE, 0, 0);
 570           
 571               PEG_METHOD_EXIT();
 572           }
 573           
 574           void ProviderManagerService::responseChunkCallback(
 575               CIMRequestMessage* request,
 576               CIMResponseMessage* response)
 577           {
 578               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 579                   "ProviderManagerService::responseChunkCallback");
 580           
 581               try
 582               {
 583                   // only incomplete messages are processed because the caller ends up
 584                   // sending the complete() stage
 585                   PEGASUS_ASSERT(response->isComplete() == false);
 586           
 587                   AsyncLegacyOperationStart *requestAsync =
 588                       dynamic_cast<AsyncLegacyOperationStart *>(request->_async);
 589                   PEGASUS_ASSERT(requestAsync);
 590 kumpf 1.1         AsyncOpNode *op = requestAsync->op;
 591                   PEGASUS_ASSERT(op);
 592                   PEGASUS_ASSERT(!response->_async);
 593                   response->_async = new AsyncLegacyOperationResult(
 594                       op, response);
 595           
 596                   // set the destination
 597                   op->_op_dest = op->_callback_response_q;
 598           
 599                   MessageQueueService *service =
 600                       dynamic_cast<MessageQueueService *>(op->_callback_response_q);
 601           
 602                   PEGASUS_ASSERT(service);
 603           
 604                   // the last chunk MUST be sent last, so use execute the callback
 605                   // not all chunks are going through the dispatcher's chunk
 606                   // resequencer, so this must be a synchronous call here
 607                   // After the call is done, response and asyncResponse are now invalid
 608                   // as they have been sent and deleted externally
 609           
 610                   op->_async_callback(op, service, op->_callback_ptr);
 611 kumpf 1.1     }
 612               catch(Exception &e)
 613               {
 614                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 615                       "Exception in ProviderManagerService::responseChunkCallback: " +
 616                           e.getMessage() + ".  Chunk not delivered.");
 617               }
 618               catch(...)
 619               {
 620                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
 621                       "Exception in ProviderManagerService::responseChunkCallback.  "
 622                           "Chunk not delivered.");
 623               }
 624           
 625               PEG_METHOD_EXIT();
 626           }
 627           
 628           Message* ProviderManagerService::_processMessage(CIMRequestMessage* request)
 629           {
 630               Message* response = 0;
 631           
 632 kumpf 1.1     if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
 633                   (request->getType() ==
 634                       CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
 635                   (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
 636               {
 637                   if (_basicProviderManagerRouter)
 638                   {
 639                       response = _basicProviderManagerRouter->processMessage(request);
 640                   }
 641           
 642                   if (_oopProviderManagerRouter)
 643                   {
 644                       // Note: These responses do not contain interesting data, so just
 645                       // use the last one.
 646                       delete response;
 647           
 648                       response = _oopProviderManagerRouter->processMessage(request);
 649                   }
 650               }
 651               else
 652               {
 653 kumpf 1.1         CIMInstance providerModule;
 654           
 655                   if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
 656                   {
 657                       CIMEnableModuleRequestMessage* emReq =
 658                           dynamic_cast<CIMEnableModuleRequestMessage*>(request);
 659                       providerModule = emReq->providerModule;
 660                   }
 661                   else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
 662                   {
 663                       CIMDisableModuleRequestMessage* dmReq =
 664                           dynamic_cast<CIMDisableModuleRequestMessage*>(request);
 665                       providerModule = dmReq->providerModule;
 666                   }
 667                   else
 668                   {
 669                       ProviderIdContainer pidc =
 670                           request->operationContext.get(ProviderIdContainer::NAME);
 671                       providerModule = pidc.getModule();
 672           #ifdef PEGASUS_ZOS_SECURITY
 673                       if (request->getType() != CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
 674 kumpf 1.1             {
 675                           // this is a z/OS only function
 676                           // the function checks user authorization
 677                           // based on CIM operation versus provider profile
 678                           // Input: request and Provider ID Container
 679                           //Return: failure: a response message for the client
 680                           //        success: NULL 
 681                           response = checkSAFProviderProfile(request, pidc);
 682                           if (response != NULL)
 683                           {
 684                               return response;
 685                           }
 686                       }
 687           #endif
 688                   }
 689           
 690                   Uint16 userContext = PEGASUS_DEFAULT_PROV_USERCTXT;
 691                   Uint32 pos = providerModule.findProperty(
 692                       PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT);
 693                   if (pos != PEG_NOT_FOUND)
 694                   {
 695 kumpf 1.1             providerModule.getProperty(pos).getValue().get(userContext);
 696                   }
 697           
 698                   // Forward the request to the appropriate ProviderManagerRouter, based
 699                   // on the CIM Server configuration and the UserContext setting.
 700           
 701                   if (_forceProviderProcesses
 702           #ifndef PEGASUS_DISABLE_PROV_USERCTXT
 703                       || (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
 704                       || (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED)
 705                       || ((userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED) &&
 706                           !System::isPrivilegedUser(System::getEffectiveUserName()))
 707           #endif
 708                      )
 709                   {
 710                       response = _oopProviderManagerRouter->processMessage(request);
 711                   }
 712                   else
 713                   {
 714                       response = _basicProviderManagerRouter->processMessage(request);
 715                   }
 716 kumpf 1.1     }
 717           
 718               return response;
 719           }
 720           
 721           void ProviderManagerService::unloadIdleProviders()
 722           {
 723               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 724                   "ProviderManagerService::unloadIdleProviders");
 725 kumpf 1.3 
 726 kumpf 1.1     // Ensure that only one _unloadIdleProvidersHandler thread runs at a time
 727               _unloadIdleProvidersBusy++;
 728 kumpf 1.3     if (_unloadIdleProvidersBusy.get() != 1)
 729 kumpf 1.1     {
 730 kumpf 1.3         _unloadIdleProvidersBusy--;
 731                   PEG_METHOD_EXIT();
 732                   return;
 733 kumpf 1.1     }
 734 kumpf 1.3 
 735               //
 736               // Start an idle provider unload thread
 737               //
 738           
 739               if (_thread_pool->allocate_and_awaken((void*)this,
 740                       ProviderManagerService::_unloadIdleProvidersHandler) !=
 741                           PEGASUS_THREAD_OK)
 742 kumpf 1.1     {
 743                   Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
 744                       "Not enough threads to unload idle providers.");
 745           
 746                   Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 747                       "Could not allocate thread for %s to unload idle providers.",
 748                       getQueueName());
 749 kumpf 1.3 
 750                   // If we fail to allocate a thread, don't retry now.
 751                   _unloadIdleProvidersBusy--;
 752                   PEG_METHOD_EXIT();
 753                   return;
 754 kumpf 1.1     }
 755 kumpf 1.3 
 756               // Note: _unloadIdleProvidersBusy is decremented in
 757               // _unloadIdleProvidersHandler
 758           
 759 kumpf 1.1     PEG_METHOD_EXIT();
 760           }
 761           
 762           ThreadReturnType PEGASUS_THREAD_CDECL
 763           ProviderManagerService::_unloadIdleProvidersHandler(void* arg) throw()
 764           {
 765 kumpf 1.3     ProviderManagerService* myself =
 766                   reinterpret_cast<ProviderManagerService*>(arg);
 767           
 768 kumpf 1.1     try
 769               {
 770                   PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 771 kumpf 1.3             "ProviderManagerService::_unloadIdleProvidersHandler");
 772 kumpf 1.1 
 773                   if (myself->_basicProviderManagerRouter)
 774                   {
 775                       try
 776                       {
 777                           myself->_basicProviderManagerRouter->unloadIdleProviders();
 778                       }
 779                       catch (...)
 780                       {
 781                           // Ignore errors
 782                           PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 783                               "Unexpected exception from "
 784                                   "BasicProviderManagerRouter::_unloadIdleProviders");
 785                       }
 786                   }
 787           
 788                   if (myself->_oopProviderManagerRouter)
 789                   {
 790                       try
 791                       {
 792                           myself->_oopProviderManagerRouter->unloadIdleProviders();
 793 kumpf 1.1             }
 794                       catch (...)
 795                       {
 796                           // Ignore errors
 797                           PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 798                               "Unexpected exception from "
 799                                   "OOPProviderManagerRouter::_unloadIdleProviders");
 800                       }
 801                   }
 802           
 803                   myself->_unloadIdleProvidersBusy--;
 804                   PEG_METHOD_EXIT();
 805               }
 806               catch (...)
 807               {
 808                   // Ignore errors
 809                   PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
 810                       "Unexpected exception in _unloadIdleProvidersHandler");
 811 kumpf 1.3 
 812                   myself->_unloadIdleProvidersBusy--;
 813 kumpf 1.1     }
 814           
 815               return(ThreadReturnType(0));
 816           }
 817           
 818           // Updates the providerModule instance and the ProviderRegistrationManager
 819           //
 820           // This method is used to update the provider module status when the module is
 821           // disabled or enabled.  If a Degraded status has been set (appended) to the
 822           // OperationalStatus, it is cleared (removed) when the module is disabled or
 823           // enabled.
 824           //
 825           void ProviderManagerService::_updateProviderModuleStatus(
 826               CIMInstance& providerModule,
 827               const Array<Uint16>& removeStatus,
 828               const Array<Uint16>& appendStatus)
 829           {
 830               PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
 831                   "ProviderManagerService::_updateProviderModuleStatus");
 832           
 833               Array<Uint16> operationalStatus;
 834 kumpf 1.1     String providerModuleName;
 835           
 836               Uint32 pos = providerModule.findProperty(CIMName("Name"));
 837               PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
 838               providerModule.getProperty(pos).getValue().get(providerModuleName);
 839           
 840               //
 841               // get operational status
 842               //
 843               pos = providerModule.findProperty(CIMName("OperationalStatus"));
 844               PEGASUS_ASSERT(pos != PEG_NOT_FOUND);
 845               CIMProperty operationalStatusProperty = providerModule.getProperty(pos);
 846           
 847               if (_providerRegistrationManager->updateProviderModuleStatus(
 848                   providerModuleName, removeStatus, appendStatus, operationalStatus) ==
 849                   false)
 850               {
 851                   throw PEGASUS_CIM_EXCEPTION_L(
 852                       CIM_ERR_FAILED,
 853                       MessageLoaderParms(
 854                           "ProviderManager.ProviderManagerService."
 855 kumpf 1.1                     "SET_MODULE_STATUS_FAILED",
 856                           "set module status failed."));
 857               }
 858           
 859               operationalStatusProperty.setValue(CIMValue(operationalStatus));
 860           
 861               PEG_METHOD_EXIT();
 862           }
 863           
 864           void ProviderManagerService::indicationCallback(
 865               CIMProcessIndicationRequestMessage* request)
 866           {
 867               if(request->operationContext.contains(AcceptLanguageListContainer::NAME))
 868               {
 869                   AcceptLanguageListContainer cntr = request->operationContext.get(AcceptLanguageListContainer::NAME);
 870               }
 871               else
 872               {
 873                   request->operationContext.insert(AcceptLanguageListContainer(AcceptLanguageList()));
 874               }
 875           
 876 kumpf 1.1     if (_indicationServiceQueueId == PEG_NOT_FOUND)
 877               {
 878                   Array<Uint32> serviceIds;
 879           
 880                   providerManagerService->find_services(
 881                       PEGASUS_QUEUENAME_INDICATIONSERVICE, 0, 0, &serviceIds);
 882                   PEGASUS_ASSERT(serviceIds.size() != 0);
 883           
 884                   _indicationServiceQueueId = serviceIds[0];
 885               }
 886           
 887               request->queueIds = QueueIdStack(
 888                   _indicationServiceQueueId, providerManagerService->getQueueId());
 889           
 890               AsyncLegacyOperationStart * asyncRequest =
 891                   new AsyncLegacyOperationStart(
 892                   0,
 893                   _indicationServiceQueueId,
 894                   request,
 895                   _indicationServiceQueueId);
 896           
 897 kumpf 1.1     providerManagerService->SendForget(asyncRequest);
 898           
 899           
 900           
 901           
 902           #ifdef PEGASUS_INDICATIONS_Q_THRESHOLD
 903           
 904               // See Comments in config.mak asociated with
 905               //  PEGASUS_INDICATIONS_Q_THRESHOLD
 906               //
 907               // if INDICATIONS_Q_STALL THRESHOLD is gt 0
 908               // then if there are over INDICATIONS_Q_STALL_THRESHOLD
 909               //           indications in the queue
 910               //      then force this provider to sleep until the queue count
 911               //      is lower than INDICATIONS_Q_RESUME_THRESHOLD
 912           
 913           static Mutex   indicationThresholdReportedLock;
 914           static Boolean indicationThresholdReported = false;
 915           
 916           #define INDICATIONS_Q_STALL_THRESHOLD PEGASUS_INDICATIONS_Q_THRESHOLD
 917           #define INDICATIONS_Q_RESUME_THRESHOLD (int)(PEGASUS_INDICATIONS_Q_THRESHOLD*.90)
 918 kumpf 1.1 #define INDICATIONS_Q_STALL_DURATION 250 // milli-seconds
 919           
 920               MessageQueue * indicationsQueue = MessageQueue::lookup(_indicationServiceQueueId);
 921           
 922               if (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_STALL_THRESHOLD)
 923               {
 924                   AutoMutex indicationThresholdReportedAutoMutex(indicationThresholdReportedLock);
 925                   if (!indicationThresholdReported)
 926                   {
 927                       indicationThresholdReported = true;
 928                       indicationThresholdReportedAutoMutex.unlock();
 929           
 930                       // make log entry to record que max exceeded
 931           
 932                       Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
 933                           "Indication generation stalled: maximum queue count ($0) exceeded.",
 934                           INDICATIONS_Q_STALL_THRESHOLD);
 935                   }
 936                   else
 937                   {
 938                       indicationThresholdReportedAutoMutex.unlock();
 939 kumpf 1.1         }
 940           
 941                   while (((MessageQueueService *)indicationsQueue)->getIncomingCount() > INDICATIONS_Q_RESUME_THRESHOLD)
 942                   {
 943                       Threads::sleep(INDICATIONS_Q_STALL_DURATION);
 944                   }
 945           
 946                   AutoMutex indicationThresholdReportedAutoMutex1(indicationThresholdReportedLock);
 947                   //        indicationThresholdReportedLock.lock();
 948                   if(indicationThresholdReported)
 949                   {
 950                       indicationThresholdReported = false;
 951                       indicationThresholdReportedAutoMutex1.unlock();
 952           
 953                       Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
 954                             "Indication generation resumed: current queue count = $0",
 955                             ((MessageQueueService *)indicationsQueue)->getIncomingCount() );
 956           
 957                   }
 958                   else
 959                   {
 960 kumpf 1.1             indicationThresholdReportedAutoMutex1.unlock();
 961                   }
 962               }
 963           #endif /* INDICATIONS_Q_STALL_THRESHOLD */
 964           
 965           }
 966           
 967           void ProviderManagerService::providerModuleFailureCallback
 968               (const String & moduleName,
 969                const String & userName,
 970                Uint16 userContext)
 971           {
 972               PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
 973                   "ProviderManagerService::providerModuleFailureCallback");
 974           
 975               if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR)
 976               {
 977                   Logger::put_l (
 978                       Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
 979                       "ProviderManager.OOPProviderManagerRouter."
 980                           "OOP_PROVIDER_MODULE_USER_CTXT_FAILURE_DETECTED", 
 981 kumpf 1.1             "A failure was detected in provider module $0 with"
 982                           " user context $1.",
 983                       moduleName, userName);
 984               }
 985               else  //  not requestor context
 986               {
 987                   Logger::put_l (
 988                       Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
 989                       "ProviderManager.OOPProviderManagerRouter."
 990                           "OOP_PROVIDER_MODULE_FAILURE_DETECTED", 
 991                       "A failure was detected in provider module $0.",
 992                       moduleName);
 993               }
 994                           
 995               //
 996               //  Create Notify Provider Fail request message
 997               //
 998               CIMNotifyProviderFailRequestMessage * request =
 999                   new CIMNotifyProviderFailRequestMessage
1000                       (XmlWriter::getNextMessageId (),
1001                       moduleName,
1002 kumpf 1.1             userName,
1003                       QueueIdStack ());
1004           
1005               //
1006               //  Send Notify Provider Fail request message to Indication Service
1007               //
1008               if (_indicationServiceQueueId == PEG_NOT_FOUND)
1009               {
1010                   Array <Uint32> serviceIds;
1011            
1012                   providerManagerService->find_services
1013                       (PEGASUS_QUEUENAME_INDICATIONSERVICE, 0, 0, &serviceIds);
1014                   PEGASUS_ASSERT (serviceIds.size () != 0);
1015           
1016                   _indicationServiceQueueId = serviceIds [0];
1017               }
1018           
1019               request->queueIds = QueueIdStack
1020                   (_indicationServiceQueueId, providerManagerService->getQueueId ());
1021           
1022               AsyncLegacyOperationStart * asyncRequest = new AsyncLegacyOperationStart(
1023 kumpf 1.1         0,
1024                   _indicationServiceQueueId,
1025                   request,
1026                   _indicationServiceQueueId);
1027           
1028               AutoPtr <AsyncReply> asyncReply
1029                   (providerManagerService->SendWait (asyncRequest));
1030           
1031               AutoPtr <CIMNotifyProviderFailResponseMessage> response
1032                   (reinterpret_cast <CIMNotifyProviderFailResponseMessage *>
1033                       ((dynamic_cast <AsyncLegacyOperationResult *>
1034                       (asyncReply.get ()))->get_result ()));
1035           
1036               if (response->cimException.getCode () != CIM_ERR_SUCCESS)
1037               {
1038                   PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
1039                       "Unexpected exception in providerModuleFailureCallback: " +
1040                       response->cimException.getMessage ());
1041               }
1042               else
1043               {
1044 kumpf 1.1         //
1045                   //  Successful response
1046                   //  Examine result to see if any subscriptions were affected
1047                   //
1048                   if (response->numSubscriptionsAffected > 0)
1049                   {
1050                       //
1051                       //  Subscriptions were affected
1052                       //  Update the provider module status to Degraded
1053                       //
1054                       try
1055                       {
1056                           CIMInstance providerModule;
1057                           CIMKeyBinding keyBinding(
1058                               _PROPERTY_PROVIDERMODULE_NAME,
1059                               moduleName,
1060                               CIMKeyBinding::STRING);
1061                           Array<CIMKeyBinding> kbArray;
1062                           kbArray.append(keyBinding);
1063                           CIMObjectPath modulePath("", PEGASUS_NAMESPACENAME_INTEROP,
1064                               PEGASUS_CLASSNAME_PROVIDERMODULE, kbArray);
1065 kumpf 1.1                 providerModule = 
1066                               providerManagerService->_providerRegistrationManager->
1067                                   getInstance(
1068                                       modulePath, false, false, CIMPropertyList());
1069           
1070                           Array<Uint16> removeStatus;
1071                           Array<Uint16> appendStatus;
1072                           removeStatus.append(CIM_MSE_OPSTATUS_VALUE_OK);
1073                           appendStatus.append(CIM_MSE_OPSTATUS_VALUE_DEGRADED);
1074                           providerManagerService->_updateProviderModuleStatus(
1075                               providerModule, removeStatus, appendStatus);
1076                       }
1077                       catch (const Exception & e)
1078                       {
1079                           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
1080                               "Failed to update provider module status: " +
1081                               e.getMessage());
1082                       }
1083           
1084                       //
1085                       //  Log a warning message since subscriptions were affected
1086 kumpf 1.1             //
1087                       Logger::put_l (
1088                           Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
1089                           "ProviderManager.OOPProviderManagerRouter."
1090                               "OOP_PROVIDER_MODULE_SUBSCRIPTIONS_AFFECTED", 
1091                           "The generation of indications by providers in module $0 "
1092                           "may be affected.  To ensure these providers are serving "
1093                           "active subscriptions, disable and then re-enable this "
1094                           "module using the cimprovider command.",
1095                           moduleName);
1096                   }
1097               }
1098           
1099               PEG_METHOD_EXIT();
1100           }
1101           
1102           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2