diff options
Diffstat (limited to 'tilemgr/tile.cc')
-rw-r--r-- | tilemgr/tile.cc | 1187 |
1 files changed, 1187 insertions, 0 deletions
diff --git a/tilemgr/tile.cc b/tilemgr/tile.cc new file mode 100644 index 0000000..627a336 --- /dev/null +++ b/tilemgr/tile.cc @@ -0,0 +1,1187 @@ +#include "mymalloc/mymalloc.h" + +/* +* 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: + * Tiles store BLOBTiles together with their type and + * their coordinates. + * + * + * COMMENTS: + * none + * + ************************************************************/ + +static const char rcsid[] = "@(#)cachetamgr,Tile: $Id: tile.cc,v 1.79 2005/09/03 21:05:53 rasdev Exp $"; + +#include <iostream> +#include "catalogmgr/ops.hh" +#include "tile.hh" +#include "relblobif/blobtile.hh" +#include "reladminif/adminif.hh" +#include "relblobif/inlinetile.hh" +#include "compression/tilecompression.hh" +#include "raslib/rmdebug.hh" +#include "raslib/miter.hh" +#include "raslib/miterf.hh" +#include "raslib/miterd.hh" +#include "raslib/basetype.hh" + +#include <cstring> + +const Tile& +Tile::operator=(const Tile& tile) + { + if(this != &tile) + { + type = tile.type; + domain = tile.domain; + //cloning is faster than recreation + if (tile.compEngine != NULL) { + if(compEngine != NULL) { + delete compEngine; + } + compEngine = tile.compEngine->clone(); + } + blobTile->resize(tile.blobTile->getSize()); + blobTile->setDataFormat(tile.blobTile->getDataFormat()); + blobTile->setCurrentFormat(tile.blobTile->getCurrentFormat()); + memcpy(blobTile->getCells(), tile.blobTile->getCells(), blobTile->getSize()); + setParameters(tile.getParameters()); + } + return *this; + } + +Tile::Tile(const Tile& tile) + : domain(tile.domain), + type(tile.type), + blobTile((DBTile*)NULL), + //cloning is faster than recreation + compEngine(NULL), + params(NULL) + { + if (tile.compEngine != NULL) + compEngine = tile.compEngine->clone(); + if (RMInit::useTileContainer) + blobTile = new InlineTile(tile.blobTile->getSize(), tile.blobTile->getCells(), tile.blobTile->getDataFormat()); + else + blobTile = new BLOBTile(tile.blobTile->getSize(), tile.blobTile->getCells(), tile.blobTile->getDataFormat()); + blobTile->setCurrentFormat(tile.blobTile->getCurrentFormat()); + setParameters(tile.getParameters()); + } + +Tile::Tile(std::vector<Tile*>* tilesVec) + : domain(), + type(NULL), + compEngine(NULL), + params(NULL), + blobTile((DBTile*)NULL) + { + // iterators for tiles + std::vector<Tile*>::iterator tileIt = tilesVec->begin(); + std::vector<Tile*>::iterator tileEnd = tilesVec->end(); + domain = (*(tileIt++))->getDomain(); + while (tileIt != tilesVec->end()) + { + domain.closure_with((*(tileIt++))->getDomain()); + } + tileIt = tilesVec->begin(); + // initialize type with type of first tile + type = (*tileIt)->getType(); + if (RMInit::useTileContainer) + blobTile = new InlineTile(getSize(), (char)0, (*tileIt)->getDataFormat()); + else + blobTile = new BLOBTile(getSize(), (char)0, (*tileIt)->getDataFormat()); + // initialize compression with compression of first tile + //cloning is faster than recreation + if ((*tileIt)->compEngine != NULL) + compEngine = (*tileIt)->compEngine->clone(); + setParameters((*tileIt)->getParameters()); + // initialize domain + domain = (*(tileIt++))->getDomain(); + while (tileIt != tileEnd) + domain.closure_with((*(tileIt++))->getDomain()); + + // insert all tiles in the result tile + tileIt = tilesVec->begin(); + while (tileIt != tileEnd) + { + const r_Minterval& currDom = (*tileIt)->getDomain(); + copyTile(currDom, (*tileIt), currDom); + tileIt++; + } + } + +Tile::Tile(std::vector<Tile*>* tilesVec, const r_Minterval& resDom) + : params(NULL), + domain(resDom), + compEngine(NULL) + { + // iterators for tiles + std::vector<Tile*>::iterator tileIt; + // domain of the current tile + r_Minterval currDom; + + // get first Tile + tileIt = tilesVec->begin(); + // initialize type with type of first tile + type = (*tileIt)->getType(); + // initialize compression with compression of first tile + //cloning is faster than recreation + if ((*tileIt)->compEngine != NULL) + compEngine = (*tileIt)->compEngine->clone(); + setParameters((*tileIt)->getParameters()); + + // init contents + if (RMInit::useTileContainer) + blobTile = new InlineTile(getSize(), (char)0, (*tileIt)->getDataFormat()); + else + blobTile = new BLOBTile(getSize(), (char)0, (*tileIt)->getDataFormat()); + + // insert all tiles in the result tile + tileIt = tilesVec->begin(); + while (tileIt != tilesVec->end()) + { + currDom = (*tileIt)->getDomain(); + currDom.intersection_with(resDom); + + copyTile(currDom, (*tileIt), currDom); + + tileIt++; + } + } + +Tile::Tile(const Tile* projTile, const r_Minterval& projDom, const std::set<r_Dimension, std::less<r_Dimension> >* projDimSet) + : domain(projDom.dimension() - projDimSet->size()), + type(projTile->type), + compEngine(NULL), + params(NULL), + blobTile((DBTile*)NULL) + { + // calculate dimension of new Tile + r_Dimension dim = 0; + // pointer to cells in tile to be projected and new tile + char* cellTile = NULL; + char* cellProj = NULL; + + for(dim = 0; dim < projDom.dimension(); dim++) + { + // do not include dimensions projected away + std::set<r_Dimension, std::less<r_Dimension> >::const_iterator tempIt = projDimSet->find(dim); + if(tempIt == projDimSet->end()) + { + domain << projDom[dim]; + } + } + + RMDBGONCE(3, RMDebug::module_tilemgr, "Tile", "domain result: " << domain << " domain original: " << projTile->getDomain()); + + // have to initialize the uncompressed contents in case an operation is called on the tile + //cloning is faster than recreation + if (projTile->compEngine) + compEngine = projTile->compEngine->clone(); + setParameters(projTile->getParameters()); + + // init contents + if (RMInit::useTileContainer) + blobTile = new InlineTile(getSize(), (char)0, projTile->getDataFormat()); + else + blobTile = new BLOBTile(getSize(), (char)0, projTile->getDataFormat()); + // using r_Miter to iterate through tile to be projected and new tile. + r_Miter projTileIter(&projDom, &projTile->getDomain(), type->getSize(), (const char*)projTile->getContents()); + r_Miter newTileIter(&domain, &domain, type->getSize(), blobTile->getCells()); + + // identity operation for base type, used for copying + UnaryOp* op = type->getUnaryOp(Ops::OP_IDENTITY, (BaseType*)type); + + while(!projTileIter.isDone()) + { + cellTile = newTileIter.nextCell(); + cellProj = projTileIter.nextCell(); + RMDBGONCE(3, RMDebug::module_tilemgr, "TransTile", "offset in original: " << (int)(cellProj-((Tile*)projTile)->getContents()) << " {" << (int)*cellProj << "} offset in result: " << (int)((int)(cellTile-getContents())) << " {" << (int)*cellTile << "}"); + // execute operation on cell + (*op)(cellTile, cellProj); + } + + delete op; + } + +Tile::Tile(const r_Minterval& newDom, const BaseType* newType, DBTileId newBLOBTile) + : domain(newDom), + type(newType), + params(NULL), + compEngine(NULL), + blobTile(newBLOBTile) + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","Tile(" << newDom << ", " << newType->getName() << ", blob)"); + } + +Tile::Tile(const r_Minterval& newDom, const BaseType* newType, r_Data_Format newFormat) + : domain(newDom), + params(NULL), + type(newType), + compEngine(NULL), + blobTile((DBTile*)NULL) + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","Tile(new), size " << getSize()); + // note that the size is not correct (usually too big) for compressed + // tiles. Doesn't matter, because resize is called anyway. + if (RMInit::useTileContainer) + blobTile = new InlineTile(getSize(), (char)0, newFormat); + else + blobTile = new BLOBTile(getSize(), (char)0, newFormat); + //not neccessary now + //initCompEngine(); + } + +Tile::Tile(const r_Minterval& newDom, const BaseType* newType, char* newCells, r_Bytes newSize, r_Data_Format newFormat) + : domain(newDom), + params(NULL), + type(newType), + compEngine(NULL), + blobTile((DBTile*)NULL) + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","Tile(), fmt " << newFormat << ", size " << newSize); + r_Data_Format current = r_Array; + if (!newSize) + { + // setting uncompressed contents + newSize = getSize(); + } + else { + // setting compressed contents + current = newFormat; + } + if (RMInit::useTileContainer) + blobTile = new InlineTile(newSize, newCells, newFormat); + else + blobTile = new BLOBTile(newSize, newCells, newFormat); + blobTile->setCurrentFormat(current); + free(newCells); + //not neccessary now + //initCompEngine(); + } + +Tile::Tile(const r_Minterval& newDom, const BaseType* newType, const char* newCells, bool, r_Bytes newSize, r_Data_Format newFormat) + : domain(newDom), + params(NULL), + type(newType), + compEngine(NULL), + blobTile((DBTile*)NULL) + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","Tile(), fmt " << newFormat << ", size " << newSize); + r_Data_Format current = r_Array; + if (!newSize) + { + // setting uncompressed contents + newSize = getSize(); + } + else { + // setting compressed contents + current = newFormat; + } + if (RMInit::useTileContainer) + blobTile = new InlineTile(newSize, newCells, newFormat); + else + blobTile = new BLOBTile(newSize, newCells, newFormat); + blobTile->setCurrentFormat(current); + // this one doesn't do this stupid thing: free(newCells); + //not neccessary now + //initCompEngine(); + } + +void +Tile::initCompEngine() const + { + if (compEngine == NULL) + { + char* typeStruct = type->getTypeStructure(); + r_Base_Type *useType = (r_Base_Type*)(r_Type::get_any_type(typeStruct)); + compEngine = r_Tile_Compression::create(blobTile->getDataFormat(), domain, useType); + delete useType; + free(typeStruct); + } + } + +void +Tile::setCompressionFormat(r_Data_Format newFormat) + { + if (blobTile->getDataFormat() != newFormat) + { + decompress(); + delete compEngine; + char* typeStruct = type->getTypeStructure(); + r_Base_Type *useType = (r_Base_Type*)(r_Type::get_any_type(typeStruct)); + compEngine = r_Tile_Compression::create(newFormat, domain, useType); + delete useType; + free(typeStruct); + blobTile->setDataFormat(newFormat); + } + } + +void +Tile::setPersistent(bool state) + { + blobTile->setPersistent(state); + } + +r_Bytes +Tile::getCompressedSize() const + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","getCompressedSize()"); + compress(); + return blobTile->getSize(); + } + +const char* +Tile::getCompressedContents() const + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile","getCompressedContents() const"); + compress(); + const char* cellPtr = blobTile->getCells(); + return cellPtr; + } + +bool +Tile::isPersistent() const + { + return blobTile->isPersistent(); + } + +Tile::~Tile() + { + RMDBGONCE(3, RMDebug::module_rasodmg, "Tile", "~Tile() " << (r_Ptr) this); + // this function has to check now if a tile has to be compressed. + // The old scheme of compression in AdminIf::compCompTiles does + // not work, because tiles may be destroyed before with releaseAll. + compress(); + delete compEngine; + delete [] params; + } + +DBTileId +Tile::getDBTile() + { + return blobTile; + } + +char* +Tile::execCondenseOp(CondenseOp* myOp, const r_Minterval& areaOp) + { + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "execCondenseOp()"); + char* cellOp = NULL; + char* dummy = getContents(); + r_Miter opTileIter(&areaOp, &getDomain(), getType()->getSize(), dummy); +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + + while(!opTileIter.isDone()) + { + cellOp = opTileIter.nextCell(); + // execute operation on cell + (*myOp)(cellOp); + } + +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "execCondenseOp()"); + + return myOp->getAccuVal(); + } + + +void +Tile::execUnaryOp(UnaryOp* myOp, const r_Minterval& areaRes, const Tile* opTile, const r_Minterval& areaOp) + { + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "execUnaryOp()"); + char* cellRes = NULL; + const char* cellOp = NULL; + + char* dummy1 = getContents(); + const char* dummy2 = opTile->getContents(); + r_Miter resTileIter(&areaRes, &getDomain(), getType()->getSize(), dummy1); + r_Miter opTileIter(&areaOp, &opTile->getDomain(), opTile->getType()->getSize(), dummy2); + +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + + while(!resTileIter.isDone()) + { + cellRes = resTileIter.nextCell(); + cellOp = opTileIter.nextCell(); + // execute operation on cell + (*myOp)(cellRes, cellOp); + } + +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "execUnaryOp()"); + } + +void +Tile::execBinaryOp(BinaryOp* myOp, const r_Minterval& areaRes, const Tile* op1Tile, const r_Minterval& areaOp1, const Tile* op2Tile, const r_Minterval& areaOp2) + + { + if ( myOp == NULL ) + { + throw r_Error (OPERANDSRESULTTYPESNOMATCH); + } + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "execBinaryOp()"); + char* cellRes = NULL; + const char* cellOp1 = NULL; + const char* cellOp2 = NULL; + + char* dummy1 = getContents(); + const char* dummy2 = op1Tile->getContents(); + const char* dummy3 = op2Tile->getContents(); + + r_Miter resTileIter(&areaRes, &getDomain(), getType()->getSize(), dummy1); + r_Miter op1TileIter(&areaOp1, &op1Tile->getDomain(), op1Tile->getType()->getSize(), dummy2); + r_Miter op2TileIter(&areaOp2, &op2Tile->getDomain(), op2Tile->getType()->getSize(), dummy3); + +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + + while(!resTileIter.isDone()) + { + cellRes = resTileIter.nextCell(); + cellOp1 = op1TileIter.nextCell(); + cellOp2 = op2TileIter.nextCell(); + // execute operation on cell + (*myOp)(cellRes, cellOp1, cellOp2); + } + +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "execBinaryOp()"); + } + +void +Tile::execConstOp(BinaryOp* myOp, const r_Minterval& areaRes, const Tile* opTile, const r_Minterval& areaOp, const char* cell, int constPos) + { + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "execConstOp()"); + char* cellRes = NULL; + const char* cellOp = NULL; + char* dummy1 = getContents(); + const char* dummy2 = opTile->getContents(); + r_Miter resTileIter(&areaRes, &getDomain(), getType()->getSize(), dummy1); + r_Miter opTileIter(&areaOp, &opTile->getDomain(), opTile->getType()->getSize(), dummy2); +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + + if (constPos == 1) + { + while(!resTileIter.isDone()) + { + cellRes = resTileIter.nextCell(); + cellOp = opTileIter.nextCell(); + // execute operation on cell + (*myOp)(cellRes, cell, cellOp); + } + } + else { + while(!resTileIter.isDone()) + { + cellRes = resTileIter.nextCell(); + cellOp = opTileIter.nextCell(); + // execute operation on cell + (*myOp)(cellRes, cellOp, cell); + } + } + +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "execConstOp()"); + } + +void +Tile::execMarrayOp(MarrayOp* myOp, const r_Minterval& areaRes, const r_Minterval& areaOp) + { + r_Point pRes(areaRes.dimension()); + r_Point pOp(areaOp.dimension()); + int done = 0; + int recalc = 0; + int i = 0; + int j = 0; + int innerExtent = 0; + int resSize = 0; + int opSize = 0; + int dim = 0; + char* cellRes = NULL; + const char* cellOp = NULL; + + // !!!! check, if areaRes is inside Tile + + resSize = type->getSize(); + + dim = areaRes.dimension(); + innerExtent = (areaOp.get_extent())[dim-1]; + + // initialize points + for(i = 0; i < areaRes.dimension(); i++) + { + pRes << areaRes[i].low(); + pOp << areaOp[i].low(); + } + + cellRes = getCell(calcOffset(pRes)); + // iterate over all cells +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + while(!done) + { + if(recalc) + { + cellRes = getCell(calcOffset(pRes)); + recalc = 0; + } + + (*myOp)(cellRes, pOp); + + cellRes += resSize; + + // increment coordinates + i = dim - 1; + ++pRes[i]; + ++pOp[i]; + while(pRes[i] > areaRes[i].high()) + { + recalc = 1; + pRes[i] = areaRes[i].low(); + pOp[i] = areaOp[i].low(); + i--; + if(i < 0) + { + done = 1; + break; + } + ++pRes[i]; + ++pOp[i]; + } + } +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + } + +char* +Tile::execGenCondenseOp(GenCondenseOp* myOp, const r_Minterval& areaOp) + { + r_Point pOp(areaOp.dimension()); + int done = 0; + int i = 0; + int dim = areaOp.dimension(); + + // initialize points + for(i = 0; i < areaOp.dimension(); i++) + { + pOp << areaOp[i].low(); + } + +#ifdef RMANBENCHMARK + opTimer.resume(); +#endif + // iterate over all cells + while(!done) + { + (*myOp)(pOp); + + // increment coordinates + i = dim - 1; + ++pOp[i]; + while(pOp[i] > areaOp[i].high()) + { + pOp[i] = areaOp[i].low(); + i--; + if(i < 0) + { + done = 1; + break; + } + ++pOp[i]; + } + } +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + return myOp->getAccuVal(); + } + + +#ifdef RMANDEBUG +#define CHECK_ITER_SYNC(a,b) \ + if (a.isDone() != b.isDone()) {RMDBGONCE(3, RMDebug::module_tilemgr, "Tile", "iterators out of sync!");} +#else +#define CHECK_ITER_SYNC(a,b) +#endif + +template<class T> +static inline void tile_scale_core(r_Miter &iterDest, r_MiterFloat &iterSrc, T *dummy) + { + while (!iterDest.isDone()) + { + const T* srcPtr = (const T*)iterSrc.nextCell(); + T* destPtr = (T*)iterDest.nextCell(); + *destPtr = *srcPtr; + + CHECK_ITER_SYNC(iterSrc, iterDest) + } + CHECK_ITER_SYNC(iterSrc, iterDest) + } + +#ifdef BLVAHELP + +void fast_scale_resample_array(char *dest, const char *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length) + { + r_MiterDirect destIter((void*)dest, destIv, destIv, type_len, 1); + r_MiterDirect subIter((void*)src, srcIv, iterDom, type_len, 1); + r_MiterDirect srcIter((void*)src, srcIv, iterDom, type_len, length); + unsigned int dim = (unsigned int)srcIv.dimension(); + unsigned int i; + + for (i=0; i<dim; i++) + { + subIter.id[i].low = 0; + } + + while (srcIter.done == 0) + { + double sum = 0; + unsigned int count = 0; + + if (destIter.done != 0) cout << "dest out of sync!" << endl; + if (srcIter.id[dim-1].pos == srcIter.id[dim-1].low) + { + cout << srcIter << " : " << destIter << endl; + } + + // init sub iterator + subIter.done = 0; + for (i=0; i<dim; i++) + { + long rest; + + subIter.id[i].pos = 0; + subIter.id[i].data = srcIter.getData(); + rest = srcIter.id[i].high - srcIter.id[i].pos; + if (rest >= (long)length) rest = (long)length-1; + subIter.id[i].high = rest; + //count *= rest+1; + } + while (subIter.done == 0) + { + sum += *((const unsigned char*)(subIter.getData())); + ++subIter; + count++; + } + + cout<<"Sum="<<sum<<" count="<<count<<endl; + // use round to nearest + *((char*)(destIter.getData())) = (char)(sum / count + 0.5); + //cout << (long)(((const T*)(srcIter.getData())) - src) << " , " << (long)(((T*)(destIter.getData())) - dest) << endl; + ++srcIter; + ++destIter; + } + cout << "End: " << srcIter << " : " << destIter << endl; + if (destIter.done == 0) cout << "dest out of sync!" << endl; + } +#endif + +void +Tile::execScaleOp(const Tile* opTile, const r_Minterval& sourceDomain, const r_Point& origin, const std::vector<double>& scaleFactors) + { + // origin is not used in this version + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "execScaleOp()") + +#ifdef BLVAHELP + fast_scale_resample_array((char*)getContents(),((Tile*)opTile)->getContents(), domain, opTile->getDomain(), sourceDomain, 1, 2); +#else + + int typeLength = getType()->getSize(); + const char *srcPtr = ((Tile*)opTile)->getContents(); + + r_MiterFloat iterSrc((Tile*)opTile, (r_Minterval&)sourceDomain, domain); + r_Miter iterDest(&domain, &domain, typeLength, getContents()); + + // optimize for common basetypes + switch (typeLength) + { + case 1: + tile_scale_core(iterDest, iterSrc, (char*)0); + break; + case 2: + tile_scale_core(iterDest, iterSrc, (short*)0); + break; + case 4: + tile_scale_core(iterDest, iterSrc, (long*)0); + break; + case 8: + tile_scale_core(iterDest, iterSrc, (double*)0); + break; + default: + while (!iterDest.isDone()) + { + char *destPtr = iterDest.nextCell(); + srcPtr = iterSrc.nextCell(); + memcpy(destPtr, srcPtr, typeLength); + CHECK_ITER_SYNC(iterSrc, iterDest) + } + CHECK_ITER_SYNC(iterSrc, iterDest) + break; + } + +#endif + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "leaving Tile::execScaleOp()") + } + +// the used version +int +Tile::scaleGetDomain(const r_Minterval& areaOp, const std::vector<double>& scaleFactors, r_Minterval &areaScaled) + { + RMDBGENTER(2, RMDebug::module_tilemgr, "Tile", "scaleGetDomain() - second version") + + try { + areaScaled= areaOp.create_scale(scaleFactors); + } + catch(r_Error& err) { + //error on scalling + RMDBGEXIT(2, RMDebug::module_tilemgr, "Tile", "scaleGetDomain(): areaOp = " << areaOp << " error performing scale") + return 0; + } + + RMDBGEXIT(2, RMDebug::module_tilemgr, "Tile", "scaleGetDomain(): areaOp = " << areaOp << ", scaled = " << areaScaled) + + return 1; + } + + +void +Tile::copyTile(const r_Minterval &areaRes, const Tile *opTile, const r_Minterval &areaOp) + { + RMDBGENTER(3, RMDebug::module_tilemgr, "Tile", "copyTile(" << areaRes << ", " << (r_Ptr)opTile << "," << areaOp << ")"); + + const char *cellOp = NULL; + char *cellRes = NULL; + + // this may trigger decompression + cellOp = opTile->getContents(); + cellRes = getContents(); + + r_Dimension dim = areaRes.dimension(); + r_Range width = areaRes[dim-1].get_extent(); + unsigned int tsize = getType()->getSize(); + unsigned int tsizeOp = opTile->getType()->getSize(); + + if (tsize != tsizeOp) { + RMDBGONCE(0, RMDebug::module_tilemgr, "Tile", "copyTile() ERROR: type sizes incompatible!" + << endl << "this type: " << getType()->getName() << "(" << tsize << "), opTile type: " + << opTile->getType()->getName() << "(" << tsizeOp << ")" ); + // FIXME here we have to check if is appropiate to continue + } + + // these iterators iterate last dimension first, i.e. minimal step size + r_MiterDirect resTileIter((void*)cellRes, getDomain(), areaRes, tsize); + r_MiterDirect opTileIter((void*)cellOp, opTile->getDomain(), areaOp, tsize); + +#ifdef RMANBENCHMARK + opTiler.resume(); +#endif + + while (!resTileIter.isDone()) + { + // copy entire line (continuous chunk in last dimension) in one go + memcpy(resTileIter.getData(), opTileIter.getData(), width * tsize); + // force overflow of last dimension + resTileIter.id[dim-1].pos += width; + opTileIter.id[dim-1].pos += width; + // iterate; the last dimension will always overflow now + ++resTileIter; + ++opTileIter; + } + +#ifdef RMANBENCHMARK + opTimer.pause(); +#endif + + RMDBGEXIT(3, RMDebug::module_tilemgr, "Tile", "copyTile(" << areaRes << ", " << (r_Ptr)opTile << "," << areaOp << ")"); + } + +std::vector<Tile*>* +Tile::splitTile(r_Minterval resDom, int storageDomain) + { + // domain of current tile + r_Minterval currDom(resDom.dimension()); + // type of result tiles + const BaseType* resType; + // iterators for tiles + std::vector<Tile*>* resultVec = new std::vector<Tile*>; + // pointer to generated current tile + Tile* smallTile; + // current factor for translating + r_Point cursor(resDom.dimension()); + // origin of big tile + r_Point origin; + // size of result tiles + r_Point tileSize; + // flag + int done = 0; + // for loops + int i = 0; + + // initialize cursor + for(i = 0; i < cursor.dimension(); i++) + cursor[i] = 0; + // calculate size of Tiles + tileSize = resDom.get_extent(); + // initialize resType + resType = this->getType(); + // origin of bigTile + origin = (this->getDomain()).get_origin(); + + // initialize currDom + for(i = 0; i < cursor.dimension(); i++) + currDom << r_Sinterval(origin[i], origin[i] + tileSize[i] - 1); + // resets resDom to lower left side of bigTile + resDom = currDom; + + // intersect with bigTile + currDom.intersection_with(this->getDomain()); + initCompEngine(); + // iterate with smallTile over bigTile + while(!done) + { + currDom.intersection_with(this->getDomain()); + + // create new smallTile + smallTile = new Tile(currDom, resType, compEngine->get_data_format()); + // fill it with relevant area + smallTile->copyTile(currDom, this, currDom); + // insert it in result vector + resultVec->push_back(smallTile); + + // increment cursor, start with highest dimension + i = cursor.dimension() - 1; + cursor[i] += tileSize[i]; + // move cursor + currDom = resDom.create_translation(cursor); + while(!(currDom.intersects_with(this->getDomain()))) + { + cursor[i] = 0; + i--; + if(i < 0) + { + done = 1; + break; + } + cursor[i] += tileSize[i]; + // move cursor + currDom = resDom.create_translation(cursor); + } + } + return resultVec; + } + +void +Tile::printStatus(unsigned int level, std::ostream& stream) const + { + r_Point p(domain.dimension()); + int done = 0; + int i = 0; + const char* cell; + int dim = domain.dimension(); + + // print the contents only on very high debug level + + // initialize point + for(i = 0; i < dim; i++) + { + p << domain[i].low(); + } + + // iterate over all cells + while(!done) + { + // print cell + cell = getCell(calcOffset(p)); + type->printCell(stream, cell); + + // increment coordinate + i = dim - 1; + while(++p[i] > domain[i].high()) + { + stream << endl; + p[i] = domain[i].low(); + i--; + if(i < 0) + { + done = 1; + break; + } + } + if(i < (dim - 2)) stream << endl; + } + } + +char* +Tile::getCell(const r_Point& aPoint) + { + r_Area cellOffset = domain.cell_offset(aPoint); + return getCell(cellOffset); + } + +const char* +Tile::getCell(const r_Point& aPoint) const + { + r_Area cellOffset = domain.cell_offset(aPoint); + return getCell(cellOffset); + } + +void +Tile::setCompressionEngine(r_Tile_Compression* newCompAlg) + { + decompress(); + delete compEngine; + compEngine = newCompAlg; + blobTile->setDataFormat(compEngine->get_data_format()); + } + +const r_Minterval& +Tile::getDomain() const + { + return domain; + } + +const BaseType* +Tile::getType() const + { + return type; + } + +r_Dimension +Tile::getDimension() const + { + return domain.dimension(); + } + +r_Bytes +Tile::getSize() const + { + return domain.cell_count() * type->getSize(); + } + +r_Data_Format +Tile::getDataFormat() const + { + return blobTile->getDataFormat(); + } + +const char* +Tile::getCell(r_Area index) const + { + decompress(); + return &(blobTile->getCells()[index * type->getSize()]); + } + +char* +Tile::getCell(r_Area index) + { + decompress(); + return &(blobTile->getCells()[index * type->getSize()]); + } + +void +Tile::setCell(r_Area index, const char* newCell) + { + char* cells = getCell(index); + int typeSize = type->getSize(); + for (int i = 0; i < typeSize; i++) + cells[i] = newCell[i]; + } + +char* +Tile::getContents() + { + decompress(); + return blobTile->getCells(); + } + +const char* +Tile::getContents() const + { + decompress(); + return blobTile->getCells(); + } + +void +Tile::setContents(char* newContents) + { + decompress(); + blobTile->setCells(newContents); + } + +void +Tile::setParameters(const char *par) + { + delete [] params; + if (par != NULL) + { + params = new char[strlen(par) + 1]; + strcpy(params, par); + } + else + params = NULL; + } + +const char* +Tile::getParameters() const + { + return params; + } + +const r_Tile_Compression* +Tile::getCompressionEngine() const + { + return compEngine; + } + +void +Tile::compress() const + { + if (blobTile->getCurrentFormat() != blobTile->getDataFormat()) + { + initCompEngine(); + r_ULong compressedSize = 0; + char* compressedData = (char*)(compEngine->compress(blobTile->getCells(), compressedSize, params)); + if (!AdminIf::isReadOnlyTA()) + { + r_ULong sizee = getSize(); + if (compressedSize > sizee) + { + RMInit::logOut << "Warning: overriding compression setting(" << blobTile->getDataFormat() << ") to " + << r_Array << " for tile " << getDomain() + << " " << blobTile->getOId() << " because compressed size( " << compressedSize + << " bytes) > uncompressed size( " << sizee << " bytes)" << endl; + r_Tile_Compression* compEngineN = r_Tile_Compression::create(r_Array, getDomain(), compEngine->get_base_type()); + delete compEngine; + compEngine = compEngineN; + compEngineN = NULL; + ((DBTile*)blobTile.ptr())->setDataFormat(compEngine->get_data_format()); + free(compressedData); + compressedData = NULL; + compressedSize = sizee; + //not neccessary because already there + //blobTile->setNoModificationData(compressedData); + } + else { + blobTile->setNoModificationData(compressedData); + } + } + else { + blobTile->setNoModificationData(compressedData); + } + blobTile->setNoModificationSize(compressedSize); + blobTile->setCurrentFormat(compEngine->get_data_format()); + } + } + +bool +Tile::decompress() const + { + bool retval = true; + if (blobTile->getCurrentFormat() != r_Array) + { + initCompEngine(); + bool wrongDecompress = false; + r_Bytes compressedSize = blobTile->getSize(); + char* decompressedData = (char*)(compEngine->decompress(blobTile->getCells(), blobTile->getSize(), params)); + if (decompressedData == NULL) + { + RMInit::logOut << "Error: decompress returned NULL " << blobTile->getOId() << " " << getDomain() << endl; + wrongDecompress = true; + decompressedData = (char*)mymalloc(getSize() * sizeof(char)); + memset(decompressedData, 0, getSize()); + RMInit::logOut << "Error fixed by returning empty data. "; + if (!AdminIf::isReadOnlyTA()) + { + ((DBTile*)blobTile.ptr())->setModified(); + RMInit::logOut << "Fix was made persistent."; + } + RMInit::logOut << endl; + retval = false; + } + blobTile->setNoModificationData(decompressedData); + blobTile->setNoModificationSize(getSize()); + blobTile->setCurrentFormat(r_Array); + } + else { + if (getSize() != blobTile->getSize()) + { + RMInit::logOut << "Error: tile with wrong size " << blobTile->getOId() << " " << getDomain() << " is " << blobTile->getSize() << " should be " << getSize() << " format " << blobTile->getDataFormat() << endl; + char* tempPtr = (char*)mymalloc(getSize() * sizeof(char)); + memset(tempPtr, '\0', getSize()*sizeof(char)); + if(getSize() < blobTile->getSize()) + { + memcpy(tempPtr, blobTile->getCells(), getSize()); + } + else { + memcpy(tempPtr, blobTile->getCells(), blobTile->getSize()); + } + ((DBTile*)blobTile.ptr())->setCells(tempPtr); + blobTile->setNoModificationSize(getSize()); + RMInit::logOut << "Error fixed by resizing and copying data" << endl; + retval = false; + } + } + return retval; + } + + +r_Bytes +Tile::calcOffset(const r_Point& point) const + { + int i = 0; + r_Bytes offset = 0; + r_Bytes factor = 1; + + // calculate offset + for(i = domain.dimension() - 1; i >= 0; i--) + { + offset += (point[i] - domain[i].low()) * factor; + factor *= domain[i].high() - domain[i].low() + 1; + } + + return offset; + } |