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

VPKFile.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:48:27 EDT 2005 by ken@xorian.net  
00020 //      modified on Wed Feb 23 13:30:02 PST 2000 by mann  
00021 //      modified on Tue Sep 22 10:18:55 PDT 1998 by heydon
00022 
00023 // VPKFile -- A set of cache entries sharing the same primary key (PK). This
00024 // is the volatile version. The cache itself is a map: PK -> VPKFile.
00025 //
00026 // The methods in the "VPKFile" class are monitored.
00027 
00028 #ifndef _VPK_FILE_H
00029 #define _VPK_FILE_H
00030 
00031 #include <Basics.H>
00032 #include <FS.H>
00033 #include <SRPC.H>
00034 #include <FP.H>
00035 #include <CacheIntf.H>
00036 #include <BitVector.H>
00037 #include <CacheState.H>
00038 #include <Model.H>
00039 #include <PKEpoch.H>
00040 #include <CacheIndex.H>
00041 #include <FV.H>
00042 #include <VestaVal.H>
00043 #include <Generics.H>
00044 
00045 #include "IntIntTblLR.H"
00046 #include "CacheEntry.H"
00047 #include "VPKFileChkPt.H"
00048 #include "SPKFile.H"
00049 #include "SMultiPKFileRep.H"
00050 
00051 /* A "VPKFile" is a volatile PKFile, an in-memory structure for
00052    storing cache entries with the same primary key (PK). It provides
00053    methods for creating a new "VPKFile", for accessing the names of
00054    all its free variables (the "AllNames" method), for looking up a
00055    cache entry (the "Lookup" method), and for creating and adding new
00056    entries (the "NewEntry", and "AddEntry" methods).
00057 
00058    There are separate methods for creating a new cache entry and for adding it
00059    to the "VPKFile". This is because the spec requires the cache server's
00060    "AddEntry" method to create the cache entry, add the entry to the cache's
00061    "cacheLog", and then to add it to the "VPKFile".
00062 
00063    Some methods of a "VPKFile" are monitored, and some are not. See the
00064    REQUIRES clause of each method for details. */
00065 
00066 // exception class signalling duplicate names in "VPKFile::NewEntry"
00067 class DuplicateNames { };
00068 
00069 class VPKFile : public SPKFile {
00070   public:
00071     // Mutex for protecting private data fields; this lock is public so that
00072     // it can be acquired by a CacheS object when new entries are added.
00073     Basics::mutex mu;
00074     /* Locking order:
00075 |        (forall vf: VPKFile, cache: CacheS ::
00076 |           vf.mu < cache.mu)
00077     */
00078 
00079     VPKFile(const FP::Tag& pk, PKFile::Epoch newPKEpoch = 0, FV::Epoch newNamesEpoch = 0)
00080       throw (FS::Failure);
00081     /* REQUIRES Sup(LL) < SELF.mu */
00082     /* Create a new, empty PK file for primary key "pk". First, this
00083        tries reading the "SPKFile" for "fp" from the stable cache. If
00084        there is one, it initializes this "VPKFile" from that (but with
00085        an empty "oldEntries" table). Otherwise, it simply initializes
00086        this "VPKFile" to a new, empty "VPKFile" for "fp". In that
00087        event, it initializes the "pkEpoch" and "namesEpoch" of the new
00088        "VPKFile" to "newPKEpoch" and "newNamesEpoch". This method is
00089        analogous to the "EmptyVF" function in "SVCache.spec". */
00090 
00091     bool IsEmpty() throw ();
00092     /* REQUIRES Sup(LL) < SELF.mu */
00093     /* Return "true" iff this "VPKFile" contains no entries. */
00094 
00095     bool IsStableEmpty() const throw ()
00096       { return this->isEmpty; }
00097     /* REQUIRES Sup(LL) = SELF.mu */
00098     /* Return "true" iff this "VPKFile" contains no entries *and*
00099        there are no entries in its corresponding stable PKFile. */
00100 
00101     bool HasNewEntries() const throw ()
00102       { return (newUncommon != (CE::List *)NULL) || (newCommon.Size() > 0); }
00103     /* REQUIRES Sup(LL) = SELF.mu */
00104     /* Returns true iff this VPKFile has any new entries pending in its
00105        "newUncommon" or "newCommon" fields. */
00106 
00107     void SendAllNames(SRPC *srpc, bool debug)
00108       throw (SRPC::failure, PrefixTbl::Overflow);
00109     /* REQUIRES Sup(LL) < SELF.mu */
00110     /* This method implements the marshalling of the FreeVariables results.
00111        If "debug" is true, it prints the "FreeVariables" return debugging
00112        message. It also calls the "Etp_CacheS_FreeVariables" function with
00113        the correct arguments for performance monitoring. Finally, it marshals
00114        the "isEmpty" value, this VPKFile's free variable names, and its
00115        "namesEpoch". This work is done here (with the lock "SELF.mu" held)
00116        to avoid having to unnecessarily copy the free variable names. */
00117 
00118     CacheIntf::LookupRes Lookup(FV::Epoch id, const FP::List &fps,
00119       /*OUT*/ CacheEntry::Index &ci, /*OUT*/ const VestaVal::T* &value,
00120       /*OUT*/ CacheIntf::LookupOutcome &outcome) throw (FS::Failure);
00121     /* REQUIRES Sup(LL) = SELF.mu */
00122     /* Lookup an entry in the cache. First, "id" is compared to the epoch for
00123        all free variables for this VPKFile. If it is out of date,
00124        "CacheIntf::FVMismatch" is returned. Otherwise, an attempt is made to
00125        lookup the entry whose free variables have fingerprints "fps". If no
00126        matching entry is found, "CacheIntf::Miss" is returned and "outcome" is
00127        set to "LookupOutcome::AllMisses". In the event of a hit,
00128        "CacheIntf::Hit" is returned, "ci" and "value" are set to the index and
00129        result value of the corresponding cache entry, and "outcome" is set to
00130        the fine-grain outcome used for statistical purposes. Otherwise,
00131        "outcome" is set to the special value "LookupOutcome::NoOutcome".
00132 
00133        The search is first performed in the volatile cache, and then in the
00134        stable cache. If there is an error reading the stable cache on disk,
00135        "FS::Failure" is thrown. */
00136 
00137     CE::T* NewEntry(CacheEntry::Index ci, FV::List* names, FP::List *fps,
00138       VestaVal::T* value, Model::T model, CacheEntry::Indices* kids,
00139       /*OUT*/ FP::Tag* &commonFP)
00140       throw (DuplicateNames);
00141     /* REQUIRES Sup(LL) = SELF.mu */
00142     /* Create and return a new cache entry for this "VPKFile" according to
00143        the arguments (see "CacheS::AddEntry"). The "names" are the names of
00144        the free variables for the new entry, and the "fps" are their
00145        corresponding fingerprints. If "names" contains any names not in the
00146        name sequence for this "VPKFile", they are added to the sequence and
00147        the "VPKFile"'s epoch is incremented. If it contains duplicates,
00148        "DuplicateNames" is thrown.
00149 
00150        The "commonFP" OUT parameter is set to NULL if this entry does not
00151        contain all of the VPKFile's common names, or to a pointer to their
00152        combined fingerprint if it does.
00153 
00154        The responsibility for freeing storage for the arguments transfers
00155        from the caller to the callee. */ 
00156 
00157     void AddEntry(const Text* sourceFunc, CE::T *ce, FP::Tag* commonFP,
00158       PKFile::Epoch newPKEpoch = -1) throw ();
00159     /* REQUIRES Sup(LL) = SELF.mu */
00160     /* Add the new cache entry "ce" to this "VPKFile". The argument
00161        "sourceFunc" names the source location of the function definition
00162        for this new entry. The entry "ce" should have been created by a
00163        previous call to the "NewEntry" method for this "VPKFile". If
00164        "commonFP" is NULL, then this entry is assumed not to have all the
00165        common names for its VPKFile; otherwise, "commonFP" should be the
00166        combined fingerprint of the fingerprints of the values of those
00167        common names.
00168 
00169        If "newPKEpoch" is not defaulted, then "this->pkEpoch" is set
00170        to "newPKEpoch". It is a checked run-time error for
00171        "newPKEpoch < this->pkEpoch". */
00172 
00173     FP::Tag *CommonFP(const CE::T& entry) throw ()
00174     /* REQUIRES Sup(LL) = SELF.mu */
00175     /* Return the combined fingerprint of the fingerprints in "entry" for this
00176        VPKFile's common names. It is an unchecked runtime error for "entry"
00177        not to contain all the common names. */
00178         { return entry.CombineFP(commonNames); }
00179 
00180     VPKFileChkPt *CheckPoint() throw ();
00181     /* REQUIRES Sup(LL) < SELF.mu */
00182     /* Return a newly-allocated checkpoint of this "VPKFile". The
00183        "pkEpoch" of this VPKFile is atomically incremented after the
00184        checkpoint is taken. */
00185 
00186     void DecrPKEpoch() throw () { this->pkEpoch--; }
00187     /* REQUIRES Sup(LL) = SELF.mu */
00188 
00189     void Update(const SPKFile &pf,
00190       const VPKFileChkPt &chkpt, const BitVector *toDelete,
00191       const BitVector *exCommonNames, const BitVector *exUncommonNames,
00192       BitVector *packMask, IntIntTblLR *reMap, bool becameEmpty,
00193       /*INOUT*/ EntryState &state) throw ();
00194     /* REQUIRES sup(LL) = SELF.mu */
00195     /* Update this VPKFile to be based on the common free variables of
00196        "pf", but not to include the entries in "chkpt". "toDelete" are
00197        the entries to delete (and may be NIL), "exCommonNames",
00198        "exUncommonNames", "packMask", "reMap", and becameEmpty are the
00199        values set by the "SPKFile::Update" method for this PKFile. */
00200 
00201     void UpdateFreeEpoch(int currentEpoch) throw ()
00202     /* REQUIRES Sup(LL) = SELF.mu */
00203       { this->freePKFileEpoch = currentEpoch; }
00204 
00205     int GetFreeEpoch() throw()
00206     /* REQUIRES Sup(LL) = SELF.mu */
00207       { return this->freePKFileEpoch; }
00208 
00209     void DeleteOldEntries(int sizeHint, /*INOUT*/ EntryState &state) throw ();
00210     /* REQUIRES sup(LL) = SELF.mu */
00211     /* Delete all entries from "this->oldEntries", and update "state" to
00212        reflect the old entries so deleted from this VPKFile. */
00213 
00214     void Evict() throw()
00215     /* REQUIRES Sup(LL) = SELF.mu */
00216     /* Indicate that this VPKFile object has been evicted from the
00217        cache.  This should only be called by the cache when all
00218        references to this VPKFile have been removed from the tables in
00219        the cache itself and its owning VMultiPKFile. */
00220       { this->evicted = true; }
00221 
00222     bool Evicted() const throw()
00223     /* REQUIRES Sup(LL) = SELF.mu */
00224     /* Has this VPKFile been evicted from the cache? */
00225       { return this->evicted; }
00226 
00227     bool ReadyForPurgeWarm(int latestEpoch) const throw();
00228     /* REQUIRES Sup(LL) = SELF.mu */
00229     /* Should warm entries be purged from this VPKFile? */
00230 
00231     bool ReadyForEviction(int latestEpoch) const throw();
00232     /* REQUIRES Sup(LL) = SELF.mu */
00233     /* Should this VPKFile be evicted from the cache? */
00234 
00235   private:
00236     // dictionary types
00237     typedef Table<FV::T,int>::Default NameMap;
00238     typedef Table<FV::T,int>::Iterator NameMapIter;
00239 
00240     // data fields
00241     NameMap nameMap;            // table: name -> index in "allNames" list
00242     CE::List *newUncommon;      // new entries not containing all "commonNames"
00243     CFPEntryMap newCommon;      // new entries containing all "commonNames"
00244 
00245     /* The "nameMap" is a table that maps each name in "allNames" to its index
00246        in "allNames". Hence, the set of names in the domain of "nameMap" is
00247        exactly the set of names in "allNames". The map is defined so we have:
00248 
00249          nameMap = (allNames[i], i)   forall 0 <= i < allNames.len
00250 
00251        The "newUncommon" field is a list of the new entries that don't contain
00252        all of this PKFile's common names. The "newCommon" field is a table
00253        (indexed by common finger print) of entries that do contain all of this
00254        PKFile's common names. */
00255 
00256     // Is this a completely empty VPKFile (i.e. has no entries and no
00257     // stable PKFile)?  True in either of the following two cases:
00258 
00259     // 1. This is a newly created VPKFile that has no on-disk SPKFile
00260     // and has never had any entries added to it.
00261 
00262     // 2. This PK's stable PKFile has become empty by having all its
00263     // entries deleted by weeding, and no new entries have been added
00264     // since.
00265     bool isEmpty;
00266 
00267     int freePKFileEpoch;        // epoch of activity on this PKFile
00268 
00269     bool evicted;               // Has this VPKFile been evicted from
00270                                 // the cache?  (Needed to avoid a race
00271                                 // between freeing VPKFiles and adding
00272                                 // new entries.)
00273 
00274     // private methods
00275     void ReadPKFHeaderTail(const FP::Tag &pk)
00276       throw (FS::Failure, SMultiPKFileRep::NotFound);
00277     /* Read the <PKFHeaderTail> of the SPKFile for "pk" into this VPKFile.
00278        "SMultiPKFileRep::NotFound" is thrown if there is no stable MultiPKFile
00279        for "pk". */
00280 
00281     bool IsCommon(const BitVector &nms) throw ()
00282       { return (!this->commonNames.IsEmpty() && this->commonNames <= nms); }
00283     /* Returns true iff an entry with names "nms" should be considered
00284        "common", i.e., stored in the "newCommon" table as opposed to the
00285        "newUncommon" list. */
00286 
00287     void PutCommonEntry(CFPEntryMap &tbl, const FP::Tag &commonFP, CE::T *ce)
00288       throw ();
00289     /* REQUIRES Sup(LL) = SELF.mu */
00290     /* Add the entry "ce" to the table "tbl" under the common fingerprint
00291        "commonFP". */
00292 
00293     CE::T* LookupInList(const CE::List *entries, const FP::List &fps) throw ();
00294     /* REQUIRES Sup(LL) = SELF.mu AND ListLock(*entries) IN LL */
00295     /* Look for a hit on an entry in the list "entries" where the free
00296        variables have the given fingerprints "fps". If there is a match,
00297        return the resulting cache entry; otherwise, return NULL. The "entries"
00298        are all expected to have the correct combined common fingerprint (if
00299        any); the test for a hit is based solely on the combined uncommon
00300        fingerprint. */
00301 
00302     void DeleteCheckpointedEntries(const VPKFileChkPt &chkpt,
00303       /*INOUT*/ EntryState &state) throw ();
00304     /* REQUIRES Sup(LL) = SELF.mu */
00305     /* Remove the checkpointed entries in "chkpt" from this VPKFile's
00306        "newCommon" and "newUncommon" bins. This does not changed the set of
00307        entries stored in "chkpt". Update the counts in "state" as cache
00308        entries are removed from this VPKFile. */
00309 
00310     void MoveCommonToUncommon(const BitVector &oldCommon) throw ();
00311     /* REQUIRES newCommon.Size() > 0 */
00312     /* Move the entries in the "newCommon" table to the "newUncommon" list,
00313        OR'ing the "oldCommon" vector into each entry's "uncommonNames". */
00314 
00315     void MoveCommonListToUncommon(CE::List *head, const BitVector &oldCommon)
00316       throw ();
00317     /* REQUIRES SELF.mu IN LL */
00318     /* REQUIRES head != (CE::List *)NULL */
00319     /* Move the common entries in "head" to the "newUncommon" list, XOR'ing
00320        the "oldCommon" vector into each entry's "uncommonNames". */
00321 
00322     void UpdateUncommonList(const Text* sourceFunc,
00323       /*INOUT*/ BitVector *packMask, /*INOUT*/ IntIntTblLR *reMap,
00324       bool unlazyTag) throw ();
00325     /* REQUIRES sup(LL) = SELF.mu */
00326     /* Walk over the entries in "newUncommon", packing each entry according to
00327        "packMask" and "reMap" (if non-NULL), and unlazying the uncommon
00328        fingerprint iff "unlazyTag" is true. Each entry is added to either the
00329        "newCommon" table or the "newUncommon" list based on whether it contains
00330        all the common names or not.
00331 
00332        Note: The VPKFile's "commonNames" should already have been updated
00333        before this method is called. However, since the entry's
00334        "uncommonNames" are compared to this VPKFile's "commonNames" before the
00335        "uncommonNames" have been packed, the "commonNames" should not have been
00336        packed before this call. */
00337 
00338     void RecordCIsFromList(const CE::List *ents, /*INOUT*/ IntIntTbl& keep)
00339       const throw ();
00340     /* REQUIRES ListLock(*ents) IN LL */
00341     /* Add the CIs of all entries in "ents" to the table "keep". (Actually,
00342        the table records pairs of the form "(ci, 0)"). */
00343 
00344     void RecordCIsFromTbl(const CFPEntryMap& tbl, /*INOUT*/ IntIntTbl& keep)
00345       const throw ();
00346     /* Add the CIs of all entries in "tbl" to the table "keep". (Actually,
00347        the table records pairs of the form "(ci, 0)"). */
00348 
00349     void CopyByCIs(const CFPEntryMap& source, /*INOUT*/ IntIntTbl& cis,
00350       /*INOUT*/ EntryState &state) throw ();
00351     /* REQUIRES SELF.mu IN LL */
00352     /* Add any entry in "source" whose CI is in the domain of "cis" to the
00353        table "this->oldEntries". "cis" is an INOUT parameter because this
00354        function has benevolent side-effects on it (it increments the range
00355        value of each CI selected from the table). */
00356 
00357     void CycleDeletedNamesInList(CE::List *curr,
00358       /*INOUT*/ BitVector &packMask, /*INOUT*/ IntIntTblLR &reMap) throw ();
00359     /* REQUIRES sup(LL) = SELF.mu */
00360     /* For each entry in the list "curr" (all of which are assumed to be
00361        ``uncommon''), see if the entry contains any names not named in
00362        "packMask". If so, cycle such names to the end of the "this->allNames"
00363        list, update the "this->nameMap" appropriately, and update "packMask",
00364        "reMap", and the entries themselves to correspond to the new order of
00365        the names. */
00366 
00367     // make copy constructor inaccessible to clients
00368     VPKFile(const VPKFile&);
00369 };
00370 
00371 #endif // _VPK_FILE_H

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