00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
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> 
00053 #include <algorithm> 
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 
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    
00143    HDBUtilKeyArray kra(cop.getKeys());
00144    kra.toString(out);
00145 }
00146 } 
00148 String
00149 AssocDbEntry::makeKey(const CIMObjectPath& objectName, const CIMName& role,
00150    const CIMName& resultRole)
00151 {
00152    StringBuffer key;
00153    if (0)
00154    {
00155       
00156       
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    
00179    
00180    key += '#';
00181    key += lowerRole;
00182    key += '#';
00183    key += lowerResultRole;
00184    return key.releaseString();
00185 }
00187 String
00188 AssocDbEntry::makeKey() const
00189 {
00190    
00191    
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       
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    
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          
00296          for (size_t j = 0; j < propRa.size(); ++j)
00297          {
00298             if (j == i)
00299             {
00300                continue; 
00301             }
00302             CIMValue propValue2 = propRa[j].getValue();
00303             if (propValue2 && propValue2.getType() == CIMDataType::REFERENCE)
00304             {
00305                
00306                
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    
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          
00375          for (size_t j = 0; j < propRa.size(); ++j)
00376          {
00377             if (j == i)
00378             {
00379                continue; 
00380             }
00381             CIMProperty p2 = propRa[j];
00382             if (p2.getDataType().getType() == CIMDataType::REFERENCE)
00383             {
00384                
00385                
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; 
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       
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 
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 
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 
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 
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       
00683    }
00684 }
00686 
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 
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 
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 
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 
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 } 
00878