Merge ldb_search() and ldb_search_exp_fmt() into a simgle function.
[Samba.git] / source4 / lib / util / idtree.c
blob1e2cc2976a330a6f371c748e8913e7d7408a7668
1 /*
2 Unix SMB/CIFS implementation.
4 very efficient functions to manage mapping a id (such as a fnum) to
5 a pointer. This is used for fnum and search id allocation.
7 Copyright (C) Andrew Tridgell 2004
9 This code is derived from lib/idr.c in the 2.6 Linux kernel, which was
10 written by Jim Houston jim.houston@ccur.com, and is
11 Copyright (C) 2002 by Concurrent Computer Corporation
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 see the section marked "public interface" below for documentation
31 /**
32 * @file
35 #include "includes.h"
37 #define IDR_BITS 5
38 #define IDR_FULL 0xfffffffful
39 #if 0 /* unused */
40 #define TOP_LEVEL_FULL (IDR_FULL >> 30)
41 #endif
42 #define IDR_SIZE (1 << IDR_BITS)
43 #define IDR_MASK ((1 << IDR_BITS)-1)
44 #define MAX_ID_SHIFT (sizeof(int)*8 - 1)
45 #define MAX_ID_BIT (1U << MAX_ID_SHIFT)
46 #define MAX_ID_MASK (MAX_ID_BIT - 1)
47 #define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
48 #define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
50 #define set_bit(bit, v) (v) |= (1<<(bit))
51 #define clear_bit(bit, v) (v) &= ~(1<<(bit))
52 #define test_bit(bit, v) ((v) & (1<<(bit)))
54 struct idr_layer {
55 uint32_t bitmap;
56 struct idr_layer *ary[IDR_SIZE];
57 int count;
60 struct idr_context {
61 struct idr_layer *top;
62 struct idr_layer *id_free;
63 int layers;
64 int id_free_cnt;
67 static struct idr_layer *alloc_layer(struct idr_context *idp)
69 struct idr_layer *p;
71 if (!(p = idp->id_free))
72 return NULL;
73 idp->id_free = p->ary[0];
74 idp->id_free_cnt--;
75 p->ary[0] = NULL;
76 return p;
79 static int find_next_bit(uint32_t bm, int maxid, int n)
81 while (n<maxid && !test_bit(n, bm)) n++;
82 return n;
85 static void free_layer(struct idr_context *idp, struct idr_layer *p)
87 p->ary[0] = idp->id_free;
88 idp->id_free = p;
89 idp->id_free_cnt++;
92 static int idr_pre_get(struct idr_context *idp)
94 while (idp->id_free_cnt < IDR_FREE_MAX) {
95 struct idr_layer *new = talloc_zero(idp, struct idr_layer);
96 if(new == NULL)
97 return (0);
98 free_layer(idp, new);
100 return 1;
103 static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id)
105 int n, m, sh;
106 struct idr_layer *p, *new;
107 struct idr_layer *pa[MAX_LEVEL];
108 int l, id;
109 uint32_t bm;
111 memset(pa, 0, sizeof(pa));
113 id = *starting_id;
114 p = idp->top;
115 l = idp->layers;
116 pa[l--] = NULL;
117 while (1) {
119 * We run around this while until we reach the leaf node...
121 n = (id >> (IDR_BITS*l)) & IDR_MASK;
122 bm = ~p->bitmap;
123 m = find_next_bit(bm, IDR_SIZE, n);
124 if (m == IDR_SIZE) {
125 /* no space available go back to previous layer. */
126 l++;
127 id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
128 if (!(p = pa[l])) {
129 *starting_id = id;
130 return -2;
132 continue;
134 if (m != n) {
135 sh = IDR_BITS*l;
136 id = ((id >> sh) ^ n ^ m) << sh;
138 if ((id >= MAX_ID_BIT) || (id < 0))
139 return -1;
140 if (l == 0)
141 break;
143 * Create the layer below if it is missing.
145 if (!p->ary[m]) {
146 if (!(new = alloc_layer(idp)))
147 return -1;
148 p->ary[m] = new;
149 p->count++;
151 pa[l--] = p;
152 p = p->ary[m];
155 * We have reached the leaf node, plant the
156 * users pointer and return the raw id.
158 p->ary[m] = (struct idr_layer *)ptr;
159 set_bit(m, p->bitmap);
160 p->count++;
162 * If this layer is full mark the bit in the layer above
163 * to show that this part of the radix tree is full.
164 * This may complete the layer above and require walking
165 * up the radix tree.
167 n = id;
168 while (p->bitmap == IDR_FULL) {
169 if (!(p = pa[++l]))
170 break;
171 n = n >> IDR_BITS;
172 set_bit((n & IDR_MASK), p->bitmap);
174 return(id);
177 static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id)
179 struct idr_layer *p, *new;
180 int layers, v, id;
182 idr_pre_get(idp);
184 id = starting_id;
185 build_up:
186 p = idp->top;
187 layers = idp->layers;
188 if (!p) {
189 if (!(p = alloc_layer(idp)))
190 return -1;
191 layers = 1;
194 * Add a new layer to the top of the tree if the requested
195 * id is larger than the currently allocated space.
197 while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
198 layers++;
199 if (!p->count)
200 continue;
201 if (!(new = alloc_layer(idp))) {
203 * The allocation failed. If we built part of
204 * the structure tear it down.
206 for (new = p; p && p != idp->top; new = p) {
207 p = p->ary[0];
208 new->ary[0] = NULL;
209 new->bitmap = new->count = 0;
210 free_layer(idp, new);
212 return -1;
214 new->ary[0] = p;
215 new->count = 1;
216 if (p->bitmap == IDR_FULL)
217 set_bit(0, new->bitmap);
218 p = new;
220 idp->top = p;
221 idp->layers = layers;
222 v = sub_alloc(idp, ptr, &id);
223 if (v == -2)
224 goto build_up;
225 return(v);
228 static int sub_remove(struct idr_context *idp, int shift, int id)
230 struct idr_layer *p = idp->top;
231 struct idr_layer **pa[MAX_LEVEL];
232 struct idr_layer ***paa = &pa[0];
233 int n;
235 *paa = NULL;
236 *++paa = &idp->top;
238 while ((shift > 0) && p) {
239 n = (id >> shift) & IDR_MASK;
240 clear_bit(n, p->bitmap);
241 *++paa = &p->ary[n];
242 p = p->ary[n];
243 shift -= IDR_BITS;
245 n = id & IDR_MASK;
246 if (p != NULL && test_bit(n, p->bitmap)) {
247 clear_bit(n, p->bitmap);
248 p->ary[n] = NULL;
249 while(*paa && ! --((**paa)->count)){
250 free_layer(idp, **paa);
251 **paa-- = NULL;
253 if ( ! *paa )
254 idp->layers = 0;
255 return 0;
257 return -1;
260 static void *_idr_find(struct idr_context *idp, int id)
262 int n;
263 struct idr_layer *p;
265 n = idp->layers * IDR_BITS;
266 p = idp->top;
268 * This tests to see if bits outside the current tree are
269 * present. If so, tain't one of ours!
271 if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))
272 return NULL;
274 /* Mask off upper bits we don't use for the search. */
275 id &= MAX_ID_MASK;
277 while (n >= IDR_BITS && p) {
278 n -= IDR_BITS;
279 p = p->ary[(id >> n) & IDR_MASK];
281 return((void *)p);
284 static int _idr_remove(struct idr_context *idp, int id)
286 struct idr_layer *p;
288 /* Mask off upper bits we don't use for the search. */
289 id &= MAX_ID_MASK;
291 if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) {
292 return -1;
295 if ( idp->top && idp->top->count == 1 &&
296 (idp->layers > 1) &&
297 idp->top->ary[0]) {
298 /* We can drop a layer */
299 p = idp->top->ary[0];
300 idp->top->bitmap = idp->top->count = 0;
301 free_layer(idp, idp->top);
302 idp->top = p;
303 --idp->layers;
305 while (idp->id_free_cnt >= IDR_FREE_MAX) {
306 p = alloc_layer(idp);
307 talloc_free(p);
309 return 0;
312 /************************************************************************
313 this is the public interface
314 **************************************************************************/
317 initialise a idr tree. The context return value must be passed to
318 all subsequent idr calls. To destroy the idr tree use talloc_free()
319 on this context
321 _PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx)
323 return talloc_zero(mem_ctx, struct idr_context);
327 allocate the next available id, and assign 'ptr' into its slot.
328 you can retrieve later this pointer using idr_find()
330 _PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit)
332 int ret = idr_get_new_above_int(idp, ptr, 0);
333 if (ret > limit) {
334 idr_remove(idp, ret);
335 return -1;
337 return ret;
341 allocate a new id, giving the first available value greater than or
342 equal to the given starting id
344 _PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit)
346 int ret = idr_get_new_above_int(idp, ptr, starting_id);
347 if (ret > limit) {
348 idr_remove(idp, ret);
349 return -1;
351 return ret;
355 allocate a new id randomly in the given range
357 _PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit)
359 int id;
361 /* first try a random starting point in the whole range, and if that fails,
362 then start randomly in the bottom half of the range. This can only
363 fail if the range is over half full */
364 id = idr_get_new_above(idp, ptr, 1+(generate_random() % limit), limit);
365 if (id == -1) {
366 id = idr_get_new_above(idp, ptr, 1+(generate_random()%(limit/2)), limit);
369 return id;
373 find a pointer value previously set with idr_get_new given an id
375 _PUBLIC_ void *idr_find(struct idr_context *idp, int id)
377 return _idr_find(idp, id);
381 remove an id from the idr tree
383 _PUBLIC_ int idr_remove(struct idr_context *idp, int id)
385 int ret;
386 ret = _idr_remove((struct idr_context *)idp, id);
387 if (ret != 0) {
388 DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id));
390 return ret;