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