casa
$Rev:20696$
|
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