//# TiledDataStMan.cc: Storage manager for tables using tiled hypercubes //# Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library 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 Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #include #include #include #include #include #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN TiledDataStMan::TiledDataStMan () : TiledStMan (), nrrowLast_p (0) {} TiledDataStMan::TiledDataStMan (const String& hypercolumnName, uInt64 maximumCacheSize) : TiledStMan (hypercolumnName, maximumCacheSize), nrrowLast_p (0) {} TiledDataStMan::TiledDataStMan (const String& hypercolumnName, const Record& spec) : TiledStMan (hypercolumnName, 0), nrrowLast_p (0) { if (spec.isDefined ("MAXIMUMCACHESIZE")) { setPersMaxCacheSize (spec.asInt64 ("MAXIMUMCACHESIZE")); } } TiledDataStMan::~TiledDataStMan() {} DataManager* TiledDataStMan::clone() const { TiledDataStMan* smp = new TiledDataStMan (hypercolumnName_p, maximumCacheSize()); return smp; } DataManager* TiledDataStMan::makeObject (const String& group, const Record& spec) { TiledDataStMan* smp = new TiledDataStMan (group, spec); return smp; } String TiledDataStMan::dataManagerType() const { return "TiledDataStMan"; } void TiledDataStMan::create64 (rownr_t nrrow) { // Set up the various things. setup(-1); // Add the rows for the given number of rows. addRow64 (nrrow); } Bool TiledDataStMan::flush (AipsIO&, Bool fsync) { // Flush the caches. // Exit if nothing has changed. if (! flushCaches (fsync)) { return False; } // Create the header file and write data in it. AipsIO* headerFile = headerFileCreate(); headerFile->putstart ("TiledDataStMan", 2); // Let the base class write its data. headerFilePut (*headerFile, cubeSet_p.nelements()); // Write the data from this object. *headerFile << nrrowLast_p; *headerFile << rowMap_p << cubeMap_p << posMap_p; headerFile->putend(); headerFileClose (headerFile); return True; } void TiledDataStMan::readHeader (rownr_t tabNrrow, Bool firstTime) { // Open the header file and read data from it. AipsIO* headerFile = headerFileOpen(); uInt version = headerFile->getstart ("TiledDataStMan"); // Let the base class read and initialize its data. uInt hdrVersion = headerFileGet (*headerFile, tabNrrow, firstTime, -1); // Read the data for this object. // Version 1 was not incremented at the change to rownr_t, but the // parent class TiledStMan was. So test that version as well. if (version == 1 && hdrVersion < 3) { uInt nrow; *headerFile >> nrow; nrrowLast_p = nrow; } else { *headerFile >> nrrowLast_p; } if (version == 1) { uInt nused; *headerFile >> nused; std::vector rowMap; *headerFile >> rowMap; rowMap_p.insert (rowMap_p.end(), rowMap.begin(), rowMap.end()); *headerFile >> cubeMap_p >> posMap_p; } else { *headerFile >> rowMap_p >> cubeMap_p >> posMap_p; } headerFile->getend(); headerFileClose (headerFile); } void TiledDataStMan::addRow64 (rownr_t nrow) { nrrow_p += nrow; setDataChanged(); } void TiledDataStMan::checkNrrow (const IPosition& cubeShape, uInt64 incrInLastDim) const { rownr_t nrrow = addedNrrow (cubeShape, incrInLastDim); if (nrrowLast_p + nrrow > nrrow_p) { throw (TSMError ("Insufficient #rows in table for add/extendHypercube")); } } void TiledDataStMan::addHypercube (const IPosition& cubeShape, const IPosition& tileShape, const Record& values) { // Check if the number of rows involved fits in the table. checkNrrow (cubeShape, cubeShape(nrdim_p - 1)); // Check the hypercube definition and create the hypercube. checkAddHypercube (cubeShape, values); TSMCube* hypercube = makeHypercube (cubeShape, tileShape, values); uInt ncube = cubeSet_p.nelements(); cubeSet_p.resize (ncube + 1); cubeSet_p[ncube] = hypercube; // Update the row map with the number of pixels in last dimension. updateRowMap (ncube, cubeShape(nrdim_p-1)); } void TiledDataStMan::extendHypercube (uInt64 incrInLastDim, const Record& values) { // Check if id values are correctly given. // Get the hypercube using the id values. checkValues (idColSet_p, values); Int cubeNr = getCubeIndex (values); if (cubeNr < 0) { throw (TSMError ("extendHypercube with unknown id values")); } // Check if the number of rows involved fits in the table. checkNrrow (cubeSet_p[cubeNr]->cubeShape(), incrInLastDim); // Check if values for the last coordinate are given correctly. PtrBlock lastCoord (1, coordColSet_p[nrdim_p-1]); IPosition lastDim (1, incrInLastDim); checkCoordinates (lastCoord, lastDim, values); cubeSet_p[cubeNr]->extend (incrInLastDim, values, lastCoord[0]); updateRowMap (cubeNr, incrInLastDim); setDataChanged(); } void TiledDataStMan::updateRowMap (uInt cubeNr, uInt64 incrInLastDim) { if (incrInLastDim == 0) { return; } // Determine the numbers of rows added via the extension. const IPosition& shape = cubeSet_p[cubeNr]->cubeShape(); rowMap_p.push_back (nrrowLast_p); cubeMap_p.push_back (cubeNr); posMap_p.push_back (shape(nrdim_p-1) - incrInLastDim); // Now update the last row number used with the // number of rows this extension represents. rownr_t nr = addedNrrow (cubeSet_p[cubeNr]->cubeShape(), incrInLastDim); nrrowLast_p += nr; } TSMCube* TiledDataStMan::getHypercube (rownr_t rownr) { IPosition pos; return TiledDataStMan::getHypercube (rownr, pos); } TSMCube* TiledDataStMan::getHypercube (rownr_t rownr, IPosition& position) { // Check if the row number is correct. if (rownr >= nrrowLast_p ) { throw (TSMError ("getHypercube: rownr is too high")); } // Find the closest row number in the map (equal or less). Bool found; uInt index = binarySearchBrackets (found, rowMap_p, rownr, rowMap_p.size()); if (!found) { index--; } // Get the hypercube and the rownr relative to the start // of the hypercube chunk the requested row is in. TSMCube* hypercube = cubeSet_p[cubeMap_p[index]]; rownr_t rowDiff = rownr - rowMap_p[index]; // Transform the relative rownr into a hypercube position. // When the hypercube has axes with vector coordinates, those // axes are part of the data in the cell (thus only scalar // coordinates have to be taken into account). const IPosition& shape = hypercube->cubeShape(); position.resize (0); position = shape; for (uInt i=nrCoordVector_p; i