/*
* 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: persmddobj.cc
*
* MODULE: cachetamgr
* CLASS: MDDObj
*
* COMMENTS:
* none
*
*/
#include "mymalloc/mymalloc.h"
static const char rcsid[] = "@(#)persmddobj, PersMDDObj: $Id: mddobj.cc,v 1.26 2005/07/06 22:43:20 rasdev Exp $";
#include
#include
#include
#include "mddobj.hh"
#include "relmddif/dbmddobj.hh"
#include "relindexif/indexid.hh"
#include "reladminif/eoid.hh"
#include "tilemgr/tile.hh"
#include "relcatalogif/mdddomaintype.hh"
#include "raslib/mddtypes.hh"
#include "raslib/rmdebug.hh"
#include "indexmgr/mddobjix.hh"
const r_Minterval&
MDDObj::checkStorage(const r_Minterval& domain2) throw (r_Error)
{
r_Minterval domain(domain2.dimension());
if (myStorageLayout->getIndexType() == r_Reg_Computed_Index)
{
if (myStorageLayout->getTilingScheme() != r_RegularTiling)
{
RMInit::logOut << "MDDObj::checkStorage(" << domain2 << ") the rc index needs a regular tiling defined" << endl;
throw r_Error(RCINDEXWITHOUTREGULARTILING);
}
r_Dimension dim = domain2.dimension();
// make sure the tileConfig is fixed
r_Minterval tileConfig = myStorageLayout->getTileConfiguration();
myStorageLayout->setTileConfiguration(tileConfig);
r_Point mddDomainExtent = domain2.get_extent();
r_Point tileConfigExtent = tileConfig.get_extent();
for (r_Dimension i = 0; i < dim; i++)
{
if (!domain2[i].is_high_fixed() || !domain2[i].is_low_fixed() || !tileConfig[i].is_high_fixed() || !tileConfig[i].is_low_fixed())
{
RMInit::logOut << "MDDObj::checkStorage(" << domain2 << ") the rc index needs a domain and tile configuration with fixed domains in all dimensions. Dimension " << i << " seems not to be fixed." << endl;
throw r_Error(RCINDEXWITHINCOMPATIBLEMARRAYTYPE);
}
if (mddDomainExtent[i]%tileConfigExtent[i] != 0)
{
RMInit::logOut << "MDDObj::checkStorage(" << domain2 << ") the tile configuration (" << tileConfig << ") does not fit the domain of the marray (" << domain << ")." << endl;
throw r_Error(TILECONFIGMARRAYINCOMPATIBLE);
}
}
}
return domain2;
}
MDDObj::MDDObj(const MDDBaseType* mddType, const r_Minterval& domain)
: myMDDIndex(NULL),
myDBMDDObj(),
myStorageLayout(NULL)
{
if (!mddType)
{
RMInit::logOut << "MDD type is NULL. Please report query or raslib program to Customer Support." << endl;
throw r_Error(MDDTYPE_NULL);
}
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "MDDObj(" << mddType->getName() << ", " << domain << ") " << (r_Ptr)this);
myStorageLayout = new StorageLayout(r_Directory_Index);
myMDDIndex = new MDDObjIx(*myStorageLayout, domain);
myDBMDDObj = new DBMDDObj(mddType, domain, myMDDIndex->getDBMDDObjIxId(), myStorageLayout->getDBStorageLayout());
}
MDDObj::MDDObj(const MDDBaseType* mddType, const r_Minterval& domain, const OId& newOId, const StorageLayout& ms) throw (r_Error)
: myMDDIndex(NULL),
myDBMDDObj(),
myStorageLayout(NULL)
{
if (!mddType)
{
RMInit::logOut << "MDD type is NULL. Please report query or raslib program to Customer Support." << endl;
throw r_Error(MDDTYPE_NULL);
}
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "MDDObj(" << mddType->getName() << ", " << domain << ", " << newOId << ", " << ms.getDBStorageLayout().getOId() << ") " << (r_Ptr)this);
myStorageLayout = new StorageLayout(ms);
myMDDIndex = new MDDObjIx(*myStorageLayout, checkStorage(domain), mddType->getBaseType());
myDBMDDObj = new DBMDDObj(mddType, domain, myMDDIndex->getDBMDDObjIxId(), ms.getDBStorageLayout(), newOId);
}
MDDObj::MDDObj(const DBMDDObjId& dbmddobj) throw(r_Error)
: myMDDIndex(NULL),
myDBMDDObj(dbmddobj),
myStorageLayout(NULL)
{
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "MDDObj(DBRef " << dbmddobj.getOId() << ") " << (r_Ptr)this);
myStorageLayout = new StorageLayout(myDBMDDObj->getDBStorageLayout());
myMDDIndex = new MDDObjIx(myDBMDDObj->getDBIndexDS(), *myStorageLayout, myDBMDDObj->getMDDBaseType()->getBaseType());
}
MDDObj::MDDObj(const OId& givenOId) throw(r_Error)
: myMDDIndex(NULL),
myDBMDDObj(OId()),
myStorageLayout(NULL)
{
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "MDDObj(" << givenOId << ") " << (r_Ptr)this);
myDBMDDObj = DBMDDObjId(givenOId);
myStorageLayout = new StorageLayout(myDBMDDObj->getDBStorageLayout());
myMDDIndex = new MDDObjIx(myDBMDDObj->getDBIndexDS(), *myStorageLayout, myDBMDDObj->getMDDBaseType()->getBaseType());
}
MDDObj::MDDObj(const MDDBaseType* mddType, const r_Minterval& domain, const StorageLayout& ms)
: myMDDIndex(NULL),
myDBMDDObj(OId()),
myStorageLayout(NULL)
{
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "MDDObj(" << mddType->getName() << ", " << domain << ", " << ms.getDBStorageLayout().getOId() << ") " <<(r_Ptr)this);
if (!mddType)
{
RMInit::logOut << "MDD type is NULL. Please report query or raslib program to Customer Support." << endl;
throw r_Error(MDDTYPE_NULL);
}
myStorageLayout = new StorageLayout(ms);
myMDDIndex = new MDDObjIx(*myStorageLayout, checkStorage(domain), mddType->getBaseType());
myDBMDDObj = new DBMDDObj(mddType, domain, myMDDIndex->getDBMDDObjIxId(), ms.getDBStorageLayout());
myDBMDDObj->setPersistent();
}
/*
insert tile:
tiles may have to be retiled.
the storage layout returns the domains into which the tile should be divided before insertion.
if there is not enough data to fill a complete layout domain, then 0 will be set.
*/
void
MDDObj::insertTile(Tile* newTile)
{
RMDBGENTER(2, RMDebug::module_mddmgr, "MDDObj", "insertTile(Tile " << newTile->getDomain() << ")")
std::vector layoutDoms = myStorageLayout->getLayout(newTile->getDomain());
RMDBGIF(10, RMDebug::module_mddmgr, "printlayoutdoms", \
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "storage layout returned the following domains") \
for (std::vector ::iterator domit = layoutDoms.begin(); domit != layoutDoms.end(); domit++) \
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", *domit) \
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "end of storage layout domains"))
Tile* tile = NULL;
Tile* tile2 = NULL;
r_Area tempArea = 0;
r_Area completeArea = 0;
r_Minterval tempDom;
r_Minterval tileDom = newTile->getDomain();
std::vector* indexTiles = NULL;
char* newContents = NULL;
size_t sizeOfData = 0;
bool checkEquality = true;
for (std::vector::iterator it = layoutDoms.begin(); it != layoutDoms.end(); it++)
{
if (checkEquality && tileDom == *it)
{// normal case. just insert the tile.
// this case also means that there was no insertion in the previous loops
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "tile domain is same as layout domain, just inserting data")
myMDDIndex->insertTile((Tile*)newTile);
// set to NULL so it will not get deleted at the end of the method
newTile = NULL;
if (layoutDoms.size() != 1)
{
RMInit::logOut << "MDDObj::insertTile(Tile " << tileDom << ") the layout has more than one element but the tile domain completely covers the layout domain" << endl;
throw r_Error(LAYOUTALGORITHMPROBLEM);
}
}
else {// we need to check if there is already a tile defined here
// this could have been created in a previous loop run
// we are using retiling here. *it is therefore an indivisible layout domain.
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "tile domain (" << tileDom << ") is not the same as layout domain (" << *it << ")")
indexTiles = myMDDIndex->intersect(*it);
if (indexTiles)
{// there was a tile in the run before, which overlapped with this layout domain
// there may only be one entry in the index for this domain.
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "found tiles (" << indexTiles->size() << ") in layout domain " << *it)
if (indexTiles->size() != 1)
{
RMInit::logOut << "MDDObj::insertTile(Tile " << tileDom << ") the index contains many entries for one layout domain" << endl;
throw r_Error(LAYOUTALGORITHMPROBLEM);
}
// update the existing tile with the new data
tempDom = (*it).create_intersection(tileDom);
(*(indexTiles->begin()))->copyTile(tempDom, newTile, tempDom);
//RMInit::dbgOut << "updated tile to" << endl;
// (*(indexTiles->begin()))->printStatus(99,RMInit::dbgOut);
}
else {// there was no tile overlapping the current layout domain yet
// create a new tile covering the whole layout domain
// must be computed everytime because layoutDoms may change in size
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "found no tiles in layout domain " << *it)
// generate a tile of the domain : layout domain
completeArea = (*it).cell_count();
sizeOfData = sizeof(char) * completeArea * getMDDBaseType()->getBaseType()->getSize();
newContents = (char*)mymalloc(sizeOfData);
// initialise to 0
memset(newContents, 0, sizeOfData);
tile = new Tile(*it, getMDDBaseType()->getBaseType(), newContents, 0, newTile->getDataFormat());
tile->setParameters(newTile->getParameters());
tempDom = (*it).create_intersection(tileDom);
// only update the actual data - the rest was set to 0
tile->copyTile(tempDom, newTile, tempDom);
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "created tile with domain " << tile->getDomain())
//RMInit::dbgOut << "insert tile" << endl;
// tile->printStatus(99,RMInit::dbgOut);
//FIXME: should not be neccessary
tile->compress();
myMDDIndex->insertTile((Tile*)tile);
}
}
checkEquality = false;
}
if (newTile)
{
RMDBGMIDDLE(2, RMDebug::module_mddmgr, "MDDObj", "have to delete newTile")
if (newTile->isPersistent())
((Tile*)newTile)->getDBTile()->setPersistent(false);
delete newTile;
}
RMDBGEXIT(2, RMDebug::module_mddmgr, "MDDObj", "insertTile(Tile)")
}
std::vector< Tile* >*
MDDObj::intersect(const r_Minterval& searchInter) const
{
std::vector* retval = myMDDIndex->intersect(searchInter);
RMDBGIF(10, RMDebug::module_mddmgr, "printtiles", \
if (retval) \
{ \
int t = RManDebug; \
RManDebug = 0; \
for (std::vector::iterator it = retval->begin(); it != retval->end();it++) \
{ \
RMInit::dbgOut << "FOUND " << (*it)->getDomain() << " " << endl; \
(*it)->printStatus(0, RMInit::dbgOut); \
} \
RManDebug = t; \
})
return retval;
}
std::vector< Tile* >*
MDDObj::getTiles() const
{
return myMDDIndex->getTiles();
}
char*
MDDObj::pointQuery(const r_Point& searchPoint)
{
return myMDDIndex->pointQuery(searchPoint);
}
const char*
MDDObj::pointQuery(const r_Point& searchPoint) const
{
return myMDDIndex->pointQuery(searchPoint);
}
DBMDDObjId
MDDObj::getDBMDDObjId() const
{
return myDBMDDObj;
}
const MDDBaseType*
MDDObj::getMDDBaseType() const
{
return myDBMDDObj->getMDDBaseType();
}
r_Minterval
MDDObj::getDefinitionDomain() const
{
return myDBMDDObj->getDefinitionDomain();
}
r_Minterval
MDDObj::getCurrentDomain() const
{
return myMDDIndex->getCurrentDomain();
}
const char*
MDDObj::getCellTypeName() const
{
return myDBMDDObj->getCellTypeName();
}
const BaseType*
MDDObj::getCellType() const
{
return myDBMDDObj->getCellType();
}
r_Dimension
MDDObj::getDimension() const
{
return myDBMDDObj->dimensionality();
}
bool
MDDObj::isPersistent() const
{
return myDBMDDObj->isPersistent();
}
int
MDDObj::getOId(OId* pOId) const
{
*pOId = myDBMDDObj->getOId();
return (pOId->getCounter() == 0);
}
int
MDDObj::getEOId(EOId* pEOId) const
{
*pEOId = myDBMDDObj->getEOId();
return (pEOId->getCounter() == 0);
}
void
MDDObj::printStatus(unsigned int level, std::ostream& stream) const
{
myDBMDDObj->printStatus(level, stream);
myMDDIndex->printStatus(level, stream);
}
void
MDDObj::removeTile(Tile*& tileToRemove)
{
int found = myMDDIndex->removeTile(tileToRemove);
if (found)
{
// frees its memory. Persistent freeing??
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "removeTile() about to delete tile")
((Tile*) tileToRemove)->getDBTile().delete_object();
delete tileToRemove;
tileToRemove = 0;
}
}
MDDObj::~MDDObj()
{
RMDBGONCE(2, RMDebug::module_mddmgr, "MDDObj", "~MDDObj() " << (r_Ptr)this)
delete myMDDIndex;
myMDDIndex = NULL;
delete myStorageLayout;
myStorageLayout = NULL;
}
void
MDDObj::releaseTiles()
{
myMDDIndex->releasePersTiles();
}