OW_EmbeddedCIMOMEnvironment.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *  this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *  this list of conditions and the following disclaimer in the documentation
00013 *  and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *  contributors may be used to endorse or promote products derived from this
00017 *  software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE CONTRIBUTORS
00023 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029 * POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00038 #include "OW_config.h"
00039 #include "OW_EmbeddedCIMOMEnvironment.hpp"
00040 #include "OW_ConfigOpts.hpp"
00041 #include "OW_ConfigException.hpp"
00042 #include "OW_Format.hpp"
00043 #include "OW_FileSystem.hpp"
00044 #include "OW_SafeLibCreate.hpp"
00045 #include "OW_SelectEngine.hpp"
00046 #include "OW_CIMServer.hpp"
00047 #include "OW_CIMRepository.hpp"
00048 #include "OW_CIMInstance.hpp"
00049 #include "OW_CIMNameSpace.hpp"
00050 #include "OW_ServiceIFC.hpp"
00051 #include "OW_RequestHandlerIFC.hpp"
00052 #include "OW_IndicationServer.hpp"
00053 #include "OW_PollingManager.hpp"
00054 #include "OW_Assertion.hpp"
00055 #include "OW_LocalEmbeddedCIMOMHandle.hpp"
00056 #include "OW_WQLFilterRep.hpp"
00057 #include "OW_IndicationRepLayer.hpp"
00058 #include "OW_WQLIFC.hpp"
00059 #include "OW_SharedLibraryRepository.hpp"
00060 #include "OW_IndicationRepLayerMediator.hpp"
00061 #include "OW_OperationContext.hpp"
00062 #include "OW_Authorizer2IFC.hpp"
00063 #include "OW_ExceptionIds.hpp"
00064 #include "OW_CIMObjectPath.hpp"
00065 #include "OW_AuthorizerManager.hpp"
00066 #include "OW_AuthorizerIFC.hpp"
00067 #include "OW_LogAppender.hpp"
00068 #include "OW_AppenderLogger.hpp"
00069 #include "OW_CerrLogger.hpp"
00070 #include "OW_ProviderEnvironmentIFC.hpp"
00071 #include "OW_ProviderManager.hpp"
00072 
00073 #include <iostream>
00074 #include <map>
00075 #include <set>
00076 
00077 namespace OW_NAMESPACE
00078 {
00079 
00080 OW_DECLARE_EXCEPTION(EmbeddedCIMOMEnvironment)
00081 OW_DEFINE_EXCEPTION_WITH_ID(EmbeddedCIMOMEnvironment)
00082 
00083 using std::cerr;
00084 using std::endl;
00085 
00086 namespace
00087 {
00088 // the one and only
00089 EmbeddedCIMOMEnvironmentRef theCimomEnvironment;
00090 }
00091 
00092 EmbeddedCIMOMEnvironmentRef&
00093 EmbeddedCIMOMEnvironment::instance()
00094 {
00095    if (!theCimomEnvironment)
00096    {
00097       theCimomEnvironment = EmbeddedCIMOMEnvironmentRef(new EmbeddedCIMOMEnvironment);
00098    }
00099    return theCimomEnvironment;
00100 }
00101 
00102 String EmbeddedCIMOMEnvironment::COMPONENT_NAME("ow.owcimomd");
00103 
00104 namespace
00105 {
00106    class CIMOMProviderEnvironment : public ProviderEnvironmentIFC
00107    {
00108    public:
00109       CIMOMProviderEnvironment(EmbeddedCIMOMEnvironmentRef pCenv)
00110          : m_pCenv(pCenv)
00111          , m_context()
00112       {}
00113       virtual String getConfigItem(const String &name, const String& defRetVal="") const
00114       {
00115          return m_pCenv->getConfigItem(name, defRetVal);
00116       }
00117       virtual StringArray getMultiConfigItem(const String &itemName, 
00118          const StringArray& defRetVal, const char* tokenizeSeparator) const
00119       {
00120          return m_pCenv->getMultiConfigItem(itemName, defRetVal, tokenizeSeparator);
00121       }
00122       virtual CIMOMHandleIFCRef getCIMOMHandle() const
00123       {
00124          OW_ASSERT("Cannot call CIMOMProviderEnvironment::getCIMOMHandle()" == 0);
00125          return CIMOMHandleIFCRef();
00126       }
00127       
00128       virtual CIMOMHandleIFCRef getRepositoryCIMOMHandle() const
00129       {
00130          OW_ASSERT("Cannot call CIMOMProviderEnvironment::getRepositoryCIMOMHandle()" == 0);
00131          return CIMOMHandleIFCRef();
00132       }
00133       
00134       virtual RepositoryIFCRef getRepository() const
00135       {
00136          return m_pCenv->getRepository();
00137       }
00138       virtual LoggerRef getLogger() const
00139       {
00140          return m_pCenv->getLogger();
00141       }
00142       virtual LoggerRef getLogger(const String& componentName) const
00143       {
00144          return m_pCenv->getLogger(componentName);
00145       }
00146       virtual String getUserName() const
00147       {
00148          return String("TODO"); 
00149       }
00150       virtual OperationContext& getOperationContext()
00151       {
00152          return m_context;
00153       }
00154       virtual ProviderEnvironmentIFCRef clone() const
00155       {
00156          return ProviderEnvironmentIFCRef(new CIMOMProviderEnvironment(m_pCenv));
00157       }
00158    private:
00159       EmbeddedCIMOMEnvironmentRef m_pCenv;
00160       OperationContext m_context;
00161    };
00162    ProviderEnvironmentIFCRef createProvEnvRef(const EmbeddedCIMOMEnvironmentRef& pcenv)
00163    {
00164       return ProviderEnvironmentIFCRef(new CIMOMProviderEnvironment(pcenv));
00165    }
00166 } // end anonymous namespace
00168 // We don't initialize everything here, since startServices() and shutdown() manage the lifecycle.
00169 // We start off with a dumb logger and an empty config map.
00170 EmbeddedCIMOMEnvironment::EmbeddedCIMOMEnvironment()
00171    : m_Logger(new CerrLogger)
00172    , m_configItems(new ConfigMap)
00173    , m_indicationsDisabled(true)
00174    , m_indicationRepLayerDisabled(false)
00175    , m_state(E_STATE_INVALID)
00176    , m_indicationRepLayerMediatorRef(new IndicationRepLayerMediator)
00177 {
00178 }
00180 EmbeddedCIMOMEnvironment::~EmbeddedCIMOMEnvironment()
00181 {
00182    try
00183    {
00184       try
00185       {
00186          if (isLoaded(m_state))
00187          {
00188             shutdown();
00189          }
00190       }
00191       catch(Exception& e)
00192       {
00193          cerr << e << endl;
00194       }
00195       m_configItems = 0;
00196       m_state = E_STATE_INVALID; // just for the heck of it.
00197    }
00198    catch (Exception& e)
00199    {
00200       OW_LOG_ERROR(m_Logger, Format("Caught exception in EmbeddedCIMOMEnvironment::~EmbeddedCIMOMEnvironment(): %1", e));
00201    }
00202    catch (...)
00203    {
00204       // don't let exceptions escape!
00205    }
00206 }
00208 void
00209 EmbeddedCIMOMEnvironment::init()
00210 {
00211    // The config file config item may be set by main before init() is called.
00212    _loadConfigItemsFromFile(getConfigItem(ConfigOpts::CONFIG_FILE_opt, OW_DEFAULT_CONFIG_FILE));
00213 
00214    // logger is treated special, so it goes in init() not startServices()
00215    _createLogger();
00216 }
00218 void
00219 EmbeddedCIMOMEnvironment::startServices()
00220 {
00221    // Split up into 3 sections:
00222    // 1. load
00223    // 2. init, initialized
00224    // 3. start, started
00225 
00226    // We start out single-threaded.  The start phase is when threads enter the picture.
00227 
00228    // load
00229    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment loading services");
00230 
00231    m_authorizerManager = new AuthorizerManager;
00232    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_authorizerManager));
00233 
00234    m_providerManager = new ProviderManager;
00235    m_providerManager->load(ProviderIFCLoader::createProviderIFCLoader(
00236       this), this);
00237    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_providerManager));
00238 
00239    m_cimRepository = new CIMRepository;
00240    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_cimRepository));
00241 
00242    m_cimServer = RepositoryIFCRef(new CIMServer(this,
00243       m_providerManager, m_cimRepository, m_authorizerManager));
00244    m_services.push_back(ServiceIFCRef(SharedLibraryRef(), m_cimServer));
00245 
00246    //_loadAuthorizer();  // old stuff
00247    //_createAuthorizerManager();  // new stuff
00248    //_createAuthManager();
00249    //_loadRequestHandlers();
00250    //_loadServices();
00251 
00252    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment finished loading services");
00253 
00254    _sortServicesForDependencies();
00255 
00256    // init
00257 
00258    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment initializing services");
00259 
00260    {
00261       MutexLock l(m_stateGuard);
00262       m_state = E_STATE_INITIALIZING;
00263    }
00264 
00265    for (size_t i = 0; i < m_services.size(); i++)
00266    {
00267       OW_LOG_DEBUG(m_Logger, Format("CIMOM initializing service: %1", m_services[i]->getName()));
00268       m_services[i]->init(this);
00269    }
00270    {
00271       MutexLock l(m_stateGuard);
00272       m_state = E_STATE_INITIALIZED;
00273    }
00274    
00275    for (size_t i = 0; i < m_services.size(); i++)
00276    {
00277       OW_LOG_DEBUG(m_Logger, Format("CIMOM calling initialized() for service: %1", m_services[i]->getName()));
00278       m_services[i]->initialized();
00279    }
00280 
00281    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment finished initializing services");
00282 
00283    // start
00284    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment starting services");
00285    {
00286       MutexLock l(m_stateGuard);
00287       m_state = E_STATE_STARTING;
00288    }
00289 
00290    for (size_t i = 0; i < m_services.size(); i++)
00291    {
00292       OW_LOG_DEBUG(m_Logger, Format("CIMOM starting service: %1", m_services[i]->getName()));
00293       m_services[i]->start();
00294    }
00295    {
00296       MutexLock l(m_stateGuard);
00297       m_state = E_STATE_STARTED;
00298    }
00299 
00300    for (size_t i = 0; i < m_services.size(); i++)
00301    {
00302       OW_LOG_DEBUG(m_Logger, Format("CIMOM calling started() for service: %1", m_services[i]->getName()));
00303       m_services[i]->started();
00304    }
00305 
00306    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment finished starting services");
00307 }
00309 void
00310 EmbeddedCIMOMEnvironment::shutdown()
00311 {
00312 
00313    // notify all services of impending shutdown.
00314    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment notifying services of shutdown");
00315    // Do this in reverse order because of dependencies
00316    for (int i = int(m_services.size())-1; i >= 0; i--)
00317    {
00318       try
00319       {
00320          OW_LOG_DEBUG(m_Logger, Format("EmbeddedCIMOMEnvironment notifying service: %1", m_services[i]->getName()));
00321          m_services[i]->shuttingDown();
00322       }
00323       catch (Exception& e)
00324       {
00325          OW_LOG_ERROR(m_Logger, Format("Caught exception while calling shuttingDown(): %1", e));
00326       }
00327       catch (...)
00328       {
00329       }
00330    }
00331 
00332    // PHASE 1: SHUTDOWNS
00333    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment beginning shutdown process");
00334    {
00335       MutexLock l(m_stateGuard);
00336       m_state = E_STATE_SHUTTING_DOWN;
00337    }
00338 
00339    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment shutting down sockets");
00340 
00341    // Shutdown all services
00342    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment shutting down services");
00343    // Do this in reverse order because of dependencies
00344    for (int i = int(m_services.size())-1; i >= 0; i--)
00345    {
00346       try
00347       {
00348          OW_LOG_DEBUG(m_Logger, Format("EmbeddedCIMOMEnvironment shutting down service: %1", m_services[i]->getName()));
00349          m_services[i]->shutdown();
00350       }
00351       catch (Exception& e)
00352       {
00353          OW_LOG_ERROR(m_Logger, Format("Caught exception while calling shutdown(): %1", e));
00354       }
00355       catch (...)
00356       {
00357       }
00358    }
00359 
00360    {
00361       MutexLock l(m_stateGuard);
00362       m_state = E_STATE_SHUTDOWN;
00363    }
00364 
00365    // PHASE 2: unload/delete
00366 
00367    // get this lock here so that we delete everything atomically
00368    MutexLock ml(m_monitor);
00369 
00370    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment unloading and deleting services");
00371 
00372    m_pollingManager = 0;
00373    
00374    // We need to unload these in the opposite order that
00375    // they were loaded because of bugs in shared library
00376    // handling on certain OSes.
00377    for (int i = int(m_services.size())-1; i >= 0; i--)
00378    {
00379       m_services[i].setNull();
00380    }
00381    m_services.clear();
00382    // Unload all request handlers
00383    m_reqHandlers.clear();
00384    // Unload the wql library if loaded
00385    m_wqlLib = 0;
00386    // Shutdown indication processing
00387    if (m_indicationServer)
00388    {
00389       m_indicationServer.setNull();
00390       m_indicationRepLayerLib = 0;
00391    }
00392    // Delete the cim server
00393    m_cimServer = 0;
00394    // Delete the cim repository
00395    m_cimRepository = 0;
00396    // Delete the authorization manager
00397    m_authorizerManager = 0;
00398    // Delete the provider manager
00399    m_providerManager = 0;
00400 
00401    {
00402       MutexLock l(m_stateGuard);
00403       m_state = E_STATE_UNLOADED;
00404    }
00405 
00406    OW_LOG_DEBUG(m_Logger, "EmbeddedCIMOMEnvironment has shut down");
00407 }
00409 ProviderManagerRef
00410 EmbeddedCIMOMEnvironment::getProviderManager() const
00411 {
00412    {
00413       MutexLock l(m_stateGuard);
00414       if (!isLoaded(m_state))
00415       {
00416          OW_THROW(EmbeddedCIMOMEnvironmentException, "EmbeddedCIMOMEnvironment::getProviderManager() called when state is not constructed");
00417       }
00418    }
00419    OW_ASSERT(m_providerManager);
00420    return m_providerManager;
00421 }
00425 namespace
00426 {
00427 LogAppender::ConfigMap getAppenderConfig(const ConfigFile::ConfigMap& configItems)
00428 {
00429    LogAppender::ConfigMap appenderConfig;
00430    for (ConfigFile::ConfigMap::const_iterator iter = configItems.begin(); iter != configItems.end(); ++iter)
00431    {
00432       if (iter->first.startsWith("log") && iter->second.size() > 0)
00433       {
00434          appenderConfig[iter->first] = iter->second.back().value;
00435       }
00436    }
00437    return appenderConfig;
00438 }
00439 
00440 } // end anonymous namespace
00442 void
00443 EmbeddedCIMOMEnvironment::_createLogger()
00444 {
00445    using namespace ConfigOpts;
00446    Array<LogAppenderRef> appenders;
00447    
00448    StringArray additionalLogs = getMultiConfigItem(ADDITIONAL_LOGS_opt, StringArray(), " \t");
00449 
00450    // this also gets set if owcimomd is run with -d
00451    bool debugFlag = getConfigItem(DEBUGFLAG_opt, OW_DEFAULT_DEBUGFLAG).equalsIgnoreCase("true");
00452    if ( debugFlag )
00453    {
00454       // stick it at the beginning as a possible slight logging performance optimization
00455       additionalLogs.insert(additionalLogs.begin(), LOG_DEBUG_LOG_NAME);
00456    }
00457 
00458    for (size_t i = 0; i < additionalLogs.size(); ++i)
00459    {
00460       const String& logName(additionalLogs[i]);
00461 
00462       String logMainType = getConfigItem(Format(LOG_1_TYPE_opt, logName), OW_DEFAULT_LOG_1_TYPE);
00463       String logMainComponents = getConfigItem(Format(LOG_1_COMPONENTS_opt, logName), OW_DEFAULT_LOG_1_COMPONENTS);
00464       String logMainCategories = getConfigItem(Format(LOG_1_CATEGORIES_opt, logName));
00465       if (logMainCategories.empty())
00466       {
00467          // convert level into categories
00468          String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName), OW_DEFAULT_LOG_1_LEVEL);
00469          if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
00470          {
00471             logMainCategories = Logger::STR_DEBUG_CATEGORY + " " + Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00472          }
00473          else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
00474          {
00475             logMainCategories = Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00476          }
00477          else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
00478          {
00479             logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00480          }
00481          else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
00482          {
00483             logMainCategories = Logger::STR_FATAL_CATEGORY;
00484          }
00485       }
00486       String logMainFormat = getConfigItem(Format(LOG_1_FORMAT_opt, logName), OW_DEFAULT_LOG_1_FORMAT);
00487 
00488       appenders.push_back(LogAppender::createLogAppender(logName, logMainComponents.tokenize(), logMainCategories.tokenize(),
00489          logMainFormat, logMainType, getAppenderConfig(*m_configItems)));
00490    }
00491 
00492 
00493    // This one will eventually be handled the same as all other logs by just sticking "main" in the additionalLogs array
00494    // but we need to handle deprecated options for now, so it needs special treatment.
00495    String logName(LOG_MAIN_LOG_NAME);
00496    String logMainType = getConfigItem(Format(LOG_1_TYPE_opt, logName));
00497    String logMainComponents = getConfigItem(Format(LOG_1_COMPONENTS_opt, logName), OW_DEFAULT_LOG_1_COMPONENTS);
00498    String logMainCategories = getConfigItem(Format(LOG_1_CATEGORIES_opt, logName));
00499    String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName));
00500    String logMainFormat = getConfigItem(Format(LOG_1_FORMAT_opt, logName), OW_DEFAULT_LOG_1_FORMAT);
00501 
00502    // map the old log_location onto log.main.type and log.main.location if necessary
00503    if (logMainType.empty())
00504    {
00505       String deprecatedLogLocation = getConfigItem(ConfigOpts::LOG_LOCATION_opt, OW_DEFAULT_LOG_LOCATION);
00506       if (deprecatedLogLocation.empty() || deprecatedLogLocation.equalsIgnoreCase("syslog"))
00507       {
00508          logMainType = "syslog";
00509       }
00510       else if (deprecatedLogLocation.equalsIgnoreCase("null"))
00511       {
00512          logMainType = "null";
00513       }
00514       else
00515       {
00516          logMainType = "file";
00517          setConfigItem(Format(LOG_1_LOCATION_opt, logName), deprecatedLogLocation);
00518       }
00519    }
00520 
00521    // map the old log_level onto log.main.level if necessary
00522    if (logMainCategories.empty() && logMainLevel.empty())
00523    {
00524       String deprecatedLogLevel = getConfigItem(ConfigOpts::LOG_LEVEL_opt);
00525       if (deprecatedLogLevel.empty())
00526       {
00527          logMainLevel = OW_DEFAULT_LOG_1_LEVEL;
00528       }
00529       else
00530       {
00531          // old used "fatalerror", now we just use FATAL
00532          if (deprecatedLogLevel.equalsIgnoreCase("fatalerror"))
00533          {
00534             logMainLevel = Logger::STR_FATAL_CATEGORY;
00535          }
00536          else
00537          {
00538             deprecatedLogLevel.toUpperCase();
00539             logMainLevel = deprecatedLogLevel;
00540          }
00541       }
00542    }
00543    
00544    // convert level into categories
00545    if (logMainCategories.empty())
00546    {
00547       // convert level into categories
00548       String logMainLevel = getConfigItem(Format(LOG_1_LEVEL_opt, logName), OW_DEFAULT_LOG_1_LEVEL);
00549       if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
00550       {
00551          logMainCategories = Logger::STR_DEBUG_CATEGORY + " " + Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00552       }
00553       else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
00554       {
00555          logMainCategories = Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00556       }
00557       else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
00558       {
00559          logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
00560       }
00561       else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
00562       {
00563          logMainCategories = Logger::STR_FATAL_CATEGORY;
00564       }
00565    }
00566 
00567    appenders.push_back(LogAppender::createLogAppender(logName, logMainComponents.tokenize(), logMainCategories.tokenize(),
00568       logMainFormat, logMainType, getAppenderConfig(*m_configItems)));
00569 
00570 
00571    m_Logger = new AppenderLogger(COMPONENT_NAME, appenders);
00572 }
00574 void
00575 EmbeddedCIMOMEnvironment::_loadConfigItemsFromFile(const String& filename)
00576 {
00577    OW_LOG_DEBUG(m_Logger, "\nUsing config file: " + filename);
00578    ConfigFile::loadConfigFile(filename, *m_configItems);
00579    StringArray configDirs = ConfigFile::getMultiConfigItem(*m_configItems, 
00580       ConfigOpts::ADDITIONAL_CONFIG_FILES_DIRS_opt, 
00581       String(OW_DEFAULT_ADDITIONAL_CONFIG_FILES_DIRS).tokenize(OW_PATHNAME_SEPARATOR), 
00582       OW_PATHNAME_SEPARATOR);
00583 }
00586 String
00587 EmbeddedCIMOMEnvironment::getConfigItem(const String &name, const String& defRetVal) const
00588 {
00589    return ConfigFile::getConfigItem(*m_configItems, name, defRetVal);
00590 }
00591 
00593 StringArray
00594 EmbeddedCIMOMEnvironment::getMultiConfigItem(const String &itemName, 
00595    const StringArray& defRetVal, const char* tokenizeSeparator) const
00596 {
00597    return ConfigFile::getMultiConfigItem(*m_configItems, itemName, defRetVal, tokenizeSeparator);
00598 }
00599 
00601 CIMOMHandleIFCRef
00602 EmbeddedCIMOMEnvironment::getWQLFilterCIMOMHandle(const CIMInstance& inst,
00603       OperationContext& context) const
00604 {
00605    {
00606       MutexLock l(m_stateGuard);
00607       if (!isLoaded(m_state))
00608       {
00609          OW_THROW(EmbeddedCIMOMEnvironmentException, "EmbeddedCIMOMEnvironment::getWQLFilterCIMOMHandle() called when state is not initialized");
00610       }
00611    }
00612    OW_ASSERT(m_cimServer);
00613    return CIMOMHandleIFCRef(new LocalEmbeddedCIMOMHandle(
00614       const_cast<EmbeddedCIMOMEnvironment *>(this),
00615       RepositoryIFCRef(new WQLFilterRep(inst, m_cimServer)), context));
00616 }
00617 
00619 CIMOMHandleIFCRef
00620 EmbeddedCIMOMEnvironment::getCIMOMHandle(OperationContext& context,
00621    EBypassProvidersFlag bypassProviders,
00622    ELockingFlag locking) const
00623 {
00624    return getCIMOMHandle(context, E_SEND_INDICATIONS, bypassProviders, locking);
00625 }
00626 
00628 CIMOMHandleIFCRef
00629 EmbeddedCIMOMEnvironment::getCIMOMHandle(OperationContext& context,
00630    ESendIndicationsFlag sendIndications,
00631    EBypassProvidersFlag bypassProviders,
00632    ELockingFlag locking) const
00633 {
00634    {
00635       MutexLock l(m_stateGuard);
00636       if (!isLoaded(m_state))
00637       {
00638          OW_THROW(EmbeddedCIMOMEnvironmentException, "EmbeddedCIMOMEnvironment::getCIMOMHandle() called when state is not loaded.");
00639       }
00640    }
00641    MutexLock ml(m_monitor);
00642    OW_ASSERT(m_cimServer);
00643 
00644    // Here we construct a pipeline.  Currently it looks like:
00645    // LocalEmbeddedCIMOMHandle -> [ Authorizer -> ] [Indication Rep Layer -> ] [ CIM Server -> ] CIM Repository
00646 
00647    RepositoryIFCRef rref;
00648    if (bypassProviders == E_BYPASS_PROVIDERS)
00649    {
00650       rref = m_cimRepository;
00651    }
00652    else
00653    {
00654       rref = m_cimServer;
00655    }
00656 
00657 
00658    return CIMOMHandleIFCRef(new LocalEmbeddedCIMOMHandle(const_cast<EmbeddedCIMOMEnvironment*>(this), rref,
00659       context, locking == E_LOCKING ? LocalEmbeddedCIMOMHandle::E_LOCKING : LocalEmbeddedCIMOMHandle::E_NO_LOCKING));
00660 }
00662 WQLIFCRef
00663 EmbeddedCIMOMEnvironment::getWQLRef() const
00664 {
00665    {
00666       MutexLock l(m_stateGuard);
00667       if (!isLoaded(m_state))
00668       {
00669          OW_THROW(EmbeddedCIMOMEnvironmentException, "EmbeddedCIMOMEnvironment::getWQLRef() called when state is not loaded");
00670       }
00671    }
00672    MutexLock ml(m_monitor);
00673    if (!m_wqlLib)
00674    {
00675       String libname = getConfigItem(ConfigOpts::WQL_LIB_opt, OW_DEFAULT_WQL_LIB);
00676       OW_LOG_DEBUG(m_Logger, Format("CIMOM loading wql library %1", libname));
00677       SharedLibraryLoaderRef sll =
00678          SharedLibraryLoader::createSharedLibraryLoader();
00679       m_wqlLib = sll->loadSharedLibrary(libname, m_Logger);
00680       if (!m_wqlLib)
00681       {
00682          OW_LOG_ERROR(m_Logger, Format("CIMOM Failed to load WQL Libary: %1", libname));
00683          return WQLIFCRef();
00684       }
00685    }
00686    return  WQLIFCRef(m_wqlLib, SafeLibCreate<WQLIFC>::create(
00687       m_wqlLib, "createWQL", m_Logger));
00688 }
00694 LoggerRef
00695 EmbeddedCIMOMEnvironment::getLogger() const
00696 {
00697    OW_ASSERT(m_Logger);
00698    return m_Logger->clone();
00699 }
00701 LoggerRef
00702 EmbeddedCIMOMEnvironment::getLogger(const String& componentName) const
00703 {
00704    OW_ASSERT(m_Logger);
00705    LoggerRef rv(m_Logger->clone());
00706    rv->setDefaultComponent(componentName);
00707    return rv;
00708 }
00710 void
00711 EmbeddedCIMOMEnvironment::clearConfigItems()
00712 {
00713    m_configItems->clear();
00714 }
00716 void
00717 EmbeddedCIMOMEnvironment::setConfigItem(const String &item,
00718    const String &value, EOverwritePreviousFlag overwritePrevious)
00719 {
00720    ConfigFile::setConfigItem(*m_configItems, item, value, 
00721       overwritePrevious == E_OVERWRITE_PREVIOUS ? ConfigFile::E_OVERWRITE_PREVIOUS : ConfigFile::E_PRESERVE_PREVIOUS);
00722 }
00727 RepositoryIFCRef
00728 EmbeddedCIMOMEnvironment::getRepository() const
00729 {
00730    return m_cimRepository;
00731 }
00734 void
00735 EmbeddedCIMOMEnvironment::unloadProviders()
00736 {
00737    m_providerManager->unloadProviders(createProvEnvRef(this));
00738 }
00739 
00740 namespace
00741 {
00742 
00744 struct Node
00745 {
00746    Node(const String& name_, size_t index_ = ~0)
00747       : name(name_)
00748       , index(index_)
00749    {}
00750 
00751    String name;
00752    size_t index;
00753 };
00754 
00756 bool operator!=(const Node& x, const Node& y)
00757 {
00758    return x.name != y.name;
00759 }
00760 
00762 bool operator<(const Node& x, const Node& y)
00763 {
00764    return x.name < y.name;
00765 }
00766 
00768 Node INVALID_NODE("", ~0);
00769 
00771 class ServiceDependencyGraph
00772 {
00773 public:
00774    // returns false if serviceName has already been inserted, true otherwise
00775    bool addNode(const String& serviceName, size_t index);
00776    // returns false if serviceName already has a dependency on dependentServiceName, true otherwise
00777    // precondition: a node for serviceName has already been added via addNode()
00778    bool addDependency(const String& serviceName, const String& dependentServiceName);
00779    Node findIndependentNode() const;
00780    void removeNode(const String& serviceName);
00781    bool empty() const;
00782    Array<Node> getNodes() const;
00783 
00784 private:
00785    typedef std::map<Node, std::set<String> > deps_t;
00786    deps_t m_deps;
00787 };
00788 
00790 bool
00791 ServiceDependencyGraph::addNode(const String& serviceName, size_t index)
00792 {
00793    return m_deps.insert(std::make_pair(Node(serviceName, index), deps_t::mapped_type())).second;
00794 }
00795 
00797 bool
00798 ServiceDependencyGraph::addDependency(const String& serviceName, const String& dependentServiceName)
00799 {
00800    return m_deps.find(serviceName)->second.insert(dependentServiceName).second;
00801 }
00802 
00804 Node
00805 ServiceDependencyGraph::findIndependentNode() const
00806 {
00807    for (deps_t::const_iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
00808    {
00809       if (nodeiter->second.empty())
00810       {
00811          return nodeiter->first;
00812       }
00813    }
00814    
00815    // didn't find any :-(
00816    return INVALID_NODE;
00817 }
00818 
00820 void
00821 ServiceDependencyGraph::removeNode(const String& serviceName)
00822 {
00823    // remove it from all dependency lists
00824    for (deps_t::iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
00825    {
00826       nodeiter->second.erase(serviceName);
00827    }
00828    m_deps.erase(serviceName);
00829 }
00830 
00832 bool
00833 ServiceDependencyGraph::empty() const
00834 {
00835    return m_deps.empty();
00836 }
00837 
00839 Array<Node>
00840 ServiceDependencyGraph::getNodes() const
00841 {
00842    Array<Node> rv;
00843    rv.reserve(m_deps.size());
00844    for (deps_t::const_iterator nodeiter(m_deps.begin()); nodeiter != m_deps.end(); ++nodeiter)
00845    {
00846       rv.push_back(nodeiter->first);
00847    }
00848    return rv;
00849 }
00850 
00851 } // end anonymous namespace
00852 
00854 void
00855 EmbeddedCIMOMEnvironment::_sortServicesForDependencies()
00856 {
00857    // All services can specify a name and dependencies. If a service has an empty name, it can't be specified
00858    // as a dependency, and our algorithm requires that each service has a name, so if any have an empty name,
00859    // they'll just be put at the beginning of the list.
00860 
00861    // We need to make sure that a service is initialized before any other services which depend on it.
00862    // The depedencies reported by the services make a graph.  If it's not a DAG (i.e. contains cycles), we
00863    // can't turn it into a list of what to do, and we'll detect that and throw an exception. Doing a topological
00864    // sort on the graph will yield the order we need.
00865    //
00866    // The process is quite simple conceptually:
00867    // while (the graph has a node with no antecedents)
00868    //    remove one such node from the graph and add it to the list
00869    //
00870    // if (the graph is not empty)
00871    //    the graph contains a cycle
00872    // else
00873    //    success
00874    
00875    Array<ServiceIFCRef> sortedServices;
00876 
00877    // first build the graph
00878    ServiceDependencyGraph depGraph;
00879    // step 1 insert all the nodes and handle the no-names.
00880    for (size_t i = 0; i < m_services.size(); ++i)
00881    {
00882       String name = m_services[i]->getName();
00883       if (name == "")
00884       {
00885          // no name == no depedency tracking, just do it at the beginning.
00886          sortedServices.push_back(m_services[i]);
00887          OW_LOG_DEBUG(m_Logger, "Found service with no name, adding to sortedServices");
00888       }
00889       else
00890       {
00891          OW_LOG_DEBUG(m_Logger, Format("Adding node for service %1", name));
00892          if (!depGraph.addNode(name, i))
00893          {
00894             OW_THROW(EmbeddedCIMOMEnvironmentException, Format("Invalid: 2 services with the same name: %1", name).c_str());
00895          }
00896          
00897       }
00898    }
00899 
00900    // step 2 insert all the dependencies
00901    for (size_t i = 0; i < m_services.size(); ++i)
00902    {
00903       String name = m_services[i]->getName();
00904       if (name != "")
00905       {
00906          StringArray deps(m_services[i]->getDependencies());
00907          for (size_t j = 0; j < deps.size(); ++j)
00908          {
00909             OW_LOG_DEBUG(m_Logger, Format("Adding dependency for service %1->%2", name, deps[j]));
00910             if (!depGraph.addDependency(name, deps[j]))
00911             {
00912                OW_THROW(EmbeddedCIMOMEnvironmentException, Format("Invalid: service %1 has duplicate dependencies: %2", name, deps[j]).c_str());
00913             }
00914          }
00915 
00916          // these are just the opposite direction than the dependencies
00917          StringArray dependentServices(m_services[i]->getDependentServices());
00918          for (size_t j = 0; j < dependentServices.size(); ++j)
00919          {
00920             OW_LOG_DEBUG(m_Logger, Format("Adding dependency for service %1->%2", dependentServices[j], name));
00921             if (!depGraph.addDependency(dependentServices[j], name))
00922             {
00923                OW_THROW(EmbeddedCIMOMEnvironmentException, Format("Invalid: service %1 has duplicate dependencies: %2", dependentServices[j], name).c_str());
00924             }
00925          }
00926       }
00927    }
00928 
00929    // now do the topological sort
00930    Node curNode = depGraph.findIndependentNode();
00931    while (curNode != INVALID_NODE)
00932    {
00933       OW_LOG_DEBUG(m_Logger, Format("Found service with satisfied dependencies: %1", curNode.name));
00934       sortedServices.push_back(m_services[curNode.index]);
00935       depGraph.removeNode(curNode.name);
00936       curNode = depGraph.findIndependentNode();
00937    }
00938 
00939    if (!depGraph.empty())
00940    {
00941       OW_LOG_FATAL_ERROR(m_Logger, "Service dependency graph contains a cycle:");
00942       Array<Node> nodes(depGraph.getNodes());
00943       for (size_t i = 0; i < nodes.size(); ++i)
00944       {
00945          OW_LOG_FATAL_ERROR(m_Logger, Format("Service: %1", nodes[i].name));
00946       }
00947       OW_THROW(EmbeddedCIMOMEnvironmentException, "Service dependency graph contains a cycle");
00948    }
00949 
00950    m_services = sortedServices;
00951 }
00952 
00953 } // end namespace OW_NAMESPACE
00954 

Generated on Thu Feb 9 08:47:58 2006 for openwbem by  doxygen 1.4.6