casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
VLAArchiveInput.h
Go to the documentation of this file.
00001 //# VLAArchiveInput.h: An abstract class for reading VLA archive records
00002 //# Copyright (C) 1999,2000
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 NRAO_VLAARCHIVEINPUT_H
00029 #define NRAO_VLAARCHIVEINPUT_H
00030 
00031 #include <casa/aips.h>
00032 #include <casa/IO/ByteSinkSource.h>
00033 #include <casa/IO/ConversionIO.h>
00034 #include <casa/IO/MemoryIO.h>
00035 #include <casa/OS/ModcompDataConversion.h>
00036 
00037 #include <casa/namespace.h>
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 class ByteSource;
00040 } //# NAMESPACE CASA - END
00041 
00042 
00043 // <summary>This class reads VLA archive records from a Tape</summary>
00044 
00045 // <reviewed reviewer="" date="" tests="" demos="">
00046 
00047 // <prerequisite>
00048 // <ol>
00049 //   <li> The IO Module
00050 // </ol>
00051 // </prerequisite>
00052 //
00053 // <etymology>
00054 // This class is designed to reads VLA archive records from a Tape
00055 // </etymology>
00056 //
00057 // <synopsis> 
00058 
00059 // This class is designed to read VLA archive data.  The data may be read from
00060 // a disk, tape drive or any other data source supported by the IO module.  A
00061 // call to the operator++() function assembles the next reconstructed VLA
00062 // archive data record from the input. A reference to this data can be
00063 // obtained using the logicalRecord function.
00064 //
00065 // Refer to the "VLA Archive Data Format", VLA Computer Memorandum 186
00066 // by G.C. Hunt, K.P. Sowinski, and T.J. Bottomly; June 1993.
00067 // (This is also available as AIPS++ note 159)
00068 //
00069 // The VLA archive records are always a multiple of 2048 bytes.  The
00070 // record sizes were designed for use with magnetic tapes, so there is
00071 // a maximum physical record size of 13*2048=26624 bytes.
00072 //
00073 // The low level class (blockio), that actually does the I/O, allows
00074 // for a record (hereinafter chunk) size and for a input block size of
00075 // a multiple of the chunk size.  The low level read operation tests
00076 // for the number of bytes actually read from the device.
00077 //
00078 // The helper classes VlaDiskInput, VlaTapeInput, and VlaStdInput are
00079 // designed to deal with the low level input from the devices in an
00080 // analogous fashion to the ones used for FITS input.
00081 //
00082 // Since a read may be issued for an arbitrary number of bytes from a
00083 // disk, the chunk multiple is arbitrary and may be used to tune the
00084 // speed of operation.  There is an obvious trade-off between the
00085 // block size created in the blockio class and the number of read
00086 // operations.
00087 //
00088 // The story is quite different for tape input.  A read request for at
00089 // least the maximum physical record size must be made to avoid loss of
00090 // data.  Since a single tape record will be read with a single read
00091 // operation, there is no point is having it any larger.  The chunk
00092 // multiple must be exactly 13 so that the block size is 26624.
00093 //
00094 // The reconstitution algorithm is as follows:
00095 //
00096 // 1. Read a 2048 chunk from the input.
00097 //
00098 // The first two 16-bit integers should contain the values 1 and n,
00099 // where n is the number of "physical records" in the current "logical  
00100 // record."  (If the first value is not 1, then the chunk is rejected
00101 // and a new one read until the first 16-bit value is 1.)  These two
00102 // values are not part of the reconstituted "logical record."
00103 //
00104 // 2. The next 32-bit integer contains the length of the "logical
00105 // record" in 16-bit words.  The buffer is resized so that it can
00106 // contain the whole reconstituted "logical record."
00107 //
00108 // 3. The remainder of the chunk is copied to the buffer.
00109 //
00110 // 4. Successive chunks are read from the input.
00111 //
00112 // The chunks are copied into the buffer until the "logical record"
00113 // is complete.  For "logical records" longer than 26620 byte, this is
00114 // not the whole story.  Each "physical record" contains maximum of 13
00115 // chunks.  When the first "physical record" of 13 chunks has been read,
00116 // the next chunk will be the first of the next "physical record."  The
00117 // first two 16-bit integers will now be 2 and n, to indicate that this
00118 // is the second "physical record" of the sequence.  These 4 bytes are
00119 // decoded and the rest of this chunk is copied to the buffer.  And so
00120 // on...
00121 //
00122 // An end-of-file condition on the input will cause record processing
00123 // to be declared complete.  
00124 // </synopsis> 
00125 //
00126 // <example>
00127 // To open and read a VLA archive data file
00128 // <code>
00129 //    VLAArchiveInput *in;
00130 //    Block <Char> *buff;
00131 //    String fileName = " ";
00132 //    String fileType = "tape";
00133 //
00134 //    if (fileType == String("tape")) {
00135 //        in = new VLAArchiveInput(fileName.chars(), VLAArchiveInput::Tape);
00136 //    } else {
00137 //        in = new VLAArchiveInput(fileName.chars(), VLAArchiveInput::Disk);
00138 //    }
00139 //
00140 //    uInt record = 0;
00141 //    for (buff=&(in->next()); in->atEnd()==False; buff=&(in->next()), record++) {
00142 //        cout << "Record" << record << endl;
00143 //        // process record pointed to by buff
00144 //    }
00145 // </code>
00146 //
00147 // </example>
00148 //
00149 // <motivation>
00150 // </motivation>
00151 //
00152 // <todo asof="">
00153 // <ol>
00154 //   <li> Bulletproofing - check for realistic buffer size (<1e6)
00155 //   <li> Bulletproofing - check newn and newm on each read
00156 //   <li> What happens after a single end-of-file on a tape drive?
00157 //   <li> Add record skipping
00158 //   <li> Should it work with stdin?  This is in place but not debugged.
00159 // </ol>
00160 // </todo>
00161 
00162 class VLAArchiveInput
00163 {
00164 public: 
00165   // The destructor is virtual to ensure that the destructor in a derived
00166   // class is actually used. 
00167   virtual ~VLAArchiveInput();
00168 
00169   // This returns a reconstructed VLA logical record from the input
00170   // stream. This ByteSource has the data stored in memory, and hence is
00171   // seekable. Data read from this ByteSource will have the ModComp numeric
00172   // conversions applied.
00173   ByteSource& logicalRecord();
00174   const ByteSource& logicalRecord() const;
00175 
00176   // Reads the next logical record from specified IO source. Returns False if
00177   // there was a problem assembling the next record ie., it returns the value
00178   // of the hasData() member function.
00179   virtual Bool read() = 0;
00180 
00181   // Returns if true if the current record contains data. The current record
00182   // could be empty for a number of reasons including:
00183   // <ul> 
00184   // <li> You attempted to read beyond the end of the file.
00185   // <li> The physical record sequence numbers were not the expected ones
00186   // <li> An I/O Error occured while trying to read from the file.
00187   // <li> The beginning of a logical record could not be found. This is after
00188   //      searching 5MB of data.
00189   // </ul>
00190   Bool hasData() const;
00191 
00192 protected: 
00193   //# the default constructor initialises the itsRecord data member
00194   VLAArchiveInput();
00195   
00196   //# All reads will be in multiples of this blocksize.
00197   static const uInt BlockSize;
00198   //# The size in bytes of the physical record sequence numbers
00199   static const uInt HeaderSize;
00200   //# A Physical Record can never be bigger than this many blocks.
00201   static const uInt MaxBlocksPerPhysicalRecord;
00202 
00203   //# These objects contains the current logical record. The memory IO object
00204   //# is used to put the data. It is taken out using the ByteSinkSource which
00205   //# will apply any numeric conversions.
00206   MemoryIO itsMemIO;
00207 
00208 private:
00209   ModcompDataConversion itsModComp;
00210   ConversionIO itsCtrIO;
00211 
00212 protected: 
00213   ByteSinkSource itsRecord;
00214 };
00215 #endif