OW_CppProviderIFC.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00036 #include "OW_config.h"
00037 #include "OW_CppProviderIFC.hpp"
00038 #include "OW_SharedLibraryException.hpp"
00039 #include "OW_SharedLibraryLoader.hpp"
00040 #include "OW_Format.hpp"
00041 #include "OW_SignalScope.hpp"
00042 #include "OW_ConfigOpts.hpp"
00043 #include "OW_FileSystem.hpp"
00044 #include "OW_CppProxyProvider.hpp"
00045 #include "OW_NoSuchProviderException.hpp"
00046 #include "OW_Assertion.hpp"
00047 #include "OW_IntrusiveCountableBase.hpp"
00048 #include "OW_NonRecursiveMutex.hpp"
00049 #include "OW_NonRecursiveMutexLock.hpp"
00050 #include "OW_Condition.hpp"
00051 #include "OW_ExceptionIds.hpp"
00052 #include "OW_RepositoryIFC.hpp"
00053 
00054 namespace OW_NAMESPACE
00055 {
00056 
00057 OW_DECLARE_EXCEPTION(CppProviderIFC);
00058 OW_DEFINE_EXCEPTION_WITH_ID(CppProviderIFC);
00059 
00060 //#include <setjmp.h>
00061 typedef CppProviderBaseIFC* (*ProviderCreationFunc)();
00062 typedef const char* (*versionFunc_t)();
00063 namespace
00064 {
00065 const String COMPONENT_NAME("ow.provider.cpp.ifc");
00066 
00067 class ProvRegEnv : public ProviderRegistrationEnvironmentIFC
00068 {
00069 public:
00070    ProvRegEnv(const ProviderEnvironmentIFCRef& env)
00071       : ProviderRegistrationEnvironmentIFC()
00072       , m_env(env)
00073    {
00074    }
00075 
00076    virtual ~ProvRegEnv()
00077    {
00078    }
00079 
00080    virtual RepositoryIFCRef getRepository() const
00081    {
00082       return m_env->getRepository();
00083    }
00084 
00085    virtual LoggerRef getLogger(const String& componentName) const
00086    {
00087       return m_env->getLogger(componentName);
00088    }
00089 
00090    virtual String getConfigItem(const String &name, const String& defRetVal="") const
00091    {
00092       return m_env->getConfigItem(name, defRetVal);
00093    }
00094 
00095    virtual StringArray getMultiConfigItem(const String &itemName, 
00096       const StringArray& defRetVal, const char* tokenizeSeparator = 0) const
00097    {
00098       return m_env->getMultiConfigItem(itemName, defRetVal, tokenizeSeparator);
00099    }
00100 
00101    virtual ProviderRegistrationEnvironmentIFCRef clone() const
00102    {
00103       return ProviderRegistrationEnvironmentIFCRef(new ProvRegEnv(m_env));
00104    }
00105 
00106 private:
00107    ProviderEnvironmentIFCRef m_env;
00108 };
00109 
00110 ProviderRegistrationEnvironmentIFCRef
00111 createProvRegEnv(const ProviderEnvironmentIFCRef& env)
00112 {
00113    return ProviderRegistrationEnvironmentIFCRef(new ProvRegEnv(env));
00114 }
00115 
00116 }     // Enf of anonymous namespace
00117 
00118 const char* const CppProviderIFC::CREATIONFUNC = "createProvider";
00119 
00121 class CppProviderIFC::CppProviderInitializationHelper : public IntrusiveCountableBase
00122 {
00123 public:
00124 
00125    explicit CppProviderInitializationHelper(const CppProviderBaseIFCRef& provider)
00126       : m_initialized(false)
00127       , m_initializeFailed(false)
00128       , m_provider(provider)
00129    {
00130 
00131    }
00132 
00133    // returns false if initialization failed
00134    bool waitUntilInitialized() const
00135    {
00136       NonRecursiveMutexLock l(m_initializedGuard);
00137       while (!m_initialized && !m_initializeFailed)
00138       {
00139          m_initializedCond.wait(l);
00140       }
00141       return !m_initializeFailed;
00142    }
00143    
00144    void initialize(const ProviderEnvironmentIFCRef& env)
00145    {
00146       try
00147       {
00148          m_provider->initialize(env);
00149       }
00150       catch (...)
00151       {
00152          NonRecursiveMutexLock l(m_initializedGuard);
00153          m_initializeFailed = true;
00154          m_initializedCond.notifyAll();
00155          throw;
00156       }
00157 
00158       NonRecursiveMutexLock l(m_initializedGuard);
00159       m_initialized = true;
00160       m_initializedCond.notifyAll();
00161    }
00162 
00163    CppProviderBaseIFCRef getProvider() const
00164    {
00165       return m_provider;
00166    }
00167 private:
00168    bool m_initialized;
00169    bool m_initializeFailed;
00170    mutable NonRecursiveMutex m_initializedGuard;
00171    mutable Condition m_initializedCond;
00172    CppProviderBaseIFCRef m_provider;
00173 };
00174 
00176 CppProviderIFC::CppProviderIFC()
00177    : ProviderIFCBaseIFC()
00178    , m_provs()
00179    , m_guard()
00180    , m_noUnloadProviders()
00181    , m_loadDone(false)
00182 {
00183 }
00185 CppProviderIFC::~CppProviderIFC()
00186 {
00187    try
00188    {
00189       ProviderMap::iterator it = m_provs.begin();
00190       while (it != m_provs.end())
00191       {
00192          it->second = 0;
00193          it++;
00194       }
00195    
00196       m_provs.clear();
00197    
00198       for (size_t i = 0; i < m_noUnloadProviders.size(); i++)
00199       {
00200          m_noUnloadProviders[i].setNull();
00201       }
00202    
00203       m_noUnloadProviders.clear();
00204    }
00205    catch (...)
00206    {
00207       // don't let exceptions escape
00208    }
00209 }
00211 void
00212 CppProviderIFC::doInit(const ProviderEnvironmentIFCRef& env,
00213    InstanceProviderInfoArray& i,
00214    SecondaryInstanceProviderInfoArray& si,
00215 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00216    AssociatorProviderInfoArray& a,
00217 #endif
00218    MethodProviderInfoArray& m,
00219    IndicationProviderInfoArray& ind)
00220 {
00221    loadProviders(env, i,
00222       si,
00223 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00224       a,
00225 #endif
00226       m,
00227       ind);
00228 }
00230 InstanceProviderIFCRef
00231 CppProviderIFC::doGetInstanceProvider(const ProviderEnvironmentIFCRef& env,
00232    const char* provIdString)
00233 {
00234    CppProviderBaseIFCRef pProv = getProvider(env, provIdString);
00235    if (pProv)
00236    {
00237       CppInstanceProviderIFC* pIP = pProv->getInstanceProvider();
00238       if (pIP)
00239       {
00240          OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00241             Format("CPPProviderIFC found instance provider %1", provIdString));
00242          CppInstanceProviderIFCRef ipRef(pProv.getLibRef(), pIP);
00243 //       ipRef.useRefCountOf(pProv);
00244          return InstanceProviderIFCRef(new CppInstanceProviderProxy(ipRef));
00245       }
00246       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Provider %1 is not an instance provider",
00247          provIdString));
00248    }
00249    OW_THROW(NoSuchProviderException, provIdString);
00250 }
00252 SecondaryInstanceProviderIFCRef
00253 CppProviderIFC::doGetSecondaryInstanceProvider(const ProviderEnvironmentIFCRef& env,
00254    const char* provIdString)
00255 {
00256    CppProviderBaseIFCRef pProv = getProvider(env, provIdString);
00257    if (pProv)
00258    {
00259       CppSecondaryInstanceProviderIFC* pIP = pProv->getSecondaryInstanceProvider();
00260       if (pIP)
00261       {
00262          OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00263             Format("CPPProviderIFC found secondary instance provider %1", provIdString));
00264          CppSecondaryInstanceProviderIFCRef ipRef(pProv.getLibRef(), pIP);
00265 //       ipRef.useRefCountOf(pProv);
00266          return SecondaryInstanceProviderIFCRef(new CppSecondaryInstanceProviderProxy(ipRef));
00267       }
00268       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Provider %1 is not a secondary instance provider",
00269          provIdString));
00270    }
00271    OW_THROW(NoSuchProviderException, provIdString);
00272 }
00274 IndicationExportProviderIFCRefArray
00275 CppProviderIFC::doGetIndicationExportProviders(const ProviderEnvironmentIFCRef&)
00276 {
00277    IndicationExportProviderIFCRefArray rvra;
00278    for (size_t i = 0; i < m_noUnloadProviders.size(); i++)
00279    {
00280       CppProviderBaseIFCRef pProv = m_noUnloadProviders[i];
00281       CppIndicationExportProviderIFC* pIEP =
00282          pProv->getIndicationExportProvider();
00283       if (pIEP)
00284       {
00285          CppIndicationExportProviderIFCRef iepRef(pProv.getLibRef(), pIEP);
00286 //       iepRef.useRefCountOf(pProv);
00287          rvra.append(
00288             IndicationExportProviderIFCRef(new
00289                CppIndicationExportProviderProxy(iepRef)));
00290       }
00291    }
00292    return rvra;
00293 }
00295 PolledProviderIFCRefArray
00296 CppProviderIFC::doGetPolledProviders(const ProviderEnvironmentIFCRef&)
00297 {
00298    PolledProviderIFCRefArray rvra;
00299    for (size_t i = 0; i < m_noUnloadProviders.size(); i++)
00300    {
00301       CppProviderBaseIFCRef pProv = m_noUnloadProviders[i];
00302       CppPolledProviderIFC* pPP = pProv->getPolledProvider();
00303       if (pPP)
00304       {
00305          CppPolledProviderIFCRef ppRef(pProv.getLibRef(), pPP);
00306 //       ppRef.useRefCountOf(pProv);
00307          rvra.append(
00308             PolledProviderIFCRef(new
00309                CppPolledProviderProxy(ppRef)));
00310       }
00311    }
00312    return rvra;
00313 }
00315 MethodProviderIFCRef
00316 CppProviderIFC::doGetMethodProvider(const ProviderEnvironmentIFCRef& env,
00317    const char* provIdString)
00318 {
00319    CppProviderBaseIFCRef pProv = getProvider(env, provIdString);
00320    if (pProv)
00321    {
00322       CppMethodProviderIFC* pMP = pProv->getMethodProvider();
00323       if (pMP)
00324       {
00325          OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), Format("CPPProviderIFC found method provider %1",
00326             provIdString));
00327          CppMethodProviderIFCRef mpRef(pProv.getLibRef(), pMP);
00328 //       mpRef.useRefCountOf(pProv);
00329          return MethodProviderIFCRef(
00330             new CppMethodProviderProxy(mpRef));
00331       }
00332       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Provider %1 is not a method provider",
00333          provIdString));
00334    }
00335    OW_THROW(NoSuchProviderException, provIdString);
00336 }
00337 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00338 
00339 AssociatorProviderIFCRef
00340 CppProviderIFC::doGetAssociatorProvider(const ProviderEnvironmentIFCRef& env,
00341    const char* provIdString)
00342 {
00343    CppProviderBaseIFCRef pProv = getProvider(env, provIdString);
00344    if (pProv)
00345    {
00346       CppAssociatorProviderIFC* pAP = pProv->getAssociatorProvider();
00347       if (pAP)
00348       {
00349          OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), Format("CPPProviderIFC found associator provider %1",
00350             provIdString));
00351          CppAssociatorProviderIFCRef apRef(pProv.getLibRef(), pAP);
00352 //       apRef.useRefCountOf(pProv);
00353          return AssociatorProviderIFCRef(new
00354             CppAssociatorProviderProxy(apRef));
00355       }
00356       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Provider %1 is not an associator provider",
00357          provIdString));
00358    }
00359    OW_THROW(NoSuchProviderException, provIdString);
00360 }
00361 #endif
00362 
00363 IndicationProviderIFCRef
00364 CppProviderIFC::doGetIndicationProvider(const ProviderEnvironmentIFCRef& env,
00365    const char* provIdString)
00366 {
00367    CppProviderBaseIFCRef pProv = getProvider(env, provIdString);
00368    if (pProv)
00369    {
00370       CppIndicationProviderIFC* pAP = pProv->getIndicationProvider();
00371       if (pAP)
00372       {
00373          OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), Format("CPPProviderIFC found indication provider %1",
00374             provIdString));
00375 
00376          IndicationProviderMap::const_iterator ci = m_indicationProviders.find(provIdString);
00377          if (ci != m_indicationProviders.end())
00378          {
00379             return ci->second;
00380          }
00381 
00382          CppIndicationProviderIFCRef apRef(pProv.getLibRef(), pAP);
00383 //       apRef.useRefCountOf(pProv);
00384          IndicationProviderIFCRef rv(new
00385             CppIndicationProviderProxy(apRef));
00386          
00387          m_indicationProviders.insert(IndicationProviderMap::value_type(provIdString, rv));
00388 
00389          return rv;
00390       }
00391       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Provider %1 is not an indication provider",
00392          provIdString));
00393    }
00394    OW_THROW(NoSuchProviderException, provIdString);
00395 }
00397 void
00398 CppProviderIFC::loadProviders(const ProviderEnvironmentIFCRef& env,
00399    InstanceProviderInfoArray& instanceProviderInfo,
00400    SecondaryInstanceProviderInfoArray& secondaryInstanceProviderInfo,
00401 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00402    AssociatorProviderInfoArray& associatorProviderInfo,
00403 #endif
00404    MethodProviderInfoArray& methodProviderInfo,
00405    IndicationProviderInfoArray& indicationProviderInfo)
00406 {
00407    MutexLock ml(m_guard);
00408    if (m_loadDone)
00409    {
00410       return;
00411    }
00412    m_loadDone = true;
00413 
00414    // Create the Shared library loader
00415 
00416    SharedLibraryLoaderRef ldr =
00417       SharedLibraryLoader::createSharedLibraryLoader();
00418    if (!ldr)
00419    {
00420       const char* msg = "C++ provider ifc failed to get shared lib loader";
00421       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), msg);
00422       OW_THROW(CppProviderIFCException, msg);
00423    }
00424 
00425    StringArray paths = env->getMultiConfigItem(
00426       ConfigOpts::CPPPROVIFC_PROV_LOCATION_opt, 
00427       String(OW_DEFAULT_CPPPROVIFC_PROV_LOCATION).tokenize(OW_PATHNAME_SEPARATOR), 
00428       OW_PATHNAME_SEPARATOR);
00429    for (StringArray::size_type i1 = 0; i1 < paths.size(); i1++)
00430    {
00431       StringArray dirEntries;
00432       if (!FileSystem::getDirectoryContents(paths[i1], dirEntries))
00433       {
00434          String msg(Format("C++ provider ifc failed getting contents of directory: %1", paths[i1]));
00435          OW_LOG_INFO(env->getLogger(COMPONENT_NAME), msg);
00436          continue; 
00437       }
00438       for (size_t i = 0; i < dirEntries.size(); i++)
00439       {
00440          if (!dirEntries[i].endsWith(OW_SHAREDLIB_EXTENSION))
00441          {
00442             continue;
00443          }
00444          String libName = paths[i1];
00445          libName += OW_FILENAME_SEPARATOR;
00446          libName += dirEntries[i];
00447 
00448 #ifdef OW_DARWIN
00449          if (!FileSystem::isLink(libName))
00450          {
00451             continue;
00452          }
00453 #endif // OW_DARWIN
00454    
00455          SharedLibraryRef theLib = ldr->loadSharedLibrary(libName,
00456             env->getLogger(COMPONENT_NAME));
00457          if (!theLib)
00458          {
00459             String msg(Format("C++ provider ifc failed to load library: %1", libName));
00460             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00461             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), msg);
00462             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00463             OW_THROW(CppProviderIFCException, msg.c_str());
00464          }
00465          versionFunc_t versFunc;
00466          if (!theLib->getFunctionPointer("getOWVersion",
00467             versFunc))
00468          {
00469             String msg(Format("C++ provider ifc failed getting function pointer to \"getOWVersion\" from"
00470                " library: %1", libName));
00471             OW_LOG_INFO(env->getLogger(COMPONENT_NAME), msg);
00472             // This isn't treated as a fatal error, since the library isn't an OW library.
00473             // On Windows, providers that link to auxiliary dlls, must have those dlls in the same directory 
00474             // as the provider.
00475             continue;
00476          }
00477          const char* strVer = (*versFunc)();
00478          if (strcmp(strVer, OW_VERSION))
00479          {
00480             String msg(Format("C++ provider ifc got invalid version from provider: %1", strVer));
00481             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00482             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), msg);
00483             msg = Format("C++ provider ifc version: %1  provider version: %2  library: %3",
00484                OW_VERSION, strVer, libName);
00485             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), msg);
00486             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00487             OW_THROW(CppProviderIFCException, msg.c_str());
00488          }
00489          ProviderCreationFunc createProvider;
00490          String creationFuncName = String(CREATIONFUNC) + "NO_ID";
00491          if (!theLib->getFunctionPointer(creationFuncName,
00492             createProvider))
00493          {
00494             // it's not a no-id provider
00495             // try and load it as an id provider
00496             String providerid = dirEntries[i];
00497             // chop off lib and .so
00498             providerid = providerid.substring(3,
00499                providerid.length() - (strlen(OW_SHAREDLIB_EXTENSION) + 3));
00500 
00501             CppProviderBaseIFCRef p = getProvider(env, providerid.c_str(),
00502                dontStoreProvider, dontInitializeProvider);
00503 
00504             if (!p)
00505             {
00506                String msg(Format("C++ provider ifc: Libary %1 does not load", libName));
00507                OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), "****************************************");
00508                OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), msg);
00509                OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), "****************************************");
00510                OW_THROW(CppProviderIFCException, msg.c_str());
00511             }
00512 
00513             // The named provider may also be an indication export or a
00514             // polled provider. If so, we'll store a reference to it in
00515             // the m_noUnloadProviders and we'll skip unload processing on
00516             // it when doUnloadProviders is called. We'll skip this
00517             // processing by checking the persist flag on the provider.
00518             CppPolledProviderIFC* p_polledProv = p->getPolledProvider();
00519             CppIndicationExportProviderIFC* p_indExpProv =
00520                p->getIndicationExportProvider();
00521             if (p_polledProv || p_indExpProv)
00522             {
00523                if (p_indExpProv)
00524                {
00525                   OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00526                      Format("C++ provider ifc loaded indication export provider from lib: %1 - initializing", libName));
00527                }
00528 
00529                if (p_polledProv)
00530                {
00531                   OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00532                      Format("C++ provider ifc loaded polled provider from lib: %1 - initializing", libName));
00533                }
00534                CppProviderInitializationHelperRef p2(new CppProviderInitializationHelper(p));
00535                p2->initialize(env);
00536                p->setPersist(true);
00537                m_noUnloadProviders.append(p);
00538                m_provs[providerid] = p2;
00539             }
00540 
00541             CppInstanceProviderIFC* p_ip = p->getInstanceProvider();
00542             if (p_ip)
00543             {
00544                InstanceProviderInfo info;
00545                info.setProviderName(providerid);
00546                p_ip->getInstanceProviderInfoWithEnv(
00547                   createProvRegEnv(env), info);
00548                instanceProviderInfo.push_back(info);
00549             }
00550 
00551             CppSecondaryInstanceProviderIFC* p_sip =
00552                p->getSecondaryInstanceProvider();
00553 
00554             if (p_sip)
00555             {
00556                SecondaryInstanceProviderInfo info;
00557                info.setProviderName(providerid);
00558                p_sip->getSecondaryInstanceProviderInfoWithEnv(
00559                   createProvRegEnv(env), info);
00560                secondaryInstanceProviderInfo.push_back(info);
00561             }
00562 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00563             CppAssociatorProviderIFC* p_ap = p->getAssociatorProvider();
00564             if (p_ap)
00565             {
00566                AssociatorProviderInfo info;
00567                info.setProviderName(providerid);
00568                p_ap->getAssociatorProviderInfoWithEnv(
00569                   createProvRegEnv(env), info);
00570                associatorProviderInfo.push_back(info);
00571             }
00572 #endif
00573             CppMethodProviderIFC* p_mp = p->getMethodProvider();
00574             if (p_mp)
00575             {
00576                MethodProviderInfo info;
00577                info.setProviderName(providerid);
00578                p_mp->getMethodProviderInfoWithEnv(
00579                   createProvRegEnv(env), info);
00580                methodProviderInfo.push_back(info);
00581             }
00582             CppIndicationProviderIFC* p_indp = p->getIndicationProvider();
00583             if (p_indp)
00584             {
00585                IndicationProviderInfo info;
00586                info.setProviderName(providerid);
00587                p_indp->getIndicationProviderInfoWithEnv(
00588                   createProvRegEnv(env), info);
00589                indicationProviderInfo.push_back(info);
00590             }
00591 
00592             continue;
00593          }
00594 
00595          // If we reach this point, the NO_ID provider factory was used. This
00596          // means that the provider doesn't have an identifier (i.e. doesn't
00597          // do instance, methods, associators and such.
00598          AutoPtr<CppProviderBaseIFC> pProv((*createProvider)());
00599          if (!pProv.get())
00600          {
00601             String msg(Format("C++ provider ifc: Libary %1 - %2 returned null provider", libName, creationFuncName));
00602             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00603             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), msg);
00604             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), "****************************************");
00605             OW_THROW(CppProviderIFCException, msg.c_str());
00606          }
00607          CppPolledProviderIFC* p_itp = pProv->getPolledProvider();
00608          CppIndicationExportProviderIFC* p_iep =
00609             pProv->getIndicationExportProvider();
00610          if (p_itp || p_iep)
00611          {
00612             if (p_iep)
00613             {
00614                OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00615                   Format("C++ provider ifc loaded indication export provider from lib: %1 - initializing", libName));
00616             }
00617             if (p_itp)
00618             {
00619                OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00620                   Format("C++ provider ifc loaded  polled provider from lib: %1 - initializing",
00621                   libName));
00622             }
00623 
00624             pProv->initialize(env);
00625             m_noUnloadProviders.append(CppProviderBaseIFCRef(theLib,
00626                pProv.release()));
00627          }
00628       }
00629    }
00630 }
00631 
00633 //static
00634 CppProviderBaseIFCRef
00635 CppProviderIFC::loadProvider(const String& libName, LoggerRef logger)
00636 {
00637    String provId = libName.substring(libName.lastIndexOf(OW_FILENAME_SEPARATOR)+1);
00638    // chop of lib and .so
00639    provId = provId.substring(3, provId.length() - (strlen(OW_SHAREDLIB_EXTENSION) + 3));
00640 
00641    SharedLibraryLoaderRef ldr = SharedLibraryLoader::createSharedLibraryLoader();
00642    if (!ldr)
00643    {
00644       OW_LOG_ERROR(logger, "C++ provider ifc FAILED to get shared lib loader");
00645       return CppProviderBaseIFCRef();
00646    }
00647 
00648    OW_LOG_DEBUG(logger, Format("CppProviderIFC::loadProvider loading library: %1", libName));
00649 
00650    SharedLibraryRef theLib = ldr->loadSharedLibrary(libName, logger);
00651 
00652    versionFunc_t versFunc;
00653    if (!theLib->getFunctionPointer("getOWVersion", versFunc))
00654    {
00655       OW_LOG_ERROR(logger, Format("C++ provider ifc failed getting function pointer to \"getOWVersion\" from library %1.", libName));
00656       return CppProviderBaseIFCRef();
00657    }
00658    const char* strVer = (*versFunc)();
00659    if (strcmp(strVer, OW_VERSION))
00660    {
00661       OW_LOG_ERROR(logger, "C++ provider ifc got invalid version from provider");
00662       OW_LOG_ERROR(logger, Format("C++ provider ifc version: %1  provider version: %2  library: %3",
00663                OW_VERSION, strVer, libName));
00664       return CppProviderBaseIFCRef();
00665    }
00666 
00667    ProviderCreationFunc createProvider;
00668    String creationFuncName = String(CREATIONFUNC) + provId;
00669    if (!theLib->getFunctionPointer(creationFuncName, createProvider))
00670    {
00671       OW_LOG_ERROR(logger, Format("C++ provider ifc: Libary %1 does not contain %2 function.",
00672          libName, creationFuncName));
00673       return CppProviderBaseIFCRef();
00674    }
00675 
00676    CppProviderBaseIFC* pProv = (*createProvider)();
00677 
00678    if (!pProv)
00679    {
00680       OW_LOG_ERROR(logger, Format("C++ provider ifc: Libary %1 -"
00681          " %2 returned null provider. Not loaded.", libName, creationFuncName));
00682       return CppProviderBaseIFCRef();
00683    }
00684 
00685    CppProviderBaseIFCRef rval(theLib, pProv);
00686 
00687    OW_LOG_DEBUG(logger, Format("C++ provider ifc successfully loaded library %1 for provider %2", libName, provId));
00688 
00689    return rval;
00690 }
00691 
00693 CppProviderBaseIFCRef
00694 CppProviderIFC::getProvider(
00695    const ProviderEnvironmentIFCRef& env, const char* provIdString,
00696    StoreProviderFlag storeP, InitializeProviderFlag initP)
00697 {
00698    OW_ASSERT((initP == initializeProvider && storeP == storeProvider) || (initP == dontInitializeProvider && storeP == dontStoreProvider));
00699 
00700    MutexLock ml(m_guard);
00701 
00702    String provId(provIdString);
00703    ProviderMap::iterator it = m_provs.find(provId);
00704    if (it != m_provs.end())
00705    {
00706       // make a copy in case the map gets modified when we unlock m_guard
00707       CppProviderInitializationHelperRef prov(it->second);
00708       // do this to prevent a deadlock
00709       ml.release();
00710 
00711       // another thread may be initializing the provider, wait until it's done.
00712       if (prov->waitUntilInitialized())
00713       {
00714          return prov->getProvider();
00715       }
00716       else
00717       {
00718          // initialization failed, it's now out of the map.
00719          return CppProviderBaseIFCRef();
00720       }
00721    }
00722 
00723    String libName;
00724    CppProviderBaseIFCRef rval;
00725 
00726    StringArray paths = env->getMultiConfigItem(
00727       ConfigOpts::CPPPROVIFC_PROV_LOCATION_opt, 
00728       String(OW_DEFAULT_CPPPROVIFC_PROV_LOCATION).tokenize(OW_PATHNAME_SEPARATOR), 
00729       OW_PATHNAME_SEPARATOR);
00730    for (StringArray::size_type i = 0; i < paths.size(); i++)
00731    {
00732       libName = paths[i];
00733       libName += OW_FILENAME_SEPARATOR;
00734       libName += "lib";
00735       libName += provId;
00736       libName += OW_SHAREDLIB_EXTENSION;
00737 
00738       if (!FileSystem::exists(libName))
00739       {
00740          continue;
00741       }
00742 
00743       rval = loadProvider(libName, env->getLogger(COMPONENT_NAME));
00744 
00745       if (rval)
00746       {
00747          break;
00748       }
00749 
00750    }
00751 
00752    if (!rval)
00753    {
00754       OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), 
00755          Format("C++ provider ifc failed to load library: %1 for provider id %2.", libName, provId));
00756       return rval;
00757    }
00758 
00759    if (initP == initializeProvider && storeP == storeProvider)
00760    {
00761       CppProviderInitializationHelperRef provInitHelper(new CppProviderInitializationHelper(rval));
00762 
00763       m_provs[provId] = provInitHelper;
00764       
00765       // now it's in the map, we can unlock the mutex protecting the map
00766       ml.release();
00767 
00768       OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00769          Format("C++ provider ifc calling initialize for provider %1", provId));
00770 
00771       try
00772       {
00773          provInitHelper->initialize(env); // Let provider initialize itself
00774       }
00775       catch (...)
00776       {
00777          // provider initialization failed, we need to take it out of the map
00778          MutexLock lock(m_guard);
00779          m_provs.erase(provId);
00780          throw;
00781       }
00782 
00783       OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00784          Format("C++ provider ifc: provider %1 loaded and initialized", provId));
00785 
00786    }
00787    else
00788    {
00789       OW_LOG_DEBUG(env->getLogger(COMPONENT_NAME), 
00790          Format("C++ provider ifc: provider %1 loaded but not initialized", provId));
00791    }
00792 
00793    return rval;
00794 }
00796 void
00797 CppProviderIFC::doUnloadProviders(const ProviderEnvironmentIFCRef& env)
00798 {
00799    String timeWindow = env->getConfigItem(ConfigOpts::CPPPROVIFC_PROV_TTL_opt, OW_DEFAULT_CPPPROVIFC_PROV_TTL);
00800    Int32 iTimeWindow;
00801    try
00802    {
00803       iTimeWindow = timeWindow.toInt32();
00804    }
00805    catch (const StringConversionException&)
00806    {
00807       iTimeWindow = String(OW_DEFAULT_CPPPROVIFC_PROV_TTL).toInt32();
00808    }
00809    if (iTimeWindow < 0)
00810    {
00811       return;
00812    }
00813    DateTime dt;
00814    dt.setToCurrent();
00815    MutexLock l(m_guard);
00816    for (ProviderMap::iterator iter = m_provs.begin();
00817         iter != m_provs.end();)
00818    {
00819       // If this is not a persistent provider, see if we can unload it.
00820       if (!iter->second->getProvider()->getPersist())
00821       {
00822          DateTime provDt = iter->second->getProvider()->getLastAccessTime();
00823          provDt.addMinutes(iTimeWindow);
00824          if (provDt < dt && iter->second->getProvider()->canUnload())
00825          {
00826             OW_LOG_INFO(env->getLogger(COMPONENT_NAME), Format("Unloading Provider %1",
00827                iter->first));
00828             iter->second = 0;
00829             m_provs.erase(iter++);
00830             continue;
00831          }
00832       }
00833 
00834       ++iter;
00835    }
00836 }
00837 
00838 void CppProviderIFC::doShuttingDown(const ProviderEnvironmentIFCRef& env)
00839 {
00840    // Need to lock m_guard while accessing m_provs, but we can't leave the mutex locked
00841    // while calling shuttingDown(), since that might cause a deadlock, so make a copy.
00842    MutexLock l(m_guard);
00843    ProviderMap provsCopy(m_provs);
00844    LoadedProviderArray noUnloadProvidersCopy(m_noUnloadProviders);
00845    l.release();
00846 
00847    ProviderMap::iterator it, itend = provsCopy.end();
00848    for (it = provsCopy.begin(); it != itend; ++it)
00849    {
00850       try
00851       {
00852          it->second->getProvider()->shuttingDown(env);
00853       }
00854       catch (Exception& e)
00855       {
00856          OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Caught exception while calling shuttingDown() on provider: %1", e));
00857       }
00858    }
00859 
00860    // call shuttingDown() for any providers in noUnloadProviders which *aren't* in provsCopy,
00861    // so we don't call it twice for one provider
00862    for (LoadedProviderArray::iterator curProv = noUnloadProvidersCopy.begin(); curProv != noUnloadProvidersCopy.end(); ++curProv)
00863    {
00864       bool found(false);
00865 
00866       for (it = provsCopy.begin(); it != itend; ++it)
00867       {
00868          if (it->second->getProvider() == *curProv)
00869          {
00870             found = true;
00871             break;
00872          }
00873       }
00874 
00875       if (!found)
00876       {
00877          try
00878          {
00879             (*curProv)->shuttingDown(env);
00880          }
00881          catch (Exception& e)
00882          {
00883             OW_LOG_ERROR(env->getLogger(COMPONENT_NAME), Format("Caught exception while calling shuttingDown() on provider: %1", e));
00884          }
00885       }
00886    }
00887 }
00888 
00889 } // end namespace OW_NAMESPACE
00890 

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