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

SPKFile.H

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 // SPKFile.H -- An interface for reading/writing stable PKFile's within
00020 // MultiPKFile's on disk. This also defines the type "SPKFile", of which
00021 // "VPKFile" is a subtype.
00022 
00023 #ifndef _SPK_FILE_H
00024 #define _SPK_FILE_H
00025 
00026 #include <Basics.H>
00027 #include <FS.H>
00028 #include <Table.H>
00029 #include <FP.H>
00030 #include <CacheIntf.H>
00031 #include <BitVector.H>
00032 #include <FV.H>
00033 
00034 #include "SPKFileRep.H"
00035 #include "IntIntTblLR.H"
00036 #include "CacheEntry.H"
00037 #include "VPKFileChkPt.H"
00038 
00039 class SPKFile {
00040 public:
00041   // constructors
00042   SPKFile(const FP::Tag& pk) throw ()
00043     : pk(pk), pkEpoch(0), namesEpoch(0), sourceFunc(NULL) { /*SKIP*/ }
00044   /* Create a new, empty PKFile for primary key "pk". This will be used as
00045      the initial PKFile when none exists in the stable cache. */
00046 
00047   SPKFile(const FP::Tag& pk, std::ifstream &ifs, std::streampos origin,
00048           int version, /*OUT*/ SPKFileRep::Header* &hdr,
00049           bool readEntries = true, bool readImmutable = true)
00050     throw (FS::EndOfFile, FS::Failure)
00051     : pk(pk)
00052   { Read(ifs, origin, version, /*OUT*/ hdr, readEntries, readImmutable);}
00053   /* REQUIRES FS::Posn(ifs) == ``start of <PKFile>'' */
00054   /* Initialize a new "SPKFile" object from the disk. See "Read" below. */
00055 
00056   // update
00057   bool Update(const VPKFileChkPt *chkpt, const BitVector *toDelete,
00058               /*OUT*/ BitVector* &exCommonNames,
00059               /*OUT*/ BitVector* &exUncommonNames,
00060               /*OUT*/ BitVector* &packMask, /*OUT*/ IntIntTblLR* &reMap,
00061               /*OUT*/ bool &isEmpty) throw ();
00062   /* REQUIRES ((chkpt!=NULL) && chkpt->hasNewEntries) || (toDelete!=NULL) */
00063   /* ENSURES (packMask == NULL) == (reMap == NULL) */
00064   /* Update this SPKFile. If "chkpt != NULL", incorporate the new names
00065      and entries in "chkpt". If "toDelete" is non-NULL, then any entries
00066      in this SPKFile whose indices correspond to set bits in "*toDelete"
00067      should be deleted. The method returns "true" iff the "SPKFile" needs
00068      to be modified on disk in any way. This will be true if there are
00069      new entries to add from "chkpt", if some existing entries on the
00070      disk must be deleted, or if some entries in "chkpt" must be deleted.
00071      In the latter case, the contents of the SPKFile may not change, but
00072      its "pkEpoch" must be increased.
00073 
00074      If any entries are added or removed, the set of common names for this
00075      SPKFile may change. In particular, if any entries are added, some names
00076      that used to be common may become uncommon. In this case, the "OUT"
00077      parameter "exCommonNames" is set to point to a new bit vector of the
00078      names that used to be common; it is set to "NULL" if there are no such
00079      names. If any entries are deleted, then names that used to be uncommon
00080      may become common. In this case, the "OUT" parameter "exUncommonNames"
00081      is set to point to a new bit vector of the names that used to be
00082      uncommon; it is set to "NULL" if there are no such names. The set bits
00083      of both the "exCommonNames" and "exUncommonNames" are interpreted
00084      relative to the "allNames" array *before* this method was called; they
00085      are *not* packed according to "packMask".
00086 
00087      Finally, if entries are deleted, the union of all the names appearing
00088      in this SPKFile (its "allNames" field) may change. In this case,
00089      "packMask" is set to a new bit vector whose set bits correspond to
00090      names in the original "allNames" array that still appear in some entry
00091      in the stable PKFile. This bit vector may be used to pack the
00092      "commonNames" and "uncommonNames" bit vectors in the volatile cache.
00093      Furthermore, "reMap" is set to point to a new table mapping integers to
00094      integers. For each name that remains after the SPKFile has been
00095      updated, this table maps the index of each name in the original
00096      "allNames" array to its index in the new version of that array.
00097      Because the spec requires that the sequence of the names is preserved,
00098      a name's new index will always be at most its old index. If no name
00099      indices change, then "packMask" and "reMap" are both set to "NULL".
00100      In the event that "packMask" and "reMap" are non-NULL, the
00101      "this->allNames" array and the "this->commonNames" bit vector are
00102      packed according to "packMask". 
00103 
00104      Even in the event that "packMask" and "reMap" are non-NULL, the bit
00105      vectors "exCommonNames" and "exUncommonNames" (if non-NULL) are *not*
00106      packed. That is, they should be interpreted relative to the original
00107      "allNames" array in place on entry to this method.
00108 
00109      If the PKFile has no entries after being flushed, then "isEmpty" is set
00110      to true. It is set to false otherwise.
00111 
00112      If the PKFile changes (i.e., if this method returns "true"), the
00113      "namesEpoch" value is updated from "chkpt".  If any name indices change
00114      (i.e., if "packMask" and "reMap" are set non-NIL), then the SPKFile's
00115      "namesEpoch" is incremented.
00116 
00117      One special case worth considering is the one in which this "SPKFile"
00118      is brand new, and hence, empty. In this case, there are no existing
00119      common names, so "exCommonNames" will be set to "NULL" and
00120      "exUncommonNames" will be set to the *new* set of common names.  Also
00121      in this case, this->pkEpoch and chkpt->pkEpoch will both be zero on
00122      entry, so this->pkEpoch must be updated to 1; in all other cases,
00123      this->pkEpoch will already have been updated to chkpt->pkEpoch + 1 by
00124      VPKFile::CheckPoint.
00125 
00126      Another case worth considering is the one in which all the entries from
00127      this SPKFile have been deleted (i.e., "isEmpty" is set to true). In
00128      this case, "this->allNames" is set to the empty list, all entries are
00129      deleted from "this->oldEntries", "exCommonNames" is set to a new bit
00130      vector containing the previous set of common names, "exUncommonNames"
00131      is set to "NULL", "packMask" is set to a new, empty bit vector, and
00132      "reMap is set to a new, empty table. */
00133 
00134   // read/write
00135   void Read(std::ifstream &ifs, std::streampos origin, int version,
00136             /*OUT*/ SPKFileRep::Header* &hdr, bool readEntries = true,
00137             bool readImmutable = true) throw (FS::EndOfFile, FS::Failure);
00138   /* REQUIRES FS::Posn(ifs) == ``start of <PKFile>'' */
00139   /* Fill in the fields of this "SPKFile" from "ifs" (namely, the
00140      <PKFHeaderTail>).
00141 
00142      If "readEntries" is true, the "hdr" is set to a newly-allocated record
00143      containing the <CFPHeader> information, and all of the PKFile's
00144      <PKEntries> records are stored in this SPKFile's "oldEntries" table.
00145      Otherwise, "hdr" is set to NULL, and "ifs" is left pointing just after
00146      the <PKFHeader>.
00147 
00148      If "readEntries" is true, then the "readImmutable" parameter is
00149      significant; otherwise, it is ignored. If "readImmutable" is true,
00150      then the mutable and immutable fields of all cache entries are read
00151      from disk into memory. If "readImmutable" is false, then the cache
00152      indices of the cache entries are negated, and the immutable "value",
00153      "kids", and "fps" fields are not read from disk. Instead, those
00154      pointers are made to point to records containing the length and
00155      position of the pickled representations of those values in the SPKFile.
00156      "readImmutable" should only be passed as "false" when the cache entries
00157      are intended to be written out again. */
00158 
00159   void Write(std::ifstream &ifs, std::ostream &ofs, std::streampos origin,
00160              /*OUT*/ SPKFileRep::Header* &hdr) const throw (FS::Failure);
00161   /* REQUIRES VPKFile(SELF).mu IN LL */
00162   /* REQUIRES FS::Posn(ofs) == ``start of <PKFile>'' && hdr == NULL */
00163   /* Write this "SPKFile" to "ofs", and fill in "hdr" to correspond to the
00164      newly-allocated header information. The "hdr" is set to the written
00165      file's <PKFHeader> so it's relative offsets can be later back-patched.
00166      "origin" should be the location of the start of this <PKFile>, namely
00167      "FS::Posn(ofs)" at the start of the call. "ifs" is the seekable input
00168      file from which the data for the immutable cache fields is read. */
00169 
00170   // other methods
00171   void Debug(std::ostream &os, const SPKFileRep::Header &hdr,
00172              std::streampos origin, bool verbose = false) const throw ();
00173   /* REQUIRES VPKFile(SELF).mu IN LL */
00174   /* Write an ASCII represenation of this PKFile to "os", where "hdr" is the
00175      corresponding header data, and "origin" is the location of the start of
00176      the PKFile within the MultiPKFile.
00177 
00178      If "verbose" is false, write a concise representation that only lists
00179      the primary key, the number of distinct secondary keys, the secondary
00180      keys themselves, and the number of entries stored under each secondary
00181      key. Otherwise, write a complete representation that includes the
00182      complete header information and contents of the entries as well. */  
00183 
00184   // dictionary types
00185   typedef Table<FP::Tag,CE::List*>::Default CFPEntryMap;
00186   typedef Table<FP::Tag,CE::List*>::Iterator CFPEntryIter;
00187 
00188   // accessors
00189   const FP::Tag PK() const throw ()
00190   { return this->pk; }
00191   PKFile::Epoch PKEpoch() const throw ()
00192   { return this->pkEpoch; }
00193   FV::Epoch NamesEpoch() const throw ()
00194   { return this->namesEpoch; }
00195   const FV::ListApp *AllNames() const throw ()
00196   { return &(this->allNames); }
00197   const BitVector *CommonNames() const throw ()
00198   { return &(this->commonNames); }
00199   const CFPEntryMap *OldEntries() const throw ()
00200   { return &(this->oldEntries); }
00201   const Text *SourceFunc() const throw ()
00202   { return this->sourceFunc; }
00203 
00204 protected:
00205   // data fields
00206   FP::Tag pk;                   // the PK for this PKFile
00207   PKFile::Epoch pkEpoch;      // epoch for this PKFile
00208   FV::Epoch namesEpoch; // epoch for "allNames"
00209   FV::ListApp allNames; // list of union of names in all entries
00210   BitVector commonNames;        // set of common names for all entries
00211   CFPEntryMap oldEntries;       // this PKFile's cache entries: CFP -> CE::List
00212   const Text *sourceFunc;     // definition site of corresponding function
00213 
00214   /* The "pkEpoch" records the epoch of this PKFile. It is
00215      incremented each time the PKFile is flushed to the stable cache.
00216      Flushing is not atomic, and the field is incremented before the
00217      disk write is done, so at times it will be ahead of the value on disk.
00218 
00219      The "namesEpoch" records the epoch of the "allNames" list. It is
00220      incremented whenever that list changes, which can occur either when a
00221      new entry is added, or when deletions are pending and the PKFile is
00222      flushed to disk.
00223 
00224      The "commonNames" bit vector indicates which names are common to all
00225      entries in this PKFile. It is interpreted relative to the "allNames"
00226      sequence.
00227 
00228      The "oldEntries" table maps common fingerprints to lists of cache
00229      entries that share the same common fingerprint. Hence, it stores all
00230      of this PKFile's entries. (In the VPKFile sub-type, it stores the
00231      ``warm'' entries that have been ``paged in'' from the stable cache.)
00232 
00233      The "sourceFunc" field is a string generated by the evaluator for
00234      debugging purposes only. It is meant to denote the site where the
00235      function corresponding to the entries in this PKFile is defined.
00236      A value of NULL means the field is uninitialized; it gets initialized
00237      when entries are added to this PKFile, but may remain uninitialized
00238      if all entries in the PKFile were created before this feature was
00239      added.
00240   */
00241 
00242   void AddEntryToTable(/*INOUT*/ CFPEntryMap &tbl,
00243                        const FP::Tag &cfp, CE::T *ce) const throw ();
00244   /* Add the cache entry "ce" to "tbl" under the common fingerprint
00245      "cfp". */ 
00246 
00247   virtual VPKFileChkPt *CheckPoint()  throw ();
00248   /* Return a newly-allocated checkpoint of this "SPKFile". This does not
00249      set the "newUncommon" and "newCommon" fields of the checkpoint. */
00250 
00251   void ScanCommonTable(const CFPEntryMap &cfpTbl, const BitVector *toDelete,
00252                        /*INOUT*/ BitVector &uncommonJoin,
00253                        /*INOUT*/ BitVector &uncommonMeet,
00254                        /*INOUT*/ int &totalEntries,
00255                        /*INOUT*/ bool &delOne) const throw ();
00256   /* REQUIRES VPKFile(SELF).mu IN LL */
00257   /* Over the set of entries in "cfpTbl" whose indices do not correspond to
00258      set bits in "toDelete", augment "uncommonJoin" to include the union of
00259      all their uncommon names, reduce "uncommonMeet" so as not to include
00260      any name not set in all of their uncommon names, and increment
00261      "totalEntries" by the number of (undeleted) entries considered.
00262      "delOne" is set to true if some entry in "cfpTbl" has an index
00263      corresponding to a set bit in "toDelete". */
00264 
00265   void ScanList(const CE::List *head, const BitVector *toDelete,
00266                 /*INOUT*/ BitVector &uncommonJoin,
00267                 /*INOUT*/ BitVector &uncommonMeet,
00268                 /*INOUT*/ int &totalEntries,
00269                 /*INOUT*/ bool &delOne) const throw ();
00270   /* REQUIRES VPKFile(SELF).mu, ListLock(*head) IN LL */
00271   /* Same as "ScanCommonTable" above, but only consider the entries in the
00272      list "head" whose indices do not correspond to set bits in "toDelete".
00273      "delOne" is set to true if some entry in the list "head" has an index
00274      corresponding to a set bit in "toDelete". */
00275 
00276   CE::List *ExtractEntries(/*INOUT*/ CFPEntryMap &cfpTbl) throw ();
00277   /* REQUIRES VPKFile(SELF).mu IN LL */
00278   /* Return a list of all entries in "cfpTbl", and clear the table. */
00279 
00280   void UpdateCommonTable(/*INOUT*/ CFPEntryMap &cfpTbl,
00281                          const BitVector *toDelete,
00282                          const BitVector *exCommonNames,
00283                          const BitVector *exUncommonNames,
00284                          const BitVector *packMask,
00285                          const IntIntTblLR *reMap, bool unlazyTag = true)
00286     throw ();
00287   /* REQUIRES cfpTbl.Size() > 0 */
00288   /* REQUIRES (packMask == NULL) == (reMap == NULL) */
00289   /* Recompute the new tags for all entries in "cfpTbl" whose indices do not
00290      correspond to set bits in "toDelete", and store them back under their
00291      new common fingerprints. Use "exCommonNames", "exUncommonNames",
00292      "packMask", and "reMap" to change the common names of all entries. If
00293      "unlazyTag" is true, then the fingerprints for the entries' uncommon
00294      tags are also computed. For each entry, compute the maximum timestamp
00295      of its common names.
00296 
00297      Note: The "commonNames" for this PKFile should *not* have been
00298      packed according to "packMask" before this method is called. */
00299 
00300   static CE::T* Lookup(std::ifstream &ifs, std::streampos origin, int version,
00301                        const FP::Tag &commonTag, const FP::List &fps)
00302     throw (FS::EndOfFile, FS::Failure);
00303   /* REQUIRES FS::Posn(ifs) == origin == ``start of <PKFile>'' */
00304   /* Assuming "ifs" is properly positioned at the start of the stable
00305      PKFile, lookup the cache entry with common fingerprint "commonTag" and
00306      with individual fingerprints for all free variables for this PKFiles
00307      specified by "fps". "origin" specifies the location of the start of the
00308      SPKFile within the SMultiPKFile, and "version" specifies the version
00309      number of the SMultiPKFile on disk (i.e., its format).
00310 
00311      In the event of a hit, return the resulting cache entry; otherwise,
00312      return NULL. */
00313 
00314 private:
00315   void AddEntries(const VPKFileChkPt &chkpt, const BitVector *toDelete,
00316                   const BitVector *exCommonNames,
00317                   const BitVector *exUncommonNames,
00318                   const BitVector *packMask, const IntIntTblLR *reMap,
00319                   bool unlazyTag)
00320     throw ();
00321   /* REQUIRES (packMask == NULL) == (reMap == NULL) */
00322   /* Add the entries in "chkpt" to "this->entries", recomputing their common
00323      fingerprints and updating their tags if necessary. The uncommon tags
00324      are unlazied iff "unlazyTag" is true.
00325 
00326      Note: The "commonNames" for this PKFile should *not* have been
00327      packed according to "packMask" before this method is called. */
00328 
00329   void UpdateList(/*INOUT*/ CFPEntryMap &cfpTbl,
00330                   const CE::List *ents, const BitVector *toDelete,
00331                   const BitVector *exCommonNames,
00332                   const BitVector *exUncommonNames,
00333                   const BitVector *packMask, const IntIntTblLR *reMap,
00334                   bool unlazyTag)
00335     throw ();
00336   /* REQUIRES VPKFile(SELF).mu, ListLock(*ents) IN LL */
00337   /* REQUIRES (packMask == NULL) == (reMap == NULL) */
00338   /* Add the entries in "ents" to "cfpTbl", recomputing their common
00339      fingerprints and updating their tags if necessary. If "exCommonNames"
00340      is non-NULL, then the "uncommonNames" of all entries in "ents" are
00341      augmented to include "exCommonNames". If "exUncommonNames" is
00342      non-NULL, then the "uncommonNames" of all entries in "ents" are
00343      decreased so as not to include "exUncommonNames". If "unlazyTag" is
00344      true, then the fingerprints of their uncommon tags will also be
00345      computed.
00346 
00347      Note: The "commonNames" for this PKFile should *not* have been
00348      packed according to "packMask" before this method is called. */
00349 
00350   CE::List *ReadEntries(std::ifstream &ifs, bool readImmutable = true)
00351     throw (FS::EndOfFile, FS::Failure);
00352   /* REQUIRES FS::Posn(ifs) == ``start of <PKEntries>'' */
00353   /* Read a single <PKEntries> record from "ifs" and return the
00354      corresponding list of newly allocated entries (in order). The
00355      immutable fields of the cache entries are read into memory iff
00356      "readImmutable" is "true". */
00357 
00358   void WriteEntries(std::ifstream &ifs, std::ostream &ofs,
00359                     CE::List *entryList)
00360     const throw (FS::Failure);
00361   /* REQUIRES VPKFile(SELF).mu, ListLock(*entryList) IN LL */
00362   /* REQUIRES FS::Posn(ofs) == ``start of <PKEntries>'' */
00363   /* Write a single <PKEntries> record formed from the entries in
00364      "entryList" (in order) to "ofs". "ifs" is the input stream from
00365      which any unread immutable cache entry fields are read. */
00366 
00367   static std::streampos LookupCFP(std::ifstream &ifs, std::streampos origin,
00368                                   int version, const FP::Tag &cfp,
00369                                   const SPKFileRep::Header &hdr)
00370     throw (FS::EndOfFile, FS::Failure);
00371   /* REQUIRES FS::Posn(ifs) == ``start of <CFPTypedHeader>'' */
00372   /* Returns the index of the <PKEntries> for common fingerprint "cfp" in
00373      the stream "ifs" if any exist; -1 otherwise. */
00374 
00375   static std::streampos LookupCFPInListV1(std::ifstream &ifs,
00376                                           std::streampos origin,
00377                                           const FP::Tag &cfp, int num)
00378     throw (FS::EndOfFile, FS::Failure);
00379   /* REQUIRES FS::Posn(ifs) == ``start of <CFPSeqHeader>'' */
00380   /* Returns the index of the <PKEntries> for common fingerprint "cfp" in
00381      the stream "ifs" if any exist; -1 otherwise. This routine assumes
00382      the entries are an arbitrary list. */
00383 
00384   static std::streampos LookupCFPInSortedListV1(std::ifstream &ifs,
00385                                                 std::streampos origin,
00386                                                 const FP::Tag &cfp, int num)
00387     throw (FS::EndOfFile, FS::Failure);
00388   /* REQUIRES FS::Posn(ifs) == ``start of <CFPSeqHeader>'' */
00389   /* Returns the index of the <PKEntries> for common fingerprint "cfp" in
00390      the stream "ifs" if any exist; -1 otherwise. This routine requires
00391      the common fingerprints to be listed in sorted order. */
00392 
00393   static CE::T* LookupEntryV1(std::ifstream &ifs, const FP::List &fps)
00394     throw (FS::EndOfFile, FS::Failure);
00395   /* REQUIRES FS::Posn(ifs) == ``start of <PKEntries>'' */
00396 };
00397 
00398 #endif // _SPK_FILE_H

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