OW_AssocDb.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_AssocDb.hpp"
00038 #include "OW_DataStreams.hpp"
00039 #include "OW_IOException.hpp"
00040 #include "OW_Format.hpp"
00041 #include "OW_AutoPtr.hpp"
00042 #include "OW_CIMObjectPath.hpp"
00043 #include "OW_CIMInstance.hpp"
00044 #include "OW_CIMProperty.hpp"
00045 #include "OW_CIMValue.hpp"
00046 #include "OW_CIMClass.hpp"
00047 #include "OW_BinarySerialization.hpp"
00048 #include "OW_Assertion.hpp"
00049 #include "OW_Logger.hpp"
00050 #include "OW_HDBCommon.hpp"
00051 
00052 #include <cstdio> // for SEEK_END
00053 #include <algorithm> // for std::find and sort
00054 
00055 namespace OW_NAMESPACE
00056 {
00057 
00058 namespace
00059 {
00060    const String COMPONENT_NAME("ow.repository.hdb");
00061 }
00062 
00063 using std::istream;
00064 using std::ostream;
00065 using std::endl;
00067 // Local functions
00068 static UInt32 calcCheckSum(unsigned char* src, Int32 len);
00069 static void writeRecHeader(AssocDbRecHeader& rh, Int32 offset, File& file);
00070 static void readRecHeader(AssocDbRecHeader& rh, Int32 offset, const File& file);
00072 AssocDbEntry::AssocDbEntry(istream& istrm)
00073    : m_objectName(CIMNULL)
00074    , m_offset(-1L)
00075 {
00076    readObject(istrm);
00077 }
00079 AssocDbEntry::AssocDbEntry(const CIMObjectPath& objectName,
00080       const CIMName& role,
00081       const CIMName& resultRole) :
00082    m_objectName(objectName), m_role(role), m_resultRole(resultRole),
00083    m_offset(-1L)
00084 {
00085 }
00087 void
00088 AssocDbEntry::writeObject(ostream& ostrm) const
00089 {
00090    m_objectName.writeObject(ostrm);
00091    m_role.writeObject(ostrm);
00092    m_resultRole.writeObject(ostrm);
00093    BinarySerialization::writeArray(ostrm, m_entries);
00094 }
00096 void
00097 AssocDbEntry::entry::writeObject(ostream& ostrm) const
00098 {
00099    m_assocClass.writeObject(ostrm);
00100    m_resultClass.writeObject(ostrm);
00101    m_associatedObject.writeObject(ostrm);
00102    m_associationPath.writeObject(ostrm);
00103 }
00105 void
00106 AssocDbEntry::readObject(istream& istrm)
00107 {
00108    m_objectName.readObject(istrm);
00109    m_role.readObject(istrm);
00110    m_resultRole.readObject(istrm);
00111    BinarySerialization::readArray(istrm, m_entries);
00112 }
00114 void
00115 AssocDbEntry::entry::readObject(istream& istrm)
00116 {
00117    m_assocClass.readObject(istrm);
00118    m_resultClass.readObject(istrm);
00119    m_associatedObject.readObject(istrm);
00120    m_associationPath.readObject(istrm);
00121 }
00122 namespace
00123 {
00124 
00125 const char NS_SEPARATOR_C(':');
00126 
00128 void
00129 makeClassKey(const String& ns, const String& className, StringBuffer& out)
00130 {
00131    out += ns;
00132    out += NS_SEPARATOR_C;
00133    String lowerClassName(className);
00134    lowerClassName.toLowerCase();
00135    out += lowerClassName;
00136 }
00138 void
00139 makeInstanceKey(const CIMObjectPath& cop, StringBuffer& out)
00140 {
00141    makeClassKey(cop.getNameSpace(), cop.getClassName(), out);
00142    // Get keys from object path
00143    HDBUtilKeyArray kra(cop.getKeys());
00144    kra.toString(out);
00145 }
00146 } // end unnamed namespace
00148 String
00149 AssocDbEntry::makeKey(const CIMObjectPath& objectName, const CIMName& role,
00150    const CIMName& resultRole)
00151 {
00152    StringBuffer key;
00153    if (0)
00154    {
00155       // This is broken, but we need to handle old versions. Unfortunately there is no version field in the assoc db, so we have no way of really knowing
00156       // without going to a lot of work :(
00157       String lowerName = objectName.toString();
00158       lowerName.toLowerCase();
00159       key += lowerName;
00160    }
00161    else
00162    {
00163       if (objectName.isClassPath())
00164       {
00165          makeClassKey(objectName.getNameSpace(), objectName.getClassName(), key);
00166       }
00167       else
00168       {
00169          makeInstanceKey(objectName, key);
00170       }
00171    }
00172 
00173    String lowerRole = role.toString();
00174    lowerRole.toLowerCase();
00175    String lowerResultRole = resultRole.toString();
00176    lowerResultRole.toLowerCase();
00177 
00178    // use # as the separator, because that's not a valid character in an
00179    // object path or any CIM identifier
00180    key += '#';
00181    key += lowerRole;
00182    key += '#';
00183    key += lowerResultRole;
00184    return key.releaseString();
00185 }
00187 String
00188 AssocDbEntry::makeKey() const
00189 {
00190    // use # as the separator, because that's not a valid character in an
00191    // object path or any CIM identifier
00192    return makeKey(m_objectName, m_role, m_resultRole);
00193 }
00195 ostream&
00196 operator << (ostream& ostrm, const AssocDbEntry& arg)
00197 {
00198    ostrm
00199       << "\tobjectName: " << arg.m_objectName.toString() << endl
00200       << "\trole: " << arg.m_role << endl
00201       << "\tresultRole: " << arg.m_resultRole << endl
00202       << "\tkey: " << arg.makeKey() << endl;
00203    return ostrm;
00204 }
00206 AssocDbHandle::AssocDbHandleData::AssocDbHandleData() :
00207    m_pdb(NULL), m_file()
00208 {
00209 }
00211 AssocDbHandle::AssocDbHandleData::AssocDbHandleData(
00212    const AssocDbHandleData& arg) :
00213    IntrusiveCountableBase(arg), m_pdb(arg.m_pdb), m_file(arg.m_file)
00214 {
00215 }
00217 AssocDbHandle::AssocDbHandleData::AssocDbHandleData(AssocDb* pdb,
00218    const File& file) :
00219    m_pdb(pdb), m_file(file)
00220 {
00221 }
00223 AssocDbHandle::AssocDbHandleData::~AssocDbHandleData()
00224 {
00225    try
00226    {
00227       if (m_pdb)
00228       {
00229          m_pdb->decHandleCount();
00230          m_file.close();
00231       }
00232    }
00233    catch (...)
00234    {
00235       // if decHandleCount throws, just ignore it.
00236    }
00237 }
00239 AssocDbHandle::AssocDbHandleData&
00240 AssocDbHandle::AssocDbHandleData::operator= (const AssocDbHandleData& arg)
00241 {
00242    m_pdb = arg.m_pdb;
00243    m_file = arg.m_file;
00244    return *this;
00245 }
00247 void
00248 AssocDbHandle::addEntry(const CIMObjectPath& objectName,
00249       const CIMName& assocClassName, const CIMName& resultClass,
00250       const CIMName& role, const CIMName& resultRole,
00251       const CIMObjectPath& associatedObject,
00252       const CIMObjectPath& assocClassPath)
00253 {
00254    m_pdata->m_pdb->addEntry(objectName,
00255       assocClassName, resultClass,
00256       role, resultRole,
00257       associatedObject,
00258       assocClassPath, *this);
00259 }
00261 bool
00262 AssocDbHandle::hasAssocEntries(const String& ns, const CIMObjectPath& instanceName)
00263 {
00264    CIMObjectPath pathWithNS(instanceName);
00265    pathWithNS.setNameSpace(ns);
00266    String targetObject = pathWithNS.toString();
00267    return (m_pdata->m_pdb->findEntry(targetObject, *this)) ? true : false;
00268 }
00270 void
00271 AssocDbHandle::addEntries(const String& ns, const CIMInstance& assocInstance)
00272 {
00273    addOrDeleteEntries(ns, assocInstance, true);
00274 }
00276 void
00277 AssocDbHandle::deleteEntries(const String& ns, const CIMInstance& assocInstance)
00278 {
00279    addOrDeleteEntries(ns, assocInstance, false);
00280 }
00282 void
00283 AssocDbHandle::addOrDeleteEntries(const String& ns, const CIMInstance& assocInstance, bool add)
00284 {
00285    CIMName assocClass = assocInstance.getClassName();
00286    CIMObjectPath assocPath(assocClass, ns);
00287    assocPath.setKeys(assocInstance);
00288    // search for references
00289    CIMPropertyArray propRa = assocInstance.getProperties();
00290    for (size_t i = 0; i < propRa.size(); i++)
00291    {
00292       CIMValue propValue1 = propRa[i].getValue();
00293       if (propValue1 && propValue1.getType() == CIMDataType::REFERENCE)
00294       {
00295          // found first reference, search for second
00296          for (size_t j = 0; j < propRa.size(); ++j)
00297          {
00298             if (j == i)
00299             {
00300                continue; // don't bother with same ones.
00301             }
00302             CIMValue propValue2 = propRa[j].getValue();
00303             if (propValue2 && propValue2.getType() == CIMDataType::REFERENCE)
00304             {
00305                // found a second reference, now set up the vars we need
00306                // and create index entries.
00307                CIMObjectPath objectName(CIMNULL);
00308                propValue1.get(objectName);
00309                if (objectName.getNameSpace().empty())
00310                {
00311                   objectName.setNameSpace(ns);
00312                }
00313                CIMObjectPath associatedObject(CIMNULL);
00314                propValue2.get(associatedObject);
00315                if (associatedObject.getNameSpace().empty())
00316                {
00317                   objectName.setNameSpace(ns);
00318                }
00319                CIMName resultClass = associatedObject.getClassName();
00320                CIMName role = propRa[i].getName();
00321                CIMName resultRole = propRa[j].getName();
00322                if (add)
00323                {
00324                   addEntry(objectName, assocClass, resultClass,
00325                      role, resultRole, associatedObject, assocPath);
00326                   addEntry(objectName, assocClass, resultClass,
00327                      CIMName(), resultRole, associatedObject, assocPath);
00328                   addEntry(objectName, assocClass, resultClass,
00329                      role, CIMName(), associatedObject, assocPath);
00330                   addEntry(objectName, assocClass, resultClass,
00331                      CIMName(), CIMName(), associatedObject, assocPath);
00332                }
00333                else
00334                {
00335                   deleteEntry(objectName, assocClass, resultClass,
00336                      role, resultRole, associatedObject, assocPath);
00337                   deleteEntry(objectName, assocClass, resultClass,
00338                      CIMName(), resultRole, associatedObject, assocPath);
00339                   deleteEntry(objectName, assocClass, resultClass,
00340                      role, CIMName(), associatedObject, assocPath);
00341                   deleteEntry(objectName, assocClass, resultClass,
00342                      CIMName(), CIMName(), associatedObject, assocPath);
00343                }
00344             }
00345          }
00346       }
00347    }
00348 }
00350 void
00351 AssocDbHandle::addEntries(const String& ns, const CIMClass& assocClass)
00352 {
00353    addOrDeleteEntries(ns, assocClass, true);
00354 }
00356 void
00357 AssocDbHandle::deleteEntries(const String& ns, const CIMClass& assocClass)
00358 {
00359    addOrDeleteEntries(ns, assocClass, false);
00360 }
00362 void
00363 AssocDbHandle::addOrDeleteEntries(const String& ns, const CIMClass& assocClass, bool add)
00364 {
00365    CIMName assocClassName = assocClass.getName();
00366    CIMObjectPath assocClassPath(assocClassName, ns);
00367    // search for references
00368    CIMPropertyArray propRa = assocClass.getAllProperties();
00369    for (size_t i = 0; i < propRa.size(); i++)
00370    {
00371       CIMProperty p1 = propRa[i];
00372       if (p1.getDataType().getType() == CIMDataType::REFERENCE)
00373       {
00374          // found first reference, search for others
00375          for (size_t j = 0; j < propRa.size(); ++j)
00376          {
00377             if (j == i)
00378             {
00379                continue; // don't bother with same ones.
00380             }
00381             CIMProperty p2 = propRa[j];
00382             if (p2.getDataType().getType() == CIMDataType::REFERENCE)
00383             {
00384                // found another reference, now set up the vars we need
00385                // and create index entries.
00386                CIMObjectPath objectName(p1.getDataType().getRefClassName(), ns);
00387                CIMName resultClass = p2.getDataType().getRefClassName();
00388                CIMName role = p1.getName();
00389                CIMName resultRole = p2.getName();
00390                CIMObjectPath associatedObject(resultClass, ns);
00391                if (add)
00392                {
00393                   addEntry(objectName, assocClassName, resultClass,
00394                      role, resultRole, associatedObject, assocClassPath);
00395                   addEntry(objectName, assocClassName, resultClass,
00396                      CIMName(), resultRole, associatedObject, assocClassPath);
00397                   addEntry(objectName, assocClassName, resultClass,
00398                      role, CIMName(), associatedObject, assocClassPath);
00399                   addEntry(objectName, assocClassName, resultClass,
00400                      CIMName(), CIMName(), associatedObject, assocClassPath);
00401                }
00402                else
00403                {
00404                   deleteEntry(objectName, assocClassName, resultClass,
00405                      role, resultRole, associatedObject, assocClassPath);
00406                   deleteEntry(objectName, assocClassName, resultClass,
00407                      CIMName(), resultRole, associatedObject, assocClassPath);
00408                   deleteEntry(objectName, assocClassName, resultClass,
00409                      role, CIMName(), associatedObject, assocClassPath);
00410                   deleteEntry(objectName, assocClassName, resultClass,
00411                      CIMName(), CIMName(), associatedObject, assocClassPath);
00412                }
00413             }
00414          }
00415       }
00416    }
00417 }
00419 void
00420 AssocDbHandle::deleteEntry(const CIMObjectPath& objectName,
00421       const CIMName& assocClassName, const CIMName& resultClass,
00422       const CIMName& role, const CIMName& resultRole,
00423       const CIMObjectPath& associatedObject,
00424       const CIMObjectPath& assocClassPath)
00425 {
00426    m_pdata->m_pdb->deleteEntry(objectName,
00427       assocClassName, resultClass,
00428       role, resultRole,
00429       associatedObject,
00430       assocClassPath, *this);
00431 }
00433 void
00434 AssocDbHandle::getAllEntries(const CIMObjectPath& objectName,
00435       const SortedVectorSet<CIMName>* passocClasses,
00436       const SortedVectorSet<CIMName>* presultClasses,
00437       const CIMName& role,
00438       const CIMName& resultRole,
00439       AssocDbEntryResultHandlerIFC& result)
00440 {
00441    if ((passocClasses && passocClasses->size() == 0)
00442       || presultClasses && presultClasses->size() == 0)
00443    {
00444       return; // one of the filters will reject everything, so don't even bother
00445    }
00446    String key = AssocDbEntry::makeKey(objectName, role, resultRole);
00447    MutexLock l = m_pdata->m_pdb->getDbLock();
00448    AssocDbEntry dbentry = m_pdata->m_pdb->findEntry(key, *this);
00449    if (dbentry)
00450    {
00451       for (size_t i = 0; i < dbentry.m_entries.size(); ++i)
00452       {
00453          AssocDbEntry::entry& e = dbentry.m_entries[i];
00454          if (((passocClasses == 0) || (passocClasses->count(e.m_assocClass) > 0))
00455             && ((presultClasses == 0) || (presultClasses->count(e.m_resultClass) > 0)))
00456          {
00457             result.handle(e);
00458          }
00459       }
00460    }
00461 }
00463 AssocDb::AssocDb()
00464    : m_pIndex(NULL)
00465    , m_hdlCount(0)
00466    , m_opened(false)
00467 {
00468 }
00469 
00471 AssocDb::~AssocDb()
00472 {
00473    try
00474    {
00475       if (m_hdlCount > 0)
00476       {
00477          OW_LOG_DEBUG(m_env->getLogger(COMPONENT_NAME), "*** AssocDb::~AssocDb - STILL OUTSTANDING"
00478             " HANDLES ***");
00479       }
00480       close();
00481    }
00482    catch (...)
00483    {
00484       // logDebug or close could throw.
00485    }
00486 }
00488 void
00489 AssocDb::init(const ServiceEnvironmentIFCRef& env)
00490 {
00491    m_env = env;
00492 }
00494 void
00495 AssocDb::open(const String& fileName)
00496 {
00497    MutexLock l = getDbLock();
00498    if (m_opened)
00499    {
00500       return;
00501    }
00502    m_hdlCount = 0;
00503    m_fileName = fileName;
00504    String fname = m_fileName + ".dat";
00505    createFile();
00506    checkFile();
00507    m_opened = true;
00508 }
00510 bool
00511 AssocDb::createFile()
00512 {
00513    AssocDbHeader b = { OW_ASSOCSIGNATURE, -1L, HDBVERSION };
00514    m_hdrBlock = b;
00515    File f = FileSystem::createFile(m_fileName + ".dat");
00516    if (!f)
00517    {
00518       return false;
00519    }
00520    if (f.write(&m_hdrBlock, sizeof(m_hdrBlock), 0) != sizeof(m_hdrBlock))
00521    {
00522       OW_THROW_ERRNO_MSG(IOException, "Failed to write header of HDB");
00523    }
00524    f.close();
00525    m_pIndex = Index::createIndexObject();
00526    m_pIndex->open(m_fileName.c_str(), Index::E_ALLDUPLICATES);
00527    return true;
00528 }
00530 void
00531 AssocDb::checkFile()
00532 {
00533    File f = FileSystem::openFile(m_fileName + ".dat");
00534    if (!f)
00535    {
00536       OW_THROW_ERRNO_MSG(IOException,
00537          Format("Failed to open file: %1", m_fileName).c_str());
00538    }
00539    size_t sizeRead = f.read(&m_hdrBlock, sizeof(m_hdrBlock), 0);
00540    f.close();
00541    if (sizeRead != sizeof(m_hdrBlock))
00542    {
00543       OW_THROW_ERRNO_MSG(IOException,
00544          Format("Failed to read Assoc DB header from file: %1",
00545             m_fileName).c_str());
00546    }
00547    if (::strncmp(m_hdrBlock.signature, OW_ASSOCSIGNATURE, OW_ASSOCSIGLEN))
00548    {
00549       OW_THROW(IOException,
00550          Format("Invalid Format for Assoc db file: %1", m_fileName).c_str());
00551    }
00552    if (m_hdrBlock.version < MinHDBVERSION || m_hdrBlock.version > HDBVERSION)
00553    {
00554       OW_THROW(HDBException, Format("Invalid version (%1) for file (%2). Expected (%3)", m_hdrBlock.version, m_fileName, HDBVERSION).c_str());
00555    }
00556    m_pIndex = Index::createIndexObject();
00557    m_pIndex->open(m_fileName.c_str(), Index::E_ALLDUPLICATES);
00558 }
00560 void
00561 AssocDb::close()
00562 {
00563    MutexLock l = getDbLock();
00564    if (m_opened)
00565    {
00566       m_pIndex->close();
00567       m_pIndex = NULL;
00568       m_opened = false;
00569    }
00570 }
00572 AssocDbHandle
00573 AssocDb::getHandle()
00574 {
00575    MutexLock l = getDbLock();
00576    File file = FileSystem::openFile(m_fileName + ".dat");
00577    if (!file)
00578    {
00579       OW_THROW_ERRNO_MSG(IOException,
00580          Format("Failed to open file while creating handle: %1",
00581             m_fileName).c_str());
00582    }
00583    m_hdlCount++;
00584    return AssocDbHandle(this, file);
00585 }
00587 void
00588 AssocDb::decHandleCount()
00589 {
00590    MutexLock l = getDbLock();
00591    m_hdlCount--;
00592 }
00594 // PRIVATE - AssocDbHandle uses
00595 AssocDbEntry
00596 AssocDb::findEntry(const String& objectKey, AssocDbHandle& hdl)
00597 {
00598    MutexLock l = getDbLock();
00599    AssocDbEntry dbentry;
00600    IndexEntry ie = m_pIndex->findFirst(objectKey.c_str());
00601    if (ie && ie.key.equals(objectKey))
00602    {
00603       dbentry = readEntry(ie.offset, hdl);
00604    }
00605    return dbentry;
00606 }
00608 // PRIVATE - AssocDbHandle uses
00609 AssocDbEntry
00610 AssocDb::nextEntry(AssocDbHandle& hdl)
00611 {
00612    MutexLock l = getDbLock();
00613    AssocDbEntry dbentry;
00614    IndexEntry ie = m_pIndex->findNext();
00615    if (!ie)
00616    {
00617       return dbentry;
00618    }
00619    return readEntry(ie.offset, hdl);
00620 }
00622 // PRIVATE
00623 AssocDbEntry
00624 AssocDb::readEntry(Int32 offset, AssocDbHandle& hdl)
00625 {
00626    AssocDbEntry dbentry;
00627    AssocDbRecHeader rh;
00628    readRecHeader(rh, offset, hdl.getFile());
00629    AutoPtrVec<unsigned char> bfr(new unsigned char[rh.dataSize]);
00630    if (hdl.getFile().read(bfr.get(), rh.dataSize) != rh.dataSize)
00631    {
00632       OW_THROW_ERRNO_MSG(IOException, "Failed to read data for rec on assoc db");
00633    }
00634    DataIStream istrm(rh.dataSize, bfr.get());
00635    dbentry.readObject(istrm);
00636    dbentry.setOffset(offset);
00637    return dbentry;
00638 }
00640 // PRIVATE - AssocDbHandle uses
00641 void
00642 AssocDb::deleteEntry(const CIMObjectPath& objectName,
00643    const CIMName& assocClassName, const CIMName& resultClass,
00644    const CIMName& role, const CIMName& resultRole,
00645    const CIMObjectPath& associatedObject,
00646    const CIMObjectPath& assocClassPath, AssocDbHandle& hdl)
00647 {
00648    String key = AssocDbEntry::makeKey(objectName, role, resultRole);
00649    AssocDbEntry dbentry;
00650    MutexLock l = getDbLock();
00651    IndexEntry ie = m_pIndex->findFirst(key.c_str());
00652    if (ie)
00653    {
00654       dbentry = readEntry(ie.offset, hdl);
00655       
00656       OW_ASSERT(dbentry.makeKey().equals(key));
00657       AssocDbEntry::entry e;
00658       e.m_assocClass = assocClassName;
00659       e.m_resultClass = resultClass;
00660       e.m_associatedObject = associatedObject;
00661       e.m_associationPath = assocClassPath;
00662       Array<AssocDbEntry::entry>::iterator iter = std::find(dbentry.m_entries.begin(), dbentry.m_entries.end(), e);
00663       OW_ASSERT(iter != dbentry.m_entries.end());
00664       if (iter != dbentry.m_entries.end())
00665       {
00666          dbentry.m_entries.erase(iter);
00667       }
00668       
00669       if (dbentry.m_entries.size() == 0)
00670       {
00671          m_pIndex->remove(key.c_str(), dbentry.getOffset());
00672          addToFreeList(dbentry.getOffset(), hdl);
00673       }
00674       else
00675       {
00676          deleteEntry(dbentry, hdl);
00677          addEntry(dbentry, hdl);
00678       }
00679    }
00680    else
00681    {
00682       // TODO: Log this OW_ASSERT(0 == "AssocDb::deleteEntry failed to find key.  Database may be corrupt");
00683    }
00684 }
00686 // PRIVATE - AssocDbHandle uses
00687 void
00688 AssocDb::deleteEntry(const AssocDbEntry& entry, AssocDbHandle& hdl)
00689 {
00690    MutexLock l = getDbLock();
00691    String key = entry.makeKey();
00692    AssocDbEntry dbentry;
00693    IndexEntry ie = m_pIndex->findFirst(key.c_str());
00694    while (ie)
00695    {
00696       dbentry = readEntry(ie.offset, hdl);
00697       if (!dbentry.makeKey().equals(key))
00698       {
00699          break;
00700       }
00701       if (dbentry == entry)
00702       {
00703          m_pIndex->remove(key.c_str(), dbentry.getOffset());
00704          addToFreeList(dbentry.getOffset(), hdl);
00705          break;
00706       }
00707       ie = m_pIndex->findNext();
00708    }
00709 }
00711 // PRIVATE - AssocDbHandle uses
00712 void
00713 AssocDb::addEntry(const AssocDbEntry& nentry, AssocDbHandle& hdl)
00714 {
00715    MutexLock l = getDbLock();
00716    DataOStream ostrm;
00717    nentry.writeObject(ostrm);
00718    UInt32 blkSize = ostrm.length() + sizeof(AssocDbRecHeader);
00719    Int32 offset;
00720    AssocDbRecHeader rh = getNewBlock(offset, blkSize, hdl);
00721    rh.dataSize = ostrm.length();
00722    File f = hdl.getFile();
00723    writeRecHeader(rh, offset, f);
00724    
00725    if (f.write(ostrm.getData(), ostrm.length()) !=
00726       size_t(ostrm.length()))
00727    {
00728       OW_THROW_ERRNO_MSG(IOException, "Failed to write data assoc db");
00729    }
00730    
00731    if (!m_pIndex->add(nentry.makeKey().c_str(), offset))
00732    {
00733       OW_LOG_ERROR(m_env->getLogger(COMPONENT_NAME), Format("AssocDb::addEntry failed to add entry to"
00734          " association index: ", nentry.makeKey()));
00735       OW_THROW_ERRNO_MSG(IOException, "Failed to add entry to association index");
00736    }
00737 }
00739 // PRIVATE - AssocDbHandle uses
00740 void
00741 AssocDb::addEntry(const CIMObjectPath& objectName,
00742       const CIMName& assocClassName, const CIMName& resultClass,
00743       const CIMName& role, const CIMName& resultRole,
00744       const CIMObjectPath& associatedObject,
00745       const CIMObjectPath& assocClassPath, AssocDbHandle& hdl)
00746 {
00747    String key = AssocDbEntry::makeKey(objectName, role, resultRole);
00748    MutexLock l = getDbLock();
00749    AssocDbEntry dbentry = findEntry(key, hdl);
00750    if (dbentry)
00751    {
00752       deleteEntry(dbentry, hdl);
00753    }
00754    else
00755    {
00756       dbentry = AssocDbEntry(objectName, role, resultRole);
00757    }
00758    AssocDbEntry::entry e;
00759    e.m_assocClass = assocClassName;
00760    e.m_resultClass = resultClass;
00761    e.m_associatedObject = associatedObject;
00762    e.m_associationPath = assocClassPath;
00763    dbentry.m_entries.push_back(e);
00764    addEntry(dbentry, hdl);
00765 }
00767 // PRIVATE
00768 void
00769 AssocDb::addToFreeList(Int32 offset, AssocDbHandle& hdl)
00770 {
00771    AssocDbRecHeader rh;
00772    readRecHeader(rh, offset, hdl.getFile());
00773    rh.nextFree = m_hdrBlock.firstFree;
00774    File f = hdl.getFile();
00775    writeRecHeader(rh, offset, f);
00776    m_hdrBlock.firstFree = offset;
00777    if (f.write(&m_hdrBlock, sizeof(m_hdrBlock), 0L) !=
00778       sizeof(m_hdrBlock))
00779    {
00780       OW_THROW_ERRNO_MSG(IOException, "Failed write file header on deletion");
00781    }
00782 }
00784 // PRIVATE
00785 AssocDbRecHeader
00786 AssocDb::getNewBlock(Int32& offset, UInt32 blkSize,
00787    AssocDbHandle& hdl)
00788 {
00789    AssocDbRecHeader rh;
00790    AssocDbRecHeader lh;
00791    Int32 lastOffset = -1L;
00792    Int32 coffset = m_hdrBlock.firstFree;
00793    while (coffset != -1)
00794    {
00795       readRecHeader(rh, coffset, hdl.getFile());
00796       if (rh.blkSize >= blkSize)
00797       {
00798          if (lastOffset != -1L)
00799          {
00800             lh.nextFree = rh.nextFree;
00801             File f = hdl.getFile();
00802             writeRecHeader(lh, lastOffset, f);
00803          }
00804          if (m_hdrBlock.firstFree == coffset)
00805          {
00806             m_hdrBlock.firstFree = rh.nextFree;
00807             if (hdl.getFile().write(&m_hdrBlock, sizeof(m_hdrBlock), 0L) !=
00808                sizeof(m_hdrBlock))
00809             {
00810                OW_THROW_ERRNO_MSG(IOException,
00811                   "failed to write file header while updating free list");
00812             }
00813          }
00814          rh.nextFree = 0L;
00815          File f = hdl.getFile();
00816          writeRecHeader(rh, coffset, f);
00817          offset = coffset;
00818          return rh;
00819       }
00820       lastOffset = coffset;
00821       lh = rh;
00822       coffset = rh.nextFree;
00823    }
00824    hdl.getFile().seek(0L, SEEK_END);
00825    offset = hdl.getFile().tell();
00826    memset(&rh, 0, sizeof(rh));
00827    rh.blkSize = blkSize;
00828    return rh;
00829 }
00831 static void
00832 writeRecHeader(AssocDbRecHeader& rh, Int32 offset, File& file)
00833 {
00834    rh.chkSum = calcCheckSum(reinterpret_cast<unsigned char*>(&rh.nextFree),
00835       sizeof(rh) - sizeof(rh.chkSum));
00836    if (file.write(&rh, sizeof(rh), offset) != sizeof(rh))
00837    {
00838       OW_THROW_ERRNO_MSG(IOException, "Failed to write record to assoc db");
00839    }
00840 }
00842 static void
00843 readRecHeader(AssocDbRecHeader& rh, Int32 offset, const File& file)
00844 {
00845    if (file.read(&rh, sizeof(rh), offset) != sizeof(rh))
00846    {
00847       OW_THROW_ERRNO_MSG(IOException, "Failed to read record from assoc db");
00848    }
00849    UInt32 chkSum = calcCheckSum(reinterpret_cast<unsigned char*>(&rh.nextFree),
00850        sizeof(rh) - sizeof(rh.chkSum));
00851    if (chkSum != rh.chkSum)
00852    {
00853       OW_THROW(IOException, "Check sum failed reading rec from assoc db");
00854    }
00855 }
00857 static UInt32
00858 calcCheckSum(unsigned char* src, Int32 len)
00859 {
00860    register UInt32 cksum = 0;
00861    register Int32 i;
00862    for (i = 0; i < len; i++)
00863    {
00864       cksum += static_cast<UInt32>(src[i]);
00865    }
00866    return cksum;
00867 }
00869 bool operator==(const AssocDbEntry::entry& lhs, const AssocDbEntry::entry& rhs)
00870 {
00871    return lhs.m_assocClass == rhs.m_assocClass &&
00872       lhs.m_resultClass == rhs.m_resultClass &&
00873       lhs.m_associatedObject.equals(rhs.m_associatedObject) &&
00874       lhs.m_associationPath.equals(rhs.m_associationPath);
00875 }
00876 
00877 } // end namespace OW_NAMESPACE
00878 

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