/* * 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 . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * SOURCE: mddobjix.cc * * MODULE: indexmgr * CLASS: MDDObjIx * * COMMENTS: * none * */ static const char rcsid[] = "@(#)mddobjix, MDDObjIx: $Id: mddobjix.cc,v 1.30 2002/07/24 14:33:51 hoefner Exp $"; #include #include #include "indexmgr/mddobjix.hh" #include "raslib/rmdebug.hh" #include "tilemgr/tile.hh" #include "indexmgr/srptindexlogic.hh" #include "indexmgr/sdirindexlogic.hh" #include "indexmgr/srcindexlogic.hh" #include "indexmgr/transdirix.hh" #include "relindexif/hierindex.hh" #include "relindexif/dbtcindex.hh" #include "relindexif/dbrcindexds.hh" #include "keyobject.hh" #include "reladminif/lists.h" #include "relblobif/tileid.hh" void MDDObjIx::setNewLastAccess(const r_Minterval& newLastAccess, const std::vector* newLastTiles) { lastAccess = newLastAccess; releasePersTiles(); lastAccessTiles = *newLastTiles; } void MDDObjIx::setNewLastAccess(const Tile* newLastTile, bool clear) { if (clear) { releasePersTiles(); lastAccessTiles.erase(lastAccessTiles.begin(), lastAccessTiles.end()); } if (newLastTile) { r_Minterval region = newLastTile->getDomain(); lastAccess = region; lastAccessTiles.push_back((Tile*)newLastTile); } } bool MDDObjIx::removeTileFromLastAccesses(const Tile* tileToRemove) { bool found = false; std::vector::iterator iter; for (iter = lastAccessTiles.begin(); iter != lastAccessTiles.end() ; iter++) { if (*iter == tileToRemove) { found = true; lastAccessTiles.erase(iter); break; } } if (found) { r_Minterval emptyInterval; lastAccess = emptyInterval; } return found; } std::vector< Tile* >* MDDObjIx::lastAccessIntersect(const r_Minterval& searchInter) const { std::vector< Tile* >* interResult = 0; if ((lastAccess.dimension() != 0) && (lastAccess.covers(searchInter))) { RMDBGONCE(6, RMDebug::module_indexmgr, "MDDObjIx", "lastAccessIntersect Search in the cache ") interResult = new std::vector< Tile* >(); interResult->reserve(10); for (int i = 0; i < lastAccessTiles.size(); i++) { if (lastAccessTiles[i]->getDomain().intersects_with(searchInter)) interResult->push_back(lastAccessTiles[i]); } if (interResult->size() == 0) { delete interResult; interResult = NULL; } } return interResult; } Tile* MDDObjIx::lastAccessPointQuery(const r_Point& searchPoint) const { Tile* result = 0; if ((lastAccess.dimension() != 0) && (lastAccess.covers(searchPoint))) { for (int i = 0; !result && i < lastAccessTiles.size(); i++) { if (lastAccessTiles[i]->getDomain().covers(searchPoint)) { result = lastAccessTiles[i]; } } } return (result); } void MDDObjIx::releasePersTiles() { RMDBGENTER(6, RMDebug::module_indexmgr, "MDDObjIx", "releasePersTiles()") if (isPersistent()) { Tile* t = NULL; for(int i = 0; i < lastAccessTiles.size(); i++) { t = lastAccessTiles[i]; delete t; lastAccessTiles[i] = NULL; } lastAccessTiles.clear(); } RMDBGEXIT(6, RMDebug::module_indexmgr, "MDDObjIx", "releasePersTiles()") } void MDDObjIx::printStatus(unsigned int level, std::ostream& stream) const { stream << "MDDObjIx [ last access interval = " << lastAccess << " tile cache size = " << lastAccessTiles.size() << " index structure = "; actualIx->printStatus(level, stream); } DBObjectId MDDObjIx::getDBMDDObjIxId() const { return actualIx; } r_Minterval MDDObjIx::getCurrentDomain() const { return actualIx->getCoveredDomain(); } r_Dimension MDDObjIx::getDimension() const { return actualIx->getDimension(); } #ifdef RMANBENCHMARK void MDDObjIx::initializeTimerPointers() { pointQueryTimer= new RMTimer("DirIx", "pointQuery"); intersectTimer = new RMTimer("DirIx", "intersect"); getTilesTimer = new RMTimer("DirIx", "getTiles"); } #endif MDDObjIx::MDDObjIx(const StorageLayout& sl, const r_Minterval& dim, const BaseType* bt) : cellBaseType(bt), myStorageLayout(sl), actualIx(0), _isPersistent(true) { RMDBGENTER(10, RMDebug::module_indexmgr, "MDDObjIx", "MDDObjIx(storage, " << dim << ", type)") lastAccessTiles.reserve(10); if (bt == NULL) { RMDBGMIDDLE(10, RMDebug::module_indexmgr, "MDDObjIx", "TransIndex") _isPersistent = false; } initializeLogicStructure(); if (isPersistent()) { r_Range temp; switch(myStorageLayout.getIndexType()) { case r_RPlus_Tree_Index: actualIx = (HierIndexDS*)new DBHierIndex(dim.dimension(), false, true); break; case r_Reg_Computed_Index: actualIx = new DBRCIndexDS(dim, SRCIndexLogic::computeNumberOfTiles(myStorageLayout, dim)); break; case r_Tile_Container_Index: actualIx = (HierIndexDS*)new DBTCIndex(dim.dimension(), false); break; case r_Directory_Index: actualIx = (HierIndexDS*)new DBHierIndex(dim.dimension(), false, true); break; case r_Auto_Index: default: // should never get here. If Auto_Index, a specific index was RMDBGONCE(0, RMDebug::module_indexmgr, "MDDObjIx", "initializeLogicStructure() Auto_Index or unknown index chosen"); throw r_Error(UNKNOWN_INDEX_TYPE); break; } } else { //only dirindex supports transient indexes actualIx = new TransDirIx(dim.dimension()); } #ifdef RMANBENCHMARK initializeTimerPointers(); #endif RMDBGEXIT(10, RMDebug::module_indexmgr, "MDDObjIx", "MDDObjIx(storage, " << dim << ", type)") } MDDObjIx::MDDObjIx(DBObjectId newDBIx, const StorageLayout& sl, const BaseType* bt) : cellBaseType(bt), myStorageLayout(sl), actualIx(newDBIx), _isPersistent(true) { initializeLogicStructure(); lastAccessTiles.reserve(10); #ifdef RMANBENCHMARK initializeTimerPointers(); #endif } void MDDObjIx::initializeLogicStructure() { switch(myStorageLayout.getIndexType()) { case r_RPlus_Tree_Index: case r_Tile_Container_Index: do_getObjs = SRPTIndexLogic::getObjects; do_insertObj = SRPTIndexLogic::insertObject2; do_pointQuery = SRPTIndexLogic::containPointQuery2; do_removeObj = SRPTIndexLogic::removeObject; do_intersect = SRPTIndexLogic::intersect2; break; case r_Reg_Computed_Index: do_getObjs = SRCIndexLogic::getObjects; do_insertObj = SRCIndexLogic::insertObject; do_pointQuery = SRCIndexLogic::containPointQuery; do_removeObj = SRCIndexLogic::removeObject; do_intersect = SRCIndexLogic::intersect; break; case r_Directory_Index: // chosen before this do_getObjs = SDirIndexLogic::getObjects; do_pointQuery = SDirIndexLogic::containPointQuery; do_removeObj = SDirIndexLogic::removeObject; do_intersect = SDirIndexLogic::intersect; do_insertObj = SDirIndexLogic::insertObject; break; default: case r_Auto_Index: // should never get here. If Auto_Index, a specific index was RMInit::logOut << "MDDObjIx::initializeLogicStructure() illegal index (" << myStorageLayout.getIndexType() << ") chosen!" << endl; throw r_Error(ILLEGAL_INDEX_TYPE); break; } } void MDDObjIx::insertTile(const Tile* newTile) { if (isPersistent()) { ((Tile*)newTile)->setPersistent(); } KeyObject t(newTile); do_insertObj(actualIx, t, myStorageLayout); setNewLastAccess(newTile, false); } bool MDDObjIx::removeTile(const Tile* tileToRemove) { RMDBGENTER(4, RMDebug::module_indexmgr, "MDDObjIx", "removeTile(Tile)") bool found = false; // removes from cache, if it's there removeTileFromLastAccesses(tileToRemove); // removes from the index itself KeyObject t(tileToRemove); found = do_removeObj(actualIx, t, myStorageLayout); RMDBGEXIT(4, RMDebug::module_indexmgr, "MDDObjIx", "removeTile(Tile)") return found; } vector< Tile* >* MDDObjIx::intersect(const r_Minterval& searchInter) const { RMDBGENTER(4, RMDebug::module_indexmgr, "MDDObjIx", "intersect(" << searchInter << ")") #ifdef RMANBENCHMARK if(RManBenchmark >= 3) intersectTimer->start(); #endif vector< Tile* >* result = lastAccessIntersect(searchInter); if (!result) { KeyObjectVector resultKeys; do_intersect(actualIx, searchInter, resultKeys, myStorageLayout); result = new vector< Tile* >(); if (!resultKeys.empty()) { unsigned int resSize = resultKeys.size(); result->reserve(resSize); Tile* t = NULL; unsigned int i = 0; if (isPersistent()) { //this checks if there are double tiles in the result RMDBGIF(1, RMDebug::module_indexmgr, "MDDObjIx", \ DomainMap t; \ DomainMap::iterator it; \ for (i = 0; i < resSize; i++) \ { \ DomainPair p(resultKeys[i].getObject().getOId(), \ resultKeys[i].getDomain()); \ if ((it = t.find(p.first)) != t.end()) \ { \ RMDBGMIDDLE(0, RMDebug::module_indexmgr, "MDDObjIx", \ "intersect(" << searchInter << \ ") received double tile: " << \ resultKeys[i]) \ for (int i = 0; i < resultKeys.size(); i++) \ { \ RMInit::dbgOut << resultKeys[i] << endl; \ } \ throw r_Error(TILE_MULTIPLE_TIMES_RETRIEVED); \ } \ t.insert(p); \ } \ ); for (i = 0; i < resSize; i++) { RMDBGMIDDLE(4, RMDebug::module_indexmgr, "MDDObjIx", "received entry " << resultKeys[i]) result->push_back(new Tile(resultKeys[i].getDomain(), cellBaseType, DBTileId(resultKeys[i].getObject()))); } } else { for (i = 0; i < resSize; i++) { result->push_back(resultKeys[i].getTransObject()); } } ((MDDObjIx*) this)->setNewLastAccess(searchInter, result); } } #ifdef RMANBENCHMARK if(RManBenchmark >= 3) intersectTimer->stop(); #endif RMDBGEXIT(4, RMDebug::module_indexmgr, "MDDObjIx", "intersect(" << searchInter << ") " << (void*)result) return result; } char* MDDObjIx::pointQuery(const r_Point& searchPoint) { char* result = 0; Tile* resultTile = containPointQuery(searchPoint); if(resultTile) { result = resultTile->getCell(searchPoint); } return result; } const char* MDDObjIx::pointQuery(const r_Point& searchPoint) const { const char* result = 0; Tile* resultTile = containPointQuery(searchPoint); if(resultTile) { result = resultTile->getCell(searchPoint); } return result; } Tile* MDDObjIx::containPointQuery(const r_Point& searchPoint) const { Tile* resultTile = 0; #ifdef RMANBENCHMARK if(RManBenchmark >= 4) pointQueryTimer->start(); #endif resultTile = lastAccessPointQuery(searchPoint); if (!resultTile) { KeyObject resultKey; do_pointQuery(actualIx, searchPoint, resultKey, myStorageLayout); if (resultKey.isInitialised()) { if (isPersistent()) { resultTile = new Tile(resultKey.getDomain(), cellBaseType, DBTileId(resultKey.getObject())); // for rcindex ((DBObject*)resultKey.getObject().ptr())->setCached(false); } else { resultTile = resultKey.getTransObject(); } ((MDDObjIx*) this)->setNewLastAccess(resultTile); } } #ifdef RMANBENCHMARK if (RManBenchmark >= 4) pointQueryTimer->stop(); #endif return resultTile; } vector< Tile* >* MDDObjIx::getTiles() const { #ifdef RMANBENCHMARK if(RManBenchmark >= 3) getTilesTimer->start(); #endif vector< Tile* >* result = NULL; KeyObjectVector resultKeys; do_getObjs(actualIx, resultKeys, myStorageLayout); if (!resultKeys.empty()) { result = new vector< Tile* >(); unsigned int resSize = resultKeys.size(); result->reserve(resSize); Tile* t = 0; if (isPersistent()) { //this checks if there are double tiles in the result RMDBGIF(1, RMDebug::module_indexmgr, "MDDObjIx", \ DomainMap tmap; \ DomainMap::iterator it; \ for (int cnt = 0; cnt < resSize; cnt++) \ { \ DomainPair p(resultKeys[cnt].getObject().getOId(), \ resultKeys[cnt].getDomain()); \ if ((it = tmap.find(p.first)) != tmap.end()) \ { \ RMDBGMIDDLE(0, RMDebug::module_indexmgr, "MDDObjIx", \ "getTiles() received double tile: " << \ resultKeys[cnt]) \ for (int cnt = 0; cnt < resultKeys.size(); cnt++) \ { \ RMInit::dbgOut << resultKeys[cnt] << endl; \ } \ throw r_Error(TILE_MULTIPLE_TIMES_RETRIEVED ); \ } \ tmap.insert(p); \ } \ ); for (int i = 0; i < resSize; i++) { result->push_back(new Tile(resultKeys[i].getDomain(), cellBaseType, DBTileId(resultKeys[i].getObject()))); } } else { for (int i = 0; i < resultKeys.size(); i++) { result->push_back(resultKeys[i].getTransObject()); } } r_Minterval emptyInterval; ((MDDObjIx*) this)->setNewLastAccess(emptyInterval, result); } #ifdef RMANBENCHMARK if(RManBenchmark >= 3) getTilesTimer->stop(); #endif return result; } bool MDDObjIx::isPersistent() const { return _isPersistent; } MDDObjIx::~MDDObjIx() { releasePersTiles(); actualIx->destroy(); actualIx = 0; #ifdef RMANBENCHMARK pointQueryTimer->setOutput(0); if (pointQueryTimer) delete pointQueryTimer; intersectTimer->setOutput(0); if (intersectTimer) delete intersectTimer; getTilesTimer->setOutput(0); if (getTilesTimer) delete getTilesTimer; #endif }