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

VMultiPKFile.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 Mon May 23 22:52:04 EDT 2005 by ken@xorian.net
00020 //      modified on Fri Sep 18 16:30:19 PDT 1998 by heydon
00021 
00022 // VMultiPKFile -- a set of VPKFile's stored in memory
00023 
00024 /* A "VMultiPKFile" holds all "VPKFile"'s in the cache with a common prefix.
00025    The size of the prefix is determined by the current MultiPKFile
00026    granularity; see "SMultiPKFile.H". When one "VPKFile" is flushed to the
00027    stable cache, the "VMultiPKFile" containing is used to see which other
00028    "VPKFile"'s in the same MultiPKFile on disk can also be rewritten.
00029 
00030    The methods exported by a "VMultiPKFile" object have been designed to allow
00031    a high degree of concurrency within the cache server. The only restriction
00032    they introduce is that a MultiPKFile cannot be rewritten by more than one
00033    thread at a time. See the locking level specifications for each method. */
00034 
00035 #ifndef _V_MULTI_PK_FILE_H
00036 #define _V_MULTI_PK_FILE_H
00037 
00038 #include <Basics.H>
00039 #include <FS.H>
00040 #include <VestaLog.H>
00041 #include <FP.H>
00042 #include <PKPrefix.H>
00043 #include <BitVector.H>
00044 #include <CacheState.H>
00045 #include "EmptyPKLog.H"
00046 #include "VPKFile.H"
00047 #include "SMultiPKFile.H"
00048 
00049 class VMultiPKFile {
00050   public:
00051     VMultiPKFile(const PKPrefix::T &pfx) throw ()
00052     : prefix(pfx), freeMPKFileEpoch(-1), numWaiting(0), numRunning(0),
00053       numNewEntries(0), autoFlushPending(false) { /*SKIP*/ }
00054     /* Return a new, empty "VMultiPKFile", all of whose "VPKFile"'s
00055        will share the same prefix "pfx". */
00056 
00057     bool Get(const FP::Tag &pk, /*OUT*/ VPKFile* &vpk) throw ()
00058       { return tbl.Get(pk, /*OUT*/ vpk); }
00059     /* REQUIRES Sup(LL) = CacheS.mu */
00060     /* If there is an entry in this "VMultiPKFile" under "pk", set "vpk" to
00061        the associated value and return "true"; otherwise, return false. */
00062 
00063     bool Put(const FP::Tag &pk, VPKFile *vpk) throw ()
00064       { return tbl.Put(pk, vpk); }
00065     /* REQUIRES Sup(LL) = CacheS.mu */
00066     /* Add "vpk" to this "VMultiPKFile" under the key "pk". Return "true" iff
00067        there was already an entry in this "VMultiPKFile" under key "pk". */
00068 
00069     bool Delete(const FP::Tag &pk, VPKFile *&vpk) throw ()
00070       { return tbl.Delete(pk, vpk); }
00071     /* REQUIRES Sup(LL) = CacheS.mu */
00072     /* Remove the key "pk" from this VMultiPKFile under the key
00073        "pk". Return "true" iff there was an entry in this VMultiPKFile
00074        under key "pk".  If there was an entry with key "pk", set "vpk"
00075        to the associated value. */
00076 
00077     int NumVPKFiles() const throw ()
00078       { return tbl.Size(); }
00079     /* REQUIRES Sup(LL) = CacheS.mu */
00080     /* Returns the number of VPKFiles contained by this
00081        VMultiPKFile. */
00082 
00083     const SMultiPKFile::VPKFileMap & VPKFileTbl() const throw()
00084     /* REQUIRES Sup(LL) = CacheS.mu */
00085     /* Returns the table of VPKFiles contained by this VMultiPKFile.
00086        Note that it is unsafe to access this table without holding
00087        CacheS.mu. */
00088       { return tbl; }
00089 
00090     void IncEntries() throw () { this->numNewEntries++; }
00091     /* REQUIRES Sup(LL) = CacheS.mu */
00092     /* Increment the count of total entries in this MultiPKFile. The count is
00093        used by "IsFull" to decide if the MPKFile should be flushed to the
00094        stable cache. */
00095 
00096     bool IsFull() throw ();
00097     /* REQUIRES Sup(LL) = CacheS.mu */
00098     /* If the number of entries in this MPKFile exceeds some threshold and
00099        some thread is not already pending to flush it, return true and set
00100        state indicating that a thread is pending to flush the MPKFile to the
00101        stable cache. Otherwise, return false. */
00102 
00103     bool LockForWrite(Basics::mutex &mu, const BitVector *toDelete)
00104       throw();
00105     /* REQUIRES Sup(LL) = CacheS.mu */
00106     /* The first argument "mu" should be "CacheS.mu". It is the mutex
00107        used to protect the internal fields of a VMultiPKFile.
00108 
00109        The return value indicates whether to proceed with flushing
00110        this "MultiPKFile" to disk.  If a write should take place, this
00111        function will have acquired a lock which ensures that this
00112        thread is the exclusive writer of this MultiPKFile.  (If
00113        another thread is already re-writing the same MultiPKFile, this
00114        function will block.)  If the return value is true, the caller
00115        is responsible for calling either ChkptForRewrite followed by
00116        ToSCache (to complete the write) or ReleaseWriteLock (in case
00117        of an error prior to writing). */
00118 
00119     bool ChkptForWrite(Basics::mutex &mu, const BitVector *toDelete,
00120                        /*OUT*/ SMultiPKFile::VPKFileMap &toFlush,
00121                        /*OUT*/ SMultiPKFile::ChkPtTbl &vpkChkptTbl)
00122       throw();
00123     /* REQUIRES (FORALL vf: VPKFile :: Sup(LL) < vf.mu) */
00124     /* REQUIRES Sup(LL) = CacheS.mu */
00125     /* The first argument "mu" should be "CacheS.mu". It is the mutex
00126        used to protect the internal fields of a VMultiPKFile.
00127 
00128        Continue perparations to flush to the stable cache all
00129        VPKFile's added to this "MultiPKFile" since the last time it
00130        was flushed, and update the corresponding VPKFile's in the
00131        volatile cache.
00132 
00133        The return value indicates whether a write should take place.
00134        The caller must have previously called LockForWrite (above) and
00135        it must have also indicated that a write should take place.  If
00136        the return value is true, the caller is responsible for calling
00137        either ToSCache (to complete the write) or ReleaseWriteLock (in
00138        case of an error prior to writing).
00139 
00140        The argument "toFlush" is filled with a map of all the VPKFiles
00141        to be written to the stable MultiPKFile.  "vpkChkptTbl" is
00142        filled with in-memory checkpoints of the current contents of
00143        these VPKFiles.  These capture the exact set of entries which
00144        will be written to the stable cache.  This must be done
00145        *before* flushing the graph log, since new entries may be added
00146        concurrently with the re-writing process and new entries *must*
00147        be written to the graph log before being written to the stable
00148        cache. */
00149 
00150     void ReleaseWriteLock(Basics::mutex &mu) throw();
00151     /* Release the write lock acquired by PrepareForWrite (above).
00152        This should be called if an operation between PrepareForWrite
00153        and ToSCache (below) fails.  (For instance, if flushing the
00154        graph log fails.) */
00155 
00156     void ToSCache(Basics::mutex &mu,
00157 
00158                   // From SMultiPKFile::PrepareForRewrite
00159                   bool mpkFileExists, std::ifstream &ifs,
00160                   SMultiPKFileRep::Header *hdr,
00161 
00162                   // From ChkptForWrite above
00163                   SMultiPKFile::VPKFileMap &toFlush,
00164                   SMultiPKFile::ChkPtTbl &vpkChkptTbl,
00165 
00166                   const BitVector *toDelete,
00167                   EmptyPKLog *emptyPKLog, /*INOUT*/ EntryState &state)
00168       throw (FS::Failure, FS::EndOfFile, VestaLog::Error);
00169     /* REQUIRES (FORALL vf: VPKFile :: Sup(LL) < vf.mu) */
00170     /* The first argument "mu" should be "CacheS.mu". It is the mutex used to
00171        protect the internal fields of a VMultiPKFile.
00172 
00173        The second, third, and fourth arguments must be acquired by
00174        calling SMultiPKFile::PrepareForRewrite.  (These are passed
00175        directory on to SMultiPKFile::Rewrite.)
00176 
00177        The fifth and sixth arguments must be acquired by calling
00178        ChkptForWrite (above).
00179 
00180        Flush to the stable cache all VPKFile's added to this "MultiPKFile"
00181        since the last time it was flushed, and update the corresponding
00182        VPKFile's in the volatile cache. If "toDelete" is non-NULL, then any
00183        cache entries in this MultiPKFile with indices in "toDelete" are
00184        deleted.
00185 
00186        This is a potentially long-running operation. Since only one
00187        thread at a time can be re-writing a MultiPKFile, the caller
00188        must first call PrepareForWrite which will block if some other
00189        thread is already in the process of doing so. When the
00190        operation is complete, the state set by "IsFull" indicating
00191        that a thread is pending to flush the MultiPKFile is cleared. */
00192 
00193     void UpdateEpoch(int currentEpoch) throw ()
00194     /* REQUIRES Sup(LL) = CacheS.mu */
00195       { this->freeMPKFileEpoch = currentEpoch; }
00196 
00197     bool IsStale(int latestEpoch) throw ();
00198     /* REQUIRES Sup(LL) = CacheS.mu */
00199     /* Return "true" iff this VMultiPKFile needs to be flushed by the
00200        background thread to free its memory because its last time of
00201        use was before "latestEpoch". */
00202 
00203     inline const PKPrefix::T &Prefix() const throw()
00204     /* REQUIRES Sup(LL) = CacheS.mu */
00205       { return prefix; }
00206 
00207     bool IsUnmodified() const throw ()
00208       { return this->freeMPKFileEpoch == -1; }
00209     /* REQUIRES Sup(LL) = CacheS.mu */
00210     /* Return "true" iff this VMultiPKFile has not had any entries
00211        added since it was last flushed (or created). */
00212 
00213     bool FlushRunning() const throw()
00214       { return (this->numRunning > 0); }
00215     /* REQUIRES Sup(LL) = CacheS.mu */
00216     /* Return "true" iff this VMultiPKFile is currently being flushed
00217        to the stable cache. */
00218 
00219     bool FlushPending() const throw()
00220       { return ((this->numWaiting > 0) || autoFlushPending); }
00221     /* REQUIRES Sup(LL) = CacheS.mu */
00222     /* Return "true" if there are threads waiting to flush this
00223        VMultiPKFile to the stable cache, or a thread should start
00224        flushing it soon. */
00225 
00226   private:
00227     // read-only after initialization
00228     PKPrefix::T prefix;
00229 
00230     // data fields -- protected by CacheS.mu
00231     SMultiPKFile::VPKFileMap tbl; // set of VPKFiles
00232     int freeMPKFileEpoch;         // epoch of activity on this MultiPKFile
00233     int numWaiting;               // number of threads queued by ToSCache()
00234     int numRunning;               // number of threads running "ToSCache"
00235     Basics::cond noneRunning;     // !oneRunning
00236     int numNewEntries;            // number of new entries in all VPKFiles
00237     bool autoFlushPending;        // did "IsFull" recently return "true"?
00238 
00239     /* The "freeMPKFileEpoch" is the epoch at which an entry was last added
00240        to some VPKFile of this MultiPKFile. It is -1 if no entries have been
00241        added since the MultiPKFile was last flushed (or created).
00242 
00243        Since at most one thread can flush a MultiPKFile at a time, the value
00244        "numRunning" should only take on the values 0 and 1. Hence, it could be
00245        implemented as a Boolean value. However, we use an integer to represent
00246        it so we can check that the invariant is not violated on return from
00247        flushing the MultiPKFile.
00248 
00249        The "numNewEntries" field is an upper bound on the total number of new
00250        entries in all of this MultiPKFile's PKFiles that are not scheduled to
00251        be flushed. Before flushing the VMultiPKFile, the "ToSCache" method
00252        resets "numNewEntries" to zero. After that, new entries could be added,
00253        but those new entries might be flushed also. In that case, the total
00254        number of new entries after the flush completed would be 0, but
00255        "numNewEntries" would be strictly positive. The "numNewEntries" field
00256        is used heuristically by "ToSCache" to avoid flushing the MultiPKFile
00257        if possible.
00258 
00259        The set of VPKFiles is represented by a map "tbl: PK -> VPKFile*". If
00260        "(pk, vpkfile)" is an entry in the table, then "pk" has prefix
00261        "prefix", and "vpkfile" is a VPKFile for entries with PK "pk". */
00262 };
00263 
00264 #endif // _V_MULTI_PK_FILE_H

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