OpenAFS
OpenAFS distributed network file system
|
00001 /* 00002 * Copyright 2007 Secure Endpoints Inc. 00003 * 00004 * All Rights Reserved. 00005 * 00006 * This software has been released under the terms of the IBM Public 00007 * License. For details, see the LICENSE file in the top-level source 00008 * directory or online at http://www.openafs.org/dl/license10.html 00009 * 00010 * Thanks to Jan Jannink for B+ tree algorithms. 00011 */ 00012 00013 #ifndef BPLUSTREE_H 00014 #define BPLUSTREE_H 1 00015 00016 /******** flag bits (5 of 16 used, 11 for magic value) ********/ 00017 00018 /* bits set at node creation/split/merge */ 00019 #define isLEAF 0x01 00020 #define isROOT 0x02 00021 #define isDATA 0x04 00022 00023 /* bits set at key insertion/deletion */ 00024 #define isFULL 0x08 00025 #define FEWEST 0x10 00026 #define FLAGS_MASK 0xFF 00027 00028 /* identifies data as being a B+tree node */ 00029 #define BTREE_MAGIC 0xBEE0BEE0 00030 #define BTREE_MAGIC_MASK 0xFFFFFFFF 00031 00032 00033 /************************* constants ************************/ 00034 00035 /* The maximum number of Entrys in one Node */ 00036 #define MAX_FANOUT 9 00037 00038 /* corresponds to a NULL node pointer value */ 00039 #define NONODE NULL 00040 00041 /* special node slot values used in key search */ 00042 #define BTERROR -1 00043 #define BTUPPER -2 00044 #define BTLOWER -3 00045 00046 00047 /************************* Data Types **********************************/ 00048 typedef struct node *Nptr; 00049 00050 typedef struct key { 00051 normchar_t *name; /* Normalized name */ 00052 } keyT; 00053 00054 typedef struct dirdata { 00055 cm_fid_t fid; 00056 int shortform; /* This is the short form entry. If 00057 this value is non-zero, then there 00058 is another entry in the B-Plus tree 00059 corresponding to the long name of 00060 this fid. */ 00061 clientchar_t *cname; /* Client name (long) */ 00062 fschar_t * fsname; /* FileServer name */ 00063 } dataT; 00064 00065 typedef struct entry { 00066 keyT key; 00067 Nptr downNode; 00068 } Entry; 00069 00070 typedef struct inner { 00071 short pairs; 00072 Nptr firstNode; 00073 } Inner; 00074 00075 00076 typedef struct leaf { 00077 short pairs; 00078 Nptr nextNode; 00079 } Leaf; 00080 00081 typedef struct btree_data { 00082 keyT key; 00083 dataT value; 00084 Nptr next; 00085 } Data; 00086 00087 typedef struct node { 00088 Nptr pool; 00089 unsigned short number; 00090 unsigned short flags; 00091 unsigned long magic; 00092 union { 00093 Entry e[MAX_FANOUT]; /* allows access to entry array */ 00094 Inner i; 00095 Leaf l; 00096 Data d; 00097 } X; 00098 } Node; 00099 00100 00101 typedef int (*KeyCmp)(keyT, keyT, int); 00102 #define EXACT_MATCH 0x01 00103 00104 00105 typedef struct tree { 00106 unsigned int flags; /* tree flags */ 00107 unsigned int poolsize; /* # of nodes allocated for tree */ 00108 Nptr root; /* pointer to root node */ 00109 Nptr leaf; /* pointer to first leaf node in B+tree */ 00110 unsigned int fanout; /* # of pointers to other nodes */ 00111 unsigned int minfanout; /* usually minfanout == ceil(fanout/2) */ 00112 unsigned int height; /* nodes traversed from root to leaves */ 00113 Nptr pool; /* list of all nodes */ 00114 Nptr empty; /* list of empty nodes */ 00115 union { /* nodes to change in insert and delete */ 00116 Nptr split; /* protected by scp->dirlock write-lock */ 00117 Nptr merge; 00118 } branch; 00119 KeyCmp keycmp; /* pointer to function comparing two keys */ 00120 char message[1024]; 00121 } Tree; 00122 00123 #define TREE_FLAGS_MASK 0x01 00124 #define TREE_FLAG_UNIQUE_KEYS 0x01 00125 00126 /************************* B+ tree Public functions ****************/ 00127 Tree *initBtree(unsigned int poolsz, unsigned int fan, KeyCmp keyCmp); 00128 void freeBtree(Tree *B); 00129 00130 #ifdef DEBUG_BTREE 00131 void showNode(Tree *B, const char * str, Nptr node); 00132 void showBtree(Tree *B); 00133 void listBtreeValues(Tree *B, Nptr start, int count); 00134 void listAllBtreeValues(Tree *B); 00135 void listBtreeNodes(Tree *B, const char * where, Nptr node); 00136 void findAllBtreeValues(Tree *B); 00137 #endif 00138 00139 void insert(Tree *B, keyT key, dataT data); 00140 void delete(Tree *B, keyT key); 00141 Nptr lookup(Tree *B, keyT key); 00142 00143 /******************* cache manager directory operations ***************/ 00144 00145 int cm_BPlusCompareNormalizedKeys(keyT key1, keyT key2, int flags); 00146 int cm_BPlusDirLookup(cm_dirOp_t * op, clientchar_t *entry, cm_fid_t * cfid); 00147 int cm_BPlusDirLookupOriginalName(cm_dirOp_t * op, clientchar_t *entry, fschar_t **originalNameRetp); 00148 long cm_BPlusDirCreateEntry(cm_dirOp_t * op, clientchar_t *entry, cm_fid_t * cfid); 00149 int cm_BPlusDirDeleteEntry(cm_dirOp_t * op, clientchar_t *entry); 00150 long cm_BPlusDirBuildTree(cm_scache_t *scp, cm_user_t *userp, cm_req_t* reqp); 00151 int cm_BPlusDirFoo(struct cm_scache *scp, struct cm_dirEntry *dep, void *dummy, osi_hyper_t *entryOffsetp); 00152 void cm_BPlusDumpStats(void); 00153 int cm_MemDumpBPlusStats(FILE *outputFile, char *cookie, int lock); 00154 00155 /******************* directory enumeration operations ****************/ 00156 typedef struct cm_direnum_entry { 00157 clientchar_t *name; 00158 cm_fid_t fid; 00159 normchar_t shortName[13]; 00160 afs_uint32 flags; 00161 afs_uint32 errorCode; 00162 } cm_direnum_entry_t; 00163 00164 #define CM_DIRENUM_FLAG_GOT_STATUS 1 00165 00166 typedef struct cm_direnum { 00167 cm_scache_t *dscp; 00168 cm_user_t *userp; 00169 afs_uint64 dataVersion; /* enumeration snapshot dir version */ 00170 afs_uint32 reqFlags; 00171 afs_uint32 count; 00172 afs_uint32 next; 00173 afs_uint32 fetchStatus; 00174 cm_direnum_entry_t entry[1]; 00175 } cm_direnum_t; 00176 00177 long cm_BPlusDirEnumerate(cm_scache_t *dscp, cm_user_t *userp, cm_req_t *reqp, 00178 afs_uint32 locked, clientchar_t *maskp, afs_uint32 fetchStatus, cm_direnum_t **enumpp); 00179 long cm_BPlusDirNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp); 00180 long cm_BPlusDirPeekNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp); 00181 long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump); 00182 long cm_BPlusDirEnumTest(cm_scache_t * dscp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked); 00183 long cm_BPlusDirEnumBulkStat(cm_direnum_t *enump); 00184 long cm_BPlusDirEnumBulkStatOne(cm_direnum_t *enump, cm_scache_t *scp); 00185 00186 long cm_InitBPlusDir(void); 00187 00188 /************ Statistic Counter ***************************************/ 00189 00190 extern afs_uint32 bplus_free_tree; 00191 extern afs_uint32 bplus_dv_error; 00192 extern afs_uint64 bplus_free_time; 00193 00194 00195 /************ Accessor Macros *****************************************/ 00196 00197 /* low level definition of Nptr value usage */ 00198 #define nAdr(n) (n)->X 00199 00200 /* access keys and pointers in a node */ 00201 #define getkey(j, q) (nAdr(j).e[(q)].key) 00202 #define getnode(j, q) (nAdr(j).e[(q)].downNode) 00203 #define setkey(j, q, v) ((q > 0) ? nAdr(j).e[(q)].key.name = cm_NormStrDup((v).name) : NULL) 00204 #define setnode(j, q, v) (nAdr(j).e[(q)].downNode = (v)) 00205 00206 /* access tree flag values */ 00207 #define settreeflags(B,v) (B->flags |= (v & TREE_FLAGS_MASK)) 00208 #define gettreeflags(B) (B->flags) 00209 #define cleartreeflags(B) (B->flags = 0); 00210 00211 /* access node flag values */ 00212 #define setflag(j, v) ((j)->flags |= (v & FLAGS_MASK)) 00213 #define clrflag(j, v) ((j)->flags &= ~(v & FLAGS_MASK)) 00214 #define getflags(j) ((j)->flags & FLAGS_MASK) 00215 #define getmagic(j) ((j)->magic & BTREE_MAGIC_MASK) 00216 #define clearflags(j) ((j)->flags = 0, (j)->magic = BTREE_MAGIC) 00217 00218 00219 /* check that a node is in fact a node */ 00220 #define isnode(j) (((j) != NONODE) && (((j)->magic & BTREE_MAGIC_MASK) == BTREE_MAGIC) && !((j)->flags & isDATA)) 00221 #define isntnode(j) ((j) == NONODE) 00222 00223 00224 /* test individual flag values */ 00225 #define isinternal(j) (((j)->flags & isLEAF) == 0) 00226 #define isleaf(j) (((j)->flags & isLEAF) == isLEAF) 00227 #define isdata(j) (((j)->flags & isDATA) == isDATA) 00228 #ifndef DEBUG_BTREE 00229 #define isroot(j) (((j)->flags & isROOT) == isROOT) 00230 #define isfull(j) (((j)->flags & isFULL) == isFULL) 00231 #define isfew(j) (((j)->flags & FEWEST) == FEWEST) 00232 #else 00233 #define isroot(j) _isRoot(B, j) 00234 #define isfew(j) _isFew(B, j) 00235 #define isfull(j) _isFull(B, j) 00236 #endif 00237 00238 /* manage number of keys in a node */ 00239 #define numentries(j) (nAdr(j).i.pairs) 00240 #define clearentries(j) (nAdr(j).i.pairs = 0) 00241 #define incentries(j) (nAdr(j).i.pairs++) 00242 #define decentries(j) (nAdr(j).i.pairs--) 00243 00244 00245 /* manage first/last node pointers in internal nodes */ 00246 #define setfirstnode(j, v) (nAdr(j).i.firstNode = (v)) 00247 #define getfirstnode(j) (nAdr(j).i.firstNode) 00248 #define getlastnode(j) (nAdr(j).e[nAdr(j).i.pairs].downNode) 00249 00250 00251 /* manage pointers to next nodes in leaf nodes */ 00252 /* also used for free nodes list */ 00253 #define setnextnode(j, v) (nAdr(j).l.nextNode = (v)) 00254 #define getnextnode(j) (nAdr(j).l.nextNode) 00255 00256 /* manage pointers to all nodes list */ 00257 #define setallnode(j, v) ((j)->pool = (v)) 00258 #define getallnode(j) ((j)->pool) 00259 00260 /* manage access to data nodes */ 00261 #define getdata(j) (nAdr(j).d) 00262 #define getdatavalue(j) (getdata(j).value) 00263 #define getdatakey(j) (getdata(j).key) 00264 #define getdatanext(j) (getdata(j).next) 00265 00266 /* shift/transfer entries for insertion/deletion */ 00267 #define clrentry(j, q) _clrentry(j,q) 00268 #define pushentry(j, q, v) _pushentry(j, q, v) 00269 #define pullentry(j, q, v) _pullentry(j, q, v) 00270 #define xferentry(j, q, v, z) _xferentry(j, q, v, z) 00271 #define setentry(j, q, v, z) _setentry(j, q, v, z) 00272 00273 /* define number of B+tree nodes for free node pool */ 00274 #define getpoolsize(B) ((B)->poolsize) 00275 #define setpoolsize(B,v) ((B)->poolsize = (v)) 00276 00277 /* locations from which tree access begins */ 00278 #define getroot(B) ((B)->root) 00279 #define setroot(B,v) ((B)->root = (v)) 00280 #define getleaf(B) ((B)->leaf) 00281 #define setleaf(B,v) ((B)->leaf = (v)) 00282 00283 /* define max/min number of pointers per node */ 00284 #define getfanout(B) ((B)->fanout) 00285 #define setfanout(B,v) ((B)->fanout = (v) - 1) 00286 #define getminfanout(B,j) (isroot(j) ? (isleaf(j) ? 0 : 1) : (isleaf(j) ? (B)->fanout - (B)->minfanout: (B)->minfanout)) 00287 #define setminfanout(B,v) ((B)->minfanout = (v) - 1) 00288 00289 /* manage B+tree height */ 00290 #define inittreeheight(B) ((B)->height = 0) 00291 #define inctreeheight(B) ((B)->height++) 00292 #define dectreeheight(B) ((B)->height--) 00293 #define gettreeheight(B) ((B)->height) 00294 00295 /* access pool of free nodes */ 00296 #define getfirstfreenode(B) ((B)->empty) 00297 #define setfirstfreenode(B,v) ((B)->empty = (v)) 00298 00299 /* access all node list */ 00300 #define getfirstallnode(B) ((B)->pool) 00301 #define setfirstallnode(B,v) ((B)->pool = (v)) 00302 00303 /* handle split/merge points during insert/delete */ 00304 #define getsplitpath(B) ((B)->branch.split) 00305 #define setsplitpath(B,v) ((B)->branch.split = (v)) 00306 #define getmergepath(B) ((B)->branch.merge) 00307 #define setmergepath(B,v) ((B)->branch.merge = (v)) 00308 00309 /* exploit function to compare two B+tree keys */ 00310 #define comparekeys(B) (*(B)->keycmp) 00311 #define setcomparekeys(B,v) ((B)->keycmp = (v)) 00312 00313 /* location containing B+tree class variables */ 00314 #define setbplustree(B,v) ((B) = (Tree *)(v)) 00315 00316 /* representation independent node numbering */ 00317 #define setnodenumber(B,v,q) ((v)->number = (q)) 00318 #define getnodenumber(B,v) ((v) != NONODE ? (v)->number : -1) 00319 00320 #endif /* BPLUSTREE_H */ 00321