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

CacheEntry.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 // Last modified on Thu Apr 28 23:48:20 EDT 2005 by ken@xorian.net
00020 //      modified on Fri Feb 27 18:38:04 PST 1998 by heydon
00021 
00022 #include <Basics.H>
00023 #include <FS.H>
00024 #include <VestaLog.H>
00025 #include <Recovery.H>
00026 #include <FP.H>
00027 #include <BitVector.H>
00028 #include <Model.H>
00029 #include <CacheIndex.H>
00030 #include <VestaVal.H>
00031 
00032 #include "IntIntTblLR.H"
00033 #include "Combine.H"
00034 #include "CacheEntry.H"
00035 
00036 using std::istream;
00037 using std::ostream;
00038 using std::ifstream;
00039 using std::cout;
00040 using std::endl;
00041 
00042 // CE::T ----------------------------------------------------------------------
00043 
00044 // mask of MSB for cache index
00045 static const CacheEntry::Index Index_MSB =
00046   (1 << ((sizeof(CacheEntry::Index) * 8) - 1));
00047 
00048 CE::T::T(CacheEntry::Index ci, BitVector *uncommonNames, FP::List* fps,
00049   IntIntTblLR *imap, VestaVal::T *value, CacheEntry::Indices *kids,
00050   Model::T model) throw () 
00051 /* REQUIRES VPKFile(SELF).mu IN LL */
00052 : ci(ci), uncommonNames(uncommonNames), value(value), kids(kids),
00053   model(model), imap(imap), fps(fps)
00054 {
00055     // compute uncommon tag
00056     uncommonTag = Combine::XorFPTag(*fps, *uncommonNames, imap);
00057 }
00058 
00059 CE::T::T(const T *ce) throw ()
00060 /* REQUIRES VPKFile(SELF).mu IN LL */
00061 : ci(ce->ci), uncommonTag(ce->uncommonTag), value(ce->value),
00062   kids(ce->kids), model(ce->model), fps(ce->fps)
00063 {
00064   this->uncommonNames = NEW_CONSTR(BitVector, (ce->uncommonNames));
00065   this->imap = (ce->imap == NULL) ? NULL : NEW_CONSTR(IntIntTblLR, (ce->imap));
00066 }
00067 
00068 bool CE::T::FPMatch(const FP::List& pkFPs) throw ()
00069 /* Note: This function has been implemented as a series of "if" statements so
00070    it can easily be modified to keep statistics on hit rates. It would be
00071    interesting to count the percentage of each of these three cases:
00072 
00073 |         XOR test       FP test     Overall
00074 |    1.    Match          Match        Hit
00075 |    2.    Match        No match      Miss
00076 |    3.   No match         ???        Miss
00077 
00078    We hope that the overall percentage of misses is low, but when we do miss,
00079    we hope the percentage due to case (2) is small compared to case (3). If
00080    not, the XOR test is not saving us much. */
00081 {
00082     // fast path: no uncommon names to compare against
00083     if (this->uncommonNames->Size() == 0) {
00084         return true;
00085     }
00086 
00087     // check uncommon FP's using XOR test
00088     Combine::XorFPTag tag(pkFPs, *(this->uncommonNames));
00089     if (tag.Xor() != this->uncommonTag.Xor()) {
00090         // case (3)
00091         return false;
00092     }
00093 
00094     // check uncommon FP's using full test (if necessary)
00095     if (tag.FPVal(pkFPs, *(this->uncommonNames)) !=
00096         uncommonTag.FPVal(*(this->fps), *(this->uncommonNames), this->imap)) {
00097         // case (2)
00098         return false;
00099     }
00100 
00101     // case (1)
00102     return true;
00103 }
00104 
00105 void CE::T::Pack(const BitVector *packMask, const IntIntTblLR *reMap) throw ()
00106 /* REQUIRES VPKFile(SELF).mu IN LL */
00107 /* REQUIRES (packMask == NULL) == (reMap == NULL) */
00108 {
00109     assert((packMask == (BitVector *)NULL) == (reMap == (IntIntTblLR *)NULL));
00110     if (packMask != (BitVector *)NULL) {
00111         // pack "uncommonNames"
00112         uncommonNames->Pack(*packMask);
00113 
00114         // update "imap" if it is not the identity
00115         if (this->imap != (IntIntTblLR *)NULL) {
00116           IntIntTblLR *imap2 = NEW_CONSTR(IntIntTblLR,
00117                                           (this->imap->ArraySize()));
00118             IntIntTblIter it(this->imap);
00119             short k, v, newK;
00120             while (it.Next(/*OUT*/ k, /*OUT*/ v)) {
00121                 bool inTbl = reMap->Get(k, /*OUT*/ newK); assert(inTbl);
00122                 inTbl = imap2->Put(newK, v); assert(!inTbl);
00123             }
00124             this->imap = imap2;
00125             imap2 = (IntIntTblLR *)NULL; // drop on floor
00126 
00127             // test if resulting map is the identity; if so, delete it
00128             int mapSz = this->imap->Size();
00129             for (k = 0; k < mapSz; k++) {
00130                 if ((!(this->imap->Get(k, /*OUT*/ v))) || (k != v))
00131                     // not the identity; exit loop early
00132                     break;
00133             }
00134             if (k == mapSz) {
00135                 // "imap" is the identity, so drop it on the floor
00136                 this->imap = (IntIntTblLR *)NULL;
00137             }
00138         }
00139     }
00140 }
00141 
00142 void CE::T::CycleNames(const BitVector &delBV,
00143   const IntIntTblLR &delMap) throw ()
00144 /* REQUIRES VPKFile(SELF).mu IN LL */
00145 {
00146     assert((uncommonNames != NULL) && (!delBV.IsEmpty()));
00147 
00148     // fill in "imap" if it is the identity
00149     if (this->imap == (IntIntTblLR *)NULL) {
00150       this->imap = NEW_CONSTR(IntIntTblLR, (fps->len));
00151       for (short k = 0; k < fps->len; k++) {
00152         bool inTbl = this->imap->Put(k, k); assert(!inTbl);
00153       }
00154     }
00155 
00156     // update "uncommonNames", "imap"
00157     BVIter it(&delBV); int oldBx; short newBx;
00158     while (it.Next(/*OUT*/ oldBx)) {
00159         // update "this->uncommonNames"
00160         bool inTbl = delMap.Get(oldBx, /*OUT*/ newBx); assert(inTbl);
00161         bool set = this->uncommonNames->Reset(oldBx); assert(set);
00162         set = this->uncommonNames->Set(newBx); assert(!set);
00163 
00164         // update "this->imap"
00165         short fpIndex;
00166         inTbl = this->imap->Delete(oldBx, /*OUT*/ fpIndex); assert(inTbl);
00167         inTbl = this->imap->Put(newBx, fpIndex); assert(!inTbl);
00168     }
00169 
00170     // update "this->uncommonTag"
00171     /* Note: we don't have to recompute the XOR because it won't change;
00172        but we do have to invalidate the unlazied fingerprint (if any),
00173        since the order of the names has changed. */
00174     this->uncommonTag.InvalidateFPVal();
00175 }
00176 
00177 void CE::T::Update(const BitVector *exCommonNames,
00178   const BitVector *exUncommonNames, const BitVector *packMask,
00179   const IntIntTblLR *reMap) throw ()
00180 /* REQUIRES VPKFile(SELF).mu IN LL */
00181 /* REQUIRES (packMask == NULL) == (reMap == NULL) */
00182 {
00183     if (exCommonNames != NULL || exUncommonNames != NULL) {
00184         // update "uncommonNames"
00185         if (exCommonNames != (BitVector *)NULL)
00186             *(this->uncommonNames) |= *exCommonNames;
00187         if (exUncommonNames != (BitVector *)NULL)
00188             *(this->uncommonNames) -= *exUncommonNames;
00189 
00190         // update uncommon tag
00191         this->uncommonTag.Init(*(this->fps),
00192           *(this->uncommonNames), this->imap);
00193     }
00194 
00195     // pack "unCommonNames" and "imap" (if necessary)
00196     Pack(packMask, reMap);
00197 }
00198 
00199 void CE::T::XorUncommonNames(const BitVector &mask) throw ()
00200 /* REQUIRES VPKFile(SELF).mu IN LL */
00201 {
00202     *(this->uncommonNames) ^= mask;
00203     this->uncommonTag.Init(*(this->fps), *(this->uncommonNames), this->imap);
00204 }
00205 
00206 
00207 // Note: this method is a class member, not an instance member.  There
00208 // is an instance member of the same name that calls this function.
00209 bool CE::T::CheckUsedNames(const BitVector *commonNames,
00210                            const BitVector *uncommonNames,
00211                            const IntIntTblLR* imap,
00212                            const FP::List *fps,
00213                            /*OUT*/ unsigned int &missing)
00214   throw ()
00215 {
00216   if(imap != 0)
00217     {
00218       IntIntTblIter it(imap);
00219       short k, v;
00220       while (it.Next(/*OUT*/ k, /*OUT*/ v))
00221         {
00222           // Every key in imap must be either commonNames or
00223           // this->uncommonNames.
00224           if(((commonNames == 0) || !commonNames->Read(k)) &&
00225              ((uncommonNames == 0) || !uncommonNames->Read(k)))
00226             {
00227               missing = k;
00228               return true;
00229             }
00230         }
00231     }
00232   // Identity map: use the length of fps to determine which names are
00233   // used by this entry.
00234   else if(fps != 0)
00235     {
00236       for(unsigned int i = 0; i < fps->len; i++)
00237         {
00238           // Every name for which we have a fingerprint must be in
00239           // either commonNames or this->uncommonNames.
00240           if(((commonNames == 0) || !commonNames->Read(i)) &&
00241              ((uncommonNames == 0) || !uncommonNames->Read(i)))
00242             {
00243               missing = i;
00244               return true;
00245             }
00246         }
00247     }
00248 
00249   // If we make it to the end, then we found no problems.
00250   return false;
00251 }
00252 
00253 void CE::T::Log(VestaLog& log) const
00254   throw (VestaLog::Error)
00255 /* REQUIRES VPKFile(SELF).mu IN LL */
00256 {
00257     log.write((char *)(&(this->ci)), sizeof(this->ci));
00258     this->uncommonNames->Log(log);
00259     if (this->uncommonNames->Size() > 0) {
00260         this->uncommonTag.Log(log);
00261     }
00262     this->value->Log(log);
00263     this->kids->Log(log);
00264     Model::Log(this->model, log);
00265     if (this->imap == (IntIntTblLR *)NULL) {
00266         IntIntTblLR empty;
00267         empty.Log(log);
00268     } else {
00269         this->imap->Log(log);
00270     }
00271     this->fps->Log(log);
00272 }
00273 
00274 void CE::T::Recover(RecoveryReader &rd)
00275   throw (VestaLog::Error, VestaLog::Eof)
00276 /* REQUIRES VPKFile(SELF).mu IN LL */
00277 {
00278     rd.readAll((char *)(&(this->ci)), sizeof(this->ci));
00279     this->uncommonNames = NEW_CONSTR(BitVector, (rd));
00280     if (this->uncommonNames->Size() > 0) {
00281         this->uncommonTag.Recover(rd);
00282     } else {
00283         this->uncommonTag.Zero();
00284     }
00285     this->value = NEW_CONSTR(VestaVal::T, (rd));
00286     this->kids = NEW_CONSTR(CacheEntry::Indices, (rd));
00287     Model::Recover(/*OUT*/ this->model, rd);
00288     this->imap = NEW_CONSTR(IntIntTblLR, (rd));
00289     if (this->imap->Size() == 0) {
00290         // drop it on the floor
00291         this->imap = (IntIntTblLR *)NULL;
00292     }
00293     this->fps = NEW_CONSTR(FP::List, (rd));
00294 }
00295 
00296 void CE::T::Write(ostream &ofs, ifstream *ifs) const throw (FS::Failure)
00297 /* REQUIRES VPKFile(SELF).mu IN LL */
00298 {
00299     // write main values
00300     CacheEntry::Index ciToWrite = this->ci;
00301     if (ciToWrite & Index_MSB) {
00302         // reset MSB
00303         ciToWrite &= (~Index_MSB);
00304     }
00305     assert(!(ciToWrite & Index_MSB));
00306     FS::Write(ofs, (char *)(&ciToWrite), sizeof(ciToWrite));
00307     this->uncommonNames->Write(ofs);
00308     if (this->uncommonNames->Size() > 0) {
00309         this->uncommonTag.Write(ofs);
00310     }
00311     if (this->ci & Index_MSB) {
00312         // immutable values stored in backing file "ifs"
00313         assert(ifs != (ifstream *)NULL);
00314         ((ImmutableVal *)(this->value))->Copy(*ifs, ofs);
00315         ((ImmutableVal *)(this->kids))->Copy(*ifs, ofs);
00316     } else {
00317         // normal case; write values in memory
00318         this->value->Write(ofs);
00319         this->kids->Write(ofs);
00320     }
00321     Model::Write(this->model, ofs);
00322 }
00323 
00324 void CE::T::Read(istream &ifs, bool readImmutable)
00325   throw (FS::EndOfFile, FS::Failure)
00326 /* REQUIRES VPKFile(SELF).mu IN LL */
00327 {
00328     // read main values
00329     FS::Read(ifs, (char *)(&(this->ci)), sizeof(this->ci));
00330     this->uncommonNames = NEW_CONSTR(BitVector, (ifs));
00331     if (this->uncommonNames->Size() > 0) {
00332         this->uncommonTag.Read(ifs);
00333     } else {
00334         this->uncommonTag.Zero();
00335     }
00336     if (readImmutable) {
00337       this->value = NEW_CONSTR(VestaVal::T, (ifs));
00338       this->kids = NEW_CONSTR(CacheEntry::Indices, (ifs));
00339     } else {
00340         assert(!(this->ci & Index_MSB));
00341         this->ci |= Index_MSB;
00342         this->value = (VestaVal::T *)(VestaVal::T::ReadImmutable(ifs));
00343         this->kids = (CacheEntry::Indices *)
00344           (CacheEntry::Indices::ReadImmutable(ifs));
00345     }
00346     Model::Read(/*OUT*/ this->model, ifs);
00347 
00348     // null out ``extra'' fields
00349     this->imap = (IntIntTblLR *)NULL;
00350     this->fps = (FP::List *)NULL;
00351 }
00352 
00353 void CE::T::WriteExtras(ostream &ofs) const throw (FS::Failure)
00354 /* REQUIRES VPKFile(SELF).mu IN LL */
00355 {
00356     if (this->imap == (IntIntTblLR *)NULL) {
00357         IntIntTblLR empty;
00358         empty.Write(ofs);
00359     } else {
00360         this->imap->Write(ofs);
00361     }
00362     this->fps->Write(ofs);
00363 }
00364 
00365 void CE::T::ReadExtras(istream &ifs) throw (FS::EndOfFile, FS::Failure)
00366 /* REQUIRES VPKFile(SELF).mu IN LL */
00367 {
00368   this->imap = NEW_CONSTR(IntIntTblLR, (ifs));
00369   if (this->imap->Size() == 0) {
00370     // drop it on the floor
00371     this->imap = (IntIntTblLR *)NULL;
00372   }
00373   this->fps = NEW_CONSTR(FP::List, (ifs));
00374 }
00375 
00376 inline void Indent(ostream &os, int indent) throw ()
00377 {
00378     for (int i = 0; i < indent; i++) os << " ";
00379 }
00380 
00381 void CE::T::Debug(ostream &os, int indent) const throw ()
00382 /* REQUIRES VPKFile(SELF).mu IN LL */
00383 {
00384     Indent(os, indent); os << "ci    = " << this->ci << endl;
00385     Indent(os, indent); os << "unFVs = {" << endl;
00386     this->uncommonNames->PrintAll(cout, indent+4);
00387     Indent(os, indent); os << "  } ("
00388                            << this->uncommonNames->Cardinality() << " total)"
00389                            << endl;
00390     if (this->uncommonNames->Size() > 0) {
00391         Indent(os, indent);
00392         os << "unTag =" << endl; this->uncommonTag.Debug(os, indent+2);
00393         os << endl;
00394     }
00395     Indent(os, indent);
00396     os << "value =" << endl; this->value->Print(os, indent + 2);
00397     Indent(os, indent); os << "kids  = "; this->kids->Print(os, indent + 2);
00398     Indent(os, indent); os << "model = " << this->model << endl;
00399 }
00400 
00401 void CE::T::DebugExtras(ostream &os, int indent) const throw ()
00402 /* REQUIRES VPKFile(SELF).mu IN LL */
00403 {
00404     Indent(os, indent); os << "imap = ";
00405     if (this->imap == (IntIntTblLR *)NULL) {
00406         os << "<identity-map>" << endl;
00407     } else {
00408         this->imap->Print(os, indent+2);
00409     }
00410     Indent(os, indent);
00411     os << "fps  =" << endl; this->fps->Print(os, indent + 2);
00412 }
00413 
00414 unsigned CE::List::Length(const List *list) throw ()
00415 {
00416     unsigned res = 0;
00417     for (/*SKIP*/; list != (List *)NULL; list = list->tail) res++;
00418     return res;
00419 }

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