00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 // 00003 // This file is part of Vesta. 00004 // 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 // 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // SMultiPKFileRep.H -- classes for reading/writing MultiPKFile header records 00020 00021 #ifndef _SMULTI_PK_FILE_REP_H 00022 #define _SMULTI_PK_FILE_REP_H 00023 00024 #include <Basics.H> 00025 #include <FS.H> 00026 #include <Table.H> 00027 #include <FP.H> 00028 #include <BitVector.H> 00029 00030 #include "SPKFileRep.H" 00031 #include "IntIntTblLR.H" 00032 #include "SPKFile.H" 00033 00034 class SMultiPKFileRep { 00035 public: 00036 // type for offsets/lengths within a file 00037 typedef unsigned short UShort; 00038 typedef unsigned int UInt; 00039 00040 // Exceptions 00041 class NotFound {}; 00042 class BadMPKFile {}; // the file is not a valid MultiPKFile 00043 00044 // <HeaderEntry> ---------------------------------------------------------- 00045 00046 class HeaderEntry { 00047 public: 00048 // constructors 00049 HeaderEntry() throw () 00050 : pk(), offset(0), offsetLoc(0), pkLen(0), pkfile(NULL), pkhdr(NULL), 00051 pkfileModified(false), becameEmpty(false) 00052 { /*SKIP*/ } 00053 HeaderEntry(const FP::Tag &pk) throw () 00054 : pk(pk), offset(0), offsetLoc(0), pkLen(0), pkfile(NULL),pkhdr(NULL), 00055 pkfileModified(false), becameEmpty(false) 00056 { /*SKIP*/ } 00057 HeaderEntry(std::ifstream &ifs) throw (FS::EndOfFile, FS::Failure) 00058 : pkLen(0), pkfile(NULL), 00059 pkfileModified(false), becameEmpty(false) 00060 { Read(ifs); } 00061 /* REQUIRES FS::Posn(ifs) == ``start of <HeaderEntry>'' */ 00062 00063 // read/write 00064 void Read(std::ifstream &ifs) throw (FS::EndOfFile, FS::Failure); 00065 /* REQUIRES FS::Posn(ifs) == ``start of <HeaderEntry>'' */ 00066 00067 void Write(std::ostream &ofs) throw (FS::Failure); 00068 /* REQUIRES FS::Posn(ofs) == ``start of <HeaderEntry>'' */ 00069 00070 // other methods 00071 static int Size() { return sizeof(FP::Tag) + sizeof(UInt); } 00072 /* Return the size of a "HeaderEntry" on disk. */ 00073 00074 bool SPKFileExists() const throw () { return offset != 0UL; } 00075 /* Return "true" iff this "HeaderEntry" was created for a real SPKFile 00076 in the MultiPKFile using the "HeaderEntry(ifstream)" constructor 00077 or the "Read(ifstream)" method. */ 00078 00079 void Debug(std::ostream &os, bool verbose = false) const throw (); 00080 /* By default, write a one-line elided representation of this 00081 <HeaderEntry> to "os". If "verbose" is true, write a complete, 00082 multi-line representation. */ 00083 00084 // disk data 00085 FP::Tag pk; 00086 UInt offset; // start of this PKFile w/in the MultiPKFile 00087 00088 // auxiliary data -- not written to disk 00089 UInt offsetLoc; // location of "offset" on disk 00090 UInt pkLen; // length of this PKFile on disk 00091 00092 // auxiliary SPKFile data 00093 SPKFile *pkfile; // the corresponding PKFile... 00094 SPKFileRep::Header *pkhdr; // and its <CFPHeader> (for back-patching) 00095 00096 /* The auxiliary SPKFile fields are not changed as part of the "Read" 00097 and "Write" methods. */ 00098 00099 // pkfile->Update results 00100 bool pkfileModified; // was PKFile changed by "pkfile->Update"? 00101 BitVector *exCommonNames; // ex-common names from updating 00102 BitVector *exUncommonNames;// ex-uncommon names from updating 00103 BitVector *packMask; // packing bit vector for "allNames" indices 00104 IntIntTblLR *reMap; // remapping of "allNames" indices 00105 bool becameEmpty; // were all entries deleted? 00106 00107 /* The "exCommonNames", "exUncommonNames", "packMask", 00108 "reMap", and "becameEmpty" fields are temporary values used 00109 to store the result of the "pkfile->Update" "OUT" 00110 variables. They are only valid if "pkfileModified" is 00111 true. */ 00112 }; 00113 00114 // <Header> --------------------------------------------------------------- 00115 00116 // dictionary types for Header 00117 typedef Table<FP::Tag,HeaderEntry*>::Default HdrEntryMap; 00118 typedef Table<FP::Tag,HeaderEntry*>::Iterator HdrEntryIter; 00119 00120 // "Header.type" values 00121 enum HeaderType { HT_List, HT_SortedList, HT_HashTable, HT_Last }; 00122 00123 class Header { 00124 public: 00125 // constructors 00126 Header() throw () 00127 : version(0), num(0), totalLen(0), type(HT_Last), 00128 lenOffset(0), pksLen(0) { /*SKIP*/ } 00129 Header(std::ifstream &ifs) throw (BadMPKFile, FS::EndOfFile, FS::Failure) 00130 { Read(ifs); } 00131 /* REQUIRES FS::Posn(ifs) == ``start of <Header>'' */ 00132 00133 // methods 00134 bool AppendNewHeaderEntry(const FP::Tag &pk) throw (); 00135 /* If there is no header entry in "pkTbl" under key "pk", create a new 00136 one for "pk", add it to the table, append it to the "pkSeq" array, 00137 and return "false". Otherwise, do nothing and return "true". */ 00138 00139 void RemoveHeaderEntry(const FP::Tag &pk) throw (); 00140 /* Remove "pk" from this header's "pkSeq" array, but not from its 00141 "pkTbl". It is a checked run-time error if "pk" does not occur in 00142 "pkSeq". This only modifies the locations of the entries in 00143 the "pkSeq" array array above the one that is deleted. */ 00144 00145 // reading/writing 00146 void Read(std::ifstream &ifs) throw (BadMPKFile, FS::EndOfFile,FS::Failure); 00147 /* REQUIRES FS::Posn(ifs) == ``start of <Header>'' */ 00148 /* Read the "Header" disk data from "ifs", i.e., the fields, 00149 "version", "num", "totalLen", and "type". The value of the 00150 auxilliary fields "lenOffset" and "pksLen" are also set. */ 00151 00152 void ReadEntries(std::ifstream &ifs) throw (FS::EndOfFile, FS::Failure); 00153 /* REQUIRES FS::Posn(ifs) == ``start of <TypedHeader>'' */ 00154 /* Initialize the auxiliary fields "pkTbl" and "pkSeq" from "ifs" to 00155 contain a representation of this MultiPKFile's <HeaderEntry> 00156 records. This sets the "offsetLoc" and "pkLen" auxiliary fields 00157 of the "HeaderEntry" objects stored in "pkTbl", but not their 00158 "pkfile" or "pkhdr" fields. */ 00159 00160 void ReadPKFiles(std::ifstream &ifs) throw (FS::EndOfFile, FS::Failure); 00161 /* REQUIRES FS::Posn(ofs) == ``start of <PKFile>*'' */ 00162 /* Read the <PKFile> records into the "pkfile" and "pkhdr" fields of 00163 the "HeaderEntry" records in "pkTbl" in the order specified by the 00164 "pks" array. */ 00165 00166 void Write(std::ostream &ofs) throw (FS::Failure); 00167 /* REQUIRES FS::Posn(ofs) == ``start of <Header>'' */ 00168 /* Write the "Header" disk data to "ifs", i.e., the fields, 00169 "version", "num", "totalLen", and "type". The value of "lenOffset" 00170 is set to the location where the "totalLen" field was written. */ 00171 00172 void WriteEntries(std::ostream &ofs) throw (FS::Failure); 00173 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */ 00174 /* Write this MultiPKFile's <HeaderEntry> records to "ofs" according 00175 to the "pkTbl" and "pkSeq" fields. This may have the side-effect of 00176 permuting the PK's in the "pkSeq" array. It may also change the 00177 values of the "version and "type" fields. */ 00178 00179 void BackPatch(std::ostream &ofs) throw (FS::Failure); 00180 /* Back-patch the offsets and length values in this <Header> by 00181 seeking to their locations and writing their values to "ofs". The 00182 initial position of "ofs" is used as the value for the "totalLen" 00183 field. */ 00184 00185 // other methods 00186 int Size() 00187 { return sizeof(this->version) + sizeof(this->num) 00188 + sizeof(this->totalLen) + sizeof(this->type); } 00189 00190 void Debug(std::ostream &os, bool verbose = false) const throw (); 00191 /* Write an ASCII representation of this <Header> and its 00192 <HeaderEntry> records to "os". This does not write the PKFile's 00193 themselves. If "verbose" is false, write a concise representation. 00194 Otherwise, write the complete values of the structures. */ 00195 00196 // pointer to a FP::Tag 00197 typedef FP::Tag *FPTagPtr; 00198 00199 // disk data 00200 UShort version; // version number of MultiPKFile file format 00201 UShort num; // number of PKFile's within this MultiPKFile 00202 UInt totalLen; // must be back-patched 00203 UShort type; // header entry format type (list, hashtable, etc) 00204 00205 // auxiliary data -- not written to disk 00206 UInt lenOffset; // location of "totalLen" field 00207 UShort pksLen; // size of "pkSeq" array; "pksLen >= num" 00208 FPTagPtr *pkSeq; // an array of the PK's in "Domain(pkTbl)" 00209 HdrEntryMap pkTbl; // map of this MPKFile's PKFiles: PK -> HeaderEntry 00210 00211 /* The "pkSeq" array records the *order* in which the <HeaderEntry> 00212 records (and hence the corresponding <PKFile> records) are written 00213 in the MultiPKFile. "pksLen" records the allocated size of the 00214 "pkSeq" array. */ 00215 00216 private: 00217 void ReadListV1(std::ifstream &ifs) throw (FS::EndOfFile, FS::Failure); 00218 /* REQUIRES FS::Posn(ifs) == ``start of <SeqHeader>'' */ 00219 /* Read a list of "HeaderEntry"'s into this "Header"'s "pkTbl". */ 00220 00221 void WriteList(std::ostream &ofs) throw (FS::Failure); 00222 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */ 00223 /* Write the entries in this "Header"'s "pkTbl" to "ofs" as an 00224 unordered list. */ 00225 00226 void WriteSortedList(std::ostream &ofs) throw (FS::Failure); 00227 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */ 00228 /* Write the entries in this "Header"'s "pkTbl" to "ofs" is 00229 sorted order by PK. */ 00230 }; 00231 }; 00232 00233 #endif // _SMULTI_PK_FILE_REP_H