00001 //# BaseTable.h: Abstract base class for tables 00002 //# Copyright (C) 1994,1995,1996,1997,1998,2000,2001,2002,2003 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef TABLES_BASETABLE_H 00029 #define TABLES_BASETABLE_H 00030 00031 00032 //# Includes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/tables/Tables/TableInfo.h> 00035 #include <casacore/tables/Tables/TableDesc.h> 00036 #include <casacore/tables/Tables/StorageOption.h> 00037 #include <casacore/casa/Utilities/Compare.h> 00038 #include <casacore/casa/Utilities/CountedPtr.h> 00039 #include <casacore/casa/BasicSL/String.h> 00040 #include <casacore/casa/IO/FileLocker.h> 00041 00042 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00043 00044 //# Forward Declarations 00045 class RefTable; 00046 // class TableDesc; !Forward declaration not recognized SGI compiler 00047 class TableLock; 00048 class BaseColumn; 00049 class ColumnDesc; 00050 class TableRecord; 00051 class Record; 00052 class TableExprNode; 00053 class BaseTableIterator; 00054 class DataManager; 00055 class IPosition; 00056 template<class T> class Vector; 00057 template<class T> class Block; 00058 template<class T> class PtrBlock; 00059 class AipsIO; 00060 00061 00062 // <summary> 00063 // Abstract base class for tables 00064 // </summary> 00065 00066 // <use visibility=local> 00067 00068 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests=""> 00069 // </reviewed> 00070 00071 // <prerequisite> 00072 //# Classes you should understand before using this one. 00073 // <li> Table 00074 // <li> Sort 00075 // <li> TableExprNode 00076 // </prerequisite> 00077 00078 // <etymology> 00079 // BaseTable is the (abstract) base class for different kind of tables. 00080 // </etymology> 00081 00082 // <synopsis> 00083 // BaseTables defines many virtual functions, which are actually 00084 // implemented in the underlying table classes like PlainTable and 00085 // RefTable. Other functions like sort and select are implemented 00086 // in BaseTable itself. 00087 // 00088 // The functions in BaseTable and its derived classes can only be 00089 // used by the table system classes. All user access is via the 00090 // envelope class Table, which references (counted) BaseTable. 00091 // </synopsis> 00092 00093 // <todo asof="$DATE:$"> 00094 //# A List of bugs, limitations, extensions or planned refinements. 00095 // <li> Implement function renameColumn, removeColumn. 00096 // </todo> 00097 00098 00099 class BaseTable 00100 { 00101 public: 00102 00103 // Initialize the object. 00104 BaseTable (const String& tableName, int tableOption, uInt nrrow); 00105 00106 virtual ~BaseTable(); 00107 00108 // Link to this BaseTable object (i.e. increase reference count). 00109 void link(); 00110 00111 // Unlink from a BaseTable. 00112 // Delete it if no more references. 00113 static void unlink (BaseTable*); 00114 00115 // Is the table a null table? 00116 // By default it is not. 00117 virtual Bool isNull() const; 00118 00119 // Reopen the table for read/write. 00120 virtual void reopenRW() = 0; 00121 00122 // Is the table stored in big or little endian format? 00123 virtual Bool asBigEndian() const = 0; 00124 00125 // Get the storage option used for the table. 00126 virtual const StorageOption& storageOption() const = 0; 00127 00128 // Is the table in use (i.e. open) in another process? 00129 // If <src>checkSubTables</src> is set, it is also checked if 00130 // a subtable is used in another process. 00131 virtual Bool isMultiUsed(Bool checkSubTables) const = 0; 00132 00133 // Get the locking info. 00134 virtual const TableLock& lockOptions() const = 0; 00135 00136 // Merge the given lock info with the existing one. 00137 virtual void mergeLock (const TableLock& lockOptions) = 0; 00138 00139 // Has this process the read or write lock, thus can the table 00140 // be read or written safely? 00141 virtual Bool hasLock (FileLocker::LockType) const = 0; 00142 00143 // Try to lock the table for read or write access. 00144 virtual Bool lock (FileLocker::LockType, uInt nattempts) = 0; 00145 00146 // Unlock the table. This will also synchronize the table data, 00147 // thus force the data to be written to disk. 00148 virtual void unlock() = 0; 00149 00150 // Flush the table, i.e. write it to disk. 00151 virtual void flush (Bool fsync, Bool recursive) = 0; 00152 00153 // Resync the Table object with the table file. 00154 virtual void resync() = 0; 00155 00156 // Get the modify counter. 00157 virtual uInt getModifyCounter() const = 0; 00158 00159 // Set the table to being changed. By default it does nothing. 00160 virtual void setTableChanged(); 00161 00162 // Do not write the table (used in in case of exceptions). 00163 void doNotWrite() 00164 { noWrite_p = True; } 00165 00166 // Test if this table is writable. 00167 // This tells if values can be put into a column. 00168 virtual Bool isWritable() const = 0; 00169 00170 // Test if the given column is writable. 00171 // <group> 00172 Bool isColumnWritable (const String& columnName) const; 00173 Bool isColumnWritable (uInt columnIndex) const; 00174 // </group> 00175 00176 // Test if the given column is stored (otherwise it is virtual). 00177 // <group> 00178 Bool isColumnStored (const String& columnName) const; 00179 Bool isColumnStored (uInt columnIndex) const; 00180 // </group> 00181 00182 // Get the table name. 00183 const String& tableName() const 00184 { return name_p; } 00185 00186 // Get the names of the tables this table consists of. 00187 // The default implementation adds the name of this table to the block. 00188 virtual void getPartNames (Block<String>& names, Bool recursive) const; 00189 00190 // Rename the table. 00191 // The following options can be given: 00192 // <dl> 00193 // <dt> Table::Update 00194 // <dd> A table with this name must already exists, which will be 00195 // overwritten. When succesfully renamed, the table is unmarked 00196 // for delete (if necessary). 00197 // <dt> Table::New 00198 // <dd> When a table with this name exists, it will be overwritten. 00199 // When succesfully renamed, the table is unmarked 00200 // for delete (if necessary). 00201 // <dt> Table::NewNoReplace 00202 // <dd> When a table with this name already exists, an exception 00203 // is thrown. When succesfully renamed, the table 00204 // is unmarked for delete (if necessary). 00205 // <dt> Table::Scratch 00206 // <dd> Same as Table::New, but followed by markForDelete(). 00207 // </dl> 00208 // The rename function in this base class renames the table file. 00209 // In a derived class (e.g. PlainTable) the function should also 00210 // be implemented to rename subtables in its keywords. 00211 virtual void rename (const String& newName, int tableOption); 00212 00213 // Copy the table and all its subtables. 00214 // The default implementation of deepCopy is to call copy. 00215 // The following options can be given: 00216 // <dl> 00217 // <dt> Table::New 00218 // <dd> When a table with this name exists, it will be overwritten. 00219 // <dt> Table::NewNoReplace 00220 // <dd> When a table with this name already exists, an exception 00221 // is thrown. 00222 // <dt> Table::Scratch 00223 // <dd> Same as Table::New, but followed by markForDelete(). 00224 // </dl> 00225 // <group> 00226 virtual void copy (const String& newName, int tableOption) const; 00227 virtual void deepCopy (const String& newName, 00228 const Record& dataManagerInfo, 00229 const StorageOption&, 00230 int tableOption, 00231 Bool valueCopy, 00232 int endianFormat, 00233 Bool noRows) const; 00234 // </group> 00235 00236 // Get the table type. 00237 // By default it returns Table::Plain. 00238 virtual int tableType() const; 00239 00240 // Get the table option. 00241 int tableOption() const 00242 { return option_p; } 00243 00244 // Mark the table for delete. 00245 // This means that the underlying table gets deleted when it is 00246 // actually destructed. 00247 // The scratchCallback function is called when needed. 00248 void markForDelete (Bool callback, const String& oldName); 00249 00250 // Unmark the table for delete. 00251 // This means the underlying table does not get deleted when destructed. 00252 // The scratchCallback function is called when needed. 00253 void unmarkForDelete (Bool callback, const String& oldName); 00254 00255 // Test if the table is marked for delete. 00256 Bool isMarkedForDelete() const 00257 { return delete_p; } 00258 00259 // Get the table description. 00260 const TableDesc& tableDesc() const 00261 { return (tdescPtr_p == 0 ? makeTableDesc() : *tdescPtr_p); } 00262 00263 // Get the actual table description. 00264 virtual TableDesc actualTableDesc() const = 0; 00265 00266 // Get the data manager info. 00267 virtual Record dataManagerInfo() const = 0; 00268 00269 // Show the table structure (implementation of Table::showStructure). 00270 void showStructure (std::ostream&, 00271 Bool showDataMan, 00272 Bool showColumns, 00273 Bool showSubTables, 00274 Bool sortColumns, 00275 Bool cOrder); 00276 00277 // Get readonly access to the table keyword set. 00278 virtual TableRecord& keywordSet() = 0; 00279 00280 // Get read/write access to the table keyword set. 00281 // This requires that the table is locked (or it gets locked 00282 // when using AutoLocking mode). 00283 virtual TableRecord& rwKeywordSet() = 0; 00284 00285 // Get access to the TableInfo object. 00286 TableInfo& tableInfo() 00287 { return info_p; } 00288 00289 // Get the table info of the table with the given name. 00290 // An empty object is returned when the table is unknown. 00291 static TableInfo tableInfo (const String& tableName); 00292 00293 // Write the TableInfo object. 00294 virtual void flushTableInfo(); 00295 00296 // Get number of rows. 00297 uInt nrow() const 00298 { return nrrow_p; } 00299 00300 // Get a column object using its index. 00301 virtual BaseColumn* getColumn (uInt columnIndex) const = 0; 00302 00303 // Get a column object using its name. 00304 virtual BaseColumn* getColumn (const String& columnName) const = 0; 00305 00306 // Test if it is possible to add a row to this table. 00307 virtual Bool canAddRow() const; 00308 00309 // Add one or more rows and possibly initialize them. 00310 // This will fail for tables not supporting addition of rows. 00311 virtual void addRow (uInt nrrow = 1, Bool initialize = True); 00312 00313 // Test if it is possible to remove a row from this table. 00314 virtual Bool canRemoveRow() const; 00315 00316 // Remove rows. 00317 // This will fail for tables not supporting removal of rows. 00318 // <note role=tip> 00319 // The following code fragments do NOT have the same result: 00320 // <srcblock> 00321 // tab.removeRow (10); // remove row 10 00322 // tab.removeRow (20); // remove row 20, which was 21 00323 // 00324 // Vector<uInt> vec(2); 00325 // vec(0) = 10; 00326 // vec(1) = 20; 00327 // tab.removeRow (vec); // remove row 10 and 20 00328 // </srcblock> 00329 // because in the first fragment removing row 10 turns the former 00330 // row 21 into row 20. 00331 // </note> 00332 // <group> 00333 virtual void removeRow (uInt rownr); 00334 void removeRow (const Vector<uInt>& rownrs); 00335 // </group> 00336 00337 // Find the data manager with the given name or for the given column. 00338 virtual DataManager* findDataManager (const String& name, 00339 Bool byColumn) const = 0; 00340 00341 // Select rows using the given expression (which can be null). 00342 // Skip first <src>offset</src> matching rows. 00343 // Return at most <src>maxRow</src> matching rows. 00344 BaseTable* select (const TableExprNode&, uInt maxRow, uInt offset); 00345 00346 // Select maxRow rows and skip first offset rows. maxRow=0 means all. 00347 BaseTable* select (uInt maxRow, uInt offset); 00348 00349 // Select rows using a vector of row numbers. 00350 BaseTable* select (const Vector<uInt>& rownrs); 00351 00352 // Select rows using a mask block. 00353 // The length of the block must match the number of rows in the table. 00354 // If True, the corresponding row will be selected. 00355 BaseTable* select (const Block<Bool>& mask); 00356 00357 // Project the given columns (i.e. select the columns). 00358 BaseTable* project (const Block<String>& columnNames); 00359 00360 //# Virtually concatenate all tables in this column. 00361 //# The column cells must contain tables with the same description. 00362 //#// BaseTable* concatenate (const String& columnName); 00363 00364 // Do logical operations on a table. 00365 // <group> 00366 // intersection with another table 00367 BaseTable* tabAnd (BaseTable*); 00368 // union with another table 00369 BaseTable* tabOr (BaseTable*); 00370 // subtract another table 00371 BaseTable* tabSub (BaseTable*); 00372 // xor with another table 00373 BaseTable* tabXor (BaseTable*); 00374 // take complement 00375 BaseTable* tabNot (); 00376 // </group> 00377 00378 // Sort a table on one or more columns of scalars. 00379 BaseTable* sort (const Block<String>& columnNames, 00380 const Block<CountedPtr<BaseCompare> >& compareObjects, 00381 const Block<Int>& sortOrder, int sortOption); 00382 00383 // Create an iterator. 00384 BaseTableIterator* makeIterator (const Block<String>& columnNames, 00385 const Block<CountedPtr<BaseCompare> >&, 00386 const Block<Int>& orders, int option); 00387 00388 // Add one or more columns to the table. 00389 // The default implementation throws an "invalid operation" exception. 00390 // <group> 00391 virtual void addColumn (const ColumnDesc& columnDesc, Bool addToParent); 00392 virtual void addColumn (const ColumnDesc& columnDesc, 00393 const String& dataManager, Bool byName, 00394 Bool addToParent); 00395 virtual void addColumn (const ColumnDesc& columnDesc, 00396 const DataManager& dataManager, Bool addToParent); 00397 virtual void addColumn (const TableDesc& tableDesc, 00398 const DataManager& dataManager, Bool addToParent); 00399 // </group> 00400 00401 // Add one or more columns to the table. 00402 // The data manager to use is described in the record. 00403 void addColumns (const TableDesc& tableDesc, const Record& dmInfo, 00404 Bool addToParent); 00405 00406 // Test if columns can be removed. 00407 virtual Bool canRemoveColumn (const Vector<String>& columnNames) const = 0; 00408 00409 // Remove columns. 00410 virtual void removeColumn (const Vector<String>& columnNames) = 0; 00411 00412 // Check if the set of columns can be removed. 00413 // It checks if columns have not been specified twice and it 00414 // checks if they exist. 00415 // If the flag is set an exception is thrown if errors are found. 00416 Bool checkRemoveColumn (const Vector<String>& columnNames, 00417 Bool throwException) const; 00418 00419 // Test if a column can be renamed. 00420 virtual Bool canRenameColumn (const String& columnName) const = 0; 00421 00422 // Rename a column. 00423 virtual void renameColumn (const String& newName, 00424 const String& oldName) = 0; 00425 00426 // Rename a hypercolumn. 00427 virtual void renameHypercolumn (const String& newName, 00428 const String& oldName) = 0; 00429 00430 // Get a vector of row numbers. 00431 // By default it returns the row numbers 0..nrrow()-1. 00432 // It needs to be implemented for RefTable only. 00433 virtual Vector<uInt> rowNumbers() const; 00434 00435 // Get pointer to root table (i.e. parent of a RefTable). 00436 // Default it is this table. 00437 // It is meant for the reference tables after a select or sort which 00438 // can then still name their parent as the root. 00439 virtual BaseTable* root(); 00440 00441 // Tell if the table is in row order. 00442 // By default it is, since normally a table is always in row order. 00443 // It is meant for RefTable-s, where the rows can be in 00444 // another (sorted) order. 00445 virtual Bool rowOrder() const; 00446 00447 // By the default the table cannot return the storage of rownrs. 00448 // That can only be done by a RefTable, where it is implemented. 00449 virtual Vector<uInt>* rowStorage(); 00450 00451 // Adjust the row numbers to be the actual row numbers in the 00452 // root table. This is, for instance, used when a RefTable is sorted. 00453 // Optionally it also determines if the resulting rows are in order. 00454 virtual Bool adjustRownrs (uInt nrrow, Vector<uInt>& rownrs, 00455 Bool determineOrder) const; 00456 00457 // Do the actual sort. 00458 // The default implementation is suitable for almost all cases. 00459 // Only in RefTable a smarter implementation is provided. 00460 virtual BaseTable* doSort (PtrBlock<BaseColumn*>&, 00461 const Block<CountedPtr<BaseCompare> >&, 00462 const Block<Int>& sortOrder, 00463 int sortOption); 00464 00465 // Create a RefTable object. 00466 RefTable* makeRefTable (Bool rowOrder, uInt initialNrrow); 00467 00468 // Check if the row number is valid. 00469 // It throws an exception if out of range. 00470 void checkRowNumber (uInt rownr) const 00471 { if (rownr >= nrrow_p + nrrowToAdd_p) checkRowNumberThrow (rownr); } 00472 00473 // Get the table's trace-id. 00474 int traceId() const 00475 { return itsTraceId; } 00476 00477 00478 protected: 00479 uInt nrlink_p; //# #references to this table 00480 uInt nrrow_p; //# #rows in this table 00481 uInt nrrowToAdd_p; //# #rows to be added 00482 TableDesc* tdescPtr_p; //# Pointer to table description 00483 String name_p; //# table name 00484 int option_p; //# Table constructor option 00485 Bool noWrite_p; //# False = do not write the table 00486 Bool delete_p; //# True = delete when destructed 00487 TableInfo info_p; //# Table information (type, etc.) 00488 Bool madeDir_p; //# True = table dir has been created 00489 int itsTraceId; //# table-id for TableTrace tracing 00490 00491 00492 // Do the callback for scratch tables (if callback is set). 00493 void scratchCallback (Bool isScratch, const String& oldName) const; 00494 00495 // Create the table directory when needed (and possible). 00496 // When the file already exists, check if it is a directory. 00497 // It returns True when it actually created the directory. 00498 Bool makeTableDir(); 00499 00500 // Make a true deep copy of the table. 00501 void trueDeepCopy (const String& newName, 00502 const Record& dataManagerInfo, 00503 const StorageOption&, 00504 int tableOption, 00505 int endianFormat, 00506 Bool noRows) const; 00507 00508 // Prepare for copying or renaming a table. 00509 // It checks if the target table already exists and removes it 00510 // when necessary. 00511 void prepareCopyRename (const String& newName, int tableOption) const; 00512 00513 // Rename the subtables (used by rename function). 00514 virtual void renameSubTables (const String& newName, 00515 const String& oldName); 00516 00517 // Check if the table already exists. 00518 // Throw an exception if so. 00519 void throwIfTableExists(); 00520 00521 // Test if the table is opened for write. 00522 Bool openedForWrite() const; 00523 00524 // Start writing a table. It does a putstart and writes <src>nrrow_p</src>. 00525 // It should be ended by calling <src>writeEnd</src>. 00526 void writeStart (AipsIO&, Bool bigEndian); 00527 00528 // End writing a table. 00529 void writeEnd (AipsIO&); 00530 00531 // Should the table be written. 00532 // This flag is False if an exception was thrown. 00533 Bool shouldNotWrite() const 00534 { return noWrite_p; } 00535 00536 // Read the TableInfo object. 00537 void getTableInfo(); 00538 00539 private: 00540 // Copy constructor is forbidden, because copying a table requires 00541 // some more knowledge (like table name of result). 00542 // Declaring it private, makes it unusable. 00543 BaseTable (const BaseTable&); 00544 00545 // Assignment is forbidden, because copying a table requires 00546 // some more knowledge (like table name of result). 00547 // Declaring it private, makes it unusable. 00548 BaseTable& operator= (const BaseTable&); 00549 00550 // Show a possible extra table structure header. 00551 // It is used by e.g. RefTable to show which table is referenced. 00552 virtual void showStructureExtra (std::ostream&) const; 00553 00554 // Show the info of the given columns. 00555 // Sort the columns if needed. 00556 void showColumnInfo (ostream& os, const TableDesc&, uInt maxNameLength, 00557 const Array<String>& columnNames, Bool sort, 00558 Bool cOrder) const; 00559 00560 // Throw an exception for checkRowNumber. 00561 void checkRowNumberThrow (uInt rownr) const; 00562 00563 // Check if the tables combined in a logical operation have the 00564 // same root. 00565 void logicCheck (BaseTable* that); 00566 00567 // Get the rownrs of the table in ascending order to be 00568 // used in the logical operation on the table. 00569 uInt logicRows (uInt*& rownrs, Bool& allocated); 00570 00571 // Make an empty table description. 00572 // This is used if one asks for the description of a NullTable. 00573 // Creating an empty TableDesc in the NullTable takes too much time. 00574 // Furthermore it causes static initialization order problems. 00575 const TableDesc& makeTableDesc() const; 00576 00577 // Make the name absolute. 00578 // It first checks if the name contains valid characters (not only . and /). 00579 String makeAbsoluteName (const String& name) const; 00580 }; 00581 00582 00583 00584 00585 } //# NAMESPACE CASACORE - END 00586 00587 #endif