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 // Created on Mon Mar 3 16:36:52 PST 1997 by heydon 00020 // Last modified on Mon Aug 9 17:08:16 EDT 2004 by ken@xorian.net 00021 // modified on Tue Jun 27 15:42:14 PDT 2000 by mann 00022 // modified on Wed Apr 14 11:50:39 PDT 1999 by heydon 00023 00024 // Weeder.H -- the Vesta-2 weeder class 00025 00026 #ifndef _WEEDER_H 00027 #define _WEEDER_H 00028 00029 #include <Basics.H> 00030 #include <FS.H> 00031 #include <SRPC.H> 00032 #include <VestaLog.H> 00033 #include <Recovery.H> 00034 #include <VestaLogSeq.H> 00035 #include <SourceOrDerived.H> 00036 #include <CacheIntf.H> 00037 #include <BitVector.H> 00038 #include <WeederC.H> // cache server weeder-client interface 00039 00040 #include "CommonErrors.H" 00041 #include "WeedArgs.H" 00042 #include "RootTbl.H" 00043 #include "GLNode.H" 00044 #include "GLNodeBuffer.H" 00045 #include "ReposRoots.H" 00046 00047 class Weeder { 00048 public: 00049 // constructor 00050 Weeder(CacheIntf::DebugLevel debug =CacheIntf::None) 00051 throw (SRPC::failure, FS::Failure); 00052 /* Initialize the weeder and recover its stable state. */ 00053 00054 // do work 00055 bool Weed(WeedArgs &args) throw (SRPC::failure, 00056 FS::Failure, FS::DoesNotExist, VestaLog::Error, VestaLog::Eof, 00057 InputError, SysError, ReposError); 00058 /* Check for a previous incomplete weed, and if one exists, 00059 complete it and return true. Otherwise, perform a new weed 00060 and return false, keeping all cache entries and deriveds 00061 reachable from roots found in the graphLog that to be kept 00062 according to the weeding instructions in the file named by 00063 "args.instrFile", or from the standard input if "args.instrFile 00064 == NULL". If "args.doDeletions" is false, then no entries are 00065 actually deleted. If "args.globArgs" is true, the expansion of 00066 each file matched by a pattern in the weeder instructions is 00067 printed. If "args.printRoots" is true, for each Root in the 00068 graphLog, a line is printed indicating whether or not the 00069 weeder instructions indicate that the root should be kept. */ 00070 00071 private: 00072 // read-only after init 00073 CacheIntf::DebugLevel debug; 00074 const WeedArgs *args; 00075 WeederC *cache; 00076 00077 // STABLE fields 00078 BitVector *weeded; // set of CI's to delete 00079 time_t startTime; // time recorded before graph log is flushed 00080 ShortId disShortId; // ShortId of file containing DIs to keep 00081 RootTbl *instrRoots; // roots to keep according to instructions file 00082 RootTbl *markedRoots; // roots marked during mark phase 00083 /* Note: 'markedRoots' is a subset of the Root nodes encountered in the 00084 GraphLog during the mark phase. It includes all such encountered roots 00085 that are in 'instrRoots', plus all roots deemed ``fresh'' enough as 00086 per the "-keep" command-line switch. */ 00087 00088 // volatile fields 00089 BitVector *initCIs; // initial CI's at start of weed 00090 BitVector *marked; // CI's marked during the mark phase 00091 BitVector *wLeases; // set of leased CI's 00092 BitVector *glCIs; // set of CI's found in GL (used to 00093 // check for inconsistencies) 00094 VestaLogSeq graphLogSeq; // cache server's graph log sequence 00095 int newLogVer; // version of "graphLogSeq" to read up to 00096 Text logChkptFName; // temporary filename to which we checkpoint 00097 // the pruned graph log 00098 std::ofstream pendingGL; // output stream for overflow nodes 00099 int markedCnt; // number of nodes marked on scan of (pending)GL 00100 int markedCntTotal; // total entries marked 00101 GLNodeBuffer *nodeBuff; // buffer of unprocessed graphLog nodes 00102 FILE *disFP; // file for list of DIs to keep 00103 time_t keepTime; // keep anything newer than this 00104 00105 // mark phase methods ----------------------------------------------------- 00106 00107 void MarkPhase() throw (SRPC::failure, FS::Failure, FS::DoesNotExist, 00108 VestaLog::Error, VestaLog::Eof, InputError, SysError, ReposError); 00109 /* The weeder's mark phase. Call the cache server's "StartMark" method to 00110 checkpoint the graphLog, then process the weeder instructions. If "-n" 00111 was specified, then print the disposition of each of the roots in the 00112 graphLog. Otherwise, do the actual marking work by calling "MarkWork". 00113 If the call to "StartMark" succeeded but an exception is thrown 00114 thereafter, "ResumeLeaseExp" is called and the exception is re-thrown. 00115 00116 During a successful run, this method performs the following steps: 00117 00118 1. calls the cache's "StartMark" method, which has the side-effect 00119 of disabling lease expiration; 00120 2. calls GatherWeedRoots::P to read the weeder instructions; and 00121 3. calls MarkWork below to do the actual marking work. 00122 00123 This method sets "this->roots" to the table of weeder roots to keep. 00124 */ 00125 00126 void MarkWork() throw (SRPC::failure, FS::Failure, VestaLog::Error, 00127 VestaLog::Eof, SourceOrDerived::Fatal, ReposError); 00128 /* Read "this->graphLogSeq", setting "this->weeded" to the set of cache 00129 entries to delete. Also, write the indices of any DIs to keep to a new 00130 derived file, and set "this->disShortId" to the ShortId of that file. 00131 If an exception is thrown before the call to "ResumeLeaseExp", 00132 "ResumeLeaseExp" is called and the exception is re-thrown. 00133 00134 During a successful run, this method performs the following steps: 00135 00136 1. creates/opens the derived ``keep file''; 00137 2. does marking work by scanning graph log until there are no more 00138 entries to mark; 00139 3. calls the cache's SetHitFilter method; 00140 4. calls the cache's GetLeases method; 00141 5. calls the cache's ResumeLeaseExp method; 00142 6. marks all leased cache entries, and scans graph log until all 00143 entries protected by leased entries are also marked; 00144 7. closes the file created in step 1; 00145 */ 00146 00147 void CopyGLtoPending(const PkgTbl *pkgTbl) 00148 throw (FS::Failure, VestaLog::Error); 00149 /* Copy the graph log "this->graphLogSeq" (reading up to but not including 00150 version "this->newLogVer" of the log) to the "pendingGL" file named by 00151 the Vesta configuration file. Any "Root" nodes encountered in the 00152 graphLog that are contained in "this->roots" are processed. If "pkgTbl" 00153 is non-NULL, print the disposition of each Root node in the graph log. 00154 */ 00155 00156 void ScanLogOnce() throw (FS::Failure); 00157 /* Repeatedly scan the "pendingGL" file, marking any reachable nodes, 00158 until there are no more nodes to mark. Write the indices of reachable 00159 deriveds from each marked node to the file "this->disFP". */ 00160 00161 void MarkNode(CacheEntry::Index ci) throw (FS::Failure); 00162 /* Mark the node with index "ci" as being reachable. If there is a 00163 node in the weeder's buffer with this "ci", process that node 00164 recursively. This sets the internal "markedOne" bit if "ci" was not 00165 already marked. */ 00166 00167 void ProcessNode(const GLNode &node) throw (FS::Failure); 00168 /* Process the node "node"; that is, mark each of its children. Also, 00169 write the set of DIs in "node" to "this->disFP". */ 00170 00171 void PrintRoot(const PkgBuild &root, const PkgTbl &pkgTbl, 00172 bool chosenRoot, bool freshRoot) throw (); 00173 /* Print the disposition of "root" according to "pkgTbl", "chosenRoot", 00174 and "freshRoot". "pkgTbl" is a table of all of the names of ".main.ves" 00175 files in the repository, "chosenRoot" is true iff "root" was designated 00176 as a root to keep, and "freshRoot" is true iff the root should be 00177 kept because it is new enough. */ 00178 00179 // deletion phase methods ------------------------------------------------- 00180 00181 void DeletionPhase() 00182 throw (SRPC::failure, FS::Failure, VestaLog::Error, VestaLog::Eof); 00183 /* The weeder's deletion phase. Uses "this->roots" to decide which root 00184 nodes of the cache's graph log to keep. */ 00185 00186 PKPrefixTbl *WeededPrefixes() throw (VestaLog::Error, FS::Failure); 00187 /* Return a new table whose domain is the set of all PKPrefix values for 00188 those nodes in the graphLog that are to be weeded according to 00189 "this->weeded". */ 00190 00191 void PruneGraphLog() 00192 throw (FS::Failure, VestaLog::Error, VestaLog::Eof); 00193 /* Prune the graphLog, writing the new version to a checkpoint file with 00194 version number "this->newLogVer". Only graph log root nodes in the 00195 domain of "this->roots" are kept. */ 00196 00197 // stable variable methods ------------------------------------------------ 00198 00199 void Recover() throw (SRPC::failure, FS::Failure); 00200 /* Recover the stable variables and call "CacheW.WeederRecovering" 00201 to indicate that the weeder has just recovered. */ 00202 00203 void RecoverWeeded() throw (FS::Failure); 00204 /* Initialize "weeded" from stable storage. */ 00205 00206 void WriteWeeded() throw (FS::Failure); 00207 /* Write the current value of "weeded" to stable storage. */ 00208 00209 void RecoverMiscVars() throw (FS::Failure); 00210 /* Initialize "startTime", "disShortId", and "roots" from 00211 stable storage. */ 00212 00213 void WriteMiscVars() throw (FS::Failure); 00214 /* Write the current values of "startTime", "disShortId", and 00215 "roots" to stable storage. */ 00216 00217 void TimedMsg(char *msg, bool blankline = true, 00218 int level = CacheIntf::StatusMsgs) throw (); 00219 /* Write the message "msg" to the standard output if the debugging level 00220 is at or above "level". If "newline" is true, append an extra blank 00221 line. */ 00222 }; 00223 00224 #endif // _WEEDER_H