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 // 00020 // VestaSource.H 00021 // Last modified on Fri Feb 10 16:09:24 EST 2006 by ken@xorian.net 00022 // modified on Mon Nov 15 08:53:29 EST 2004 by irina.furman@intel.com 00023 // modified on Fri Aug 10 15:09:15 PDT 2001 by mann 00024 // modified on Tue May 4 10:51:22 PDT 1999 by heydon 00025 // 00026 // Primary internal interface for the Vesta repository directory 00027 // structure. 00028 00029 #ifndef _VSOURCE 00030 #define _VSOURCE 1 00031 00032 #include "SourceOrDerived.H" 00033 #include "ArcTable.H" 00034 #include "AccessControl.H" 00035 #include "ReadersWritersLock.H" 00036 #include "FP.H" 00037 #include "VRErrorCode.H" 00038 #include "VestaAttribs.H" 00039 #include <iostream> 00040 00041 typedef const char* Arc; // must not contain /, \, or \000 00042 #define MAX_ARC_LEN 255 00043 00044 class VestaSource; // forward 00045 00046 // A LongId is an identifier for a Vesta source that is suitable for 00047 // use with NFS. Every source in the /vesta directory tree at a site 00048 // has a LongId, as does every source in a Vesta mutable (working) 00049 // directory tree. 00050 // 00051 class LongId { 00052 public: 00053 Byte32 value; 00054 00055 // Form the LongId of the indexth child of this source. 00056 // (1-origin) Return NullLongId if there is no room for more 00057 // children. Crash if invoked on NullLongId. 00058 LongId append(unsigned int index) const throw (); 00059 00060 // Form the LongId of the parent directory of this source. If 00061 // index is not NULL, also set *index to the index of this source 00062 // within its parent. Return NullLongId if this source has no 00063 // parent. 00064 LongId getParent(unsigned int* index =NULL) const throw (); 00065 00066 // Return true if this LongId is an ancestor of the given child. 00067 // A LongId is considered to be its own ancestor. 00068 bool isAncestorOf(const LongId& child) const throw (); 00069 00070 // Compare two LongIds 00071 bool operator==(const LongId& child) throw () { 00072 return memcmp(this->value.byte, child.value.byte, sizeof(Byte32)) == 0; 00073 }; 00074 00075 // Construct a LongId from a ShortId. If the ShortId belongs to 00076 // a file, the fingerprint must be supplied. If the ShortId 00077 // belongs to an immutable directory, the fingerprint is ignored; 00078 // the repository looks it up internally when the LongId is used. 00079 static LongId fromShortId(ShortId sid, const FP::Tag* fptag =NULL) 00080 throw (); 00081 00082 // Find the length of a LongId. When pickling and unpickling 00083 // LongIds, only the first "length" bytes need be pickled; the 00084 // rest are zeros (and must be filled with zeros upon unpickling). 00085 int length() const throw (); 00086 00087 // Look up LongId to get a VestaSource. Return NULL if this 00088 // LongId does not correspond to any extant source. The caller is 00089 // responsible for freeing the object returned. 00090 // 00091 // The following feature is available only inside the repository 00092 // address space: If lockKind == readLock, readLockV, writeLock, 00093 // or writeLockV, acquire the repository global read or write lock 00094 // on the directory tree that the LongId is in (either the stable 00095 // tree lock or a volatile tree lock), and return a pointer to the 00096 // correct lock. If lockKind == readLockV or writeLockV, the 00097 // caller already has the volatile root read lock, so it is not 00098 // acquired again during the call. If lockKind == checkLock, 00099 // check that the supplied lock pointer is the correct one for the 00100 // tree the LongId is in, and return NULL if it is not. If the 00101 // LongId represents a file ShortId, *lock is set to NULL, as no 00102 // tree lock is needed. 00103 // 00104 // The method can throw SRPC::failure only if used outside the 00105 // repository address space. 00106 // 00107 enum lockKindTag { readLock, writeLock, noLock, checkLock, 00108 readLockV, writeLockV }; 00109 VestaSource* lookup(lockKindTag lockKind =noLock, 00110 ReadersWritersLock** lock =NULL) 00111 throw (SRPC::failure); 00112 00113 // Check whether a LongId is valid. Returns false if lookup would 00114 // return NULL; true if it would return non-NULL . 00115 bool valid() throw (SRPC::failure); 00116 }; 00117 00118 extern const LongId RootLongId; // LongId of /vesta 00119 extern const LongId MutableRootLongId; 00120 extern const LongId VolatileRootLongId; 00121 extern const LongId DirShortIdRootLongId; 00122 extern const LongId FileShortIdRootLongId; 00123 extern const LongId NullLongId; // A known invalid LongId 00124 00125 // VestaSource is the base class for all types of Vesta source. 00126 00127 // The logical type of a VestaSource is given by a typeTag (see 00128 // below). Most of these types are discussed in the repository design 00129 // notes. 00130 00131 // The representation type (subclass) used for a VestaSource is 00132 // generally determined by its logical type and whether the source is 00133 // local or remote. The representation types include VLeaf, 00134 // VDirUnchangeable, VDirChangeable, VDirEvaluator, and VDirSurrogate. 00135 // Do not create an object of the base class. 00136 00137 // All these representations are in-memory data structures. The 00138 // on-disk representation of a directory is the repository log and 00139 // checkpoint. The on-disk representation of a ghost or stub is in 00140 // its parent directory. The on-disk representation of a file is 00141 // partly in its parent directory and partly in the file corresponding 00142 // to its ShortId. 00143 00144 // Here is how the representations are used. Note that some logical 00145 // types have multiple representations possible. 00146 00147 // Logical type Representation Notes 00148 // ------------ -------------- ----- 00149 // any source VDirSurrogate 1 00150 // immutableFile VLeaf 00151 // mutableFile VLeaf 00152 // immutableDirectory VDirChangeable 2 00153 // appendableDirectory VDirChangeable 00154 // mutableDirectory VDirChangeable 00155 // ghost VLeaf 00156 // stub VLeaf 00157 // deleted none 3 00158 // outdated none 3 00159 // volatileDirectory VDirChangeable 00160 // volatileROEDirectory VDirChangeable 00161 // evaluatorDirectory VDirEvaluator 4 00162 // evaluatorROEDirectory VDirEvaluator 4 00163 // device none 5 00164 // gap none 3 00165 // unused none 3 00166 00167 // 1) Used on the client side of the SRPC interface to the repository 00168 // server, for all sources. The "Dir" in the name is historical; the 00169 // type is no longer used only for directories. 00170 // 2) It was once intended to have a separate type VDirUnchangeable 00171 // for immutable directories, but that idea has been abandoned. 00172 // 3) These values are used inside the directory implementation, and 00173 // "deleted" may be returned by the listCallback if the caller has 00174 // asked to see a delta instead of a full directory. 00175 // 4) This is a kind of surrogate inside the repository server for a 00176 // "directory" that is really a binding in the evaluator value space. 00177 // 5) /dev/null implementation inside the repository NFS server. 00178 00179 // Note: Most methods have SRPC::failure in their throw () clauses, but 00180 // they can really throw this exception only in the subclass 00181 // VDirSurrogate. 00182 00183 class VestaSource : public VestaAttribs, public VRErrorCode { 00184 public: 00185 enum dupeCheck { dontReplace = 0, // Report error if name is in use. 00186 replaceDiff, // Replace existing object, if 00187 // any, with a different object 00188 // having the same name. 00189 replaceNonMaster // Replace existing object, if any, 00190 // with a different object 00191 // having the same name, unless 00192 // the existing object is master. 00193 }; 00194 enum typeTag { immutableFile=0, mutableFile, immutableDirectory, 00195 appendableDirectory, mutableDirectory, ghost, stub, 00196 deleted, outdated, volatileDirectory, 00197 evaluatorDirectory, device, volatileROEDirectory, 00198 evaluatorROEDirectory, gap, unused=15 }; 00199 00200 // The following two functions return pointers to static storage 00201 static const char* errorCodeString(errorCode err) throw (); 00202 static const char* typeTagString(typeTag type) throw (); 00203 static char typeTagChar(typeTag type) throw (); 00204 // immutable(f)ile, m(u)tableFile, (i)mmutableDirectory, 00205 // (a)ppendableDirectory, (m)utableDirectory, (g)host, (s)tub, 00206 // (d)eleted, (o)utdated, (v)olatileDirectory, (e)valuatorDirectory, 00207 // dev(n)ull, volatile(r)OEDirectory, eva(l)uatorROEDirectory, 00208 // ga(p), unused(x) 00209 00210 // Find roots. Outside the repository address space, the 00211 // parameters must be defaulted. 00212 static VestaSource* 00213 repositoryRoot(LongId::lockKindTag lockKind =LongId::noLock, 00214 ReadersWritersLock** lock =NULL) throw (SRPC::failure); 00215 static VestaSource* 00216 mutableRoot(LongId::lockKindTag lockKind =LongId::noLock, 00217 ReadersWritersLock** lock =NULL) throw (SRPC::failure); 00218 static VestaSource* 00219 volatileRoot(LongId::lockKindTag lockKind =LongId::noLock, 00220 ReadersWritersLock** lock =NULL) throw (SRPC::failure); 00221 00222 // The following fields should not be modified after initialization 00223 typeTag type; 00224 LongId longid; 00225 bool master; 00226 Bit32 pseudoInode; // See below 00227 FP::Tag fptag; // See below 00228 00229 // Server-side initialization. These methods are not 00230 // needed (or supplied) in the client-side implementation. 00231 // init() must be called before the first use of anything else in 00232 // this interface. recoveryDone() must be called after recovery 00233 // from the repository log is complete, to turn on logging of new 00234 // updates; it sets doLogging to true. 00235 static void init() throw (); 00236 static void recoveryDone() throw (); 00237 static bool doLogging; 00238 00239 // Someone else may have modified the representation that this 00240 // object points to, so discard any state cached in the object. 00241 virtual void resync(AccessControl::Identity who =NULL) 00242 throw (SRPC::failure); 00243 00244 // Get a VestaSource for the parent directory. Returns 0 if this 00245 // object has no parent directory. (Note: not implemented inside 00246 // the repository server.) 00247 VestaSource* getParent() throw (SRPC::failure); 00248 00249 // The following methods work only on files. If you call one on 00250 // a non-file, it will return an error, except as noted below. 00251 // These methods are meant only for remote, "arm's length" use by 00252 // the replicator: local processes with sufficient privilege can 00253 // obtain a file's ShortId and access it more efficiently through 00254 // the SourceOrDerived interface. These methods modify the 00255 // underlying ShortId file directly and immediately; they are not 00256 // part of the current failure-atomic transaction. 00257 00258 // Immutable or mutable files 00259 virtual errorCode 00260 read(void* buffer, /*INOUT*/int* nbytes, Basics::uint64 offset, 00261 AccessControl::Identity who =NULL) throw (SRPC::failure); 00262 // Read the entire file at once. Write its contents to the 00263 // specified ostream. (Note: not implemented inside the 00264 // repository server.) 00265 virtual errorCode 00266 readWhole(std::ostream &out, AccessControl::Identity who =NULL) 00267 throw (SRPC::failure); 00268 // Returns false for non-files: 00269 virtual bool executable() throw (SRPC::failure); 00270 // Returns 0 for non-files: 00271 virtual Basics::uint64 size() throw (SRPC::failure); 00272 00273 // Mutable files only 00274 virtual errorCode 00275 write(const void* buffer, /*INOUT*/int* nbytes, Basics::uint64 offset, 00276 AccessControl::Identity who =NULL) throw (SRPC::failure); 00277 virtual errorCode 00278 setExecutable(bool x, AccessControl::Identity who =NULL) 00279 throw (SRPC::failure); 00280 virtual errorCode 00281 setSize(Basics::uint64 s, AccessControl::Identity who =NULL) 00282 throw (SRPC::failure); 00283 00284 // The following methods work on both files and directories. 00285 00286 // Get the modified time. Returns "2" on ghosts and stubs. 00287 virtual time_t timestamp() throw (SRPC::failure); 00288 00289 // Set the modified time. No-op on ghosts and stubs. When 00290 // applied to a file, this method modifies the underlying ShortId 00291 // file directly and immediately; it is not part of the current 00292 // failure-atomic transaction. 00293 virtual errorCode 00294 setTimestamp(time_t ts, AccessControl::Identity who =NULL) 00295 throw (SRPC::failure); 00296 00297 // The following method works only on a file or immutable 00298 // directory. If you call it on another type of source, it will 00299 // return NullShortId. 00300 virtual ShortId shortId() throw (SRPC::failure); 00301 00302 // The following methods work only on directories. If you 00303 // call one on a non-directory, it will return notADirectory, 00304 // unless the specific comments state otherwise. In the methods 00305 // that take a timestamp argument, this value is used as the 00306 // modified time if supplied; otherwise the current time is used. 00307 00308 // Look up an Arc relative to this directory. Note that ".", 00309 // "..", and "" arcs are not understood at this layer. The 00310 // indexOffset argument to lookup() is for internal use only; 00311 // clients must always default it. The caller is responsible for 00312 // freeing the object returned in result. 00313 virtual errorCode 00314 lookup(Arc arc, VestaSource*& result, AccessControl::Identity who =NULL, 00315 unsigned int indexOffset =0) throw (SRPC::failure); 00316 00317 // Look up a pathname, consisting of arcs separated by 00318 // pathnameSep characters, relative to this directory. Again, 00319 // ".", "..", and "" arcs are not understood. Also, an initial 00320 // pathnameSep character does not specify the root. The caller is 00321 // responsible for freeing the object returned in result. 00322 virtual errorCode 00323 lookupPathname(const char* pathname, VestaSource*& result, 00324 AccessControl::Identity who =NULL, 00325 char pathnameSep =PathnameSep) throw (SRPC::failure); 00326 00327 // Find the indexth child of this directory. If arcbuf is not 00328 // NULL, the arc corresponding to the child found is returned in 00329 // the supplied buffer, which must be at least MAX_ARC_LEN+1 bytes 00330 // long. This method may indirect through a forwarding pointer 00331 // (if the indexth entry was renamed), so the LongId of the result may 00332 // be different from longid.append(index). The caller is 00333 // responsible for freeing the object returned in result. 00334 virtual errorCode lookupIndex(unsigned int index, VestaSource*& result, 00335 char* arcbuf =NULL) throw (SRPC::failure); 00336 00337 // Really delete this entry; do not leave a ghost. WARNING: do not 00338 // use on a master appendable directory, or the repository's guarantee 00339 // not to reuse a name with a different meaning can be violated. 00340 // If existCheck is false, the routine succeeds even if no entry by the 00341 // given name exists. 00342 virtual errorCode reallyDelete(Arc arc, AccessControl::Identity who =NULL, 00343 bool existCheck =true, 00344 time_t timestamp =0) throw (SRPC::failure); 00345 00346 // Insert an entry into the directory. The behavior if this name 00347 // is already bound depends on the dupeCheck parameter; see above. 00348 // If the newvs parameter is not NULL, a VestaSource object 00349 // referring to the new entry is returned there; the caller is 00350 // responsible for freeing this object. 00351 00352 // Link to an existing file by ShortId. Parent may be mutable, 00353 // appendable, or volatile (including volatileROE). Normally 00354 // fptag is NULL, but you can choose the fingerprint by setting it. 00355 virtual errorCode 00356 insertFile(Arc arc, ShortId sid, bool master, 00357 AccessControl::Identity who =NULL, 00358 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00359 time_t timestamp =0, FP::Tag* fptag =NULL) 00360 throw (SRPC::failure); 00361 // Mutable link to an existing or new file by ShortId. Parent must be 00362 // mutable or volatile (including volatileROE). If sid is NullShortId, 00363 // a new shortid is assigned and an empty file is created. 00364 virtual errorCode 00365 insertMutableFile(Arc arc, ShortId sid, bool master, 00366 AccessControl::Identity who =NULL, 00367 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00368 time_t timestamp =0) throw (SRPC::failure); 00369 // If dir is immutable, bind arc to it. If dir is mutable, bind 00370 // arc to a new immutableDirectory that is a deep copy of dir. If 00371 // dir is NULL, bind arc to an empty immutableDirectory. Parent 00372 // must be appendable or mutable. CheckIn and Advance use this method. 00373 // Normally fptag is NULL, but if dir is mutable or NULL, you can 00374 // choose the new directory's fingerprint by setting fptag. 00375 virtual errorCode 00376 insertImmutableDirectory(Arc arc, 00377 VestaSource* dir, bool master, 00378 AccessControl::Identity who =NULL, 00379 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00380 time_t timestamp =0, FP::Tag* fptag =NULL) 00381 throw (SRPC::failure); 00382 // Create new, empty appendableDirectory. Parent must be appendable. 00383 virtual errorCode 00384 insertAppendableDirectory(Arc arc, bool master, 00385 AccessControl::Identity who =NULL, 00386 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00387 time_t timestamp =0) throw (SRPC::failure); 00388 // Create new mutable (or volatile, or volatileROE) directory. 00389 // Parent must be mutable (or volatile, or volatileROE, 00390 // respectively). If dir is NULL, the new directory is empty; 00391 // otherwise, dir must be immutable, and the new directory is 00392 // initially a shallow copy of it. CheckOut uses this method. 00393 virtual errorCode 00394 insertMutableDirectory(Arc arc, VestaSource* dir, bool master, 00395 AccessControl::Identity who =NULL, 00396 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00397 time_t timestamp =0) throw (SRPC::failure); 00398 // Create new ghost. Parent must be appendable. 00399 virtual errorCode 00400 insertGhost(Arc arc, bool master, 00401 AccessControl::Identity who =NULL, 00402 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00403 time_t timestamp =0) throw (SRPC::failure); 00404 // Create new stub. Parent must be appendable. 00405 virtual errorCode 00406 insertStub(Arc arc, bool master, 00407 AccessControl::Identity who =NULL, 00408 dupeCheck chk=dontReplace, VestaSource** newvs =NULL, 00409 time_t timestamp =0) throw (SRPC::failure); 00410 00411 // Rename existing file or directory. Should be used only on 00412 // mutable or volatile/volatileROE directories. Currently also 00413 // works on appendable directories for backward compatibility 00414 // only; this functionality may be removed in the future. 00415 virtual errorCode 00416 renameTo(Arc arc, VestaSource* fromDir, Arc fromArc, 00417 AccessControl::Identity who =NULL, 00418 dupeCheck chk=dontReplace, time_t timestamp =0) 00419 throw (SRPC::failure); 00420 00421 // Directory listing. For each directory entry, beginning with 00422 // firstIndex, the callback is invoked with the corresponding 00423 // object's parameters. The shortid is provided only for files, 00424 // not directories, and is also omitted for files in an evaluator 00425 // directory (including the base of a volatile directory). If the 00426 // callback returns true, the listing is continued; if not, it is 00427 // stopped. Note that "." and ".." arcs are not understood at 00428 // this layer. You can get the LongId for ".." with 00429 // longid.getParent(). To list starting at the next entry after 00430 // one returned with index=i, begin with firstIndex=i+2. To list 00431 // starting at the first entry, begin with firstIndex=0. 00432 // 00433 // If deltaOnly is true for a mutable, volatile, or volatileROE 00434 // directory, only the changes with respect to the directory base 00435 // are shown; deletions are shown as arcs of type deleted. (In 00436 // a deleted arc may sometimes appear for a name that transiently 00437 // existed in the directory but never existed in the base.) 00438 // 00439 // The indexOffset argument is for internal use only; clients 00440 // must always default it. 00441 00442 typedef bool (*listCallback)(void* closure, typeTag type, Arc arc, 00443 unsigned int index, Bit32 pseudoInode, 00444 ShortId fileSid, bool master); 00445 virtual errorCode 00446 list(unsigned int firstIndex, listCallback callback, 00447 void* closure, AccessControl::Identity who =NULL, 00448 bool deltaOnly =false, unsigned int indexOffset =0) 00449 /*throw (SRPC::failure or anything thrown by the callback)*/; 00450 00451 // Acquire base of directory and return a new VestaSource object 00452 // for the base. The caller is responsible for freeing the 00453 // object returned. 00454 virtual errorCode 00455 getBase(VestaSource*& result, AccessControl::Identity who =NULL) 00456 throw (SRPC::failure); 00457 00458 // Replace an immutableFile or immutableDirectory with a mutable 00459 // (or volatile) one, and return a new VestaSource object for the 00460 // new source. The new source has the same name and (unlike 00461 // sources inserted with other methods) the same LongId as the old 00462 // source had. The source must be a descendent of MutableRoot (or 00463 // VolatileRoot). 00464 // 00465 // If the source parent is an immutable (or evaluator) directory, 00466 // the parent is made mutable (resp. volatile) recursively. If 00467 // the old source was a directory, the new source is a shallow 00468 // copy of the old one, as with insertMutableDirectory above. 00469 // 00470 // If the old source was a file, the caller may either supply the 00471 // ShortId of a new source, or supply NullShortId. In the latter 00472 // case, the repository assigns a new shortid and copies the first 00473 // copyMax bytes of the old data to it. 00474 // 00475 // It is an error to apply this method to a file whose LongId is 00476 // based on its ShortId; such LongIds are assigned explicitly by 00477 // LongId::fromShortId, or implicitly to files in directory trees 00478 // created by createVolatileDirectory with the readOnlyExisting 00479 // flag. 00480 // 00481 // On return, the old VestaSource object is invalid (but has not 00482 // been freed). The caller is responsible for freeing the object 00483 // returned. 00484 virtual errorCode 00485 makeMutable(VestaSource*& result, ShortId sid =NullShortId, 00486 Basics::uint64 copyMax = (Basics::uint64) -1, 00487 AccessControl::Identity who =NULL) 00488 throw (SRPC::failure); 00489 00490 // Similar to makeMutable, but doesn't make the object itself 00491 // mutable. This allows for adding attributes to an object in a 00492 // mutable directory without actually creating a mutable copy. As 00493 // with makeMutable, the new source has the same name and LongId 00494 // as the old source. The source must be a descendent of 00495 // MutableRoot. 00496 // 00497 // If the source parent is an immutable directory, the parent is 00498 // made mutable recursively. 00499 // 00500 // On return, the old VestaSource object is invalid (but has not 00501 // been freed). The caller is responsible for freeing the object 00502 // returned. 00503 virtual errorCode 00504 copyToMutable(VestaSource*& result, 00505 AccessControl::Identity who =NULL) 00506 throw (SRPC::failure); 00507 00508 // Make files in a directory tree immutable and optionally 00509 // cause their fingerprints to be based on content. 00510 // The object must be a mutable, volatile, or volatileROE 00511 // directory, or a mutable file. Walks the directory tree rooted 00512 // at the object and examines each mutable file. If a mutable 00513 // file is less than threshold bytes long, it is made immutable 00514 // with a fingerprint computed based on its content. Otherwise, 00515 // if the directory is volatile[ROE], the file is made immutable 00516 // with a fingerprint based on its preassigned unique id. 00517 // Otherwise (i.e., if the file is threshold or more bytes long 00518 // and the directory is mutable), the file remains mutable and a 00519 // fingerprint is not assigned yet. A threshold of (unsigned int) 00520 // -1 is "infinity". 00521 // 00522 // This method must be used at the end of every tool invocation, 00523 // to ensure that the files created will really be read-only in 00524 // volatileROE directories created later. It is also used by 00525 // vadvance to implement the -F flag. 00526 // 00527 virtual errorCode 00528 makeFilesImmutable(unsigned int threshold, 00529 AccessControl::Identity who =NULL) 00530 throw (SRPC::failure); 00531 00532 // Turn the master flag on or off. Use with care to preserve the 00533 // replication invariants! setMaster is a convenience method 00534 // implemented on top of setIndexMaster. Subclasses need only 00535 // provide the latter. 00536 virtual errorCode setMaster(bool state, 00537 AccessControl::Identity who =NULL) 00538 throw (SRPC::failure); 00539 virtual errorCode setIndexMaster(unsigned int index, bool state, 00540 AccessControl::Identity who =NULL) 00541 throw (SRPC::failure); 00542 00543 // Find out which repository this VestaSource is in 00544 virtual Text host() throw (); 00545 virtual Text port() throw (); 00546 00547 // The following method should be called only from inside the 00548 // repository that is acquiring mastership, not from ordinary clients. 00549 // See Mastership.C. Caller is responsible for freeing *grantidOut. 00550 virtual errorCode 00551 cedeMastership(const char* requestid, const char** grantidOut, 00552 AccessControl::Identity who =NULL) throw (SRPC::failure); 00553 00554 // Access control 00555 AccessControl ac; 00556 00557 // The following methods give an assertion failure if applied to 00558 // a nondirectory. 00559 00560 // Methods for use in source weeding (garbage collection). 00561 // Cannot be used outside the repository address space. 00562 virtual bool hasName() throw (); 00563 virtual void setHasName(bool val) throw (); 00564 virtual bool visited() throw (); 00565 virtual void setVisited(bool val) throw (); 00566 virtual void mark(bool byName =true, ArcTable* hidden =NULL) throw(); 00567 00568 // Method for explicit free of directory tree. The object must 00569 // be a volatile or evaluator directory. Used to reclaim memory 00570 // allocated to volatile directory trees eagerly instead of 00571 // waiting for the next source weed. The caller guarantees that 00572 // there are no references to this rep or any of its substructure 00573 // from outside the tree. Cannot be used outside the repository 00574 // address space. 00575 virtual void freeTree() throw (); 00576 00577 // Method for checkpointing. nextSP is the new short pointer 00578 // that the next item written to the checkpoint file will receive. 00579 // The method increments nextSP by the number of bytes it writes 00580 // into the checkpoint. The new short pointer for this object is 00581 // returned. Cannot be used outside the repository address space. 00582 virtual Bit32 checkpoint(Bit32& nextSP, std::fstream& ckpt) throw (); 00583 00584 // Utility method for generating pseudo-inode numbers. 00585 // Should not be used outside the repository address space. 00586 inline Bit32 indexToPseudoInode(unsigned int index) throw (){ 00587 return 0x7fffffff & (((pseudoInode << 8) | (pseudoInode >> 23)) + index); 00588 } 00589 00590 // 00591 // Convenience wrappers around writeAttrib 00592 // 00593 00594 // opSet: Bind name to the singleton set {value}. Equivalent to clear 00595 // followed by add, but atomic even in the presence of other 00596 // changes with the same timestamp. 00597 inline VRErrorCode::errorCode 00598 setAttrib(const char* name, const char* value, 00599 AccessControl::Identity who =NULL, 00600 time_t timestamp =0) throw (SRPC::failure) 00601 { return writeAttrib(opSet, name, value, who, timestamp); }; 00602 00603 // opClear: Bind name to the empty set; i.e., unbind it. 00604 // Client should pass "" as value. 00605 inline VRErrorCode::errorCode 00606 clearAttrib(const char* name, AccessControl::Identity who =NULL, 00607 time_t timestamp =0) throw (SRPC::failure) 00608 { return writeAttrib(opClear, name, "", who, timestamp); }; 00609 00610 // opAdd: Add value to the set that is bound to name. 00611 inline VRErrorCode::errorCode 00612 addAttrib(const char* name, const char* value, 00613 AccessControl::Identity who =NULL, 00614 time_t timestamp =0) throw (SRPC::failure) 00615 { return writeAttrib(opAdd, name, value, who, timestamp); }; 00616 00617 // opRemove: Remove value from the set that is bound to name, if present. 00618 inline VRErrorCode::errorCode 00619 removeAttrib(const char* name, const char* value, 00620 AccessControl::Identity who =NULL, 00621 time_t timestamp =0) throw (SRPC::failure) 00622 { return writeAttrib(opRemove, name, value, who, timestamp); }; 00623 00624 // Our own version of VestaAttribs::writeAttrib. This one does 00625 // access checking and logging; the base class's method does not. 00626 // The method is a no-op if this source does not have attributes. 00627 virtual errorCode 00628 writeAttrib(attribOp op, const char* name, const char* value, 00629 AccessControl::Identity who =NULL, time_t timestamp =0) 00630 throw (SRPC::failure); 00631 00632 // Statistics primarily intended for VDirChangeable. Other object 00633 // types return inapproprateOp. 00634 struct directoryStats 00635 { 00636 Basics::uint32 00637 // A mutable/immutable directory can be based on another, in 00638 // which case it represents a delta over the base. (See 00639 // getBase above.) This measurement tells you how long the 00640 // chain of base directories is. 00641 baseChainLength, 00642 // When one directory is based on another, only some of 00643 // directory entries along the base chain will be used to make 00644 // up the directory at the head. However, the repository must 00645 // walk along all of these entries when listing the directory. 00646 // These measurements give the number and size in bytes of 00647 // directory entries used by the directory at the head and by 00648 // all directories along the base chain. 00649 usedEntryCount, 00650 usedEntrySize, 00651 totalEntryCount, 00652 totalEntrySize; 00653 }; 00654 virtual errorCode 00655 measureDirectory(/*OUT*/directoryStats &result, 00656 AccessControl::Identity who =NULL) 00657 throw (SRPC::failure); 00658 00659 // Special method for immutable directories. Causes the base 00660 // directory of this directory to be collapsed, eliminating some 00661 // amount of directory delta encoding, which may make some 00662 // operations (lookup, directory listing, changes) more efficient. 00663 virtual errorCode 00664 collapseBase(AccessControl::Identity who =NULL) 00665 throw (SRPC::failure); 00666 00667 // Get the number of links to a file. Returns 1 except for mutable 00668 // files in directories which support hard links. 00669 virtual unsigned int linkCount(); 00670 00671 // Create a duplicate of this instance of the appropriate subclass. 00672 virtual VestaSource *copy() throw(); 00673 00674 virtual ~VestaSource() { } 00675 00676 public: 00677 Bit8* rep; 00678 }; 00679 00680 // FILEHANDLE PERSISTENCE 00681 00682 // The longid of a source is used as its NFS filehandle. NFS 00683 // filehandles have one property that longids do not share: an object 00684 // is supposed to keep the same filehandle despite renaming or 00685 // copy-on-write. We use two mechanisms to ensure this. 00686 00687 // 1) A VForward pointer keeps the old longid of a renamed object 00688 // working as long as its old parent directory is not deleted. 00689 // Opening the object under its new name gives a new longid. This 00690 // seems to work well enough in practice. 00691 00692 // 2) After copy-on-write, the new directory entry has a "sameAsBase" 00693 // flag set, indicating that it should appear to have the longid of 00694 // the newest object of the same name in the base rather than its own 00695 // natural longid. The object is accessible under its own longid as 00696 // well, but this longid is never actually used. 00697 00698 // PSEUDO-INODE NUMBERS 00699 00700 // The pseudo-inode number of a source is presented through the NFS 00701 // interface as its inode number. 00702 00703 // Some NFS clients expect every file and directory to have a unique 00704 // and persistent inode number, not just a 32-byte NFS file handle 00705 // (longid). Even though inode numbers cannot be used for lookup 00706 // through the NFS interface, some clients use the inode number to 00707 // index their cache and/or check it for consistency; in particular, 00708 // the Linux 2.2 NFS client is quite fussy about inode numbers. 00709 00710 // These requirements are difficult to meet in Vesta for several 00711 // reasons. There is no truly unique 32-bit identifier across all 00712 // types of object that can appear in Vesta directories. One cannot 00713 // simply use the 32-bit shortid, for several reasons: (1) Only files 00714 // and immutable directories have shortids. (2) A file changes its 00715 // shortid when copy-on-write occurs. (3) The same immutable 00716 // directory can (and frequently does) appear in multiple places in 00717 // the hierarchy, with either the same or different parent. Each 00718 // instance has a different filehandle (since its virtual ".." link is 00719 // different), but the same shortid. 00720 00721 // Here are the measures taken to alleviate (but not fully solve) 00722 // these problems. 00723 00724 // The pseudo-inode number of a file that is not subject to 00725 // copy-on-write is its shortid. This includes files in the appendable 00726 // tree and files in volatileROE or evaluatorROE directories. 00727 00728 // The pseudo-inode number of a mutable, volatile, or volatileROE 00729 // directory is stored in its representation and remains the same 00730 // across renamings. For a directory that is created by 00731 // copy-on-write, the pseudo-inode number is initialized to that of 00732 // the base directory; otherwise it is initialized as described in the 00733 // next paragraph. 00734 00735 // The pseudo-inode number of any other source is a 31-bit hash of its 00736 // longid, computed incrementally on the sequence of indices. The 00737 // high-order bit of the hash is set to 0 to prevent collisions with 00738 // file shortids. 00739 00740 // With the scheme above, pseudo-inode number collisions should be 00741 // infrequent, but they can occur. The known problems that collisions 00742 // can cause are: 00743 00744 // 1) If two directories with the same inode number appear in the same 00745 // parent directory, some implementations of the Unix "pwd" program or 00746 // "getwd" library routine will return the wrong answer when asked for 00747 // the name of the second of them (or of one of the descendants of the 00748 // latter). The hash function used does an excellent job of 00749 // preventing collisions within the same parent directory, however. 00750 00751 // 2) If two different objects with the same inode number are accessed 00752 // by the same client fairly close together in time, and the client 00753 // indexes its cache by inode instead of file handle, cached 00754 // information about the first might be erroneously accepted as 00755 // applying to the second. (On Linux 2.2, this case seems to cause 00756 // confusion only if both objects are directories. On Tru64 Unix, 00757 // it seems never to cause a problem.) It would be nice to have a 00758 // solution that makes this error impossible instead of just very 00759 // unlikely. 00760 00761 // FINGERPRINTS 00762 00763 // The repository maintains fingerprints (type FP::Tag) of some 00764 // sources for use by the evaluator. 00765 00766 // The appendable tree rooted at repositoryRoot keeps a fingerprint 00767 // for every immutableDirectory and immutableFile. Repository 00768 // operations return a source fingerprint in the VestaSource::fptag 00769 // field. Ghosts, stubs, and appendableDirectories do not have 00770 // fingerprints; their fptag fields contain FP::Tag(""). 00771 00772 // Two sources with different contents are guaranteed to have 00773 // different fingerprints. Two sources with the same content may or 00774 // may not have the same fingerprint. A source acquires a fingerprint 00775 // based on the pathname under which it is first placed in the 00776 // appendable part of the repository. That fingerprint stays with it 00777 // as the same source acquires new names via the checkin/advance/ 00778 // checkout cycle or by renaming in an appendable directory. (But see 00779 // below.) 00780 00781 // The mutable tree does not keep fingerprints for its sources. The 00782 // fptag field of a source looked up in the mutable tree is 00783 // unspecified. 00784 00785 // Volatile directory trees keep a fingerprint for every file, but no 00786 // fingerprints for directories; the fptag field of a volatile (or 00787 // evaluator) directory is unspecified. 00788 00789 // Fingerprints for existing files in a volatile directory (that is, 00790 // files in the base evaluator directory) are obtained from the 00791 // evaluator. When a new file is created, an arbitrary unique id 00792 // number is generated for it and the fingerprint of that value is 00793 // used. 00794 00795 // A mutable file's fingerprint can be recomputed to be based on its 00796 // content by calling makeFilesImmutable with the proper arguments. 00797 // This applies both to new files in mutable directories and new files 00798 // in volatile directories. 00799 00800 #endif //_VSOURCE