idtree.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. Based on SAMBA 7ce1356c9f571c55af70bd6b966fe50898c1582d.
  3. very efficient functions to manage mapping a id (such as a fnum) to
  4. a pointer. This is used for fnum and search id allocation.
  5. Copyright (C) Andrew Tridgell 2004
  6. This code is derived from lib/idr.c in the 2.6 Linux kernel, which was
  7. written by Jim Houston jim.houston@ccur.com, and is
  8. Copyright (C) 2002 by Concurrent Computer Corporation
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <ccan/idtree/idtree.h>
  21. #include <ccan/tal/tal.h>
  22. #include <stdint.h>
  23. #include <string.h>
  24. #define IDTREE_BITS 5
  25. #define IDTREE_FULL 0xfffffffful
  26. #if 0 /* unused */
  27. #define TOP_LEVEL_FULL (IDTREE_FULL >> 30)
  28. #endif
  29. #define IDTREE_SIZE (1 << IDTREE_BITS)
  30. #define IDTREE_MASK ((1 << IDTREE_BITS)-1)
  31. #define MAX_ID_SHIFT (sizeof(int)*8 - 1)
  32. #define MAX_ID_BIT (1U << MAX_ID_SHIFT)
  33. #define MAX_ID_MASK (MAX_ID_BIT - 1)
  34. #define MAX_LEVEL (MAX_ID_SHIFT + IDTREE_BITS - 1) / IDTREE_BITS
  35. #define IDTREE_FREE_MAX MAX_LEVEL + MAX_LEVEL
  36. #define set_bit(bit, v) (v) |= (1<<(bit))
  37. #define clear_bit(bit, v) (v) &= ~(1<<(bit))
  38. #define test_bit(bit, v) ((v) & (1<<(bit)))
  39. struct idtree_layer {
  40. uint32_t bitmap;
  41. struct idtree_layer *ary[IDTREE_SIZE];
  42. int count;
  43. };
  44. struct idtree {
  45. struct idtree_layer *top;
  46. struct idtree_layer *id_free;
  47. int layers;
  48. int id_free_cnt;
  49. };
  50. static struct idtree_layer *alloc_layer(struct idtree *idp)
  51. {
  52. struct idtree_layer *p;
  53. if (!(p = idp->id_free))
  54. return NULL;
  55. idp->id_free = p->ary[0];
  56. idp->id_free_cnt--;
  57. p->ary[0] = NULL;
  58. return p;
  59. }
  60. static int find_next_bit(uint32_t bm, int maxid, int n)
  61. {
  62. while (n<maxid && !test_bit(n, bm)) n++;
  63. return n;
  64. }
  65. static void free_layer(struct idtree *idp, struct idtree_layer *p)
  66. {
  67. p->ary[0] = idp->id_free;
  68. idp->id_free = p;
  69. idp->id_free_cnt++;
  70. }
  71. static int idtree_pre_get(struct idtree *idp)
  72. {
  73. while (idp->id_free_cnt < IDTREE_FREE_MAX) {
  74. struct idtree_layer *pn = talz(idp, struct idtree_layer);
  75. if(pn == NULL)
  76. return (0);
  77. free_layer(idp, pn);
  78. }
  79. return 1;
  80. }
  81. static int sub_alloc(struct idtree *idp, const void *ptr, int *starting_id)
  82. {
  83. int n, m, sh;
  84. struct idtree_layer *p, *pn;
  85. struct idtree_layer *pa[MAX_LEVEL+1];
  86. unsigned int l;
  87. int id, oid;
  88. uint32_t bm;
  89. memset(pa, 0, sizeof(pa));
  90. id = *starting_id;
  91. restart:
  92. p = idp->top;
  93. l = idp->layers;
  94. pa[l--] = NULL;
  95. while (1) {
  96. /*
  97. * We run around this while until we reach the leaf node...
  98. */
  99. n = (id >> (IDTREE_BITS*l)) & IDTREE_MASK;
  100. bm = ~p->bitmap;
  101. m = find_next_bit(bm, IDTREE_SIZE, n);
  102. if (m == IDTREE_SIZE) {
  103. /* no space available go back to previous layer. */
  104. l++;
  105. oid = id;
  106. id = (id | ((1 << (IDTREE_BITS*l))-1)) + 1;
  107. /* if already at the top layer, we need to grow */
  108. if (!(p = pa[l])) {
  109. *starting_id = id;
  110. return -2;
  111. }
  112. /* If we need to go up one layer, continue the
  113. * loop; otherwise, restart from the top.
  114. */
  115. sh = IDTREE_BITS * (l + 1);
  116. if (oid >> sh == id >> sh)
  117. continue;
  118. else
  119. goto restart;
  120. }
  121. if (m != n) {
  122. sh = IDTREE_BITS*l;
  123. id = ((id >> sh) ^ n ^ m) << sh;
  124. }
  125. if ((id >= MAX_ID_BIT) || (id < 0))
  126. return -1;
  127. if (l == 0)
  128. break;
  129. /*
  130. * Create the layer below if it is missing.
  131. */
  132. if (!p->ary[m]) {
  133. if (!(pn = alloc_layer(idp)))
  134. return -1;
  135. p->ary[m] = pn;
  136. p->count++;
  137. }
  138. pa[l--] = p;
  139. p = p->ary[m];
  140. }
  141. /*
  142. * We have reached the leaf node, plant the
  143. * users pointer and return the raw id.
  144. */
  145. p->ary[m] = (struct idtree_layer *)ptr;
  146. set_bit(m, p->bitmap);
  147. p->count++;
  148. /*
  149. * If this layer is full mark the bit in the layer above
  150. * to show that this part of the radix tree is full.
  151. * This may complete the layer above and require walking
  152. * up the radix tree.
  153. */
  154. n = id;
  155. while (p->bitmap == IDTREE_FULL) {
  156. if (!(p = pa[++l]))
  157. break;
  158. n = n >> IDTREE_BITS;
  159. set_bit((n & IDTREE_MASK), p->bitmap);
  160. }
  161. return(id);
  162. }
  163. static int idtree_get_new_above_int(struct idtree *idp,
  164. const void *ptr, int starting_id)
  165. {
  166. struct idtree_layer *p, *pn;
  167. int layers, v, id;
  168. idtree_pre_get(idp);
  169. id = starting_id;
  170. build_up:
  171. p = idp->top;
  172. layers = idp->layers;
  173. if (!p) {
  174. if (!(p = alloc_layer(idp)))
  175. return -1;
  176. layers = 1;
  177. }
  178. /*
  179. * Add a new layer to the top of the tree if the requested
  180. * id is larger than the currently allocated space.
  181. */
  182. while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDTREE_BITS)))) {
  183. layers++;
  184. if (!p->count)
  185. continue;
  186. if (!(pn = alloc_layer(idp))) {
  187. /*
  188. * The allocation failed. If we built part of
  189. * the structure tear it down.
  190. */
  191. for (pn = p; p && p != idp->top; pn = p) {
  192. p = p->ary[0];
  193. pn->ary[0] = NULL;
  194. pn->bitmap = pn->count = 0;
  195. free_layer(idp, pn);
  196. }
  197. return -1;
  198. }
  199. pn->ary[0] = p;
  200. pn->count = 1;
  201. if (p->bitmap == IDTREE_FULL)
  202. set_bit(0, pn->bitmap);
  203. p = pn;
  204. }
  205. idp->top = p;
  206. idp->layers = layers;
  207. v = sub_alloc(idp, ptr, &id);
  208. if (v == -2)
  209. goto build_up;
  210. return(v);
  211. }
  212. static int sub_remove(struct idtree *idp, int shift, int id)
  213. {
  214. struct idtree_layer *p = idp->top;
  215. struct idtree_layer **pa[1+MAX_LEVEL];
  216. struct idtree_layer ***paa = &pa[0];
  217. int n;
  218. *paa = NULL;
  219. *++paa = &idp->top;
  220. while ((shift > 0) && p) {
  221. n = (id >> shift) & IDTREE_MASK;
  222. clear_bit(n, p->bitmap);
  223. *++paa = &p->ary[n];
  224. p = p->ary[n];
  225. shift -= IDTREE_BITS;
  226. }
  227. n = id & IDTREE_MASK;
  228. if (p != NULL && test_bit(n, p->bitmap)) {
  229. clear_bit(n, p->bitmap);
  230. p->ary[n] = NULL;
  231. while(*paa && ! --((**paa)->count)){
  232. free_layer(idp, **paa);
  233. **paa-- = NULL;
  234. }
  235. if ( ! *paa )
  236. idp->layers = 0;
  237. return 0;
  238. }
  239. return -1;
  240. }
  241. void *idtree_lookup(const struct idtree *idp, int id)
  242. {
  243. int n;
  244. struct idtree_layer *p;
  245. n = idp->layers * IDTREE_BITS;
  246. p = idp->top;
  247. /*
  248. * This tests to see if bits outside the current tree are
  249. * present. If so, tain't one of ours!
  250. */
  251. if (n + IDTREE_BITS < 31 &&
  252. (id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDTREE_BITS))
  253. return NULL;
  254. /* Mask off upper bits we don't use for the search. */
  255. id &= MAX_ID_MASK;
  256. while (n >= IDTREE_BITS && p) {
  257. n -= IDTREE_BITS;
  258. p = p->ary[(id >> n) & IDTREE_MASK];
  259. }
  260. return((void *)p);
  261. }
  262. bool idtree_remove(struct idtree *idp, int id)
  263. {
  264. struct idtree_layer *p;
  265. /* Mask off upper bits we don't use for the search. */
  266. id &= MAX_ID_MASK;
  267. if (sub_remove(idp, (idp->layers - 1) * IDTREE_BITS, id) == -1) {
  268. return false;
  269. }
  270. if ( idp->top && idp->top->count == 1 &&
  271. (idp->layers > 1) &&
  272. idp->top->ary[0]) {
  273. /* We can drop a layer */
  274. p = idp->top->ary[0];
  275. idp->top->bitmap = idp->top->count = 0;
  276. free_layer(idp, idp->top);
  277. idp->top = p;
  278. --idp->layers;
  279. }
  280. while (idp->id_free_cnt >= IDTREE_FREE_MAX) {
  281. p = alloc_layer(idp);
  282. tal_free(p);
  283. }
  284. return true;
  285. }
  286. struct idtree *idtree_new(void *mem_ctx)
  287. {
  288. return talz(mem_ctx, struct idtree);
  289. }
  290. int idtree_add(struct idtree *idp, const void *ptr, int limit)
  291. {
  292. int ret = idtree_get_new_above_int(idp, ptr, 0);
  293. if (ret > limit) {
  294. idtree_remove(idp, ret);
  295. return -1;
  296. }
  297. return ret;
  298. }
  299. int idtree_add_above(struct idtree *idp, const void *ptr,
  300. int starting_id, int limit)
  301. {
  302. int ret = idtree_get_new_above_int(idp, ptr, starting_id);
  303. if (ret > limit) {
  304. idtree_remove(idp, ret);
  305. return -1;
  306. }
  307. return ret;
  308. }