casa
$Rev:20696$
|
00001 //# VLATapeInput.h: This class reads VLA archive records from a Tape 00002 //# Copyright (C) 1995,1999,2000,2001 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_VLATAPEINPUT_H 00029 #define NRAO_VLATAPEINPUT_H 00030 00031 #include <casa/aips.h> 00032 #include <casa/IO/TapeIO.h> 00033 #include <casa/Containers/Block.h> 00034 #include <nrao/VLA/VLAArchiveInput.h> 00035 00036 #include <casa/namespace.h> 00037 namespace casa { //# NAMESPACE CASA - BEGIN 00038 class Path; 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 VLATapeInput: public VLAArchiveInput 00163 { 00164 public: 00165 // Create an object that reads its data from the specified file on the 00166 // specified tape device. The whichFile argument indicates which tape to read 00167 // from the tape with zero meaning "read the next file". The first file 00168 // containing data (ie ignoring the tape header file) is file 1. An exception 00169 // is thrown if there is any problem opening (readonly) the tape device or if 00170 // the tape cannot be positioned to the start of the specified file. 00171 VLATapeInput(const Path& device, uInt whichFile=0); 00172 00173 // Create an object that reads its data from the specified files on the 00174 // specified tape device. The tape is rewound and only the specified file is 00175 // read. The first file containing data (ie ignoring the tape header file) is 00176 // file 1 and zero means "read the next file". An exception is thrown if 00177 // there is any problem opening (readonly) the tape device or if the tape 00178 // cannot be positioned to the start of the first specified file. The file 00179 // numbers should be in increasing order as only one pass through the tape is 00180 // made. 00181 VLATapeInput(const Path& device, const Block<uInt>& whichFiles); 00182 00183 // The destructor closes the tape device. 00184 ~VLATapeInput(); 00185 00186 // Reads the next logical record from specified tape. Returns False if 00187 // there was a problem assembling the next record ie., it returns the value 00188 // of the hasData() member function. 00189 virtual Bool read(); 00190 00191 private: 00192 //# This is the amount data that is read with every system call. It needs to 00193 //# be at least as big as the biggest record on tape. However it can bigger 00194 //# as this code will not complain if less data was read (although all data 00195 //# read must be in multiples of the BlockSize) 00196 static const uInt ReadSize; 00197 00198 //# The default constructor is private and undefined 00199 VLATapeInput(); 00200 00201 //# The copy constructor is private and undefined 00202 VLATapeInput(const VLATapeInput& other); 00203 00204 //# The assignment operator is private and undefined 00205 VLATapeInput& operator=(const VLATapeInput& other); 00206 00207 //# Reads through a VLA archive looking for the first physical record in a 00208 //# logical record. Returns False if the first record could not be found. If 00209 //# It was found then this function also returns the number of physical 00210 //# records in this logical record. 00211 Bool findFirstRecord(Short& m); 00212 00213 //# Positions the tape to the beginning of the next file. Uses and 00214 //# manipulates the itsFiles and itsCurFile data members. Returns False if 00215 //# the tape could not be positioned. 00216 Bool nextFile(); 00217 00218 //# Reads the next record from the tape. Skips over bad data but not 00219 //# filemarks. Throws an exception if no valid records could be read. 00220 Bool nextRecord(); 00221 00222 //# Read the specified number of bytes from the current ByteIO. Returns False 00223 //# if no data was written, a read error was detected or the data read was 00224 //# not a multiple of the BlockSize. Sets the appropriate Flags when 00225 //# returning False. Writes the data into an internal buffer. 00226 Bool fillBuffer(uInt& bytesToRead); 00227 00228 //# This object that provides the data input. Usually a Tape, File, Socket 00229 //# etc. 00230 TapeIO itsTape; 00231 00232 //# This object indicates which files we are to read on the tape; 00233 Block<uInt> itsFiles; 00234 00235 //# An index into the itsFiles block indicating which file, in tape, we 00236 //# are currently reading. A negative number indicates that the tape has not 00237 //# been positioned yet. 00238 Int itsCurFile; 00239 00240 //# A temporary buffer that is used to store the data prior to copying it 00241 //# into the MemoryIO object. This is necessary because the MemoryIO object 00242 //# does not allow you low level access to its data. 00243 Block<uChar> itsBuffer; 00244 }; 00245 #endif