//# TiledStMan.cc: Storage manager for tables using tiled hypercubes //# Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,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 #include #include #include #include #include #include #include #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN TiledStMan::TiledStMan () : DataManager (), nrrow_p (0), fileSet_p (1, static_cast(0)), persMaxCacheSize_p(0), maxCacheSize_p (0), nrdim_p (0), nrCoordVector_p (0), dataChanged_p (False) {} TiledStMan::TiledStMan (const String& hypercolumnName, uInt maximumCacheSize) : DataManager (), hypercolumnName_p (hypercolumnName), nrrow_p (0), fileSet_p (1, static_cast(0)), persMaxCacheSize_p(maximumCacheSize), maxCacheSize_p (maximumCacheSize), nrdim_p (0), nrCoordVector_p (0), dataChanged_p (False) {} TiledStMan::~TiledStMan() { uInt i; for (i=0; i weight(hypercubeShape.nelements()); weight = double(1); Vector tol(hypercubeShape.nelements()); tol = tolerance; return makeTileShape (hypercubeShape, weight, tol, nrPixelsPerTile); } IPosition TiledStMan::makeTileShape (const IPosition& hypercubeShape, const Vector& weight, const Vector& tolerance, uInt64 nrPixelsPerTile) { uInt nrdim = hypercubeShape.nelements(); if (weight.nelements() != nrdim || tolerance.nelements() != nrdim) { throw (TSMError ("makeTileShape: nelements mismatch")); } double nrLeft = nrPixelsPerTile; Vector tmpShape(nrdim); IPosition tileShape(nrdim, 0); uInt i; // Iterate until the tile shape is set nicely. // This is needed to prevent tile shape dimensions from underflow // or overflow. while (True) { double prod = 1; uInt n = 0; for (i=0; i 1) { diff = hypercubeShape(i) / diff; } if (maxIndex < 0 || diff < maxDiff) { maxDiff = diff; maxIndex = i; } } } // If there is no underflow/overflow we can copy the dimensions // and exit. if (maxDiff >= 1) { for (i=0; i maxShape(i)) { Int64 sav = minShape(i); minShape(i) = maxShape(i); maxShape(i) = sav; } if (minShape(i) < 1) { minShape(i) = 1; } if (maxShape(i) > hypercubeShape(i)) { maxShape(i) = hypercubeShape(i); } cubeSpace *= hypercubeShape(i); } // Find the shapes on each axis that will be tried. Block nval(nrdim, uInt64(0)); PtrBlock*> values(nrdim); for (i=0; i (maxShape(i) - minShape(i) + 1); // First find exactly fitting shapes. for (Int64 j=minShape(i); j<=maxShape(i); j++) { if (hypercubeShape(i) % j == 0) { (*values[i])[nval[i]] = j; nval[i]++; } } // If none available, use all possible shapes within half the range. if (nval[i] == 0) { for (Int64 j=(tileShape(i)+minShape(i))/2; j<=(tileShape(i)+maxShape(i))/2; j++) { (*values[i])[nval[i]] = j; nval[i]++; } } } // Now calculate the cost for all the possibilities. // Take the one with the lowest cost. Block ndone (nrdim, uInt64(0)); IPosition tshape (nrdim); for (i=0; icubeShape().nelements() > 0) { Record srec; srec.define ("CubeShape", cubeSet_p[i]->cubeShape().asVector()); srec.define ("TileShape", cubeSet_p[i]->tileShape().asVector()); srec.define ("CellShape", cubeSet_p[i]->cellShape().asVector()); srec.define ("BucketSize", Int(cubeSet_p[i]->bucketSize())); srec.defineRecord ("ID", cubeSet_p[i]->valueRecord()); subrec.defineRecord (nrrec++, srec); } } rec.defineRecord ("HYPERCUBES", subrec); rec.define ("SEQNR", sequenceNr()); return rec; } Record TiledStMan::getProperties() const { Record rec; rec.define ("MaxCacheSize", Int(maxCacheSize_p)); return rec; } void TiledStMan::setProperties (const Record& rec) { if (rec.isDefined("MaxCacheSize")) { setMaximumCacheSize (rec.asInt("MaxCacheSize")); } } void TiledStMan::setShape (rownr_t, TSMCube*, const IPosition&, const IPosition&) { throw (TSMError ("setShape is not possible for TSM " + hypercolumnName_p)); } void TiledStMan::reopenRW() { for (uInt i=0; ibucketFile()->setRW(); } } } void TiledStMan::deleteManager() { for (uInt i=0; iclearCache (False); } } for (uInt i=0; ibucketFile()->remove(); } } // Remove the header file. /// removeFile(); DOos::remove (fileName(), False, False); } void TiledStMan::setMaximumCacheSize (uInt nMiB) { maxCacheSize_p = nMiB; } Bool TiledStMan::canChangeShape() const { return False; } Bool TiledStMan::canAccessColumn() const { return (nhypercubes() == 1); } Bool TiledStMan::hasMultiFileSupport() const { return True; } //# Does the storage manager allow to add rows? (yes) Bool TiledStMan::canAddRow() const { return True; } TSMCube* TiledStMan::makeTSMCube (TSMFile* file, const IPosition& cubeShape, const IPosition& tileShape, const Record& values, Int64 fileOffset) { TSMCube* hypercube; if (tsmOption().option() == TSMOption::MMap) { //cout << "mmapping TSM1" << endl; AlwaysAssert (file->bucketFile()->isMapped(), AipsError); hypercube = new TSMCubeMMap (this, file, cubeShape, tileShape, values, fileOffset); } else if (tsmOption().option() == TSMOption::Buffer) { //cout << "buffered TSM1" << endl; AlwaysAssert (file->bucketFile()->isBuffered(), AipsError); hypercube = new TSMCubeBuff (this, file, cubeShape, tileShape, values, fileOffset, tsmOption().bufferSize()); } else { //cout << "caching TSM1" << endl; AlwaysAssert (file->bucketFile()->isCached(), AipsError); hypercube = new TSMCube (this, file, cubeShape, tileShape, values, fileOffset); } return hypercube; } TSMCube* TiledStMan::getTSMCube (uInt hypercube) { if (hypercube >= nhypercubes() || cubeSet_p[hypercube] == 0) { throw (AipsError ("TiledStMan::getTSMCube - hypercube nr " + String::toString(hypercube) + " does not exist in " + hypercolumnName_p)); } return cubeSet_p[hypercube]; } const IPosition& TiledStMan::hypercubeShape (rownr_t rownr) const { return getHypercube(rownr)->cubeShape(); } const IPosition& TiledStMan::tileShape (rownr_t rownr) const { return getHypercube(rownr)->tileShape(); } uInt64 TiledStMan::bucketSize (rownr_t rownr) const { return getHypercube(rownr)->bucketSize(); } uInt TiledStMan::cacheSize (rownr_t rownr) const { return getHypercube(rownr)->cacheSize(); } uInt TiledStMan::calcCacheSize (rownr_t rownr, const IPosition& sliceShape, const IPosition& windowStart, const IPosition& windowLength, const IPosition& axisPath) const { // Calculate the cache size for the given hypercube. return getHypercube(rownr)->calcCacheSize (sliceShape, windowStart, windowLength, axisPath); } void TiledStMan::setCacheSize (rownr_t rownr, const IPosition& sliceShape, const IPosition& windowStart, const IPosition& windowLength, const IPosition& axisPath, Bool forceSmaller) { // Set the cache size for the given hypercube. getHypercube(rownr)->setCacheSize (sliceShape, windowStart, windowLength, axisPath, forceSmaller, True); } void TiledStMan::setCacheSize (rownr_t rownr, uInt nbuckets, Bool forceSmaller) { // Set the cache size (in buckets) for the given hypercube. TSMCube* hypercube = getHypercube(rownr); hypercube->setCacheSize (nbuckets, forceSmaller, True); } void TiledStMan::setHypercubeCacheSize (uInt hypercube, uInt nbuckets, Bool forceSmaller) { // Set the cache size (in buckets) for the given hypercube. TSMCube* tsmCube = getTSMCube (hypercube); tsmCube->setCacheSize (nbuckets, forceSmaller, True); } Bool TiledStMan::userSetCache (rownr_t rownr) const { return getHypercube(rownr)->userSetCache(); } void TiledStMan::emptyCaches() { for (uInt i=0; iemptyCache(); } } } void TiledStMan::showCacheStatistics (ostream& os) const { for (uInt i=0; ishowCacheStatistics (os); } } } TSMCube* TiledStMan::singleHypercube() { if (cubeSet_p.nelements() != 1 || cubeSet_p[0] == 0) { throw (TSMError ("TiledStMan: function on hypercolumn " + hypercolumnName_p + " cannot be done " "when it is using multiple hypercubes")); } return cubeSet_p[0]; } uInt64 TiledStMan::getLengthOffset (uInt64 nrPixels, Block& dataOffset, Block& localOffset, uInt& localTileLength) const { localTileLength = 0; uInt64 length = 0; uInt nrcol = dataCols_p.nelements(); dataOffset.resize (nrcol); localOffset.resize (nrcol); for (uInt i=0; idataLength (nrPixels); localTileLength += nrPixels * dataCols_p[i]->localPixelSize(); } return length; } void TiledStMan::readTile (char* local, const Block& localOffset, const char* external, const Block& externalOffset, uInt nrPixels) { uInt nr = dataCols_p.nelements(); for (uInt i=0; ireadTile (local + localOffset[i], external + externalOffset[i], nrPixels); } } void TiledStMan::writeTile (char* external, const Block& externalOffset, const char* local, const Block& localOffset, uInt nrPixels) { uInt nr = dataCols_p.nelements(); for (uInt i=0; iwriteTile (external + externalOffset[i], local + localOffset[i], nrPixels); } } DataManagerColumn* TiledStMan::makeScalarColumn (const String& columnName, int dataType, const String& dataTypeId) { return makeIndArrColumn (columnName, dataType, dataTypeId); } DataManagerColumn* TiledStMan::makeDirArrColumn (const String& columnName, int dataType, const String& dataTypeId) { return makeIndArrColumn (columnName, dataType, dataTypeId); } DataManagerColumn* TiledStMan::makeIndArrColumn (const String& columnName, int dataType, const String&) { //# Check if data type is not TpOther. throwDataTypeOther (columnName, dataType); //# Extend colSet_p block if needed. if (ncolumn() >= colSet_p.nelements()) { colSet_p.resize (colSet_p.nelements() + 32); } TSMColumn* colp = new TSMColumn (this, dataType, columnName); colSet_p[ncolumn()] = colp; return colp; } int TiledStMan::coordinateDataType (const String& columnName) const { for (uInt i=0; icolumnName()) { return coordColSet_p[i]->dataType(); } } } throw (TSMError ("coordinateDataType: column " + columnName + " is unknown")); return 0; } // Get the proper array data type. int TiledStMan::arrayDataType (int dataType) const { switch (dataType) { case TpBool: return TpArrayBool; case TpChar: return TpArrayChar; case TpUChar: return TpArrayUChar; case TpShort: return TpArrayShort; case TpUShort: return TpArrayUShort; case TpInt: return TpArrayInt; case TpUInt: return TpArrayUInt; case TpInt64: return TpArrayInt64; case TpFloat: return TpArrayFloat; case TpDouble: return TpArrayDouble; case TpComplex: return TpArrayComplex; case TpDComplex: return TpArrayDComplex; case TpString: return TpArrayString; } return dataType; } IPosition TiledStMan::defaultTileShape() const { return IPosition(); } Bool TiledStMan::canReallocateColumns() const { return True; } DataManagerColumn* TiledStMan::reallocateColumn (DataManagerColumn* column) { for (uInt i=0; iunlink(); delete ptr; return colSet_p[i]; } } // The column is not part of this storage manager, so return column itself. return column; } void TiledStMan::setup (Int extraNdim) { uInt i; // Get the description of the hypercolumn. Vector dataNames; Vector coordNames; Vector idNames; const TableDesc& tableDesc = getDesc(); if (extraNdim < 0 || tableDesc.isHypercolumn (hypercolumnName_p)) { // If defined as a hypercolumn get the columns in it. nrdim_p = tableDesc.hypercolumnDesc (hypercolumnName_p, dataNames, coordNames, idNames); // Determine the number of vector coordinates. // This is the dimensionality of the cells. nrCoordVector_p = tableDesc.columnDesc(dataNames(0)).ndim(); } else { // No hypercolumn definition; assume all columns are data columns. Int ndim = 0; dataNames.resize (ncolumn()); for (uInt i=0; icolumnName(); Int nd = tableDesc.columnDesc(dataNames(i)).ndim(); if (nd > 0) { if (ndim == 0) { ndim = nd; } else if (nd != ndim) { throw TSMError ("TiledStMan: dimensionality of column " + dataNames(i) + " mismatches other columns"); } } } if (ndim == 0) { throw TSMError ("TiledStMan: unknown dimensionality for column " + dataNames(0)); } nrCoordVector_p = ndim; nrdim_p = ndim + extraNdim; } // Check if the required columns are bound // and get the pointers to those columns. dataCols_p.resize (dataNames.nelements()); dataColSet_p.resize (dataNames.nelements()); coordColSet_p.resize (nrdim_p); idColSet_p.resize (idNames.nelements()); uInt nrDataBound = getBindings (dataNames, dataColSet_p, True); uInt nrCoordBound = getBindings (coordNames, coordColSet_p, False); uInt nrIdBound = getBindings (idNames, idColSet_p, True); // Check if no non-TiledStMan columns are bound. if (nrDataBound + nrCoordBound + nrIdBound != ncolumn()) { throw (TSMError ("non-TiledStMan columns bound in " + hypercolumnName_p)); } // Let the derived class do some more checks. setupCheck (tableDesc, dataNames); // Find the first fixed shape data column. // Check if FixedShape column shapes of data and coordinate columns match. for (i=0; ishapeColumn(); if (fixedCellShape_p.nelements() > 0) { break; } } checkShapeColumn (fixedCellShape_p); // Construct the various TSMColumn objects. for (i=0; imakeCoordColumn (i); } } for (i=0; imakeIdColumn(); } uInt nrd = dataColSet_p.nelements(); PtrBlock dataColSet(nrd); for (i=0; imakeDataColumn(); } // Organize the pixel offset in the data columns in descending // order of external pixel length. // The sort is stable, so equal lengths will always occur in // the same order. // In that way we are sure that their data are aligned in a tile // (which may be needed for TSMCube::accessLine). Block lengths(nrd); for (i=0; itilePixelSize(); } Vector inx; GenSortIndirect::sort (inx, lengths, nrd, Sort::Descending); // Rearrange the objects and set their column number. // In this way function setLengths will behave correctly. for (i=0; isetColumnNumber (i); dataColSet_p[i] = dataCols_p[i]; } } const TableDesc& TiledStMan::getDesc() const { return table().tableDesc(); } void TiledStMan::setupCheck (const TableDesc&, const Vector&) const {} void TiledStMan::checkCubeShape (const TSMCube* hypercube, const IPosition& cubeShape) const { // Check if the dimensionalities are correct. if (cubeShape.nelements() != nrdim_p) { throw (TSMError ("addHypercube dimensionality mismatch in " + hypercolumnName_p)); } // Check if all dimensions are > 0. // Only the last one in shape can be 0 (meaning extensible). for (uInt i=0; ishapeColumn(); for (uInt j=0; jcolumnName())); } } } for (i=0; ishapeColumn(); if (shapeColumn.nelements() > 0) { if (shape(i) != shapeColumn(0)) { throw (TSMError ("Mismatch in fixed shape of coordinate column " + coordColSet_p[i]->columnName())); } } } } } void TiledStMan::checkCoordinatesShapes (const TSMCube* hypercube, const IPosition& cubeShape) const { //# Check for all coordinates if their length (if defined) //# matches the hypercube shape. for (uInt i=0; icoordinateSize (coordColSet_p[i]->columnName()); if (size != 0 && size != cubeShape(i)) { throw (TSMError ("Mismatch in shape of coordinate column " + coordColSet_p[i]->columnName())); } } } } void TiledStMan::initCoordinates (TSMCube* hypercube) { for (uInt i=0; iextendCoordinates (Record(), coordColSet_p[i]->columnName(), hypercube->cubeShape()(i)); dataChanged_p = True; } } } uInt TiledStMan::getBindings (const Vector& columnNames, PtrBlock& colSet, Bool mustExist) const { colSet = static_cast(0); uInt nrfound = 0; uInt j; Bool found = False; for (uInt i=0; icolumnName()) { colSet[i] = colSet_p[j]; found = True; nrfound++; break; } } if (!found && mustExist) { throw (TSMError ("TiledStMan column " + columnNames(i) + " is not bound")); } } return nrfound; } void TiledStMan::checkAddHypercube (const IPosition& cubeShape, const Record& values) const { //# Check if the cube shape is correct. checkCubeShape (0, cubeShape); // Check whether all id and coordinate values are given correctly. checkValues (idColSet_p, values); checkCoordinates (coordColSet_p, cubeShape, values); // Check whether no double id values are given. if (getCubeIndex (values) >= 0) { throw (TSMError ("addHypercube with already existing id values in " + hypercolumnName_p)); } } TSMCube* TiledStMan::makeHypercube (const IPosition& cubeShape, const IPosition& tileShape, const Record& values) { dataChanged_p = True; // Pick a TSMFile object for the hypercube. // Non-extensible cubes share the first file; others get their own file. uInt filenr = 0; if (cubeShape(nrdim_p - 1) == 0) { filenr = fileSet_p.nelements(); fileSet_p.resize (filenr + 1); fileSet_p[filenr] = 0; } // Create the file when needed. if (fileSet_p[filenr] == 0) { createFile (filenr); } // Create a TSMCube object. // Its data will be written at the end of the file. return makeTSMCube (fileSet_p[filenr], cubeShape, tileShape, values); } void TiledStMan::createFile (uInt index) { TSMFile* file = new TSMFile (this, index, tsmOption(), multiFile()); fileSet_p[index] = file; } Int TiledStMan::getCubeIndex (const Record& idValues) const { // When there are no id columns, return the one and single hypercube // (or -1 if no one created yet). if (idColSet_p.nelements() == 0) { if (cubeSet_p.nelements() == 0) { return -1; } return 0; } // Look if a hypercube matches the id values. for (uInt i=0; imatches (idColSet_p, idValues)) { return i; } } } return -1; } void TiledStMan::checkValues (const PtrBlock& colSet, const Record& values) const { // Check if all values are given and if their data types match. for (uInt i=0; icolumnName(); if (! values.isDefined (name)) { throw (TSMError ("No value given for column " + name)); } if (values.dataType(name) != colSet[i]->dataType()) { throw (TSMError ("Data type mismatch for column " + name)); } } } } void TiledStMan::checkCoordinates (const PtrBlock& coordColSet, const IPosition& cubeShape, const Record& values) const { // Check if the coordinates data types and shapes are correct, // i.e. if the coordinates shapes match the hypercube shape. for (uInt i=0; icolumnName(); if (values.isDefined (name)) { int dataType = arrayDataType (coordColSet[i]->dataType()); if (values.dataType(name) != dataType) { throw (TSMError ("Data type mismatch for coordinate " + name)); } IPosition shape = values.shape (name); if (shape.nelements() != 1) { throw (TSMError ("Values of coordinate " + name + " do not form a vector")); } if (shape(0) != cubeShape(i)) { throw (TSMError ("Shape mismatch for coordinate " + name)); } } } } } rownr_t TiledStMan::addedNrrow (const IPosition& shape, uInt incrInLastDim) const { rownr_t nrrowAdded = 1; for (uInt i=nrCoordVector_p; iflushCache(); } } if (fsync) { for (i=0; ibucketFile()->fsync(); } } } return True; } AipsIO* TiledStMan::headerFileCreate() { return new AipsIO (fileName(), ByteIO::New, 16384, multiFile()); } AipsIO* TiledStMan::headerFileOpen() { return new AipsIO (fileName(), ByteIO::Old, 16384, multiFile()); } void TiledStMan::headerFilePut (AipsIO& headerFile, uInt64 nrCube) { // The endian switch is a new feature. So only put it if little endian // is used. In that way older software can read newer tables. // Similarly, use older version if number of rows less than maxUint. Bool useNewVersion = False; if (nrrow_p > MAXROWNR32 || persMaxCacheSize_p != uInt(persMaxCacheSize_p)) { headerFile.putstart ("TiledStMan", 3); headerFile << asBigEndian(); useNewVersion = True; } else if (asBigEndian()) { headerFile.putstart ("TiledStMan", 1); } else { headerFile.putstart ("TiledStMan", 2); headerFile << asBigEndian(); } //# Write StMan sequence number, the number of rows and columns, //# and the column data types. //# This is only done to check it when reading back. headerFile << sequenceNr(); if (useNewVersion) { headerFile << nrrow_p; } else { headerFile << uInt(nrrow_p); } headerFile << ncolumn(); for (uInt i=0; idataType(); } headerFile << hypercolumnName_p; if (useNewVersion) { headerFile << persMaxCacheSize_p; } else { headerFile << uInt(persMaxCacheSize_p); } headerFile << nrdim_p; // nrfile and nrcube can never exceed nrrow, // so it's safe to use uInt for old version. if (useNewVersion) { headerFile << uInt64(fileSet_p.nelements()); } else { headerFile << uInt(fileSet_p.nelements()); } for (uInt64 i=0; iputObject (headerFile); } } if (useNewVersion) { headerFile << nrCube; } else { headerFile << uInt(nrCube); } for (uInt64 i=0; iputObject (headerFile); } headerFile.putend(); } uInt TiledStMan::headerFileGet (AipsIO& headerFile, rownr_t tabNrrow, Bool firstTime, Int extraNdim) { nrrow_p = tabNrrow; uInt version = headerFile.getstart ("TiledStMan"); Bool bigEndian = True; if (version >= 2) { headerFile >> bigEndian; } if (bigEndian != asBigEndian()) { throw DataManError("Endian flag in TSM mismatches the table flag"); } //# Get and check the number of rows and columns and the column types. rownr_t nrrow; uInt nrcol, seqnr; int dtype; headerFile >> seqnr; if (version >= 3) { headerFile >> nrrow; } else { uInt nrrowOld; headerFile >> nrrowOld; nrrow = nrrowOld; } headerFile >> nrcol; if (seqnr != sequenceNr() || nrcol != ncolumn()) { //# Temporary hack to fix a corrupted table. //#if (sequenceNr() != 7) { throw (DataManInternalError ("TiledStMan::headerFileGet: mismatch in seqnr,#col")); //#} } if (nrrow != nrrow_p) { #if defined(TABLEREPAIR) cerr << "TiledStMan::headerFileGet: mismatch in #row (expected " << nrrow_p << ", found " << nrrow << ")" << endl; dataChanged_p = True; #else throw (DataManInternalError ("TiledStMan::headerFileGet: mismatch in #row; expected " + String::toString(nrrow_p) + ", found " + String::toString(nrrow))); #endif } for (uInt i=0; i> dtype; if (dtype != colSet_p[i]->dataType()) { throw (DataManInternalError ("TiledStMan::headerFileGet: mismatch in data type")); } } headerFile >> hypercolumnName_p; if (version >= 3) { headerFile >> persMaxCacheSize_p; } else { uInt tmp; headerFile >> tmp; persMaxCacheSize_p = tmp; } maxCacheSize_p = persMaxCacheSize_p; if (firstTime) { // Setup the various things (i.e. initialize other variables). setup (extraNdim); } uInt nrdim; headerFile >> nrdim; if (nrdim != nrdim_p) { throw (DataManInternalError ("TiledStMan::headerFileGet: mismatch in nrdim")); } uInt64 nrFile; Bool flag; if (version >= 3) { headerFile >> nrFile; } else { uInt nrFile32; headerFile >> nrFile32; nrFile = nrFile32; } uInt64 nrFileOld = fileSet_p.nelements(); fileSet_p.resize (nrFile); for (uInt64 i=nrFileOld; i> flag; if (flag) { if (fileSet_p[i] == 0) { fileSet_p[i] = new TSMFile (this, headerFile, i, tsmOption(), multiFile()); }else{ fileSet_p[i]->getObject (headerFile); } }else{ delete fileSet_p[i]; fileSet_p[i] = 0; } } uInt64 nrCube; if (version >= 3) { headerFile >> nrCube; } else { uInt nrCube32; headerFile >> nrCube32; nrCube = nrCube32; } uInt64 nrCubeOld = cubeSet_p.nelements(); cubeSet_p.resize (nrCube); for (uInt64 i=nrCubeOld; iresync (headerFile); } } headerFile.getend(); //# The following can only be executed in case of TABLEREPAIR. if (nrrow < nrrow_p) { cubeSet_p[0]->extend (nrrow_p-nrrow, Record(), coordColSet_p[nrdim_p - 1]); } return version; } void TiledStMan::headerFileClose (AipsIO* headerFile) { delete headerFile; } TSMFile* TiledStMan::getFile (uInt sequenceNumber) { //# Do internal check to see if TSMFile really exists. if (sequenceNumber >= fileSet_p.nelements() || fileSet_p[sequenceNumber] == 0) { throw (DataManInternalError ("TiledStMan::getFile in " + hypercolumnName_p)); } return fileSet_p[sequenceNumber]; } } //# NAMESPACE CASACORE - END