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

EmptyPKLog.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 Mon May 23 22:31:22 EDT 2005 by ken@xorian.net  
00020 //      modified on Wed Feb 23 17:29:53 PST 2000 by mann  
00021 //      modified on Sat Aug 22 15:45:32 PDT 1998 by heydon
00022 
00023 #include <Basics.H>
00024 #include <VestaLog.H>
00025 #include <Recovery.H>
00026 #include <FP.H>
00027 #include <CacheConfig.H>
00028 #include <CacheIntf.H>
00029 #include <PKEpoch.H>
00030 #include <Debug.H>
00031 
00032 #include "EmptyPKLog.H"
00033 
00034 using std::fstream;
00035 using std::cout;
00036 using std::endl;
00037 
00038 /* Note: Although the cache server's "CleanCacheLog" method checkpoints the
00039    "emptyPKLog", it does not write anything into that checkpoint. Hence,
00040    the checkpoint file can be ignored at recovery. */
00041 
00042 EmptyPKLog::EmptyPKLog(Basics::mutex *mu, CacheIntf::DebugLevel debug,
00043                        bool readonly)
00044   throw (VestaLog::Error)
00045 /* REQUIRES Sup(LL) = CacheS.mu */
00046   : mu(mu), debug(debug)
00047 {
00048   this->log = NEW(VestaLog);
00049   this->log->open(Config_EmptyPKLogPath.chars(), /*ver=*/ -1, readonly);
00050   this->rd = NEW_CONSTR(RecoveryReader, (this->log));
00051   this->oldEmptyPKTbl = NULL;
00052   this->emptyPKTbl = NEW(EmptyPKLog::PKEpochTbl);
00053 }
00054 
00055 void EmptyPKLog::Read(/*OUT*/ FP::Tag &pk, /*OUT*/ PKFile::Epoch &pkEpoch)
00056   throw (VestaLog::Error, VestaLog::Eof)
00057 /* REQUIRES Sup(LL) = CacheS.mu && ``private log in recovering state'' */
00058 {
00059     // read the pair from the log
00060     pk.Recover(*(this->rd));
00061     this->rd->readAll((char *)(&pkEpoch), sizeof(pkEpoch));
00062 
00063     // add it to the table
00064     PKFile::Epoch tblEpoch;
00065     bool inTbl = this->emptyPKTbl->Get(pk, /*OUT*/ tblEpoch);
00066     // entries in log are (strictly) monotonically increasing
00067     assert(!inTbl || pkEpoch > tblEpoch);
00068     bool inTbl2 = this->emptyPKTbl->Put(pk, pkEpoch);
00069     assert(inTbl == inTbl2);
00070 }
00071 
00072 void EmptyPKLog::CheckpointBegin()
00073   throw (FS::Failure, VestaLog::Error)
00074 /* REQUIRES Sup(LL) < CacheS.mu && ``private log in ready state'' */
00075 {
00076     this->mu->lock();
00077     try {
00078         fstream *chkptFile = this->log->checkpointBegin();
00079         // the EmptyPKLog checkpoint is always empty
00080         FS::Close(*chkptFile);
00081         this->oldEmptyPKTbl = this->emptyPKTbl;
00082         this->emptyPKTbl = NEW(EmptyPKLog::PKEpochTbl);
00083     } catch (...) { this->mu->unlock(); throw; }
00084     this->mu->unlock();
00085 }
00086 
00087 void EmptyPKLog::CheckpointEnd() throw (VestaLog::Error)
00088 /* REQUIRES Sup(LL) < CacheS.mu && ``private log in ready state'' */
00089 {
00090     this->mu->lock();
00091     try {
00092         this->log->checkpointEnd();
00093         this->log->prune(/*ckpkeep=*/ 1);
00094         delete this->oldEmptyPKTbl;
00095         this->oldEmptyPKTbl = NULL;
00096     } catch (...) { this->mu->unlock(); throw; }
00097     this->mu->unlock();
00098 }
00099 
00100 void EmptyPKLog::Write(const FP::Tag &pk, PKFile::Epoch pkEpoch)
00101   throw (VestaLog::Error)
00102 /* REQUIRES Sup(LL) < CacheS.mu && ``private log in ready state'' */
00103 {
00104     this->mu->lock();
00105     PKFile::Epoch tblEpoch = 0;
00106     if (this->emptyPKTbl->Get(pk, /*OUT*/ tblEpoch)) {
00107         assert(pkEpoch >= tblEpoch);
00108     }
00109     if (pkEpoch > tblEpoch) {
00110         if (this->debug >= CacheIntf::LogFlush) {
00111             Debug::Lock();
00112             cout << Debug::Timestamp() << "Writing entry to EmptyPKLog" <<endl;
00113             cout << "  pk = " << pk << endl;
00114             cout << "  pkEpoch = " << pkEpoch << endl;
00115             cout << endl;
00116             Debug::Unlock();
00117         }
00118         (void)this->emptyPKTbl->Put(pk, pkEpoch);
00119         try {
00120             this->log->start();
00121             pk.Log(*(this->log));
00122             this->log->write((char *)(&pkEpoch), sizeof(pkEpoch));
00123             this->log->commit();
00124         }
00125         catch (...) {
00126             this->mu->unlock();
00127             throw;
00128         }
00129     }
00130     this->mu->unlock();
00131 }
00132 
00133 bool EmptyPKLog::GetEpoch0(const FP::Tag &pk, /*OUT*/ PKFile::Epoch &pkEpoch)
00134   throw ()
00135 /* REQUIRES Sup(LL) = CacheS.mu */
00136 {
00137   if (this->emptyPKTbl->Get(pk, /*OUT*/ pkEpoch)) return true;
00138   if (this->oldEmptyPKTbl == NULL) return false;
00139   return this->oldEmptyPKTbl->Get(pk, /*OUT*/ pkEpoch);
00140 }
00141 
00142 bool EmptyPKLog::GetEpoch(const FP::Tag &pk, /*OUT*/ PKFile::Epoch &pkEpoch)
00143   throw ()
00144 /* REQUIRES Sup(LL) < CacheS.mu */
00145 {
00146     this->mu->lock();
00147     bool res = this->GetEpoch0(pk, /*OUT*/ pkEpoch);
00148     this->mu->unlock();
00149     return res;
00150 }

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