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

Generated on Thu May 24 23:01:42 2007 for Vesta by  doxygen 1.5.1