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

SMultiPKFile.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 // Last modified on Thu Aug  5 00:19:51 EDT 2004 by ken@xorian.net
00020 //      modified on Tue May  4 11:16:46 PDT 1999 by heydon
00021 
00022 // SMultiPKFile -- operations for reading/writing MultiPKFile's on disk
00023 
00024 /* The cache entries for a single primary key (PK) are grouped together on the
00025    disk in what is called a PKFile. It would be too expensive to use a single
00026    disk file for each PKFile, so PKFiles are grouped together into so-called
00027    MultiPKFiles on the disk.
00028 
00029    An SMultiPKFile exports operations for reading/writing MultiPKFiles on
00030    disk in the stable cache.
00031 
00032    The start of a MultiPKFile has an index for locating the PKFile within the
00033    MultiPKFile for a particular PK. The methods of this interface are used for
00034    opening MultiPKFiles, and for reading and writing their indices. See the
00035    PKFile interface for reading and writing individual PKFile's.
00036 
00037    The mapping from a PK to its MultiPKFile is implemented by the file system.
00038    The MultiPKFile for a given PK is formed from a prefix of the PK. The size
00039    used for the prefix determines the {\def granularity} of the MultiPKFile's,
00040    and is defined by the "PKPrefix" interface. The implementation is allowed
00041    to change the PKPrefix granularity, but it must of course support the
00042    ability to find MultiPKFile's of older granularity, and to write files of
00043    the latest granularity from older ones when the granularity changes. The
00044    ability to support MultiPKFiles of differing granularity is currently not
00045    supported. */
00046 
00047 #ifndef _S_MULTI_PK_FILE_H
00048 #define _S_MULTI_PK_FILE_H
00049 
00050 #include <Basics.H>
00051 #include <FS.H>
00052 #include <Table.H>
00053 #include <VestaLog.H>
00054 #include <AtomicFile.H>
00055 #include <FP.H>
00056 #include <BitVector.H>
00057 #include <CacheState.H>
00058 #include <PKPrefix.H>
00059 
00060 #include "EmptyPKLog.H"
00061 #include "SMultiPKFileRep.H"
00062 #include "VPKFile.H"
00063 
00064 class SMultiPKFile {
00065 public:
00066   // dictionary types
00067   typedef Table<FP::Tag,VPKFile*>::Default VPKFileMap;
00068   typedef Table<FP::Tag,VPKFile*>::Iterator VPKFileIter;
00069 
00070   // ChkPtTbl: FP::Tag -> (VPKFileChkPt *)
00071   typedef Table<FP::Tag,VPKFileChkPt*>::Default ChkPtTbl;
00072   typedef Table<FP::Tag,VPKFileChkPt*>::Iterator ChkPtIter;
00073 
00074   static void OpenRead(const PKPrefix::T &pfx, /*OUT*/ std::ifstream &ifs)
00075     throw (SMultiPKFileRep::NotFound, FS::Failure);
00076   /* Open the MultiPKFile with prefix "pfx" for reading, and set "ifs" to
00077      an input file stream on it. If there is no such MultiPKFile, raise
00078      "SMultiPKFileRep::NotFound".
00079 
00080      The name of the MultiPKFile for "pfx" is determined from the values of
00081      the "[CacheServer]/MetaDataRoot", "[CacheServer]/MetaDataDir", and
00082      "[CacheServer]/SCacheDir" configuration variables, from the "pfx"
00083      itself, and from the "granularity" at which the latest MultiPKFile
00084      for "pfx" was written. */ 
00085 
00086   static std::streampos SeekToPKFile(std::ifstream &ifs, const FP::Tag &pk,
00087                                      /*OUT*/ int &version)
00088     throw (SMultiPKFileRep::NotFound, FS::Failure);
00089   /* REQUIRES ifs.tellg() == ``start of <MultiPKFile>'' */
00090   /* Assuming "ifs" is positioned at the start of the MultiPKFile "ifs",
00091      seek to the position in that file where the PKFile for "pk" begins
00092      if such a PKFile exists, set "version" to the version number found
00093      in the MultiPKFile <Header>, and return that position; raise
00094      "SMultiPKFileRep::NotFound" otherwise. */
00095 
00096   static bool ChkptForRewrite(VPKFileMap& vpkFiles,
00097                               const BitVector *toDelete,
00098                               /*OUT*/ ChkPtTbl &vpkChkptTbl) throw();
00099   /* REQUIRES (forall vf: VPKFile :: Sup(LL) < vf.mu) */
00100   /* In preparation for rewriting a MultiPKFile, checkpoint in
00101      memory all of its VPKFiles to capture what is to be written.
00102      This is neceessary because new entries may be added in parallel
00103      with re-writng. "vpkFiles" is a table of "VPKFiles" stored in
00104      the cache; this table must be a *superset* of the "SPKFiles"
00105      stored in the corresponding MultiPKFile on disk. If "toDelete"
00106      is non-NULL, it points to a bit vector whose set bits
00107      correspond to the indices of cache entries to delete from the
00108      cache.
00109 
00110      "vpkChkptTbl" is filled with VPKFileChkPt objects, one per
00111      VPKFile in "vpkFiles".  The return value indicates whether a
00112      re-write is neccessary.  If toDelete is NULL and there are no
00113      new entries in any of the VPKFiles, the result will be false
00114      (indicating that there is nothing that needs to be written to
00115      disk). */
00116 
00117   static bool PrepareForRewrite(const PKPrefix::T &pfx,
00118                                 std::ifstream &ifs,
00119                                 /*OUT*/ SMultiPKFileRep::Header *&hdr)
00120     throw (FS::Failure, FS::EndOfFile);
00121   /* Perform the initial steps of re-writing the MultiPKFile with
00122      prefix "pfx".
00123 
00124      The return value indicates if the stable MultiPKFile already
00125      exists on disk.  If it does, it will be opened with "ifs" and
00126      its header and header entries will be read into "hdr".  If it
00127      does not, "hdr" will be set to a new empty
00128      SMultiPKFileRep::Header.
00129 
00130      This step is separated from Rewrite (below) to allow the cache
00131      to create VPKFiles for all PKFiles in the stable copy of the
00132      MultiPKFile.  Doing so avoids a race between rewriting and
00133      client requests. */
00134 
00135   static void Rewrite(const PKPrefix::T &pfx,
00136 
00137                       // From PrepareForRewrite above
00138                       bool mpkFileExists, std::ifstream &ifs,
00139                       SMultiPKFileRep::Header *hdr,
00140 
00141                       // In-memory representations to be updated
00142                       VPKFileMap &vpkFiles,
00143 
00144                       // Changes to be committed
00145                       ChkPtTbl &vpkChkptTbl,
00146 
00147                       const BitVector *toDelete, EmptyPKLog *emptyPKLog,
00148                       /*INOUT*/ EntryState & state)
00149     throw (FS::Failure, FS::EndOfFile, VestaLog::Error);
00150   /* REQUIRES (forall vf: VPKFile :: Sup(LL) < vf.mu) */
00151   /* Rewrite the MultiPKFile with prefix "pfx".
00152 
00153   "mpkFileExists" is the return value of PrepareForRewrite
00154   (above).  "ifs" and "hdr" are also prepared by the same
00155   function.
00156 
00157   "vpkFiles" is a table of "VPKFiles" stored in the cache under
00158   PK's with prefix "pfx"; this table must be a *superset* of the
00159   "SPKFiles" stored in the corresponding MultiPKFile on
00160   disk. "vpkChkptTbl" is a table of checkpoints of the VPKFiles
00161   in "vpkFiles", generated by calling
00162   SMultiPKFile::ChkptForRewrite (above). If "toDelete" is
00163   non-NULL, it points to a bit vector whose set bits correspond
00164   to the indices of cache entries to delete from the cache.
00165 
00166   This is the only method that reads and writes MultiPKFiles on disk.
00167   It is unmonitored; that is, its correctness requires that it is only
00168   called by one thread at a time. */
00169 
00170 private:
00171   // lookup private methods -------------------------------------------------
00172 
00173   static std::streampos SeekInListV1(std::ifstream &ifs,
00174                                      SMultiPKFileRep::UShort numEntries,
00175                                      const FP::Tag &pk)
00176     throw (SMultiPKFileRep::NotFound, FS::EndOfFile, FS::Failure);
00177   /* REQUIRES ifs.tellg() == ``start of <SeqHeader>'' */
00178   /* Return the absolute offset for "pk" in the file "ifs", assumming "ifs"
00179      is positioned at the start of a <SeqHeader>, version 1. Throws
00180      "SMultiPKFileRep::NotFound" if there is no entry in the header matching
00181      "pk", "FS::EndOfFile" in the event of premature end-of-file, and
00182      "FS::Failure" in the event of any other file error. */
00183 
00184   static std::streampos SeekInSortedListV1(std::ifstream &ifs,
00185                                            SMultiPKFileRep::UShort numEntries,
00186                                            const FP::Tag &pk)
00187     throw (SMultiPKFileRep::NotFound, FS::EndOfFile, FS::Failure);
00188   /* REQUIRES ifs.tellg() == ``start of <SeqHeader>'' */
00189   /* Return the absolute offset for "pk" in the file "ifs", assumming "ifs"
00190      is positioned at the start of a sorted <SeqHeader>, version 1. Throws
00191      "SMultiPKFileRep::NotFound" if there is no entry in the header matching
00192      "pk", "FS::EndOfFile" in the event of premature end-of-file, and
00193      "FS::Failure" in the event of any other file error. */
00194 
00195   // rewrite private methods ------------------------------------------------
00196 
00197   static SMultiPKFileRep::Header* ReadHeader(const PKPrefix::T &pfx,
00198                                              bool readEntries,
00199                                              std::ifstream &ifs)
00200     throw (FS::Failure, FS::EndOfFile);
00201   /* Read the <Header> of the MultiPKFile for "pfx" from "ifs", and if
00202      "readEntries" is "true", fill in its "pkTbl" with the <HeaderEntry>'s.
00203      Even if "readEntries" is true, the PKFiles themselves are not read.
00204      Throw "FS::Failure" for any other I/O error. */
00205 
00206   static Text Name(const PKPrefix::T &pfx, int granBits) throw ();
00207   /* Return the pathname for the MultiPKFile of granularity "granBits"
00208      with prefix "p". */
00209 
00210   static Text FullName(const PKPrefix::T &pfx) throw ();
00211   /* Return the complete filename of the SMultiPKFile for prefix "pfx". */
00212 
00213   static void OpenAtomicWrite(const PKPrefix::T &pfx,
00214                               /*OUT*/ AtomicFile &ofs) throw (FS::Failure);
00215   /* Open the stream "ofs" for writing on the MultiPKFile for "pfx" at the
00216      current granularity. This opens the file under a different name; the
00217      "close" method on the "ofs" can then be used to atomically rename the
00218      file to its correct name. */
00219 
00220   static void DeleteFile(const PKPrefix::T &pfx) throw (FS::Failure);
00221   /* Delete the SMultiPKFile for prefix "pfx". */
00222 
00223   static void MakeDirs(const Text &name) throw (FS::Failure);
00224   /* Create any necessary directories along the path named by the file
00225      "name". If one of the directories cannot be created, throw
00226      "FS::Failure". */
00227 
00228   static void PauseDeletionThread() throw ();
00229   /* Print debugging information to standard output and pause the calling
00230      thread for the number of seconds specified in the global configuration
00231      variable "Config_WeedPauseDur". */
00232 };
00233 
00234 #endif // _S_MULTI_PK_FILE_H

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