OW_CIMRepository2.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2002 Center 7, 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 Center 7 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 Center 7, 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 #include "OW_config.h"
00031 #include "OW_CIMRepository2.hpp"
00032 #include "OW_FileSystem.hpp"
00033 #include "OW_CIMValueCast.hpp"
00034 #include "OW_CIMOMHandleIFC.hpp"
00035 #include "OW_ConfigOpts.hpp"
00036 #include "OW_Format.hpp"
00037 #include "OW_WQLIFC.hpp"
00038 #include "OW_Assertion.hpp"
00039 #include "OW_IOException.hpp"
00040 #include "OW_CIMParamValue.hpp"
00041 #include "OW_ConfigOpts.hpp"
00042 #include "OW_Map.hpp"
00043 #include "OW_CIMQualifierType.hpp"
00044 #include "OW_CIMClass.hpp"
00045 #include "OW_CIMInstance.hpp"
00046 #include "OW_CIMProperty.hpp"
00047 #include "OW_CIMValue.hpp"
00048 #include "OW_CIMQualifier.hpp"
00049 #include "OW_CIMObjectPath.hpp"
00050 #include "OW_Logger.hpp"
00051 #include "OW_dbUtils.hpp"
00052 
00053 namespace OW_NAMESPACE
00054 {
00055 
00056 OW_DEFINE_EXCEPTION(CIMRepository2);
00057 
00058 using namespace WBEMFlags;
00059 
00060 
00062 namespace
00063 {
00064 LoggerRef g_logger;
00065 void dbErrorCallback(const char *errpfx, char *msg)
00066 {
00067    // have to use the global here since we can't pass in any sort of handle into db :-(
00068    if (g_logger)
00069    {
00070       OW_LOG_ERROR(g_logger, msg);
00071    }
00072 }
00073 }
00074 
00076 CIMRepository2::CIMRepository2(ServiceEnvironmentIFCRef env)
00077    : RepositoryIFC()
00078    , m_iStore(env)
00079    , m_mStore(env)
00080 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00081    , m_classAssocDb(env)
00082    , m_instAssocDb(env)
00083 #endif
00084    , m_env(env)
00085    , m_checkReferentialIntegrity(false)
00086    , m_dbenv(0)
00087 {
00088    g_logger = m_env->getLogger(COMPONENT_NAME);
00089 
00090    if (m_env->getConfigItem(ConfigOpts::CHECK_REFERENTIAL_INTEGRITY_opt,
00091       OW_DEFAULT_CHECK_REFERENTIAL_INTEGRITY).equalsIgnoreCase("true"))
00092    {
00093       m_checkReferentialIntegrity = true;
00094    }
00095 
00096    OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 initializing with libdb version: %1", ::db_version(0, 0, 0)));
00097 
00098 }
00100 CIMRepository2::~CIMRepository2()
00101 {
00102    try
00103    {
00104       close();
00105    }
00106    catch (...)
00107    {
00108       // don't let exceptions escape
00109    }
00110 }
00111 
00113 namespace
00114 {
00115 class DBTransactionScope
00116 {
00117 public:
00118    DBTransactionScope(::DB_ENV* env)
00119       : m_tid(0)
00120    {
00121       OW_ASSERT(env != 0);
00122       int ret = env->txn_begin(env, 0, &m_tid, 0);
00123       dbUtils::checkReturn(ret, "txn_begin");
00124    }
00125    ~DBTransactionScope()
00126    {
00127       if (m_tid != 0)
00128       {
00129          try
00130          {
00131             abort();
00132          }
00133          catch (...)
00134          {
00135             // can't let exceptions escape
00136          }
00137       }
00138    }
00139    void commit()
00140    {
00141       OW_ASSERT(m_tid != 0);
00142       int ret = m_tid->commit(m_tid, 0);
00143       dbUtils::checkReturn(ret, "txn_commit");
00144       m_tid = 0;
00145    }
00146    void abort()
00147    {
00148       OW_ASSERT(m_tid != 0);
00149       int ret = m_tid->abort(m_tid);
00150       dbUtils::checkReturn(ret, "txn_abort");
00151       m_tid = 0;
00152    }
00153 
00154    operator ::DB_TXN*()
00155    {
00156       return m_tid;
00157    }
00158 
00159 private:
00160    ::DB_TXN* m_tid;
00161 };
00162 } // end unnamed namespace
00163 
00165 void
00166 CIMRepository2::open(const String& path)
00167 {
00168    FileSystem::makeDirectory(path, 0700);
00169    if (!FileSystem::exists(path))
00170    {
00171       String msg("failed to create directory: " );
00172       msg += path;
00173       OW_THROW(IOException, msg.c_str());
00174    }
00175    else
00176    {
00177       if (!FileSystem::canWrite(path))
00178       {
00179          String msg("don't have write access to directory: ");
00180          msg += path;
00181          OW_THROW(IOException, msg.c_str());
00182       }
00183    }
00184    String fname = path;
00185    if (!fname.endsWith(String(OW_FILENAME_SEPARATOR)))
00186    {
00187       fname += OW_FILENAME_SEPARATOR;
00188    }
00189    
00190    // Create a db environment object and initialize it for error
00191    // reporting.
00192    int ret;
00193    if ((ret = ::db_env_create(&m_dbenv, 0)) != 0)
00194    {
00195       OW_THROW(CIMRepository2Exception, format("::db_env_create() failed: %1(%2)", ret, ::db_strerror(ret)).c_str());
00196    }
00197    m_dbenv->set_errcall(m_dbenv, dbErrorCallback);
00198    m_dbenv->set_errpfx(m_dbenv, "CIMRepository2");
00199 
00200    // We want to specify the shared memory buffer pool cachesize,
00201    // but everything else is the default.
00202    const int size = 64 * 1024;
00203    if ((ret = m_dbenv->set_cachesize(m_dbenv, 0, size, 0)) != 0)
00204    {
00205       m_dbenv->close(m_dbenv, 0);
00206       OW_THROW(CIMRepository2Exception, format("m_dbenv->set_cachesize() failed: %1(%2)", ret, ::db_strerror(ret)).c_str());
00207    }
00208 
00209 #ifdef OW_DEBUG
00210    m_dbenv->set_verbose(m_dbenv,DB_VERB_CHKPOINT | DB_VERB_DEADLOCK | DB_VERB_RECOVERY | DB_VERB_REPLICATION | DB_VERB_WAITSFOR, 1);
00211 #endif
00212 
00213 
00214    // Open the db environment with full transactional support.
00215    // DB_CREATE creates the db env if this is the first time we're running.  It's also required if DB_RECOVER is specified.
00216    // DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN initializes the sub-systems we need for transactions.
00217    // DB_PRIVATE is used since we (currently) only access the db from the cimom.  Recovery has to run single-threaded and we don't have any way of
00218    // ensuring that if multiple processes are involved.  If the cimom is changed to use a fork() model this should be changed.
00219    // DB_THREAD since we are multi-threaded.  This shouldn't be removed if the cimom is changed to fork() for each connection unless all threads are removed.
00220    // DB_RECOVER replays the transaction logs and will clean up the db if the cimom didn't correctly shut down previously.
00221    ret = m_dbenv->open(m_dbenv, fname.c_str(),
00222       DB_CREATE |
00223       DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN |
00224       DB_PRIVATE |
00225       DB_THREAD |
00226       DB_RECOVER,
00227       0600);
00228    dbUtils::checkReturn(ret, "m_dbenv->open");
00229 
00230    // opens happen in the context of a transaction
00231    DBTransactionScope tid(m_dbenv);
00232    m_iStore.open(m_dbenv, tid);
00233 
00234    m_mStore.open(m_dbenv, tid);
00235 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00236    m_classAssocDb.open("classassoc", m_dbenv, tid);
00237    m_instAssocDb.open("instanceassoc", m_dbenv, tid);
00238 #endif
00239    tid.commit();
00240 }
00242 void
00243 CIMRepository2::close()
00244 {
00245    m_iStore.close();
00246    m_mStore.close();
00247 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00248    m_classAssocDb.close();
00249    m_instAssocDb.close();
00250 #endif
00251    if (m_dbenv)
00252    {
00253       m_dbenv->close(m_dbenv, 0);
00254       m_dbenv = 0;
00255    }
00256 }
00257 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00258 
00259 void
00260 CIMRepository2::createNameSpace(const String& ns,
00261    OperationContext& context)
00262 {
00263    m_mStore.createNameSpace(ns, context);
00264 
00265    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00266    {
00267       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 created namespace: %1", ns));
00268    }
00269 }
00271 void
00272 CIMRepository2::deleteNameSpace(const String& ns,
00273    OperationContext& context)
00274 {
00275    m_mStore.deleteNameSpace(ns, context);
00276    
00277    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00278    {
00279       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted namespace: %1", ns));
00280    }
00281 }
00282 #endif
00283 
00284 void
00285 CIMRepository2::enumNameSpace(StringResultHandlerIFC& result,
00286    OperationContext& context)
00287 {
00288    m_mStore.enumNameSpace(result, context);
00289    
00290    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00291    {
00292       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), "CIMRepository2 enumerated namespaces");
00293    }
00294 }
00296 CIMQualifierType
00297 CIMRepository2::getQualifierType(const String& ns,
00298    const String& qualifierName,
00299    OperationContext&)
00300 {
00301    CIMQualifierType rv = m_mStore.getQualifierType(ns, qualifierName);
00302    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00303    {
00304       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 getting qualifier type: %1",
00305          CIMObjectPath(qualifierName,ns).toString()));
00306    }
00307    return rv;
00308 }
00309 #ifndef OW_DISABLE_QUALIFIER_DECLARATION
00310 
00311 void
00312 CIMRepository2::enumQualifierTypes(
00313    const String& ns,
00314    CIMQualifierTypeResultHandlerIFC& result,
00315    OperationContext&)
00316 {
00317    m_mStore.enumQualifierTypes(ns, result);
00318    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00319    {
00320       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated qualifiers in namespace: %1", ns));
00321    }
00322 }
00324 void
00325 CIMRepository2::deleteQualifierType(const String& ns, const String& qualName,
00326    OperationContext&)
00327 {
00328    // TODO: What happens if the qualifier is being used???
00329    if (!m_mStore.deleteQualifierType(ns, qualName))
00330    {
00331       if (m_mStore.nameSpaceExists(ns))
00332       {
00333          OW_THROWCIMMSG(CIMException::NOT_FOUND,
00334             String(ns + "/" + qualName).c_str());
00335       }
00336       else
00337       {
00338          OW_THROWCIMMSG(CIMException::INVALID_NAMESPACE,
00339             String(ns + "/" + qualName).c_str());
00340       }
00341    }
00342    
00343    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00344    {
00345       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted qualifier type: %1 in namespace: %2", qualName, ns));
00346    }
00347 }
00349 void
00350 CIMRepository2::setQualifierType(
00351    const String& ns,
00352    const CIMQualifierType& qt, OperationContext&)
00353 {
00354    m_mStore.setQualifierType(ns, qt);
00355    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00356    {
00357       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 set qualifier type: %1 in "
00358          "namespace: %2", qt.toString(), ns));
00359    }
00360 }
00361 #endif // #ifndef OW_DISABLE_QUALIFIER_DECLARATION
00362 
00363 CIMClass
00364 CIMRepository2::getClass(
00365    const String& ns, const String& className,
00366    ELocalOnlyFlag localOnly, EIncludeQualifiersFlag includeQualifiers,
00367    EIncludeClassOriginFlag includeClassOrigin, const StringArray* propertyList,
00368    OperationContext&)
00369 {
00370    CIMClass theClass(CIMNULL);
00371    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className,
00372       localOnly, includeQualifiers, includeClassOrigin, propertyList,
00373       theClass);
00374    checkGetClassRvalAndThrow(rval, ns, className);
00375    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00376    {
00377       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 got class: %1 from "
00378          "namespace: %2", theClass.getName(), ns));
00379    }
00380    return theClass;
00381 }
00383 CIMClass
00384 CIMRepository2::_getClass(const String& ns, const String& className)
00385 {
00386    CIMClass theClass(CIMNULL);
00387    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0, theClass);
00388    checkGetClassRvalAndThrow(rval, ns, className);
00389    return theClass;
00390 }
00392 CIMClass
00393 CIMRepository2::_instGetClass(const String& ns, const String& className)
00394 {
00395    CIMClass theClass(CIMNULL);
00396    CIMException::ErrNoType rval = m_mStore.getCIMClass(ns, className, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, 0, theClass);
00397    checkGetClassRvalAndThrowInst(rval, ns, className);
00398    return theClass;
00399 }
00400 #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00401 
00402 namespace
00403 {
00404    class CIMClassDeleter : public CIMClassResultHandlerIFC
00405    {
00406    public:
00407       CIMClassDeleter(MetaRepository2& mr, const String& ns_,
00408          InstanceRepository2& mi
00409 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00410          , AssocDb2& m_assocDb_
00411 #endif
00412          )
00413       : m_mStore(mr)
00414       , ns(ns_)
00415       , m_iStore(mi)
00416 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00417       , m_assocDb(m_assocDb_)
00418 #endif
00419       {}
00420    protected:
00421       virtual void doHandle(const CIMClass &c)
00422       {
00423          String cname = c.getName();
00424          // TODO: this doesn't work quite right. Fix deleteInstance to also delete
00425          // associations, then we could just call enumInstances and then
00426          // deleteInstance for all instances.
00427          // delete any instances of the class
00428          //m_iStore.deleteClass(ns, cname);
00429 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00430          // remove class from association index
00431          if (c.isAssociation())
00432          {
00433             m_assocDb.deleteEntries(ns,c);
00434          }
00435 #endif
00436          if (!m_mStore.deleteClass(ns, cname))
00437          {
00438             OW_THROWCIM(CIMException::NOT_FOUND);
00439          }
00440       }
00441    private:
00442       MetaRepository2& m_mStore;
00443       const String& ns;
00444       InstanceRepository2& m_iStore;
00445 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00446       AssocDb2& m_assocDb;
00447 #endif
00448    };
00449 }
00451 CIMClass
00452 CIMRepository2::deleteClass(const String& ns, const String& className,
00453    OperationContext& acl)
00454 {
00455    CIMClass cc = _getClass(ns, className);
00456    OW_ASSERT(cc);
00457    // TODO: delete associations to the instances we delete
00458    CIMClassDeleter ccd(m_mStore, ns, m_iStore
00459 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00460       , m_classAssocDb
00461 #endif
00462       );
00463    this->enumClasses(ns, className, ccd,
00464       E_DEEP, E_LOCAL_ONLY,
00465       E_EXCLUDE_QUALIFIERS,
00466       E_EXCLUDE_CLASS_ORIGIN,
00467       acl);
00468    ccd.handle(cc);
00469    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00470    {
00471       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 deleted class: %1:%2",
00472          ns, className));
00473    }
00474    return cc;
00475 }
00477 void
00478 CIMRepository2::createClass(const String& ns, const CIMClass& cimClass_,
00479    OperationContext&)
00480 {
00481    // m_mStore.createClass modifies cimClass to be consistent with base
00482    // classes, etc.
00483    CIMClass cimClass(cimClass_);
00484    m_mStore.createClass(ns, cimClass);
00485    // we need to re-get the class, so that it will be consistent.  currently
00486    // cimClass only contains "unique" items that are added in the child class.
00487    cimClass = _getClass(ns, cimClass.getName());
00488 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00489    if (cimClass.isAssociation())
00490    {
00491       m_classAssocDb.addEntries(ns,cimClass);
00492    }
00493 #endif
00494    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00495    {
00496       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("Created class: %1:%2", ns, cimClass.toMOF()));
00497    }
00498 }
00500 CIMClass
00501 CIMRepository2::modifyClass(
00502    const String& ns,
00503    const CIMClass& cc,
00504    OperationContext&)
00505 {
00506    OW_ASSERT(cc);
00507    CIMClass origClass = _getClass(ns, cc.getName());
00508    // TODO: this needs to update the subclasses of the modified class.
00509    //       If that's not possible, then we need to throw a
00510    //       CLASS_HAS_CHILDREN CIMException.
00511    // TODO: Need to update the instances of the class and any subclasses.
00512    //       If that's not possible, then we need to throw a
00513    //       CLASS_HAS_INSTANCES CIMException.
00514    m_mStore.modifyClass(ns, cc);
00515    OW_ASSERT(origClass);
00516    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00517    {
00518       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("Modified class: %1:%2 from %3 to %4", ns,
00519          cc.getName(), origClass.toMOF(), cc.toMOF()));
00520    }
00521    return origClass;
00522 }
00523 #endif // #ifndef OW_DISABLE_SCHEMA_MANIPULATION
00524 
00525 void
00526 CIMRepository2::enumClasses(const String& ns,
00527       const String& className,
00528       CIMClassResultHandlerIFC& result,
00529       EDeepFlag deep, ELocalOnlyFlag localOnly, EIncludeQualifiersFlag includeQualifiers,
00530       EIncludeClassOriginFlag includeClassOrigin, OperationContext&)
00531 {
00532    m_mStore.enumClass(ns, className,
00533       result, deep,
00534       localOnly, includeQualifiers, includeClassOrigin);
00535    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00536    {
00537       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated classes: %1:%2", ns,
00538          className));
00539    }
00540 }
00542 void
00543 CIMRepository2::enumClassNames(
00544    const String& ns,
00545    const String& className,
00546    StringResultHandlerIFC& result,
00547    EDeepFlag deep, OperationContext&)
00548 {
00549    m_mStore.enumClassNames(ns, className, result, deep);
00550    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00551    {
00552       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated class names: %1:%2", ns,
00553          className));
00554    }
00555 }
00557 namespace {
00558 class stringArrayBuilder : public StringResultHandlerIFC
00559 {
00560 public:
00561    stringArrayBuilder(StringArray& result)
00562       : m_result(result)
00563    {}
00564    void doHandle(const String& name)
00565    {
00566       m_result.push_back(name);
00567    }
00568 private:
00569    StringArray& m_result;
00570 };
00571 // utility function
00572 StringArray getClassChildren(MetaRepository2& rep, const String& ns, const String& clsName)
00573 {
00574    StringArray result;
00575    stringArrayBuilder handler(result);
00576    rep.enumClassNames(ns, clsName, handler, E_DEEP);
00577    return result;
00578 }
00579 }
00581 void
00582 CIMRepository2::enumInstanceNames(
00583    const String& ns,
00584    const String& className,
00585    CIMObjectPathResultHandlerIFC& result,
00586    EDeepFlag deep,
00587    OperationContext&)
00588 {
00589    CIMClass theClass = _instGetClass(ns, className);
00590    m_iStore.getInstanceNames(ns, theClass, result);
00591    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00592    {
00593       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated instance names: %1:%2", ns,
00594          className));
00595    }
00596    if (!deep)
00597    {
00598       return;
00599    }
00600    // This code probably won't ever be executed, because CIMServer
00601    // has to do each class at a time because of providers, and will
00602    // thus only call us with deep=false.
00603    // If the situation ever changes, fix and enable the code below.
00604    OW_THROWCIMMSG(CIMException::FAILED, "Internal server error");
00605    // TODO: Switch this to use a callback interface.
00606    /*
00607    StringArray classNames = m_mStore.getClassChildren(ns,
00608       theClass.getName());
00609    for (size_t i = 0; i < classNames.size(); i++)
00610    {
00611       theClass = _instGetClass(ns, classNames[i]);
00612       m_iStore.getInstanceNames(ns, theClass, result);
00613       if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00614       {
00615          OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 enumerated derived instance names: %1:%2", ns,
00616             classNames[i]));
00617       }
00618    }
00619    */
00620 }
00622 namespace {
00623 class instEnumerator : public StringResultHandlerIFC
00624 {
00625 public:
00626    instEnumerator(CIMRepository2& rep_,
00627       const String& ns_,
00628       const CIMClass& theTopClass_,
00629       CIMInstanceResultHandlerIFC& result_,
00630       EDeepFlag deep_,
00631       ELocalOnlyFlag localOnly_,
00632       EIncludeQualifiersFlag includeQualifiers_,
00633       EIncludeClassOriginFlag includeClassOrigin_,
00634       const StringArray* propertyList_)
00635       : rep(rep_)
00636       , ns(ns_)
00637       , theTopClass(theTopClass_)
00638       , result(result_)
00639       , deep(deep_)
00640       , localOnly(localOnly_)
00641       , includeQualifiers(includeQualifiers_)
00642       , includeClassOrigin(includeClassOrigin_)
00643       , propertyList(propertyList_)
00644    {}
00645    void doHandle(const String& className)
00646    {
00647       CIMClass theClass = rep._instGetClass(ns, className);
00648       rep.m_iStore.getCIMInstances(ns, className, theTopClass, theClass, result,
00649          deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00650       if (rep.m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00651       {
00652          OW_LOG_DEBUG(rep.m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 Enumerated derived instances: %1:%2", ns, className));
00653       }
00654    }
00655 private:
00656    CIMRepository2& rep;
00657    const String& ns;
00658    const CIMClass& theTopClass;
00659    CIMInstanceResultHandlerIFC& result;
00660    EDeepFlag deep;
00661    ELocalOnlyFlag localOnly;
00662    EIncludeQualifiersFlag includeQualifiers;
00663    EIncludeClassOriginFlag includeClassOrigin;
00664    const StringArray* propertyList;
00665 };
00666 } // end unnamed namespace
00668 void
00669 CIMRepository2::enumInstances(
00670    const String& ns,
00671    const String& className,
00672    CIMInstanceResultHandlerIFC& result, EDeepFlag deep,
00673    ELocalOnlyFlag localOnly,
00674    EIncludeQualifiersFlag includeQualifiers,
00675    EIncludeClassOriginFlag includeClassOrigin,
00676    const StringArray* propertyList,
00677    EEnumSubclassesFlag enumSubclasses, OperationContext&)
00678 {
00679    // deep means a different thing here than for enumInstanceNames.  See the spec.
00680    CIMClass theTopClass = _instGetClass(ns, className);
00681    m_iStore.getCIMInstances(ns, className, theTopClass, theTopClass, result,
00682       deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00683    
00684    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00685    {
00686       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2 Enumerated instances: %1:%2", ns,
00687          className));
00688    }
00689    if (enumSubclasses)
00690    {
00691       instEnumerator ie(*this, ns, theTopClass, result, deep, localOnly, includeQualifiers, includeClassOrigin, propertyList);
00692       m_mStore.enumClassNames(ns, className, ie, E_DEEP);
00693    }
00694 }
00696 CIMInstance
00697 CIMRepository2::getInstance(
00698    const String& ns,
00699    const CIMObjectPath& instanceName,
00700    ELocalOnlyFlag localOnly,
00701    EIncludeQualifiersFlag includeQualifiers,
00702    EIncludeClassOriginFlag includeClassOrigin,
00703    const StringArray* propertyList, OperationContext& context)
00704 {
00705    return getInstance(ns, instanceName, localOnly, includeQualifiers, includeClassOrigin,
00706       propertyList, NULL, context);
00707 }
00709 CIMInstance
00710 CIMRepository2::getInstance(
00711    const String& ns,
00712    const CIMObjectPath& instanceName,
00713    ELocalOnlyFlag localOnly,
00714    EIncludeQualifiersFlag includeQualifiers, EIncludeClassOriginFlag includeClassOrigin,
00715    const StringArray* propertyList, CIMClass* pOutClass,
00716    OperationContext&)
00717 {
00718    StringArray lpropList;
00719    if (propertyList)
00720    {
00721       lpropList = *propertyList;
00722    }
00723    CIMInstance ci(CIMNULL);
00724    CIMClass cc(_instGetClass(ns, instanceName.getClassName()));
00725    ci = m_iStore.getCIMInstance(ns, instanceName, cc, localOnly,
00726       includeQualifiers, includeClassOrigin, propertyList);
00727    OW_ASSERT(ci);
00728    if (pOutClass)
00729    {
00730       *pOutClass = cc;
00731    }
00732    
00733    return ci;
00734 }
00735 #ifndef OW_DISABLE_INSTANCE_MANIPULATION
00736 
00737 CIMInstance
00738 CIMRepository2::deleteInstance(const String& ns, const CIMObjectPath& cop_,
00739    OperationContext& acl)
00740 {
00741    CIMObjectPath cop(cop_);
00742    cop.setNameSpace(ns);
00743    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00744    {
00745       OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), format("CIMRepository2::deleteInstance.  cop = %1",
00746          cop.toString()));
00747    }
00748    CIMClass theClass(CIMNULL);
00749    CIMInstance oldInst = getInstance(ns, cop, E_NOT_LOCAL_ONLY, E_INCLUDE_QUALIFIERS, E_INCLUDE_CLASS_ORIGIN, NULL,
00750       &theClass, acl);
00751 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00752    // Ensure no associations exist for this instance
00753    if (m_instAssocDb.hasAssocEntries(ns, cop))
00754    {
00755       // TODO: Revisit this.  Instead of throwing, it is allowed in the
00756       // spec to to delete the associations that reference the instance.
00757       // See http://dmtf.org/standards/documents/WBEM/DSP200.html
00758       //   2.3.2.4. DeleteInstance
00759       OW_THROWCIMMSG(CIMException::FAILED,
00760          format("Instance %1 has associations", cop.toString()).c_str());
00761    }
00762    // TODO: It would be good to check for Min(1) relationships to the
00763    // instance.
00764    
00765    // If we're deleting an association instance, then remove all
00766    // traces of it in the association database.
00767    if (theClass.isAssociation())
00768    {
00769       m_instAssocDb.deleteEntries(ns, oldInst);
00770    }
00771 #endif
00772    // Delete the instance from the instance repository
00773    m_iStore.deleteInstance(ns, cop, theClass);
00774    OW_ASSERT(oldInst);
00775    return oldInst;
00776 }
00778 CIMObjectPath
00779 CIMRepository2::createInstance(
00780    const String& ns,
00781    const CIMInstance& ci,
00782    OperationContext&)
00783 {
00784    CIMObjectPath rval(ns, ci);
00785    if (m_env->getLogger(COMPONENT_NAME)->getLogLevel() == E_DEBUG_LEVEL)
00786    {
00787       OW_LOG_DEBUG(