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 // VestaAttribs.H 00021 // 00022 // Mutable attributes for Vesta sources. 00023 // 00024 00025 #ifndef _VATTR 00026 #define _VATTR 1 00027 00028 #include "Basics.H" 00029 #include "VRErrorCode.H" 00030 #include "SRPC.H" 00031 00032 class VestaAttribs { 00033 00034 // A VestaSource has mutable attributes if it or its parent directory 00035 // is appendable or mutable. 00036 00037 // At the highest level of abstraction (the "function" level), the 00038 // attributes of a Vesta source are a total function F from strings 00039 // (names) to sets of strings (values). Initially every string is 00040 // bound to the empty set of values. Operations are available to read 00041 // and write the current state. Abstractly, there is just one read 00042 // operation, which returns F. The write operations are: 00043 // 00044 // set(name, value) // F(name) = {value} 00045 // clear(name) // F(name) = {} 00046 // add(name, value) // F(name) = F(name) u {value} 00047 // remove(name, value) // F(name) = F(name) - {value} 00048 // 00049 00050 // At a lower level of abstraction (the "history" level), the write 00051 // operations include a timestamp argument in addition to the 00052 // arguments listed above, and the abstract state is the set H of 00053 // all write operations that have been requested, called the 00054 // history. 00055 00056 // The operation to read F remains. This F(H) is computed by sorting 00057 // the history H into timestamp order, with ties broken by taking the 00058 // operation, name, and value as secondary sort keys, and applying the 00059 // resulting sequence of operations to the empty function. 00060 00061 // Also provided is an operation to return a history, but this 00062 // operation does not necessarily return H. Rather, it returns some 00063 // history K that is *equivalent* to H, in the following sense. 00064 // Histories H and K are equivalent if for any history L, 00065 // F(H u L) = F(K u L). That is, K might as well have been the real 00066 // history, because one cannot tell the difference by observing the 00067 // present and future behavior of F. 00068 00069 // Note: As you might guess, the implementation does not really store 00070 // H, but rather stores an equivalent history K that is smaller, and 00071 // it is this history that is returned by the history operation. 00072 // There are some additional invariants on K that are important only 00073 // inside the implementation, and are described in the .C file. 00074 00075 // The history level is present to support partial replication. If 00076 // operations are done independently to two objects (in particular, 00077 // two objects at different sites that are considered partial replicas 00078 // of one another), the changes can later be merged with well-defined 00079 // results. 00080 00081 public: 00082 enum attribOp { opSet = 0, opClear, opAdd, opRemove }; 00083 // Warning: the implementation relies on the ordering of this type, 00084 // and the log relies on the integer values. Do not change it. 00085 00086 // The following function returns a pointer to static storage 00087 static const char* attribOpString(attribOp op) throw (); 00088 // (s)et, (c)lear, (a)dd, (r)emove: 00089 static char attribOpChar(attribOp op) throw (); 00090 00091 00092 typedef bool (*valueCallback)(void* closure, const char* value); 00093 typedef bool (*historyCallback)(void* closure, attribOp op, 00094 const char* name, const char* value, 00095 time_t timestamp); 00096 00097 // attribs is actually a VestaAttribsRep@*, unaligned. 00098 Bit8* attribs; 00099 00100 inline bool hasAttribs() throw () { return attribs != NULL; } 00101 00102 // Methods to read the current state of the attributes. 00103 00104 // Is value a member of the set bound to name? Always returns 00105 // false if this source does not have attributes. 00106 virtual bool inAttribs(const char* name, const char* value) 00107 throw (SRPC::failure); 00108 00109 // If name is bound to {} (or this source does not have 00110 // attributes), return NULL. If name is bound to the singleton 00111 // set {value}, return value. If name is bound to a set 00112 // containing more than one element, return some value in the set; 00113 // it is unspecified which value is returned. The caller is 00114 // responsible for freeing the storage returned by getAttrib. 00115 // getAttribConst (available only within the repository server 00116 // address space) avoids allocating storage, but the return value 00117 // is guaranteed valid only as long as the caller holds the 00118 // repository read lock. 00119 virtual char* getAttrib(const char* name) throw (SRPC::failure); 00120 const char* getAttribConst(const char* name) throw (); //private 00121 00122 // Call cb once for each element in the value set bound to name. 00123 // If the callback returns true, the listing is continued; if not, 00124 // it is stopped. If this source does not have attributes, returns 00125 // the empty set. 00126 virtual void getAttrib(const char* name, valueCallback cb, void* cl) 00127 /*throw (SRPC::failure or anything thrown by the callback)*/; 00128 00129 // Call cb once for each name that is bound to a nonempty value 00130 // set. If the callback returns true, the listing is continued; 00131 // if not, it is stopped. If this source does not have 00132 // attributes, returns the empty set. 00133 virtual void listAttribs(valueCallback cb, void* cl) 00134 /*throw (SRPC::failure or anything thrown by the callback)*/; 00135 00136 // Lower-level method to read the recorded history K. Calls cb 00137 // once for each write in the recorded history. If the callback 00138 // returns true, the listing is continued; if not, it is stopped. 00139 // Write operations are returned in an unspecified order. If this 00140 // source does not have attributes, returns the empty set. 00141 virtual void getAttribHistory(historyCallback cb, void* cl) 00142 /*throw (SRPC::failure or anything thrown by the callback)*/; 00143 00144 // Write method. Ordinary clients should default the timestamp 00145 // argument; that is, they should view the attributes at the 00146 // function level of abstraction. (If the timestamp is zero, the 00147 // current time is used, possibly adding a small increment to keep 00148 // this change from sorting after existing attribute history 00149 // records. If the timestamp is defaulted, timestamp will be 00150 // updated with the time which was actually used.) 00151 // 00152 // opSet: Bind name to the singleton set {value}. Equivalent to clear 00153 // followed by add, but atomic even in the presence of other 00154 // changes with the same timestamp. 00155 // opClear: Bind name to the empty set; i.e., unbind it. 00156 // Client should pass "" as value. 00157 // opAdd: Add value to the set that is bound to name. 00158 // opRemove: Remove value from the set that is bound to name, if present. 00159 // 00160 // (Note: May return nameInUse if the write has no effect. This 00161 // is not an error, it just tells the caller not to log this 00162 // operation as a change.) 00163 VRErrorCode::errorCode 00164 writeAttrib(attribOp op, const char* name, 00165 const char* value, /*INOUT*/ time_t ×tamp) throw (); 00166 00167 // Low-level routines that work only inside the repository 00168 // address space: 00169 00170 // Test whether calling writeAttrib with the given arguments would 00171 // change K, but don't actually change it. (As with writeAttrib, 00172 // if timestamp os zero it will be defaulted and updated with the 00173 // time used.) 00174 bool wouldWriteAttrib(attribOp op, const char* name, 00175 const char* value, 00176 /*INOUT*/ time_t ×tamp) throw (); 00177 00178 // Return a short pointer to the first VestaAttribsRep 00179 Bit32 firstAttrib() throw (); 00180 // Set the first VestaAttribsRep 00181 void setFirstAttrib(Bit32 newval) throw (); 00182 // Make a copy of the attribs of an object. Accepts and returns 00183 // a VestaAttribsRep@. 00184 static Bit32 copyAttribs(Bit32 from) throw(); 00185 }; 00186 00187 #endif //_VATTR