00001 //# ColumnSet.h: Class to manage a set of table columns 00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,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_COLUMNSET_H 00029 #define TABLES_COLUMNSET_H 00030 00031 00032 //# Includes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/tables/Tables/TableLockData.h> 00035 #include <casacore/tables/Tables/BaseTable.h> 00036 #include <casacore/tables/Tables/StorageOption.h> 00037 #include <casacore/casa/Containers/SimOrdMap.h> 00038 #include <casacore/casa/BasicSL/String.h> 00039 00040 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00041 00042 //# Forward Declarations 00043 class SetupNewTable; 00044 class Table; 00045 class TableDesc; 00046 class TSMOption; 00047 class BaseTable; 00048 class TableAttr; 00049 class ColumnDesc; 00050 class PlainColumn; 00051 class DataManager; 00052 class MultiFile; 00053 class Record; 00054 class IPosition; 00055 class AipsIO; 00056 template<class T> class Vector; 00057 00058 00059 // <summary> 00060 // Class to manage a set of table columns 00061 // </summary> 00062 00063 // <use visibility=local> 00064 00065 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests=""> 00066 // </reviewed> 00067 00068 // <prerequisite> 00069 //# Classes you should understand before using this one. 00070 // <li> PlainTable 00071 // <li> DataManager 00072 // </prerequisite> 00073 00074 // <etymology> 00075 // ColumnSet represent the set of columns in a table. 00076 // </etymology> 00077 00078 // <synopsis> 00079 // ColumnSet contains all columns in a plain table (thus not in a RefTable). 00080 // Furthermore it contains the set of data managers used by the columns 00081 // in the table. 00082 // 00083 // The main purpose of the class is to deal with constructing, writing 00084 // and reading the column objects. It is used by classes SetupNewTable 00085 // and Table. 00086 // </synopsis> 00087 00088 // <todo asof="$DATE:$"> 00089 //# A List of bugs, limitations, extensions or planned refinements. 00090 // </todo> 00091 00092 00093 class ColumnSet 00094 { 00095 public: 00096 00097 // Construct from the table description. 00098 // This creates all underlying filled and virtual column objects. 00099 ColumnSet (TableDesc*, const StorageOption& = StorageOption()); 00100 00101 ~ColumnSet(); 00102 00103 // Reopen the data managers for read/write. 00104 void reopenRW(); 00105 00106 // Rename the necessary subtables in the column keywords. 00107 void renameTables (const String& newName, const String& oldName); 00108 00109 // Get the storage option. 00110 const StorageOption& storageOption() const 00111 { return storageOpt_p; } 00112 00113 // Are subtables used in other processes. 00114 Bool areTablesMultiUsed() const; 00115 00116 // Get a column by name. 00117 PlainColumn* getColumn (const String& columnName) const; 00118 00119 // Get a column by index. 00120 PlainColumn* getColumn (uInt columnIndex) const; 00121 00122 // Add a data manager. 00123 // It increments seqCount_p and returns that as a unique sequence number. 00124 // This can, for instance, be used to create a unique file name. 00125 void addDataManager (DataManager*); 00126 00127 // Initialize the data managers for a new table. 00128 // It creates the data manager column objects for each column 00129 // and it allows the data managers to link themselves to the 00130 // Table object and to initialize themselves. 00131 void initDataManagers (uInt nrrow, Bool bigEndian, 00132 const TSMOption& tsmOption, 00133 Table& tab); 00134 00135 // Link the ColumnSet object to the BaseTable object. 00136 void linkToTable (BaseTable* baseTableObject); 00137 00138 // Link the ColumnSet object to the TableLockData object. 00139 void linkToLockObject (TableLockData* lockObject); 00140 00141 // Check if the table is locked for read or write. 00142 // If manual or permanent locking is in effect, it checks if the 00143 // table is properly locked. 00144 // If autolocking is in effect, it locks the table when needed. 00145 // <group> 00146 void checkReadLock (Bool wait); 00147 void checkWriteLock (Bool wait); 00148 // </group> 00149 00150 // Inspect the auto lock when the inspection interval has expired and 00151 // release it when another process needs the lock. 00152 void autoReleaseLock(); 00153 00154 // If needed, get a temporary user lock. 00155 // It returns False if the lock was already there. 00156 Bool userLock (FileLocker::LockType, Bool wait); 00157 00158 // Release a temporary user lock if the given release flag is True. 00159 void userUnlock (Bool releaseFlag); 00160 00161 // Do all data managers and engines allow to add rows? 00162 Bool canAddRow() const; 00163 00164 // Do all data managers and engines allow to remove rows? 00165 Bool canRemoveRow() const; 00166 00167 // Can the given columns be removed from the data manager? 00168 Bool canRemoveColumn (const Vector<String>& columnNames) const; 00169 00170 // Can a column be renamed in the data manager? 00171 Bool canRenameColumn (const String& columnName) const; 00172 00173 // Add rows to all data managers. 00174 void addRow (uInt nrrow); 00175 00176 // Remove a row from all data managers. 00177 // It will throw an exception if not possible. 00178 void removeRow (uInt rownr); 00179 00180 // Remove the columns from the map and the data manager. 00181 void removeColumn (const Vector<String>& columnNames); 00182 00183 // Rename the column in the map. 00184 void renameColumn (const String& newName, const String& oldName); 00185 00186 // Add a column to the table. 00187 // The default implementation throws an "invalid operation" exception. 00188 // <group> 00189 void addColumn (const ColumnDesc& columnDesc, 00190 Bool bigEndian, const TSMOption& tsmOption, Table& tab); 00191 void addColumn (const ColumnDesc& columnDesc, 00192 const String& dataManager, Bool byName, 00193 Bool bigEndian, const TSMOption& tsmOption, Table& tab); 00194 void addColumn (const ColumnDesc& columnDesc, 00195 const DataManager& dataManager, 00196 Bool bigEndian, const TSMOption& tsmOption, Table& tab); 00197 void addColumn (const TableDesc& tableDesc, 00198 const DataManager& dataManager, 00199 Bool bigEndian, const TSMOption& tsmOption, Table& tab); 00200 // </group> 00201 00202 // Get nr of rows. 00203 uInt nrow() const; 00204 00205 // Get the actual table description. 00206 TableDesc actualTableDesc() const; 00207 00208 // Get the data manager info. 00209 // Optionally only the virtual engines are retrieved. 00210 Record dataManagerInfo (Bool virtualOnly=False) const; 00211 00212 // Get the trace-id of the table. 00213 int traceId() const 00214 { return baseTablePtr_p->traceId(); } 00215 00216 // Initialize rows startRownr till endRownr (inclusive). 00217 void initialize (uInt startRownr, uInt endRownr); 00218 00219 // Write all the data and let the data managers flush their data. 00220 // This function is called when a table gets written (i.e. flushed). 00221 // It returns True if any data manager wrote something. 00222 Bool putFile (Bool writeTable, AipsIO&, const TableAttr&, Bool fsync); 00223 00224 // Read the data, reconstruct the data managers, and link those to 00225 // the table object. 00226 // This function gets called when an existing table is read back. 00227 // It returns the number of rows in case a data manager thinks there are 00228 // more. That is in particular used by LofarStMan. 00229 uInt getFile (AipsIO&, Table& tab, uInt nrrow, Bool bigEndian, 00230 const TSMOption& tsmOption); 00231 00232 // Set the table to being changed. 00233 void setTableChanged(); 00234 00235 // Get the data manager change flags (used by PlainTable). 00236 Block<Bool>& dataManChanged(); 00237 00238 // Synchronize the data managers when data in them have changed. 00239 // It returns the number of rows it think it has, which is needed for 00240 // storage managers like LofarStMan. 00241 // <src>forceSync=True</src> means that the data managers are forced 00242 // to do a sync. Otherwise the contents of the lock file tell if a data 00243 // manager has to sync. 00244 uInt resync (uInt nrrow, Bool forceSync); 00245 00246 // Invalidate the column caches for all columns. 00247 void invalidateColumnCaches(); 00248 00249 // Get the correct data manager. 00250 // This is used by the column objects to link themselves to the 00251 // correct datamanagers when they are read back. 00252 DataManager* getDataManager (uInt seqnr) const; 00253 00254 // Check if no double data manager names have been given. 00255 void checkDataManagerNames (const String& tableName) const; 00256 00257 // Find the data manager with the given name or for the given column. 00258 // If the data manager or column is unknown, an exception is thrown. 00259 // A blank name means the data manager is unknown. 00260 DataManager* findDataManager (const String& name, 00261 Bool byColumn=False) const; 00262 00263 // Make a unique data manager name by appending a suffix _n if needed 00264 // where n is a number that makes the name unique. 00265 String uniqueDataManagerName (const String& name) const; 00266 00267 // Synchronize the columns after it appeared that data in the 00268 // main table file have changed. 00269 // It cannot deal with changes in number of columns, so it throws an 00270 // exception when they have changed. 00271 // Keywords in all columns are updated. 00272 // The other ColumnSet gives the new data. 00273 void syncColumns (const ColumnSet& other, const TableAttr& defaultAttr); 00274 00275 private: 00276 // Remove the last data manager (used by addColumn after an exception). 00277 // It does the opposite of addDataManager. 00278 void removeLastDataManager(); 00279 00280 // Let the data managers (from the given index on) initialize themselves. 00281 void initSomeDataManagers (uInt from, Table& tab); 00282 00283 // Let the data managers (from the given index on) prepare themselves. 00284 void prepareSomeDataManagers (uInt from); 00285 00286 // Open or create the MultiFile if needed. 00287 void openMultiFile (uInt from, const Table& tab, 00288 ByteIO::OpenOption); 00289 00290 // Check if a data manager name has not already been used. 00291 // Start checking at the given index in the array. 00292 // It returns False if the name has already been used. 00293 // By default an exception is thrown if the name has already been used. 00294 Bool checkDataManagerName (const String& name, uInt from, 00295 const String& tableName, 00296 Bool doTthrow=True) const; 00297 00298 // Do the actual addition of a column. 00299 void doAddColumn (const ColumnDesc& columnDesc, DataManager* dataManPtr); 00300 00301 // Check if columns to be removed can be removed. 00302 // It returns a map of DataManager* telling how many columns for 00303 // a data manager have to be removed. A count of -1 means that all 00304 // columns have to be removed. For such columns the flag in the 00305 // returned Block is False, otherwise True. 00306 SimpleOrderedMap<void*,Int> checkRemoveColumn 00307 (const Vector<String>& columnNames); 00308 00309 // Check if the table is locked for read or write. 00310 // If manual or permanent locking is in effect, it checks if the 00311 // table is properly locked. 00312 // If autolocking is in effect, it locks the table when needed. 00313 void doLock (FileLocker::LockType, Bool wait); 00314 00315 00316 //# Declare the variables. 00317 TableDesc* tdescPtr_p; 00318 StorageOption storageOpt_p; 00319 MultiFileBase* multiFile_p; 00320 Int64 nrrow_p; //# #rows 00321 BaseTable* baseTablePtr_p; 00322 TableLockData* lockPtr_p; //# lock object 00323 SimpleOrderedMap<String,void*> colMap_p; //# list of PlainColumns 00324 uInt seqCount_p; //# sequence number count 00325 //# (used for unique seqnr) 00326 Block<void*> blockDataMan_p; //# list of data managers 00327 Block<Bool> dataManChanged_p; //# data has changed 00328 }; 00329 00330 00331 00332 inline uInt ColumnSet::nrow() const 00333 { 00334 return nrrow_p; 00335 } 00336 inline void ColumnSet::linkToTable (BaseTable* baseTableObject) 00337 { 00338 baseTablePtr_p = baseTableObject; 00339 } 00340 inline void ColumnSet::setTableChanged() 00341 { 00342 baseTablePtr_p->setTableChanged(); 00343 } 00344 inline void ColumnSet::linkToLockObject (TableLockData* lockObject) 00345 { 00346 lockPtr_p = lockObject; 00347 } 00348 inline void ColumnSet::checkReadLock (Bool wait) 00349 { 00350 if (lockPtr_p->readLocking() 00351 && ! lockPtr_p->hasLock (FileLocker::Read)) { 00352 doLock (FileLocker::Read, wait); 00353 } 00354 } 00355 inline void ColumnSet::checkWriteLock (Bool wait) 00356 { 00357 if (! lockPtr_p->hasLock (FileLocker::Write)) { 00358 doLock (FileLocker::Write, wait); 00359 } 00360 } 00361 inline void ColumnSet::userUnlock (Bool releaseFlag) 00362 { 00363 if (releaseFlag) { 00364 lockPtr_p->release(); 00365 } 00366 } 00367 inline void ColumnSet::autoReleaseLock() 00368 { 00369 lockPtr_p->autoRelease(); 00370 } 00371 inline Block<Bool>& ColumnSet::dataManChanged() 00372 { 00373 return dataManChanged_p; 00374 } 00375 00376 00377 00378 00379 } //# NAMESPACE CASACORE - END 00380 00381 #endif