Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

SMultiPKFileRep.C

Go to the documentation of this file.
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 #include <Basics.H>
00020 #include <FS.H>
00021 #include <FP.H>
00022 
00023 #include "SPKFileRep.H"      // for SPKFileRep::*Version
00024 #include "SPKFile.H"
00025 #include "SMultiPKFileRep.H"
00026 
00027 using std::ostream;
00028 using std::ifstream;
00029 using std::endl;
00030 
00031 // HeaderEntry routines -------------------------------------------------------
00032 
00033 void SMultiPKFileRep::HeaderEntry::Read(ifstream &ifs)
00034   throw (FS::EndOfFile, FS::Failure)
00035 /* REQUIRES FS::Posn(ifs) == ``start of <Header>'' */
00036 {
00037     FS::Read(ifs, (char *)(&(this->pk)), sizeof(this->pk));
00038     this->offsetLoc = FS::Posn(ifs);
00039     FS::Read(ifs, (char *)(&(this->offset)), sizeof(this->offset));
00040 }
00041 
00042 void SMultiPKFileRep::HeaderEntry::Write(ostream &ofs)
00043   throw (FS::Failure)
00044 /* REQUIRES FS::Posn(ofs) == ``start of <Header>'' */
00045 {
00046     FS::Write(ofs, (char *)(&(this->pk)), sizeof(this->pk));
00047     this->offsetLoc = FS::Posn(ofs);
00048     FS::Write(ofs, (char *)(&(this->offset)), sizeof(this->offset));
00049 }
00050 
00051 void SMultiPKFileRep::HeaderEntry::Debug(ostream &os, bool verbose) const
00052   throw ()
00053 {
00054     if (!verbose) {
00055         os << "pk = " << pk << ", offset = " << offset << endl;
00056     } else {
00057         os << endl;
00058         os << "// <HeaderEntry>" << endl;
00059         os << "pk        = " << pk << endl;
00060         os << "offset    = " << offset << endl;
00061         os << "offsetLoc = " << offsetLoc << endl;
00062         os << "pkLen     = " << pkLen << endl;
00063     }
00064 }
00065 
00066 // Header routines ------------------------------------------------------------
00067 
00068 bool SMultiPKFileRep::Header::AppendNewHeaderEntry(const FP::Tag &pk) throw ()
00069 {
00070     bool res;
00071     HeaderEntry *he;
00072     if (!(res=this->pkTbl.Get(pk, /*OUT*/ he))) {
00073       he = NEW_CONSTR(HeaderEntry, (pk));
00074       bool inTbl = this->pkTbl.Put(pk, he); assert(!inTbl);
00075       if (this->num >= this->pksLen) {
00076         assert(this->num == this->pksLen);
00077         // allocate a larger "pks" array
00078         this->pksLen = max(this->pksLen + 2, 2 * this->pksLen);
00079         assert(this->pksLen > this->num);
00080         FPTagPtr *newPKs = NEW_ARRAY(FPTagPtr, this->pksLen);
00081         for (int i=0; i < this->num; i++) newPKs[i] = this->pkSeq[i];
00082         this->pkSeq = newPKs;
00083       }
00084       this->pkSeq[this->num++] = &(he->pk);
00085     }
00086     return res;
00087 }
00088 
00089 void SMultiPKFileRep::Header::RemoveHeaderEntry(const FP::Tag &pk) throw ()
00090 {
00091     // find the corresponding PK in "pkSeq"
00092     int i;
00093     for (i = 0; i < num; i++) {
00094         if (*pkSeq[i] == pk) break;
00095     }
00096     assert(i < num);
00097 
00098     // shift remaining elements down 1 position
00099     for (/*SKIP*/; i < num-1; i++) {
00100         pkSeq[i] = pkSeq[i+1];
00101     }
00102 
00103     // decrement count and clear last element
00104     pkSeq[--num] = (FP::Tag *)NULL;
00105 }
00106 
00107 // initialize the SMultiPKFile magic number
00108 static const Word MPKFileMagicNumber =
00109   FP::Tag("SMultiPKFileRep magic number - CAH").Hash();
00110 
00111 void SMultiPKFileRep::Header::Read(ifstream &ifs)
00112   throw (SMultiPKFileRep::BadMPKFile, FS::EndOfFile, FS::Failure)
00113 /* REQUIRES FS::Posn(ifs) == ``start of <Header>'' */
00114 {
00115     // read header info
00116     FS::Read(ifs, (char *)(&(this->version)), sizeof(this->version));
00117     if (this->version < SPKFileRep::FirstVersion ||
00118         this->version > SPKFileRep::LastVersion) {
00119         throw SMultiPKFileRep::BadMPKFile();
00120     }
00121     if (this->version >= SPKFileRep::MPKMagicNumVersion) {
00122         Word magicNumber;
00123         FS::Read(ifs, (char *)(&magicNumber), sizeof(magicNumber));
00124         if (magicNumber != MPKFileMagicNumber) {
00125             throw SMultiPKFileRep::BadMPKFile();
00126         }
00127     }
00128     FS::Read(ifs, (char *)(&(this->num)), sizeof(this->num));
00129     this->lenOffset = FS::Posn(ifs);
00130     FS::Read(ifs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00131     FS::Read(ifs, (char *)(&(this->type)), sizeof(this->type));
00132 }
00133 
00134 void SMultiPKFileRep::Header::Write(ostream &ofs) throw (FS::Failure)
00135 /* REQUIRES FS::Posn(ofs) == ``start of <Header>'' */
00136 {
00137     // determine format type
00138     if (this->num < 8) {
00139         this->type = HT_List;
00140     } else {
00141         this->type = HT_SortedList;
00142     }
00143 
00144     // always write the most recent version
00145     this->version = SPKFileRep::LastVersion;
00146 
00147     // write header
00148     FS::Write(ofs, (char *)(&(this->version)), sizeof(this->version));
00149     if (this->version >= SPKFileRep::MPKMagicNumVersion) {
00150         FS::Write(ofs, (char *)(&MPKFileMagicNumber),
00151           sizeof(MPKFileMagicNumber));
00152     }
00153     FS::Write(ofs, (char *)(&(this->num)), sizeof(this->num));
00154     this->lenOffset = FS::Posn(ofs);
00155     // reading the following field is irrelevant
00156     FS::Write(ofs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00157     FS::Write(ofs, (char *)(&(this->type)), sizeof(this->type));
00158 }
00159 
00160 void SMultiPKFileRep::Header::ReadEntries(ifstream &ifs)
00161   throw (FS::EndOfFile, FS::Failure)
00162 /* REQUIRES FS::Posn(ifs) == ``start of <TypedHeader>'' */
00163 {
00164     // read <HeaderEntry> records
00165     switch (this->type) {
00166       case HT_List:
00167       case HT_SortedList:
00168         if (this->version <= SPKFileRep::SourceFuncVersion) {
00169             ReadListV1(ifs);
00170         } else {
00171             // unsupported version
00172             assert(false);
00173         }
00174         break;
00175       case HT_HashTable:
00176         /*** NYI ***/
00177         assert(false);
00178       default:
00179         // programmer error
00180         assert(false);
00181     }
00182 }
00183 
00184 void SMultiPKFileRep::Header::WriteEntries(ostream &ofs) throw (FS::Failure)
00185 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */
00186 {
00187     switch (this->type) {
00188       case HT_List:
00189         WriteList(ofs);
00190         break;
00191       case HT_SortedList:
00192         WriteSortedList(ofs);
00193         break;
00194       case HT_HashTable:
00195         /*** NYI ***/
00196         assert(false);
00197       default:
00198         assert(false);
00199     }
00200 }
00201 
00202 void SMultiPKFileRep::Header::ReadListV1(ifstream &ifs)
00203   throw (FS::EndOfFile, FS::Failure)
00204 /* REQUIRES FS::Posn(ifs) == ``start of <SeqHeader>'' */
00205 {
00206     HeaderEntry *prev = (HeaderEntry *)NULL;
00207 
00208     // allocate "pks" array
00209     this->pksLen = this->num;
00210     this->pkSeq = NEW_ARRAY(FPTagPtr, this->pksLen);
00211 
00212     // read <HeaderEntry> records and add them to "pkTbl"
00213     for (int i = 0; i < this->num; i++) {
00214       HeaderEntry *ent = NEW_CONSTR(HeaderEntry, (ifs));
00215         this->pkSeq[i] = &(ent->pk);
00216         if (prev != NULL) {
00217             prev->pkLen = ent->offset - prev->offset;
00218         }
00219         bool inMap = this->pkTbl.Put(ent->pk, ent); assert(!inMap);
00220         prev = ent;
00221     }
00222 
00223     // set length of last <PKFile>
00224     if (prev != NULL) {
00225         prev->pkLen = this->totalLen - prev->offset;
00226     }
00227 }
00228 
00229 void SMultiPKFileRep::Header::WriteList(ostream &ofs) throw (FS::Failure)
00230 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */
00231 {
00232     // write entries in order according to "pks" array
00233     for (int i = 0; i < this->num; i++) {
00234         HeaderEntry *ent;
00235         bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), /*OUT*/ ent);
00236         assert(inTbl);
00237         ent->Write(ofs);
00238     }
00239 }
00240 
00241 extern "C"
00242 {
00243   static int SMultiPKFileRep_PKCompare(const void *p1, const void *p2) throw ()
00244   {
00245     FP::Tag *fpPtr1 = *((FP::Tag **)p1);
00246     FP::Tag *fpPtr2 = *((FP::Tag **)p2);
00247     return Compare(*fpPtr1, *fpPtr2);
00248   }
00249 }
00250 
00251 void SMultiPKFileRep::Header::WriteSortedList(ostream &ofs)
00252   throw (FS::Failure)
00253 /* REQUIRES FS::Posn(ofs) == ``start of <TypedHeader>'' */
00254 {
00255     // sort the list
00256     qsort((void *)(this->pkSeq), (size_t)(this->num),
00257       (size_t)sizeof(*(this->pkSeq)), SMultiPKFileRep_PKCompare);
00258 
00259     // write them as a simple list
00260     WriteList(ofs);
00261 }
00262 
00263 void SMultiPKFileRep::Header::ReadPKFiles(ifstream &ifs)
00264   throw (FS::EndOfFile, FS::Failure)
00265 /* REQUIRES FS::Posn(ofs) == ``start of <PKFile>*'' */
00266 {
00267     // read entries
00268     for (int i = 0; i < this->num; i++) {
00269         HeaderEntry *ent;
00270         bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), ent); assert(inTbl);
00271         ent->pkfile = NEW_CONSTR(SPKFile,
00272                                  (ent->pk, ifs, ent->offset,
00273                                   this->version, ent->pkhdr,
00274                                   /*readEntries=*/ true));
00275     }
00276 }
00277 
00278 void SMultiPKFileRep::Header::BackPatch(ostream &ofs)
00279   throw (FS::Failure)
00280 {
00281     // record "totalLen"
00282     totalLen = FS::Posn(ofs);
00283 
00284     // write "totalLen"
00285     FS::Seek(ofs, lenOffset);
00286     FS::Write(ofs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00287 
00288     // write <HeaderEntry> "offset"'s
00289     for (int i = 0; i < this->num; i++) {
00290         HeaderEntry *ent;
00291         bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), ent); assert(inTbl);
00292         FS::Seek(ofs, ent->offsetLoc);
00293         FS::Write(ofs, (char *)(&(ent->offset)), sizeof(ent->offset));
00294     }
00295 }
00296 
00297 static const char *HeaderTypeName[SMultiPKFileRep::HT_Last] =
00298   { "List", "SortedList", "HashTable" };
00299 
00300 void SMultiPKFileRep::Header::Debug(ostream &os, bool verbose) const throw ()
00301 {
00302     // write <Header> info
00303     if (!verbose) {
00304         os << endl << "num = " << num << endl;
00305     } else {
00306         os << endl << "// <Header>" << endl;
00307         os << "version   = " << version << endl;
00308         os << "num       = " << num << endl;
00309         os << "totalLen  = " << totalLen << endl;
00310         assert(/*HT_List <= type &&*/ type < HT_Last);
00311         os << "type      = " << HeaderTypeName[type] << endl;
00312         os << "lenOffset = " << lenOffset << endl;
00313     }
00314 
00315     // write header entries
00316     for (int i = 0; i < num; i++) {
00317         HeaderEntry *he;
00318         bool inTbl = pkTbl.Get(*(pkSeq[i]), he);
00319         assert(inTbl);
00320         he->Debug(os, verbose);
00321     }
00322 }

Generated on Mon May 8 00:48:35 2006 for Vesta by  doxygen 1.4.2