windows-cell-name-length-consistency-20080806
[openafs.git] / src / WINNT / afsd / cm_btree.h
1 /* 
2  * Copyright 2007 Secure Endpoints Inc.  
3  * 
4  * All Rights Reserved.
5  *
6  * This software has been released under the terms of the IBM Public
7  * License.  For details, see the LICENSE file in the top-level source
8  * directory or online at http://www.openafs.org/dl/license10.html
9  *
10  * Thanks to Jan Jannink for B+ tree algorithms.
11  */
12
13 #ifndef BPLUSTREE_H
14 #define BPLUSTREE_H 1
15
16 /********       flag bits (5 of 16 used, 11 for magic value)    ********/
17
18 /* bits set at node creation/split/merge */
19 #define isLEAF          0x01
20 #define isROOT          0x02
21 #define isDATA          0x04
22
23 /* bits set at key insertion/deletion */
24 #define isFULL          0x08
25 #define FEWEST          0x10
26 #define FLAGS_MASK      0xFF
27
28 /* identifies data as being a B+tree node */
29 #define BTREE_MAGIC           0xBEE0BEE0
30 #define BTREE_MAGIC_MASK      0xFFFFFFFF
31
32
33 /*************************      constants       ************************/
34
35 /* The maximum number of Entrys in one Node */
36 #define MAX_FANOUT      9
37
38 /* corresponds to a NULL node pointer value */
39 #define NONODE          NULL
40
41 /* special node slot values used in key search */
42 #define BTERROR         -1
43 #define BTUPPER         -2
44 #define BTLOWER         -3
45
46
47 /************************* Data Types **********************************/
48 typedef struct node     *Nptr;
49
50 typedef struct key {
51     normchar_t  *name;           /* Normalized name */
52 } keyT;
53
54 typedef struct dirdata {
55     cm_fid_t    fid;
56     int         shortform;      /* This is the short form entry.  If
57                                    this value is non-zero, then there
58                                    is another entry in the B-Plus tree
59                                    corresponding to the long name of
60                                    this fid. */
61     clientchar_t  *cname;          /* Client name (long) */
62     fschar_t * fsname;         /* FileServer name */
63 } dataT;
64
65 typedef struct entry {
66     keyT        key;
67     Nptr        downNode;
68 } Entry;
69
70 typedef struct inner {
71     short       pairs;
72     Nptr        firstNode;
73 } Inner;
74
75
76 typedef struct leaf {
77     short       pairs;
78     Nptr        nextNode;
79 } Leaf;
80
81 typedef struct data {
82     keyT        key;
83     dataT       value;
84     Nptr        next;
85 } Data;
86
87 typedef struct node {
88     Nptr                pool;
89     unsigned short      number;
90     unsigned short      flags;
91     unsigned long       magic;
92     union {
93         Entry   e[MAX_FANOUT];  /* allows access to entry array */
94         Inner   i;
95         Leaf    l;
96         Data    d;
97     } X;
98 } Node;
99
100
101 typedef int (*KeyCmp)(keyT, keyT, int);
102 #define EXACT_MATCH 0x01
103
104
105 typedef struct tree {
106     unsigned int        flags;          /* tree flags */
107     unsigned int        poolsize;       /* # of nodes allocated for tree */
108     Nptr                root;           /* pointer to root node */
109     Nptr                leaf;           /* pointer to first leaf node in B+tree */
110     unsigned int        fanout;         /* # of pointers to other nodes */
111     unsigned int        minfanout;      /* usually minfanout == ceil(fanout/2) */
112     unsigned int        height;         /* nodes traversed from root to leaves */
113     Nptr                pool;           /* list of all nodes */
114     Nptr                empty;          /* list of empty nodes */
115     union {                             /* nodes to change in insert and delete */
116         Nptr    split;                  /* protected by scp->dirlock write-lock */
117         Nptr    merge;
118     } branch;
119     KeyCmp      keycmp;                 /* pointer to function comparing two keys */
120     char message[1024];
121 } Tree;
122
123 #define TREE_FLAGS_MASK                 0x01
124 #define TREE_FLAG_UNIQUE_KEYS           0x01
125
126 /************************* B+ tree Public functions ****************/
127 Tree    *initBtree(unsigned int poolsz, unsigned int fan, KeyCmp keyCmp);
128 void    freeBtree(Tree *B);
129
130 #ifdef DEBUG_BTREE
131 void    showNode(Tree *B, const char * str, Nptr node);
132 void    showBtree(Tree *B);
133 void    listBtreeValues(Tree *B, Nptr start, int count);
134 void    listAllBtreeValues(Tree *B);
135 void    listBtreeNodes(Tree *B, const char * where, Nptr node);
136 void    findAllBtreeValues(Tree *B);
137 #endif
138
139 void    insert(Tree *B, keyT key, dataT data);
140 void    delete(Tree *B, keyT key);
141 Nptr    lookup(Tree *B, keyT key);
142
143 /******************* cache manager directory operations ***************/
144
145 int  cm_BPlusCompareNormalizedKeys(keyT key1, keyT key2, int flags);
146 int  cm_BPlusDirLookup(cm_dirOp_t * op, clientchar_t *entry, cm_fid_t * cfid);
147 int  cm_BPlusDirLookupOriginalName(cm_dirOp_t * op, clientchar_t *entry, fschar_t **originalNameRetp);
148 long cm_BPlusDirCreateEntry(cm_dirOp_t * op, clientchar_t *entry, cm_fid_t * cfid);
149 int  cm_BPlusDirDeleteEntry(cm_dirOp_t * op, clientchar_t *entry);
150 long cm_BPlusDirBuildTree(cm_scache_t *scp, cm_user_t *userp, cm_req_t* reqp);
151 void cm_BPlusDumpStats(void);
152 int  cm_MemDumpBPlusStats(FILE *outputFile, char *cookie, int lock);
153
154 /******************* directory enumeration operations ****************/
155 typedef struct cm_direnum_entry {
156     clientchar_t *name;
157     cm_fid_t     fid;
158     normchar_t   shortName[13];
159 } cm_direnum_entry_t;
160
161 typedef struct cm_direnum {
162     afs_uint32          count;
163     afs_uint32          next;
164     cm_direnum_entry_t  entry[1];
165 } cm_direnum_t;
166
167 long cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, clientchar_t *maskp, cm_direnum_t **enumpp);
168 long cm_BPlusDirNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp);
169 long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump);
170 long cm_BPlusDirEnumTest(cm_scache_t * dscp, afs_uint32 locked);
171 long cm_BPlusDirEnumBulkStat(cm_scache_t *dscp, cm_direnum_t *enump, cm_user_t *userp, cm_req_t *reqp);
172
173 long cm_InitBPlusDir(void);
174
175 /************ Statistic Counter ***************************************/
176
177 extern afs_uint32 bplus_free_tree;
178 extern afs_uint32 bplus_dv_error;
179 extern afs_uint64 bplus_free_time;
180
181
182 /************ Accessor Macros *****************************************/
183                         
184 /* low level definition of Nptr value usage */
185 #define nAdr(n) (n)->X
186
187 /* access keys and pointers in a node */
188 #define getkey(j, q) (nAdr(j).e[(q)].key)
189 #define getnode(j, q) (nAdr(j).e[(q)].downNode)
190 #define setkey(j, q, v) ((q > 0) ? nAdr(j).e[(q)].key.name = cm_NormStrDup((v).name) : NULL)
191 #define setnode(j, q, v) (nAdr(j).e[(q)].downNode = (v))
192
193 /* access tree flag values */
194 #define settreeflags(B,v) (B->flags |= (v & TREE_FLAGS_MASK))
195 #define gettreeflags(B)   (B->flags)
196 #define cleartreeflags(B) (B->flags = 0);
197
198 /* access node flag values */
199 #define setflag(j, v) ((j)->flags |= (v & FLAGS_MASK))
200 #define clrflag(j, v) ((j)->flags &= ~(v & FLAGS_MASK))
201 #define getflags(j) ((j)->flags & FLAGS_MASK)
202 #define getmagic(j)  ((j)->magic & BTREE_MAGIC_MASK)
203 #define clearflags(j) ((j)->flags = 0, (j)->magic = BTREE_MAGIC)
204
205
206 /* check that a node is in fact a node */
207 #define isnode(j) (((j) != NONODE) && (((j)->magic & BTREE_MAGIC_MASK) == BTREE_MAGIC) && !((j)->flags & isDATA))
208 #define isntnode(j) ((j) == NONODE)
209
210
211 /* test individual flag values */
212 #define isinternal(j) (((j)->flags & isLEAF) == 0)
213 #define isleaf(j) (((j)->flags & isLEAF) == isLEAF)
214 #define isdata(j) (((j)->flags & isDATA) == isDATA)
215 #ifndef DEBUG_BTREE
216 #define isroot(j) (((j)->flags & isROOT) == isROOT)
217 #define isfull(j) (((j)->flags & isFULL) == isFULL)
218 #define isfew(j) (((j)->flags & FEWEST) == FEWEST)
219 #else
220 #define isroot(j) _isRoot(B, j)
221 #define isfew(j) _isFew(B, j)
222 #define isfull(j) _isFull(B, j)
223 #endif
224
225 /* manage number of keys in a node */
226 #define numentries(j) (nAdr(j).i.pairs)
227 #define clearentries(j) (nAdr(j).i.pairs = 0)
228 #define incentries(j) (nAdr(j).i.pairs++)
229 #define decentries(j) (nAdr(j).i.pairs--)
230
231
232 /* manage first/last node pointers in internal nodes */
233 #define setfirstnode(j, v) (nAdr(j).i.firstNode = (v))
234 #define getfirstnode(j) (nAdr(j).i.firstNode)
235 #define getlastnode(j) (nAdr(j).e[nAdr(j).i.pairs].downNode)
236
237
238 /* manage pointers to next nodes in leaf nodes */
239 /* also used for free nodes list */
240 #define setnextnode(j, v) (nAdr(j).l.nextNode = (v))
241 #define getnextnode(j) (nAdr(j).l.nextNode)
242
243 /* manage pointers to all nodes list */
244 #define setallnode(j, v) ((j)->pool = (v))
245 #define getallnode(j) ((j)->pool)
246
247 /* manage access to data nodes */
248 #define getdata(j) (nAdr(j).d)
249 #define getdatavalue(j) (getdata(j).value)
250 #define getdatakey(j)   (getdata(j).key)
251 #define getdatanext(j)  (getdata(j).next)
252
253 /* shift/transfer entries for insertion/deletion */
254 #define clrentry(j, q) _clrentry(j,q)
255 #define pushentry(j, q, v) _pushentry(j, q, v)
256 #define pullentry(j, q, v) _pullentry(j, q, v)
257 #define xferentry(j, q, v, z) _xferentry(j, q, v, z)
258 #define setentry(j, q, v, z) _setentry(j, q, v, z)
259
260 /* define number of B+tree nodes for free node pool */
261 #define getpoolsize(B) ((B)->poolsize)
262 #define setpoolsize(B,v) ((B)->poolsize = (v))
263
264 /* locations from which tree access begins */
265 #define getroot(B) ((B)->root)
266 #define setroot(B,v) ((B)->root = (v))
267 #define getleaf(B) ((B)->leaf)
268 #define setleaf(B,v) ((B)->leaf = (v))
269
270 /* define max/min number of pointers per node */
271 #define getfanout(B) ((B)->fanout)
272 #define setfanout(B,v) ((B)->fanout = (v) - 1)
273 #define getminfanout(B,j) (isroot(j) ? (isleaf(j) ? 0 : 1) : (isleaf(j) ? (B)->fanout - (B)->minfanout: (B)->minfanout))
274 #define setminfanout(B,v) ((B)->minfanout = (v) - 1)
275
276 /* manage B+tree height */
277 #define inittreeheight(B) ((B)->height = 0)
278 #define inctreeheight(B) ((B)->height++)
279 #define dectreeheight(B) ((B)->height--)
280 #define gettreeheight(B) ((B)->height)
281
282 /* access pool of free nodes */
283 #define getfirstfreenode(B) ((B)->empty)
284 #define setfirstfreenode(B,v) ((B)->empty = (v))
285
286 /* access all node list */
287 #define getfirstallnode(B) ((B)->pool)
288 #define setfirstallnode(B,v) ((B)->pool = (v))
289
290 /* handle split/merge points during insert/delete */
291 #define getsplitpath(B) ((B)->branch.split)
292 #define setsplitpath(B,v) ((B)->branch.split = (v))
293 #define getmergepath(B) ((B)->branch.merge)
294 #define setmergepath(B,v) ((B)->branch.merge = (v))
295
296 /* exploit function to compare two B+tree keys */
297 #define comparekeys(B) (*(B)->keycmp)
298 #define setcomparekeys(B,v) ((B)->keycmp = (v))
299
300 /* location containing B+tree class variables */
301 #define setbplustree(B,v) ((B) = (Tree *)(v))
302
303 /* representation independent node numbering */
304 #define setnodenumber(B,v,q) ((v)->number = (q))
305 #define getnodenumber(B,v) ((v) != NONODE ? (v)->number : -1)
306
307 #endif /* BPLUSTREE_H */
308