casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
PagedArray.h
Go to the documentation of this file.
00001 //# PagedArray.h: templated Lattice, paged from disk to memory on demand
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: PagedArray.h 20364 2008-06-30 06:10:38Z gervandiepen $
00027 
00028 #ifndef LATTICES_PAGEDARRAY_H
00029 #define LATTICES_PAGEDARRAY_H
00030 
00031 //# Includes
00032 #include <lattices/Lattices/Lattice.h>
00033 #include <lattices/Lattices/TiledShape.h>
00034 #include <tables/Tables/ArrayColumn.h>
00035 #include <tables/Tables/Table.h>
00036 #include <tables/Tables/TiledStManAccessor.h>
00037 #include <casa/BasicSL/String.h>
00038 
00039 
00040 namespace casa { //# NAMESPACE CASA - BEGIN
00041 
00042 // <summary>
00043 // A Lattice that is read from or written to disk.
00044 // </summary>
00045 
00046 // <use visibility=export>
00047 
00048 // <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tPagedArray.cc" demos="dPagedArray.cc">
00049 // </reviewed>
00050 
00051 // <prerequisite>
00052 //   <li> <linkto class="Lattice">Lattice</linkto>
00053 //   <li> <linkto class="TiledShape">TiledShape</linkto>
00054 // </prerequisite>
00055 
00056 // <etymology>
00057 // "Demand paging" is a technique used to implement virtual memory in
00058 // computer operating systems.  In this scheme, code or data are read from
00059 // disk to memory only as needed by a process, and are read in fixed-sized
00060 // chunks called "pages".  PagedArrays are somewhat the same -- though
00061 // without the automatic features found in virtual memory demand paging.
00062 // However PagedArrays do allow the user to access chunks of the disk in a
00063 // flexible way, that can match the requirements of many algorithms.
00064 // </etymology>
00065 
00066 // <synopsis> 
00067 // At the time of writing, typical scientific computers provide sufficient
00068 // memory for storing and manipulating 2-dimensional astronomical images,
00069 // which have average size of around 8 MBytes.  Astronomy is increasingly
00070 // using three or higher dimensional arrays, which can be larger by one or
00071 // two orders of magnitude. PagedArrays provide a convenient way of
00072 // accessing these large arrays without requiring all the data to be read
00073 // into real or virtual memory.
00074 // <p>
00075 // When you construct a PagedArray you do not read any data into
00076 // memory. Instead a disk file (ie. a Table) is created, in a place you
00077 // specify, to hold the data. This means you need to have enough disk space
00078 // to hold the array. Constructing a PagedArray is equivalent to opening a
00079 // file. 
00080 // <p>
00081 // Because the data is stored on disk it can be saved after the program,
00082 // function, or task that created the PagedArray has finished. This saved
00083 // array can then be read again at a later stage. 
00084 // <p>
00085 // So there are two reasons for using a PagedArray:
00086 // <ol>
00087 // <li> To provide for arrays that are too large for the computer's memory.
00088 // <li> To provide a way of saving arrays to disk for later access. 
00089 // </ol>
00090 //
00091 // To access the data in a PagedArray you can either:
00092 // <ol>
00093 // <li> Use a <linkto class=LatticeIterator>LatticeIterator</linkto>
00094 // <li> Use the getSlice and putSlice member functions
00095 // <li> Use the parenthesis operator or getAt and putAt functions
00096 // </ol>
00097 // These access methods are given in order of preference.  Some examples of
00098 // these access methods are in the documentation for the 
00099 // <linkto class=Lattice>Lattice</linkto> class as well as below. 
00100 // <p>
00101 // In nearly all cases you access the PagedArray by reading a "slice" of the
00102 // PagedArray into an AIPS++ <linkto class=Array>Array</linkto>. Because the
00103 // slice is stored in memory it is important that the slice you read is not
00104 // too big compared to the physical memory on your computer. Otherwise your
00105 // computer will page excessively and performance will be poor.
00106 // <p>
00107 // To overcome this you may be tempted to access the PagedArray a pixel at a
00108 // time. This will use little memory but the overhead of accessing a large
00109 // data set by separately reading each pixel from disk will also lead to poor
00110 // performance.
00111 // <p>
00112 // In general the best way to access the data in PagedArrays is to use a
00113 // LatticeIterator with a cursor size that "fits" nicely into memory. Not
00114 // only do the LaticeIterator classes provide a relatively simple way to
00115 // read/write all the data but they optimally set up the cache that is
00116 // associated with each PagedArray. 
00117 // <p>
00118 // If the LatticeIterator classes do not access the data the way you want
00119 // you can use the getSlice and putSlice member functions. These functions
00120 // do not set up the cache for you and improved performance may be obtained
00121 // by tweaking the cache using the setCacheSizeFromPath member frunction.
00122 //
00123 // <ANCHOR NAME="PagedArray:Advanced"><h3>More Details</h3></ANCHOR>
00124 // In order to utilise PagedArrays fully and understand many of the member
00125 // functions and data access methods in this class, you need to be familiar
00126 // with some of the concepts involved in the implementation of PagedArrays.
00127 // <p>
00128 // Each PagedArray is stored in one cell of a Table as an indirect Array
00129 // (see the documentation for the <linkto module="Tables">Tables</linkto>
00130 // module for more information). This means that multiple PagedArrays can be
00131 // stored in one Table. To specify which PagedArray you are referring to in
00132 // a given Table you need to specify the cell using its column name and row
00133 // number during construction. If a cell is not specified the default column
00134 // name (as given by the defaultColumnName function) and row number (as
00135 // given by the defaultRowNumber function) are used. This ability to store
00136 // multiple PagedArrays's is used in the PagedImage class where the image is
00137 // stored in one cell and a mask is optionally stored in a another column in
00138 // the same row.
00139 // <p>
00140 // There are currently a number of limitations when storing multiple
00141 // PagedArrays in the same Table. 
00142 // <ul>
00143 // <li> All the PagedArrays in the same column MUST have the same number of
00144 // dimensions. The dimension used for any particular column is set when the
00145 // first PagedArray in that column is constructed. If you want to put a
00146 // say two-dimensional PagedArray  into another row of a column that
00147 // already contains a four-dimensional PagedArray you need to add two
00148 // degenerate axes. In principle you could use the resize function, but see
00149 // below for why this is not recommended. It is better to just ensure that
00150 // all the PagedArrays have the same number of dimensions.
00151 // <li> All the cells in a column that contains PagedArrays must have their
00152 // shape defined. This becomes important if you are creating a PagedArray in
00153 // say row five of a Table that currently only has one row. The PagedArray
00154 // constructor will add another four rows to the Table, and put your
00155 // PagedArray (with the shape you specify) in row five. For the three
00156 // rows for which no shape was specified, the constructor will construct
00157 // PagedArrays with only one element (and of an appropriate
00158 // dimensionality). As you cannot resize these single element PagedArrays
00159 // without difficulty (see below), it is recommended that you add
00160 // PagedArrays to rows in your Table sequentially. It is necessary to have
00161 // the constructor define the shape of all cells in the Table as it is an
00162 // error to write a Table to disk with undefined cell shapes.
00163 // </ul>
00164 //
00165 // Each PagedArray is stored on disk using the tiled cell storage manager
00166 // (<linkto class=TiledCellStMan>TiledCellStMan</linkto>). This stores the
00167 // data in tiles which are regular subsections of the PagedArray. For
00168 // example a PagedArray of shape [1024,1024,4,128] may have a tile shape of
00169 // [32,16,4,16]. The data in each tile is stored as a unit on the disk. This
00170 // means that there is no preferred axis when accessing multi-dimensional
00171 // data.
00172 // <br>
00173 // The tile shape can be specified when constructing a new PagedArray but
00174 // not when reading an old one as it is intrinsic to the way the data is
00175 // stored on disk. It is NOT recommended that you specify the tile shape
00176 // unless you can control the lifetime of the PagedArray (this includes the
00177 // time it spends on disk), or can guarantee the access pattern. For example
00178 // if you know that a PagedArray of shape [512,512,4,32] will always be
00179 // sliced plane by plane you may prefer to specify a tile shape of
00180 // [512,64,1,1] rather than the default of [32,16,4,16]. 
00181 // <br>
00182 // Tiles can be cached by the tile storage manager so that it does not need
00183 // to read the data from disk every time you are accessing the a pixel in a
00184 // different tile. In order to cache the correct tiles you should tell the
00185 // storage manager what section of the PagedArray you will be
00186 // accessing. This is done using the setCacheSizeFromPath member
00187 // function. Alternatively you can set the size of the cache using the
00188 // setCacheSizeInTiles member function.
00189 // <br>
00190 // By default there is no limit on how much memory the tile cache can
00191 // consume. This can be changed using the setMaximumCacheSize member
00192 // function. The tiled storage manager always tries to cache enough tiles to
00193 // ensure that each tile is read from disk only once, so setting the maximum
00194 // cache size will trade off memory usage for disk I/O. Setting the cache
00195 // size is illustrated in example 5 below.
00196 // <br>
00197 // The showCacheStatistics member function is provided to allow you to
00198 // evaluate the performance of the tile cache.
00199 // </synopsis> 
00200 
00201 // <example>
00202 // All the examples in this section are available in dPagedArray.cc
00203 //
00204 // <h4>Example 1:</h4>
00205 // Create a PagedArray of Floats of shape [1024,1024,4,256] in a file
00206 // called "myData_tmp.array" and initialize it to zero. This will create a
00207 // directory on disk called "myData_tmp.array" that contains files that
00208 // exceed 1024*1024*4*256*4 (= 4 GBytes) in size.
00209 // <srcblock>
00210 // const IPosition arrayShape(4,1024,1024,4,256);
00211 // const String filename("myData_tmp.array");
00212 // PagedArray<Float> diskArray(arrayShape, filename);
00213 // cout << "Created a PagedArray of shape " << diskArray.shape() 
00214 //   << " (" << diskArray.shape().product()/1024/1024*sizeof(Float) 
00215 //   << " MBytes)" << endl
00216 //   << "in the table called " << diskArray.tableName() << endl;
00217 // diskArray.set(0.0f);
00218 // // Using the set function is an efficient way to initialize the PagedArray
00219 // // as it uses a PagedArrIter internally. Note that the set function is
00220 // // defined in the Lattice class that PagedArray is derived from. 
00221 // </srcblock>
00222 //
00223 // <h4>Example 2:</h4>
00224 // Read the PagedArray produced in Example 1 and put a Gaussian profile into
00225 // each spectral channel.
00226 // <srcblock>
00227 // PagedArray<Float> diskArray("myData_tmp.array");
00228 // IPosition shape = diskArray.shape();
00229 // // Construct a Gaussian Profile to be 10 channels wide and centred on
00230 // // channel 16. Its height is 1.0.
00231 // Gaussian1D<Float> g(1.0f, 16.0f, 10.0f);
00232 // // Create a vector to cache a sampled version of this profile.
00233 // Vector<Float> profile(shape(3));
00234 // indgen(profile);
00235 // profile.apply(g);
00236 // // Now put this profile into every spectral channel in the paged array. This
00237 // // is best done using an iterator.
00238 // LatticeIterator<Float> iter(diskArray, 
00239 //                          TiledLineStepper(shape, diskArray.tileShape(), 3));
00240 // for (iter.reset(); !iter.atEnd(); iter++) {
00241 //    iter.woCursor() = profile;
00242 // }
00243 // </srcblock>
00244 //
00245 // <h4>Example 3:</h4>
00246 // Now multiply the I-polarization data by 10.0 in this PagedArray. The
00247 // I-polarization data occupies 1 GByte of RAM which is too big to read
00248 // into the memory of most computers. So an iterator is used to get suitable
00249 // sized chunks.
00250 // <srcblock>
00251 // Table t("myData_tmp.array", Table::Update);
00252 // PagedArray<Float> da(t);
00253 // const IPosition latticeShape = da.shape();
00254 // const nx = latticeShape(0);
00255 // const ny = latticeShape(1);
00256 // const npol = latticeShape(2);
00257 // const nchan = latticeShape(3);
00258 // IPosition cursorShape = da.niceCursorShape();
00259 // cursorShape(2) = 1;
00260 // LatticeStepper step(latticeShape, cursorShape);
00261 // step.subSection(IPosition(4,0), IPosition(4,nx-1,ny-1,0,nchan-1));
00262 // LatticeIterator<Float> iter(da, step);
00263 // for (iter.reset(); !iter.atEnd(); iter++) {
00264 //    iter.rwCursor() *= 10.0f;
00265 // }
00266 // </srcblock>
00267 // 
00268 // <h4>Example 4:</h4>
00269 // Use a direct call to getSlice to access a small central region of the
00270 // V-polarization in spectral channel 0 only. The region is small enough
00271 // to not warrant constructing iterators and setting up
00272 // LatticeNavigators. In this example the call to the getSlice function
00273 // is unnecessary but is done for illustration purposes anyway.
00274 // <srcblock>
00275 // SetupNewTable maskSetup("mask_tmp.array", TableDesc(), Table::New);
00276 // Table maskTable(maskSetup);
00277 // PagedArray<Bool> maskArray(IPosition(4,1024,1024,4,256), maskTable);
00278 // maskArray.set(False);
00279 // COWPtr<Array<Bool> > maskPtr;
00280 // maskArray.getSlice(maskPtr, IPosition(4,240,240,3,0),
00281 //                    IPosition(4,32,32,1,1), IPosition(4,1));
00282 // maskPtr.rwRef() = True;
00283 // maskArray.putSlice(*maskPtr, IPosition(4,240,240,3,1));
00284 // </srcblock>
00285 // 
00286 // <h4>Example 5:</h4>
00287 // In this example the data in the PagedArray will be accessed a row at
00288 // a time while setting the cache size to different values. The comments
00289 // illustrate the results when running on an Ultra 1/140 with 64MBytes
00290 // of memory.
00291 // <srcblock>
00292 // PagedArray<Float> pa(IPosition(4,128,128,4,32));
00293 // const IPosition latticeShape = pa.shape();
00294 // cout << "The tile shape is:" << pa.tileShape() << endl;
00295 // // The tile shape is:[32, 16, 4, 16]
00296 //   
00297 // // Setup to access the PagedArray a row at a time
00298 // const IPosition sliceShape(4,latticeShape(0), 1, 1, 1);
00299 // const IPosition stride(4,1);
00300 // Array<Float> row(sliceShape);
00301 // IPosition start(4, 0);
00302 //   
00303 // // Set the cache size to enough pixels for one tile only. This uses
00304 // // 128kBytes of cache memory and takes 125 secs.
00305 // pa.setCacheSizeInTiles (1);
00306 // Timer clock;
00307 // for (start(3) = 0; start(3) < latticeShape(3); start(3)++) {
00308 //   for (start(2) = 0; start(2) < latticeShape(2); start(2)++) {
00309 //     for (start(1) = 0; start(1) < latticeShape(1); start(1)++) {
00310 //       pa.getSlice(row,  start, sliceShape, stride);
00311 //     }
00312 //   }
00313 // }
00314 // clock.show();
00315 // pa.showCacheStatistics(cout);
00316 // pa.clearCache();
00317 //   
00318 // // Set the cache size to enough pixels for one row of tiles (ie. 4).
00319 // // This uses 512 kBytes of cache memory and takes 10 secs.
00320 // pa.setCacheSizeInTiles (4);
00321 // clock.mark();
00322 // for (start(3) = 0; start(3) < latticeShape(3); start(3)++) {
00323 //   for (start(2) = 0; start(2) < latticeShape(2); start(2)++) {
00324 //     for (start(1) = 0; start(1) < latticeShape(1); start(1)++) {
00325 //       pa.getSlice(row,  start, sliceShape, stride);
00326 //     }
00327 //   }
00328 // }
00329 // clock.show();
00330 // pa.showCacheStatistics(cout);
00331 // pa.clearCache();
00332 //   
00333 // // Set the cache size to enough pixels for one plane of tiles
00334 // // (ie. 4*8). This uses 4 MBytes of cache memory and takes 2 secs.
00335 // pa.setCacheSizeInTiles (4*8);
00336 // clock.mark();
00337 // for (start(3) = 0; start(3) < latticeShape(3); start(3)++) {
00338 //   for (start(2) = 0; start(2) < latticeShape(2); start(2)++) {
00339 //     for (start(1) = 0; start(1) < latticeShape(1); start(1)++) {
00340 //       pa.getSlice(row,  start, sliceShape, stride);
00341 //     }
00342 //   }
00343 // }
00344 // clock.show();
00345 // pa.showCacheStatistics(cout);
00346 // pa.clearCache();
00347 // </srcblock>
00348 // </example>
00349 
00350 // <motivation>
00351 // Arrays of data are sometimes much too large to hold in random access memory.
00352 // PagedArrays, especially in combination with LatticeIterator, 
00353 // provide convenient access to such large data sets.
00354 // </motivation>
00355 
00356 // <templating arg=T>
00357 //  <li> Due to storage in Tables, the templated type must be able to be 
00358 // stored in an AIPS++ Table.  This restricts the template argument to all
00359 // the common types Bool, Float, Double, Complex, String etc.) More details
00360 // can be found in the RetypedArrayEngine class.
00361 // </templating>
00362 
00363 // <todo asof="1997/04/14">
00364 //   <li> A better way of resizing PagedArrays
00365 // </todo>
00366 
00367 // <linkfrom anchor="PagedArray" classes="Lattice ArrayLattice">
00368 //  <here>PagedArray</here> - a disk based Lattice.
00369 // </linkfrom>
00370 
00371 
00372 template <class T> class PagedArray : public Lattice<T>
00373 {
00374   //# Make members of parent class known.
00375 public:
00376   using Lattice<T>::ndim;
00377 
00378 public: 
00379   // The default constructor creates a PagedArray that is useless for just
00380   // about everything, except that it can be assigned to with the assignment
00381   // operator.
00382   PagedArray();
00383 
00384   // Construct a new PagedArray with the specified shape. A new Table with
00385   // the specified filename is constructed to hold the array. The Table will
00386   // remain on disk after the PagedArray goes out of scope or is deleted.
00387   PagedArray (const TiledShape& shape, const String& filename);
00388 
00389   // Construct a new PagedArray with the specified shape. A scratch Table is
00390   // created in the current working directory to hold the array. This Table
00391   // will be deleted automatically when the PagedArray goes out of scope or
00392   // is deleted.
00393   explicit PagedArray (const TiledShape& shape);
00394 
00395   // Construct a new PagedArray, with the specified shape, in the default
00396   // row and column of the supplied Table.
00397   PagedArray (const TiledShape& shape, Table& file);
00398 
00399   // Construct a new PagedArray, with the specified shape, in the specified
00400   // row and column of the supplied Table.
00401   PagedArray (const TiledShape& shape, Table& file,
00402               const String& columnName, uInt rowNum);
00403 
00404   // Reconstruct from a pre-existing PagedArray in the default row and
00405   // column of the supplied Table with the supplied filename.
00406   explicit PagedArray (const String& filename);
00407 
00408   // Reconstruct from a pre-existing PagedArray in the default row and
00409   // column of the supplied Table.
00410   explicit PagedArray (Table& file);
00411 
00412   // Reconstruct from a pre-existing PagedArray in the specified row and
00413   // column of the supplied Table.
00414   PagedArray (Table& file, const String& columnName, uInt rowNum);
00415 
00416   // The copy constructor which uses reference semantics. Copying by value
00417   // doesn't make sense, because it would require the creation of a
00418   // temporary (but possibly huge) file on disk.
00419   PagedArray (const PagedArray<T>& other);
00420   
00421   // The destructor flushes the PagedArrays contents to disk. 
00422   ~PagedArray();
00423   
00424   // The assignment operator with reference semantics. As with the copy
00425   // constructor assigning by value does not make sense.
00426   PagedArray<T>& operator= (const PagedArray<T>& other);
00427   
00428   // Make a copy of the object (reference semantics).
00429   virtual Lattice<T>* clone() const;
00430 
00431   // A PagedArray is always persistent.
00432   virtual Bool isPersistent() const;
00433 
00434   // A PagedArray is always paged to disk.
00435   virtual Bool isPaged() const;
00436 
00437   // Is the PagedArray writable?
00438   virtual Bool isWritable() const;
00439 
00440   // Returns the shape of the PagedArray.
00441   virtual IPosition shape() const;
00442 
00443   // Return the current Table name. By default this includes the full path. 
00444   // The path preceeding the file name can be stripped off on request.
00445   virtual String name (Bool stripPath=False) const;
00446 
00447   // Functions to resize the PagedArray. The old contents are lost. Usage of
00448   // this function is NOT currently recommended (see the <linkto
00449   // class="PagedArray:Advanced">More Details</linkto> section above).
00450   void resize (const TiledShape& newShape);
00451 
00452   // Returns the current table name (ie. filename) of this PagedArray.
00453   const String& tableName() const;
00454 
00455   // Return the current table object.
00456   // <group>
00457   Table& table();
00458   const Table& table() const;
00459   // </group>
00460 
00461   // Returns the current Table column name of this PagedArray.
00462   const String& columnName() const;
00463 
00464   // Returns the default TableColumn name for a PagedArray.
00465   static String defaultColumn();
00466 
00467   // Returns an accessor to the tiled storage manager.
00468   const ROTiledStManAccessor& accessor() const;
00469 
00470   // Returns the current row number of this PagedArray.
00471   uInt rowNumber() const;
00472 
00473   // Returns the default row number for a PagedArray.
00474   static uInt defaultRow();
00475 
00476   // Returns the current tile shape for this PagedArray.
00477   IPosition tileShape() const;
00478 
00479   // Returns the maximum recommended number of pixels for a cursor. This is
00480   // the number of pixels in a tile.
00481   virtual uInt advisedMaxPixels() const;
00482 
00483   // Set the maximum allowed cache size for all Arrays in this column of the
00484   // Table.  The actual value used may be smaller. A value of zero means
00485   // that there is no maximum.
00486   virtual void setMaximumCacheSize (uInt howManyPixels);
00487 
00488   // Return the maximum allowed cache size (in pixels) for all Arrays in
00489   // this column of the Table. The actual cache size may be smaller. A
00490   // value of zero means that no maximum is currently defined.
00491   virtual uInt maximumCacheSize() const;
00492 
00493   // Set the actual cache size for this Array to be big enough for the
00494   // indicated number of tiles. This cache is not shared with PagedArrays
00495   // in other rows and is always clipped to be less than the maximum value
00496   // set using the setMaximumCacheSize member function.
00497   // Tiles are cached using a first in first out algorithm.
00498   virtual void setCacheSizeInTiles (uInt howManyTiles);
00499 
00500   // Set the actual cache size for this Array to "fit" the indicated
00501   // path. This cache is not shared with PagedArrays in other rows and is
00502   // always less than the maximum value. The sliceShape is the cursor or
00503   // slice that you will be requiring (with each call to
00504   // {get,put}Slice). The windowStart and windowLength delimit the range of
00505   // pixels that will ultimatly be accessed. The AxisPath is described in
00506   // the documentation for the LatticeStepper class.
00507   virtual void setCacheSizeFromPath (const IPosition& sliceShape,
00508                                      const IPosition& windowStart,
00509                                      const IPosition& windowLength,
00510                                      const IPosition& axisPath);
00511 
00512   // Clears and frees up the tile cache. The maximum allowed cache size is
00513   // unchanged from when <src>setMaximumCacheSize</src> was last called.
00514   virtual void clearCache();
00515 
00516   // Generate a report on how the cache is doing. This is reset every
00517   // time <src>clearCache</src> is called.
00518   virtual void showCacheStatistics (ostream& os) const;
00519 
00520   // Return the value of the single element located at the argument
00521   // IPosition.
00522   // Note that <src>Lattice::operator()</src> can also be used.
00523   virtual T getAt (const IPosition& where) const;
00524   
00525   // Put the value of a single element.
00526   virtual void putAt (const T& value, const IPosition& where);
00527 
00528   // A function which checks for internal consistency. Returns False if
00529   // something nasty has happened to the PagedArray. In that case
00530   // it also throws an exception.
00531   virtual Bool ok() const;
00532 
00533   // This function is used by the LatticeIterator class to generate an
00534   // iterator of the correct type for a specified Lattice. Not recommended
00535   // for general use. 
00536   virtual LatticeIterInterface<T>* makeIter (const LatticeNavigator& navigator,
00537                                              Bool useRef) const;
00538 
00539   // Do the actual getting of an array of values.
00540   virtual Bool doGetSlice (Array<T>& buffer, const Slicer& section);
00541 
00542   // Do the actual getting of an array of values.
00543   virtual void doPutSlice (const Array<T>& sourceBuffer,
00544                            const IPosition& where,
00545                            const IPosition& stride);
00546   
00547   // Get the best cursor shape.
00548   virtual IPosition doNiceCursorShape (uInt maxPixels) const;
00549 
00550   // Handle the (un)locking.
00551   // <group>
00552   virtual Bool lock (FileLocker::LockType, uInt nattempts);
00553   virtual void unlock();
00554   virtual Bool hasLock (FileLocker::LockType) const;
00555   // </group>
00556 
00557   // Resynchronize the PagedArray object with the lattice file.
00558   // This function is only useful if no read-locking is used, ie.
00559   // if the table lock option is UserNoReadLocking or AutoNoReadLocking.
00560   // In that cases the table system does not acquire a read-lock, thus
00561   // does not synchronize itself automatically.
00562   virtual void resync();
00563 
00564   // Flush the data (but do not unlock).
00565   virtual void flush();
00566 
00567   // Temporarily close the lattice.
00568   // It will be reopened automatically on the next access.
00569   virtual void tempClose();
00570 
00571   // Explicitly reopen the temporarily closed lattice.
00572   virtual void reopen();
00573 
00574 private:
00575   // Set the data in the TableInfo file
00576   void setTableType();
00577   // make the ArrayColumn
00578   void makeArray (const TiledShape& shape);
00579   // Make a Table to hold this PagedArray
00580   void makeTable (const String& filename, Table::TableOption option);
00581   // The default comment for PagedArray Colums
00582   static String defaultComment();
00583   // Get the writable ArrayColumn object. It is created when needed.
00584   ArrayColumn<T>& getRWArray();
00585   // Create the writable ArrayColumn object.
00586   // It reopens the table for write when needed.
00587   void makeRWArray();
00588   // Do the reopen of the table (if not open already).
00589   // <group>
00590   void doReopen() const;
00591   void tempReopen() const;
00592   // </group>
00593 
00594   mutable Table     itsTable;
00595           String    itsColumnName;
00596           uInt      itsRowNumber;
00597   mutable Bool      itsIsClosed;
00598   mutable Bool      itsMarkDelete;
00599           String    itsTableName;
00600           Bool      itsWritable;
00601           TableLock itsLockOpt;
00602   mutable ArrayColumn<T>       itsRWArray;
00603   mutable ROArrayColumn<T>     itsROArray;
00604   mutable ROTiledStManAccessor itsAccessor;
00605 };
00606 
00607 
00608 template<class T>
00609 inline ArrayColumn<T>& PagedArray<T>::getRWArray()
00610 {
00611   if (itsRWArray.isNull()) {
00612     makeRWArray();
00613   }
00614   return itsRWArray;
00615 }
00616 
00617 template<class T>
00618 inline Table& PagedArray<T>::table()
00619 {
00620   doReopen();
00621   return itsTable;
00622 }
00623 template<class T>
00624 inline const Table& PagedArray<T>::table() const
00625 {
00626   doReopen();
00627   return itsTable;
00628 }
00629 
00630 template<class T>
00631 inline const String& PagedArray<T>::columnName() const
00632 {
00633   return itsColumnName;
00634 }
00635 
00636 template<class T>
00637 inline String PagedArray<T>::defaultColumn()
00638 {
00639   return "PagedArray";
00640 }
00641 
00642 template<class T>
00643 inline const ROTiledStManAccessor& PagedArray<T>::accessor() const
00644 {
00645   return itsAccessor;
00646 }
00647 
00648 template<class T>
00649 inline uInt PagedArray<T>::rowNumber() const
00650 {
00651   return itsRowNumber;
00652 }
00653 
00654 template<class T>
00655 inline uInt PagedArray<T>::defaultRow()
00656 {
00657   return 0;
00658 }
00659 
00660 template<class T>
00661 void PagedArray<T>::doReopen() const
00662 {
00663   if (itsIsClosed) {
00664     tempReopen();
00665   }
00666 }
00667 
00668 
00669 
00670 } //# NAMESPACE CASA - END
00671 
00672 #ifndef CASACORE_NO_AUTO_TEMPLATES
00673 #include <lattices/Lattices/PagedArray.tcc>
00674 #endif //# CASACORE_NO_AUTO_TEMPLATES
00675 #endif