summaryrefslogtreecommitdiffstats
path: root/relindexif/hierindexcommon.cc
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /relindexif/hierindexcommon.cc
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
Initial commitv8.0
Diffstat (limited to 'relindexif/hierindexcommon.cc')
-rw-r--r--relindexif/hierindexcommon.cc1033
1 files changed, 1033 insertions, 0 deletions
diff --git a/relindexif/hierindexcommon.cc b/relindexif/hierindexcommon.cc
new file mode 100644
index 0000000..61ce20c
--- /dev/null
+++ b/relindexif/hierindexcommon.cc
@@ -0,0 +1,1033 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ *
+ * PURPOSE:
+ * maintain the hierarchical index in the DBMS.
+ *
+ *
+ * COMMENTS:
+ * - relies on the same-name DBMS preprocessor sources for the
+ * various DBMSs supported.
+ *
+ ************************************************************/
+
+#include <cstring>
+
+#include "mymalloc/mymalloc.h"
+#include "hierindex.hh"
+#include "reladminif/objectbroker.hh"
+#include "reladminif/dbref.hh"
+#include "raslib/rmdebug.hh"
+#include "reladminif/lists.h"
+#include "reladminif/sqlerror.hh"
+#include "reladminif/externs.h"
+#include "relblobif/blobtile.hh"
+#include "indexmgr/keyobject.hh"
+#include "storagemgr/sstoragelayout.hh"
+#include "raslib/endian.hh"
+#include "debug.hh"
+
+DBHierIndex::DBHierIndex(const OId& id)
+ : HierIndexDS(id),
+ currentDbRows(0),
+ myDomain((r_Dimension)0),
+ maxSize(0),
+ parent(0),
+ _isNode(false)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "DBHierIndex(" << myOId << ")");
+ ENTER( "DBHierIndex::DBHierIndex(" << myOId << ")" );
+
+ if (id.getType() == OId::MDDHIERIXOID)
+ readFromDb();
+ maxSize = DBHierIndex::getOptimalSize(getDimension());
+ myKeyObjects.reserve(maxSize);
+
+ LEAVE( "DBHierIndex::DBHierIndex(" << myOId << ")" );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "DBHierIndex(" << myOId << ")");
+ }
+
+DBHierIndex::DBHierIndex(r_Dimension dim, bool isNODE, bool makePersistent)
+ : HierIndexDS(),
+ maxSize(0),
+ myDomain(dim),
+ currentDbRows(-1),
+ parent(0),
+ _isNode(isNODE)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "DBHierIndex(" << dim << ", " << (int)isNODE << ", " << makePersistent << ") " << myOId);
+ ENTER( "DBHierIndex::DBHierIndex( dim=" << dim << ", isNODE=" << (int) isNODE << ", makePersistent=" << makePersistent << " ) - myOId=" << myOId );
+
+ objecttype = OId::MDDHIERIXOID;
+ if (makePersistent)
+ setPersistent(true);
+
+ maxSize = getOptimalSize(dim);
+ myKeyObjects.reserve(maxSize);
+ setCached(true);
+
+ LEAVE( "DBHierIndex::DBHierIndex( dim=" << dim << ", isNODE=" << (int) isNODE << ", makePersistent=" << makePersistent << " ) - myOId=" << myOId );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "DBHierIndex(" << dim << ", " << (int)isNODE << ", " << makePersistent << ") " << myOId);
+ }
+
+IndexDS*
+DBHierIndex::getNewInstance() const
+ {
+ ENTER( "DBHierIndex::getNewInstance()" );
+ LEAVE( "DBHierIndex::getNewInstance() - dim=" << getDimension() << ", !isLeaf=" << (!isLeaf()) );
+ return new DBHierIndex(getDimension(), !isLeaf(), true);
+ }
+
+OId::OIdPrimitive
+DBHierIndex::getIdentifier() const
+ {
+ ENTER( "DBHierIndex::getIdentifier()" );
+ LEAVE( "DBHierIndex::getIdentifier() - myOId=" << myOId );
+ return myOId;
+ }
+
+bool
+DBHierIndex::removeObject(const KeyObject& entry)
+ {
+ RMDBGENTER(4, RMDebug::module_indexif, "DBHierIndex", "removeObject(" << entry << ") " << myOId);
+ ENTER( "DBHierIndex::removeObject() - entry=" << entry << ", myOId=" << myOId );
+
+ bool found = false;
+ unsigned int pos = 0;
+ OId oid(entry.getObject().getOId());
+ for (KeyObjectVector::iterator i = myKeyObjects.begin(); i != myKeyObjects.end(); i++)
+ {
+ RMDBGMIDDLE(9, RMDebug::module_indexif, "DBHierIndex", "at pos " << pos << " of " << myKeyObjects.size());
+ TALK( "DBHierIndex::removeObject() touching object in vector at pos " << pos << " of " << myKeyObjects.size());
+ if (oid == (*i).getObject().getOId())
+ {
+ found = true;
+ myKeyObjects.erase(i);
+ setModified();
+ break;
+ }
+ else {
+ RMDBGMIDDLE(9, RMDebug::module_indexif, "DBHierIndex", "did not match " << oid << " with " << *i);
+ }
+ }
+
+ LEAVE( "DBHierIndex::removeObject() - entry=" << entry << ", myOId=" << myOId << ", found=" << found );
+ RMDBGEXIT(4, RMDebug::module_indexif, "DBHierIndex", "removeObject(" << entry << ") " << myOId << " " << found);
+ return found;
+ }
+
+bool
+DBHierIndex::removeObject(unsigned int pos)
+ {
+ RMDBGENTER(4, RMDebug::module_indexif, "DBHierIndex", "removeObject(" << pos << ") " << myOId);
+ ENTER( "DBHierIndex::removeObject() - pos=" << pos << ", myOId=" << myOId );
+
+ bool found = false;
+ if (pos <= myKeyObjects.size())
+ {
+ found = true;
+ myKeyObjects.erase(myKeyObjects.begin() + pos);
+ setModified();
+ }
+
+ LEAVE( "DBHierIndex::removeObject() - pos=" << pos << ", myOId=" << myOId << ", found=" << found );
+ RMDBGEXIT(4, RMDebug::module_indexif, "DBHierIndex", "removeObject(" << pos << ") " << myOId << " " << found);
+ return found;
+ }
+
+
+void
+DBHierIndex::insertObject(const KeyObject& theKey, unsigned int pos)
+ {
+ RMDBGENTER(8, RMDebug::module_indexif, "DBHierIndex", "insertObject(" << theKey << ", " << pos << ") " << myOId);
+ ENTER( "DBHierIndex::insertObject() - theKey=" << theKey << ", pos=" << pos << ", myOId=" << myOId );
+
+ if (!isLeaf())
+ DBHierIndexId(theKey.getObject())->setParent(this);
+ if (myKeyObjects.size() == 0)
+ {
+ // first tile to be inserted in the index, initialize domain
+ myDomain = theKey.getDomain();
+ }
+ else
+ extendCoveredDomain(theKey.getDomain());
+ myKeyObjects.insert(myKeyObjects.begin() + pos, theKey);
+ TALK( "now have " << myKeyObjects.size() << " objects in key object vector." );
+ setModified();
+
+ LEAVE( "DBHierIndex::insertObject() - theKey=" << theKey << ", pos=" << pos << ", myOId=" << myOId << ", CoveredDomain " << getCoveredDomain() << std::endl << std::endl );
+ TALK( " CoveredDomain=" << getCoveredDomain() << std::endl << std::endl );
+ RMDBGEXIT(8, RMDebug::module_indexif, "DBHierIndex", "insertObject(" << theKey << ", " << pos << ") " << myOId << " CoveredDomain " << getCoveredDomain());
+ }
+
+void
+DBHierIndex::setObjectDomain(const r_Minterval& dom, unsigned int pos)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "setObjectDomain(" << dom << ", " << pos << ") " << myOId);
+ ENTER( "DBHierIndex::setObjectDomain() - dom=" << dom << ", pos=" << pos << ", myOId=" << myOId );
+
+ myKeyObjects[pos].setDomain(dom);
+ //might be unneccessary/harmfull, check later
+ extendCoveredDomain(dom);
+
+ //setModified(); done in domain extension
+ if (!isLeaf())
+ {
+ DBHierIndexId t(myKeyObjects[pos].getObject());
+ t->setAssignedDomain(dom);
+ }
+
+ LEAVE( "DBHierIndex::setObjectDomain() - dom=" << dom << ", pos=" << pos << ", myOId=" << myOId );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "setObjectDomain(" << dom << ", " << pos << ") " << myOId);
+ }
+
+void
+DBHierIndex::setObject(const KeyObject& theKey, unsigned int pos)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "setObject(" << theKey << ", " << pos << ") " << myOId);
+ ENTER( "DBHierIndex::setObject() - theKey=" << theKey << ", pos=" << pos << ", myOId=" << myOId );
+
+ myKeyObjects[pos] = theKey;
+ setModified();
+ if (!isLeaf())
+ {
+ DBHierIndexId(theKey.getObject())->setParent(this);
+ }
+
+ LEAVE( "DBHierIndex::setObject() - theKey=" << theKey << ", pos=" << pos << ", myOId=" << myOId );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "setObject(" << theKey << ", " << pos << ") " << myOId);
+ }
+
+r_Minterval
+DBHierIndex::getCoveredDomain() const
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "getCoveredDomain() const " << myOId << " " << myDomain);
+ TALK( "DBHierIndex::getCoveredDomain( " << myOId << ") -> " << myDomain );
+ return myDomain;
+ }
+
+r_Dimension
+DBHierIndex::getDimension() const
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBDDObjIx", "getDimension() const " << myOId << " " << myDomain.dimension());
+ TALK( "DBHierIndex::getDimension( " << myOId << ") -> " << myDomain.dimension() );
+ return myDomain.dimension();
+ }
+
+r_Bytes
+DBHierIndex::getTotalStorageSize() const
+ {
+ RMDBGENTER(4, RMDebug::module_indexif, "DBHierIndex", "getTotalStorageSize() " << myOId);
+ ENTER( "DBHierIndex::getTotalStorageSize() - myOId=" << myOId );
+
+ r_Bytes sz = 0;
+
+ for (KeyObjectVector::const_iterator i = myKeyObjects.begin(); i != myKeyObjects.end(); i++)
+ {
+ sz = sz + ((DBObject*)ObjectBroker::getObjectByOId(i->getObject().getOId()))->getTotalStorageSize();
+ }
+
+ LEAVE( "DBHierIndex::getTotalStorageSize( " << myOId << " ) for " << myKeyObjects.size() << " objects -> sz=" << sz );
+ RMDBGEXIT(4, RMDebug::module_indexif, "DBHierIndex", "getTotalStorageSize() " << myOId << " " << sz);
+ return sz;
+ }
+
+bool
+DBHierIndex::isValid() const
+ {
+ ENTER( "DBHierIndex::isValid()" );
+
+ bool valid = true;
+ //may not be unsigned int (r_Area) because of error check
+ int area = 0;
+ if (!isLeaf())
+ {
+ area = myDomain.cell_count();
+ DBHierIndexId tempIx;
+ TALK( "inspecting " << myKeyObjects.size() << " objects in key object vector." );
+ for (KeyObjectVector::const_iterator i = myKeyObjects.begin(); i != myKeyObjects.end(); i++)
+ {
+ if (myDomain.covers((*i).getDomain()))
+ {
+ //ok
+ area = area - (*i).getDomain().cell_count();
+ }
+ else {
+ if (myDomain == (*i).getDomain())
+ {
+ //ok
+ area = area - (*i).getDomain().cell_count();
+ tempIx = DBHierIndexId((*i).getObject());
+ if (!tempIx->isValid())
+ {
+ valid = false;
+ break;
+ }
+ }
+ else {
+ RMDBGONCE(0, RMDebug::module_indexif, "DBHierIndex", "isValid() " << myOId << " key does not cover domain: myDomain " << myDomain << " key " << *i);
+ valid = false;
+ break;
+ }
+ }
+ }
+ if (valid)
+ {
+ if (area < 0)
+ {
+ RMDBGONCE(0, RMDebug::module_indexif, "DBHierIndex", "isValid() " << myOId << " there are double entries");
+ valid = false;
+ }
+ }
+ }
+ else {
+ area = myDomain.cell_count();
+ valid = true;
+ for (KeyObjectVector::const_iterator i = myKeyObjects.begin(); i != myKeyObjects.end(); i++)
+ {
+ if (myDomain.intersects_with((*i).getDomain()))
+ {
+ //ok
+ area = area - (*i).getDomain().create_intersection(myDomain).cell_count();
+ }
+ else {
+ RMDBGONCE(0, RMDebug::module_indexif, "DBHierIndex", "isValid() " << myOId << " key does not intersect domain: myDomain " << myDomain << " key " << *i);
+ valid = false;
+ break;
+ }
+ }
+ if (!valid)
+ {
+ if (area < 0)
+ {
+ RMDBGONCE(0, RMDebug::module_indexif, "DBHierIndex", "isValid() " << myOId << " there are double entries");
+ valid = false;
+ }
+ }
+ }
+
+ ENTER( "DBHierIndex::isValid() -> valid=" << valid );
+ return valid;
+ }
+
+void
+DBHierIndex::printStatus(unsigned int level, std::ostream& stream) const
+ {
+ ENTER( "DBHierIndex::printStatus() - level=" << level );
+
+ DBObjectId t;
+ char* indent = new char[level*2 +1];
+ for (unsigned int j = 0; j < level*2 ; j++)
+ indent[j] = ' ';
+ indent[level*2] = '\0';
+
+ stream << indent << "DBHierIndex ";
+ if (isRoot())
+ stream << "is Root ";
+ else
+ stream << "Parent " << parent << " ";
+ if (isLeaf())
+ stream << "Leaf ";
+ else
+ stream << "Node ";
+ DBObject::printStatus(level, stream);
+ stream << " size " << myKeyObjects.size() << " domain " << myDomain << std::endl;
+ int count = 0;
+ TALK( "inspecting " << myKeyObjects.size() << " objects in key object vector." );
+ for (KeyObjectVector::const_iterator i = myKeyObjects.begin(); i != myKeyObjects.end(); i++)
+ {
+ stream << indent << " entry #" << count << " is " << *i << std::endl;
+ if (!isLeaf())
+ {
+ t = DBObjectId((*i).getObject());
+ if (t.is_null())
+ stream << indent << " entry is null";
+ else
+ t->printStatus(level + 1, stream);
+ }
+ stream << std::endl;
+ count++;
+ }
+ delete[] indent;
+
+ LEAVE( "DBHierIndex::printStatus()" );
+ }
+
+unsigned int
+DBHierIndex::getSize() const
+ {
+ RMDBGONCE(4, RMDebug::module_indexif, "DBHierIndex", "getSize() " << myOId << " " << myKeyObjects.size());
+ TALK( "DBHierIndex::getSize() - myOId=" << myOId << ", size=" << myKeyObjects.size() );
+ return myKeyObjects.size();
+ }
+
+bool
+DBHierIndex::isUnderFull() const
+ {
+ //redistribute in srptindexlogic has to be checked first before any other return value may be assigned
+ TALK( "DBHierIndex::isUnderFull() -> false" );
+ return false;
+ }
+
+bool
+DBHierIndex::isOverFull() const
+ {
+ ENTER( "DBHierIndex::isOverFull()" );
+
+ bool retval = false;
+ if (getSize() >= maxSize)
+ retval = true;
+
+ RMDBGONCE(4, RMDebug::module_indexif, "DBHierIndex", "isOverFull() " << myOId << " maxSize " << maxSize << " size " << getSize() << " retval " << retval)
+ ENTER( "DBHierIndex::isOverFull() -> " << retval );
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getOptimalSize(r_Dimension dim)
+ {
+ ENTER( "DBHierIndex::getOptimalSize() - dim=" << dim );
+
+ unsigned int retval = 0;
+ //BLOCKSIZE
+ unsigned int blocksize = 0;
+ unsigned int useablespace = 0;
+ //dimension * (upperbound + upperfixed + lowerbound + lowerfixed) + entryid + entryoidtype
+ unsigned int oneentry = dim * (sizeof(r_Range) * 2 + sizeof(char) * 2) + sizeof(OId::OIdCounter) + sizeof(char);
+
+#ifdef BASEDB_ORACLE
+ blocksize = 2048;
+ //BLOCKSIZE - (BLOCK OVERHEAD + ROW OVERHEAD + 1 * largerow + number(15,0) + short)
+ useablespace = blocksize - (130 + 3 + 1 * 3 + 12 + 2);
+#else
+#ifdef BASEDB_DB2
+ blocksize = 4096;
+ //from the manual
+ useablespace = 3990;
+#else
+#ifdef BASEDB_INFORMIX
+ blocksize = 4096;
+ //from the manual
+ useablespace = 3990;
+#else
+#ifdef BASEDB_PGSQL
+ blocksize = 8192; // default only!!!;
+ useablespace = 7000; // no indication for any less space available, but to be sure we go a little lower -- PB 2005-jan-10
+#else
+#error "BASEDB not defined! please check for BASEDB_XXX define in Makefile.inc!"
+#endif // pgsql
+#endif // informix
+#endif // db2
+#endif // oracle
+
+ //remove mydomain size
+ useablespace = useablespace - dim * (sizeof(r_Range) * 2 + sizeof(char) * 2);
+ //minimum size is 8-lucky guess(good for 1,2,3,4 dimensions)
+ retval = std::max((unsigned int)8, useablespace / oneentry);
+ if (StorageLayout::DefaultIndexSize != 0)
+ retval = StorageLayout::DefaultIndexSize;
+
+ LEAVE( "DBHierIndex::getOptimalSize() - maxSize=" << retval );
+ RMDBGONCE(4, RMDebug::module_indexif, "DBHierIndex", "getOptimalSize(" << dim << ") maxSize " << retval)
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getOptimalSize() const
+ {
+ TALK( "DBHierIndex::getOptimalSize() -> " << maxSize );
+ return maxSize;
+ }
+
+r_Minterval
+DBHierIndex::getAssignedDomain() const
+ {
+ TALK( "DBHierIndex::getAssignedDomain() -> " << myDomain );
+ return myDomain;
+ }
+
+void
+DBHierIndex::setAssignedDomain(const r_Minterval& newDomain)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "setAssignedDomain(" << newDomain << ") " << myOId);
+ ENTER( "DBHierIndex::setAssignedDomain() - newDomain=" << newDomain << ", myOId=" << myOId );
+
+ myDomain = newDomain;
+ setModified();
+
+ LEAVE( "DBHierIndex::setAssignedDomain()" );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "setAssignedDomain(" << newDomain << ") " << myOId);
+ }
+
+void
+DBHierIndex::extendCoveredDomain(const r_Minterval& newTilesExtents) throw (r_Edim_mismatch, r_Eno_interval)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "extendCoveredDomain(" << newTilesExtents << ") " << myOId);
+ ENTER( "DBHierIndex::extendCoveredDomain() - newTilesExtents=" << newTilesExtents << ", myOId=" << myOId );
+
+ myDomain.closure_with(newTilesExtents);
+ setModified();
+
+ LEAVE( "DBHierIndex::extendCoveredDomain()" );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "extendCoveredDomain(" << newTilesExtents << ") " << myOId);
+ }
+
+void
+DBHierIndex::setParent(const HierIndexDS* newPa)
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "setParent(" << OId(newPa->getIdentifier()) << ") " << myOId);
+ ENTER( "DBHierIndex::setParent() - newPa=" << newPa << ", myOId=" << myOId );
+
+ if ((OId::OIdPrimitive)parent != newPa->getIdentifier())
+ {
+ parent = newPa->getIdentifier();
+ setModified();
+ }
+
+ LEAVE( "DBHierIndex::setParent()" );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "setParent(" << OId(newPa->getIdentifier()) << ") " << myOId);
+ }
+
+HierIndexDS*
+DBHierIndex::getParent() const
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "getParent() const " << myOId << " " << parent << " " << parent);
+ ENTER( "DBHierIndex::getParent() - myOId=" << myOId << ", parent=" << parent );
+
+ DBHierIndexId t(parent);
+
+ LEAVE( "DBHierIndex::getParent() - t=" << t );
+ return (HierIndexDS*)t;
+ }
+
+bool
+DBHierIndex::isRoot() const
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "isRoot() const " << myOId << " " << (int)(parent.getType() == OId::INVALID));
+ TALK( "DBHierIndex::isRoot() -> " << (parent.getType() == OId::INVALID) );
+ return (parent.getType() == OId::INVALID);
+ }
+
+bool
+DBHierIndex::isLeaf() const
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "isLeaf() const " << myOId << " " << (int)(!_isNode));
+ TALK( "DBHierIndex::isLeaf() -> " << !_isNode );
+ return !_isNode;
+ }
+
+void
+DBHierIndex::setIsNode(bool isNodea)
+ {
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "setIsNode(" << isNodea << ") " << myOId << " was " << _isNode);
+ TALK( "DBHierIndex::setIsNode() - isNodea=" << isNodea );
+ _isNode = isNodea;
+ }
+
+void
+DBHierIndex::freeDS()
+ {
+ TALK( "DBHierIndex::freeDS()" );
+ setPersistent(false);
+ }
+bool
+DBHierIndex::isSameAs(const IndexDS* other) const
+ {
+ ENTER( "DBHierIndex::isSameAs() - other=" << other );
+
+ bool result = false;
+ if (other->isPersistent())
+ if (myOId == other->getIdentifier())
+ result = true;
+
+ LEAVE( "DBHierIndex::isSameAs() -> " << result );
+ return result;
+ }
+
+
+double
+DBHierIndex::getOccupancy() const
+ {
+ cout << "DBHierIndex::getOccupancy() const NOT IMPLEMENTED" << std::endl;
+ TALK( "DBHierIndex::getOccupancy() NOT IMPLEMENTED" );
+ return 0;
+ }
+
+const KeyObject&
+DBHierIndex::getObject(unsigned int pos) const
+ {
+ RMDBGONCE(4, RMDebug::module_indexif, "DBHierIndex", "getObject(" << pos << ") " << myOId << " " << myKeyObjects[pos]);
+ TALK( "DBHierIndex::getObject() - pos=" << pos << ", myOId=" << myOId << " -> " << myKeyObjects[pos] );
+
+ return myKeyObjects[pos];
+ }
+
+void
+DBHierIndex::getObjects(KeyObjectVector& objs) const
+ {
+ RMDBGENTER(4, RMDebug::module_indexif, "DBHierIndex", "getObjects() " << myOId);
+ ENTER( "DBHierIndex::getObjects() - myOId=" << myOId );
+
+ for (KeyObjectVector::const_iterator keyIt = myKeyObjects.begin(); keyIt != myKeyObjects.end(); keyIt++)
+ {
+ objs.push_back(*keyIt);
+ }
+
+ LEAVE( "DBHierIndex::getObjects() - size=" << objs.size() );
+ RMDBGEXIT(4, RMDebug::module_indexif, "DBHierIndex", "getObjects() " << myOId << " vec.size " << objs.size());
+ }
+
+r_Minterval
+DBHierIndex::getObjectDomain(unsigned int pos) const
+ {
+ RMDBGONCE(4, RMDebug::module_indexif, "DBHierIndex", "getObjectDomain(" << pos << ") " << myOId << " " << myKeyObjects[pos]);
+ TALK( "DBHierIndex::getObjectDomain() - pos=" << pos << ", myOId=" << myOId << " -> " << myKeyObjects[pos] );
+ return myKeyObjects[pos].getDomain();
+ }
+
+unsigned int
+DBHierIndex::getHeight() const
+ {
+ TALK( "DBHierIndex::getHeight() -> " << getHeightToLeaf() );
+ return getHeightToLeaf();
+ }
+
+unsigned int
+DBHierIndex::getHeightOfTree() const
+ {
+ ENTER( "DBHierIndex::getHeightOfTree() - myOId=" << myOId );
+
+ unsigned int retval = getHeightToLeaf() + getHeightToRoot();
+
+ LEAVE( "DBHierIndex::getHeightOfTree() -> " << retval );
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "getHeightOfTree() const " << myOId << " " << retval);
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getHeightToRoot() const
+ {
+ ENTER( "DBHierIndex::getHeightToRoot() - myOId=" << myOId );
+
+ unsigned int retval = 0;
+ if (isRoot())
+ retval = 0;
+ else {
+ DBHierIndexId t(parent);
+ const DBHierIndex* tp = (DBHierIndex*)t.ptr();
+ retval = tp->getHeightToRoot() + 1;
+ }
+
+ LEAVE( "DBHierIndex::getHeightToRoot() -> " << retval );
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "getHeightToRoot() const " << myOId << " " << retval);
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getHeightToLeaf() const
+ {
+ ENTER( "DBHierIndex::getHeightToLeaf() - myOId=" << myOId );
+
+ unsigned int retval = 0;
+ if (isLeaf())
+ retval = 0;
+ else {
+ DBHierIndexId t(parent);
+ const DBHierIndex* tp = (DBHierIndex*)t.ptr();
+ retval = tp->getHeightToLeaf() + 1;
+ }
+
+ LEAVE( "DBHierIndex::getHeightToLeaf() -> " << retval );
+ RMDBGONCE(7, RMDebug::module_indexif, "DBHierIndex", "getHeightToLeaf() const " << myOId << " " << retval);
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getTotalLeafCount() const
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "getTotalLeafCount() const " << myOId);
+ ENTER( "DBHierIndex::getTotalLeafCount() - myOId=" << myOId );
+
+ unsigned int retval = 0;
+ if (!isLeaf())
+ {
+ //i am not a leaf
+ if (DBHierIndexId(myKeyObjects.begin()->getObject())->isLeaf())
+ {
+ //i contain only leafs, so i return the number of entries i contain
+ retval = getSize();
+ }
+ else {
+ //i contain only nodes, so i ask my children how many leafs there are
+ for (KeyObjectVector::const_iterator keyIt = myKeyObjects.begin(); keyIt != myKeyObjects.end(); keyIt++)
+ {
+ DBHierIndexId accessedIx((*keyIt).getObject());
+ retval = retval + accessedIx->getTotalLeafCount();
+ }
+ }
+ }
+ else {
+ retval = 1;
+ }
+
+ LEAVE( "DBHierIndex::getTotalLeafCount() -> " << retval );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "getTotalLeafCount() const " << myOId << " " << retval);
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getTotalNodeCount() const
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "getTotalNodeCount() const " << myOId);
+ ENTER( "DBHierIndex::getTotalNodeCount() - myOId=" << myOId );
+
+ unsigned int retval = 0;
+ if (!isLeaf())
+ {
+ //i am not a leaf
+ if (DBHierIndexId(myKeyObjects.begin()->getObject())->isLeaf())
+ {
+ //i contain only nodes
+ //i add the nodes i contain
+ retval = getSize();
+ //i add the nodes my children contain
+ for (KeyObjectVector::const_iterator keyIt = myKeyObjects.begin(); keyIt != myKeyObjects.end(); keyIt++)
+ {
+ DBHierIndexId accessedIx((*keyIt).getObject());
+ retval = retval + accessedIx->getTotalNodeCount();
+ }
+ }
+ }
+ //else : a leaf does not contain nodes
+
+ LEAVE( "DBHierIndex::getTotalNodeCount() -> " << retval );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "getTotalNodeCount() const " << myOId << " " << retval);
+ return retval;
+ }
+
+unsigned int
+DBHierIndex::getTotalEntryCount() const
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "getTotoalEntryCount() const " << myOId);
+ ENTER( "DBHierIndex::getTotalEntryCount() - myOId=" << myOId );
+
+ unsigned int retval = 0;
+ if (isLeaf())
+ {
+ //i contain only entries
+ //i return the number of entries i contain
+ retval = getSize();
+ }
+ else {
+ //i contain only nodes, no entries
+ //i ask my children how many entries they contain
+ for (KeyObjectVector::const_iterator keyIt = myKeyObjects.begin(); keyIt != myKeyObjects.end(); keyIt++)
+ {
+ DBHierIndexId accessedIx((*keyIt).getObject());
+ retval = retval + accessedIx->getTotalEntryCount();
+ }
+ }
+
+ LEAVE( "DBHierIndex::getTotalEntryCount() -> " << retval );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "getTotoalEntryCount() const " << myOId << " " << retval);
+ return retval;
+ }
+
+void
+DBHierIndex::destroy()
+ {
+ TALK( "DBObject::destroy()" );
+ DBObject::destroy();
+ }
+
+DBHierIndex::~DBHierIndex()
+ {
+ RMDBGENTER(7, RMDebug::module_indexif, "DBHierIndex", "~DBHierIndex() " << myOId);
+ ENTER( "DBHierIndex::~DBHierIndex() - myOId=" << myOId );
+
+ validate();
+ currentDbRows = 0;
+ parent = OId(0);
+ myKeyObjects.clear();
+ myDomain = (InlineMinterval) NULL;
+ maxSize = 0;
+ _isNode = true;
+
+ LEAVE( "DBHierIndex::~DBHierIndex()" );
+ RMDBGEXIT(7, RMDebug::module_indexif, "DBHierIndex", "~DBHierIndex() " << myOId);
+ }
+
+/*
+Encoding:
+name :
+ type_oid.raw
+value :
+ common
+ 1 byte version
+ 1 byte endianness
+ 2 bytes type
+ 4 bytes oid
+ 1 byte flags
+ 2 byte reserved
+ special
+ 4 bytes size
+ 2 bytes dimension
+ 8 bytes parent oid
+ 1 byte subtype
+ x bytes database layout
+*/
+
+BinaryRepresentation
+DBHierIndex::getBinaryRepresentation() const throw (r_Error)
+ {
+ ENTER( "DBHierIndex::getBinaryRepresentation()" );
+
+ BinaryRepresentation brp;
+ brp.binaryName = getBinaryName();
+ brp.binaryData = NULL;
+ brp.binaryLength = 0;
+ short dimension2 = myDomain.dimension();
+ size_t size2 = myKeyObjects.size();
+ short subtype = _isNode;
+ double parentid2 = 0;
+
+ if (parent.getType() == OId::INVALID)
+ parentid2 = 0;
+ else
+ parentid2 = parent;
+
+ //INSERTINTO
+
+ //number of bytes for bounds for "size" entries and mydomain
+ r_Bytes boundssize = sizeof(r_Range) * (size2 + 1) * dimension2;
+ //number of bytes for fixes for "size" entries and mydomain
+ r_Bytes fixessize = sizeof(char) * (size2 + 1) * dimension2;
+ //number of bytes for ids of entries
+ r_Bytes idssize = sizeof(OId::OIdCounter) * size2;
+ //number of bytes for types of entries
+ r_Bytes typessize = sizeof(char) * size2;
+ //number of bytes for the dynamic data
+ r_Bytes completesize = boundssize * 2 + fixessize * 2 + idssize + typessize;
+
+ char* completebuffer = new char[completesize];
+ r_Range* upperboundsbuf = new r_Range[boundssize];
+ r_Range* lowerboundsbuf = new r_Range[boundssize];
+ char* upperfixedbuf = new char[fixessize];
+ char* lowerfixedbuf = new char[fixessize];
+ OId::OIdCounter* entryidsbuf = new OId::OIdCounter[idssize];
+ char* entrytypesbuf = new char[typessize];
+
+ RMDBGMIDDLE(8, RMDebug::module_indexif, "DBHierIndex", "complete " << completesize << " bounds " << boundssize << " fixes " << fixessize << " ids " << idssize << " types " << typessize);
+
+ //counter which keeps track of the bytes that have been written to the db
+ r_Bytes byteswritten = 0;
+ //counter which keeps track of the bytes that have to be written to the db
+ r_Bytes bytestowrite = 0;
+
+ myDomain.insertInDb(&(lowerboundsbuf[0]), &(upperboundsbuf[0]), &(lowerfixedbuf[0]), &(upperfixedbuf[0]));
+ RMDBGMIDDLE(5, RMDebug::module_indexif, "DBHierIndex", "domain " << myDomain << " stored as " << InlineMinterval(dimension2, &(lowerboundsbuf[0]), &(upperboundsbuf[0]), &(lowerfixedbuf[0]), &(upperfixedbuf[0])));
+ //populate the buffers with data
+ KeyObjectVector::const_iterator it = myKeyObjects.begin();
+ InlineMinterval indom;
+ for (unsigned int i = 0; i < size2; i++, it++)
+ {
+ indom = (*it).getDomain();
+ indom.insertInDb(&(lowerboundsbuf[(i+1)*dimension2]), &(upperboundsbuf[(i+1)*dimension2]), &(lowerfixedbuf[(i+1)*dimension2]), &(upperfixedbuf[(i+1)*dimension2]));
+ entryidsbuf[i] = (*it).getObject().getOId().getCounter();
+ entrytypesbuf[i] = (char)(*it).getObject().getOId().getType();
+ RMDBGMIDDLE(5, RMDebug::module_indexif, "DBHierIndex", "entry " << entryidsbuf[i] << " " << (OId::OIdType)entrytypesbuf[i] << " at " << InlineMinterval(dimension2, &(lowerboundsbuf[(i+1)*dimension2]), &(upperboundsbuf[(i+1)*dimension2]), &(lowerfixedbuf[(i+1)*dimension2]), &(upperfixedbuf[(i+1)*dimension2])));
+ }
+
+ //write the buffers in the complete buffer
+ //this indirection is neccessary because of memory alignement of longs...
+ memcpy(completebuffer, lowerboundsbuf, boundssize);
+ delete [] lowerboundsbuf;
+ memcpy(&completebuffer[boundssize], upperboundsbuf, boundssize);
+ delete [] upperboundsbuf;
+ memcpy(&completebuffer[boundssize * 2], lowerfixedbuf, fixessize);
+ delete [] lowerfixedbuf;
+ memcpy(&completebuffer[boundssize * 2 + fixessize], upperfixedbuf, fixessize);
+ delete [] upperfixedbuf;
+ memcpy(&completebuffer[boundssize * 2 + fixessize * 2], entryidsbuf, idssize);
+ delete [] entryidsbuf;
+ memcpy(&completebuffer[boundssize * 2 + fixessize * 2 + idssize], entrytypesbuf, typessize);
+ delete [] entrytypesbuf;
+
+/*
+ 5 bytes tag
+ 1 byte version
+ 1 byte endianness
+ 8 bytes oid
+*/
+ //version + endianness + oid + size + dimension + parentoid + subtype
+ brp.binaryLength = 7 + sizeof(double) + sizeof(int) + sizeof(short) + sizeof(double) + sizeof(char) + completesize;
+ brp.binaryData = new char[brp.binaryLength];
+ memcpy(brp.binaryData, BinaryRepresentation::fileTag, 5);
+ memset(&brp.binaryData[5], 1, 1);
+ if (r_Endian::get_endianness() == r_Endian::r_Endian_Little)
+ {
+ memset(&brp.binaryData[6], 1, 1);
+ }
+ else {
+ memset(&brp.binaryData[6], 0, 1);
+ }
+ double tempd = myOId;
+ memcpy(&brp.binaryData[7], &tempd, sizeof(double));
+/*
+ special
+ 4 bytes size
+ 2 bytes dimension
+ 8 bytes parent oid
+ 1 byte subtype
+ x bytes database layout
+*/
+ int tempi = size2;
+ memcpy(&brp.binaryData[7 + sizeof(double)], &tempi, sizeof(int));
+ short temps = dimension2;
+ memcpy(&brp.binaryData[7 + sizeof(double) + sizeof(int)], &temps, sizeof(short));
+ memcpy(&brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short)], &parentid2, sizeof(double));
+ char tempc = subtype;
+ memcpy(&brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short) + sizeof(double)], &tempc, sizeof(char));
+ memcpy(&brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short) + sizeof(double) + sizeof(char)], completebuffer, completesize);
+
+ delete [] completebuffer;
+
+ LEAVE( "DBHierIndex::getBinaryRepresentation()" );
+ return brp;
+ }
+
+void
+DBHierIndex::setBinaryRepresentation(const BinaryRepresentation& brp) throw (r_Error)
+ {
+ ENTER( "DBHierIndex::setBinaryRepresentation()" );
+
+ if (memcmp(brp.binaryData, BinaryRepresentation::fileTag, 5) != 0)
+ {
+ RMInit::logOut << "DBHierIndex::setBinaryRepresentation(brp:" << brp.binaryName << ") not a correct data set " << brp.binaryData << endl;
+ throw r_Error();
+ }
+ if (brp.binaryData[5] != 1)
+ {
+ RMInit::logOut << "DBHierIndex::setBinaryRepresentation(brp:" << brp.binaryName << ") not unknown export version " << (int)brp.binaryData[5] << endl;
+ throw r_Error();
+ }
+ if (brp.binaryData[6] != (r_Endian::get_endianness() == r_Endian::r_Endian_Little))
+ {
+ RMInit::logOut << "DBHierIndex::setBinaryRepresentation(brp:" << brp.binaryName << ") endianess conversion not supported" << endl;
+ throw r_Error();
+ }
+ size_t size1;
+ short dimension1;
+ double parentid1;
+ int tempi;
+ short temps;
+ char tempc;
+ double tempd;
+
+ memcpy((char*)&tempd, &brp.binaryData[7], sizeof(double));
+ myOId = tempd;
+ char* temp = getBinaryName();
+ if (strcmp(temp, brp.binaryName) != 0)
+ {
+ RMInit::logOut << "DBHierIndex::setBinaryRepresentation(brp:" << brp.binaryName << ") my name should be " << temp << endl;
+ delete [] temp;
+ throw r_Error();
+ }
+ delete [] temp;
+ temp = NULL;
+ memcpy(&tempi, &brp.binaryData[7 + sizeof(double)], sizeof(int));
+ size1 = tempi;
+ memcpy(&temps, &brp.binaryData[7 + sizeof(double) + sizeof(int)], sizeof(short));
+ dimension1 = temps;
+ memcpy(&parentid1, &brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short)], sizeof(double));
+ memcpy(&tempc, &brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short) + sizeof(double)], sizeof(char));
+ _isNode = tempc;
+
+ if (parentid1)
+ parent = OId(parentid1);
+ else
+ parent = OId(0, OId::INVALID);
+
+ //number of bytes for bounds for "size" entries and mydomain
+ r_Bytes boundssize = sizeof(r_Range) * (size1 + 1) * dimension1;
+ //number of bytes for fixes for "size" entries and mydomain
+ r_Bytes fixessize = sizeof(char) * (size1 + 1) * dimension1;
+ //number of bytes for ids of entries
+ r_Bytes idssize = sizeof(OId::OIdCounter) * size1;
+ //number of bytes for types of entries
+ r_Bytes typessize = sizeof(char) * size1;
+ //number of bytes for the dynamic data
+ r_Bytes completesize = boundssize * 2 + fixessize * 2 + idssize + typessize;
+
+ RMDBGMIDDLE(8, RMDebug::module_indexif, "DBHierIndex", "size " << size1 << " dimension " << dimension1 << " fixes " << fixessize << " ids " << idssize << " types " << typessize);
+ TALK( "DBHierIndex::setBinaryRepresentation(): size=" << size1 << ", dimension=" << dimension1 << ", fixes=" << fixessize << ", ids=" << idssize << ", types=" << typessize );
+
+ char* completebuffer = new char[completesize];
+ r_Range* upperboundsbuf = new r_Range[boundssize];
+ r_Range* lowerboundsbuf = new r_Range[boundssize];
+ char* upperfixedbuf = new char[fixessize];
+ char* lowerfixedbuf = new char[fixessize];
+ OId::OIdCounter* entryidsbuf = new OId::OIdCounter[idssize];
+ char* entrytypesbuf = new char[typessize];
+ memcpy(completebuffer, &brp.binaryData[7 + sizeof(double) + sizeof(int) + sizeof(short) + sizeof(double) + sizeof(char)], completesize);
+
+ //all dynamic data is in completebuffer
+ //put that stuff in the correct buffers
+ memcpy(lowerboundsbuf, completebuffer, boundssize);
+ memcpy(upperboundsbuf, &completebuffer[boundssize], boundssize);
+ memcpy(lowerfixedbuf, &completebuffer[boundssize * 2], fixessize);
+ memcpy(upperfixedbuf, &completebuffer[boundssize * 2 + fixessize], fixessize);
+ memcpy(entryidsbuf, &completebuffer[boundssize * 2 + fixessize * 2], idssize);
+ memcpy(entrytypesbuf, &completebuffer[boundssize * 2 + fixessize * 2 + idssize], typessize);
+ //all dynamic data is in its buffer
+ delete [] completebuffer;
+ completebuffer = NULL;
+ int i = 0;
+ //rebuild the attributes from the buffers
+ myDomain = InlineMinterval(dimension1, &(lowerboundsbuf[0]), &(upperboundsbuf[0]), &(lowerfixedbuf[0]), &(upperfixedbuf[i*dimension1]));
+ RMDBGMIDDLE(5, RMDebug::module_indexif, "DBHierIndex", "domain " << myDomain << " constructed from " << InlineMinterval(dimension1, &(lowerboundsbuf[0]), &(upperboundsbuf[0]), &(lowerfixedbuf[0]), &(upperfixedbuf[0])));
+ KeyObject theKey = KeyObject(DBObjectId(), myDomain);
+ for (i = 0; i < size1; i++)
+ {
+ theKey.setDomain(InlineMinterval(dimension1, &(lowerboundsbuf[(i+1)*dimension1]), &(upperboundsbuf[(i+1)*dimension1]), &(lowerfixedbuf[(i+1)*dimension1]), &(upperfixedbuf[(i+1)*dimension1])));
+ theKey.setObject(OId(entryidsbuf[i], (OId::OIdType)entrytypesbuf[i]));
+ myKeyObjects.push_back(theKey);
+ RMDBGMIDDLE(5, RMDebug::module_indexif, "DBHierIndex", "entry " << entryidsbuf[i] << " " << (OId::OIdType)entrytypesbuf[i] << " at " << InlineMinterval(dimension1, &(lowerboundsbuf[(i+1)*dimension1]), &(upperboundsbuf[(i+1)*dimension1]), &(lowerfixedbuf[(i+1)*dimension1]), &(upperfixedbuf[(i+1)*dimension1])));
+ }
+
+ delete [] upperboundsbuf;
+ delete [] lowerboundsbuf;
+ delete [] upperfixedbuf;
+ delete [] lowerfixedbuf;
+ delete [] entryidsbuf;
+ delete [] entrytypesbuf;
+ _isInDatabase = true;
+ _isPersistent = true;
+ _isModified = true;
+ currentDbRows = 1;
+
+ LEAVE( "DBHierIndex::setBinaryRepresentation()" );
+ }
+