OpenAFS
OpenAFS distributed network file system
/cygdrive/c/src/openafs/openafs.git/repo/src/WINNT/afsd/cm_btree.h
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 
 All Data Structures Files Functions Variables