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