]> git.proxmox.com Git - mirror_frr.git/blob - lib/skiplist.c
Merge pull request #2829 from donaldsharp/more_upstream
[mirror_frr.git] / lib / skiplist.c
1 /*
2 * Copyright 1990 William Pugh
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
8 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
9 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
10 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
11 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
12 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
13 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
14 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
15 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
16 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
17 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18 * SUCH DAMAGE.
19 *
20 * Permission to include in quagga provide on March 31, 2016
21 */
22
23 /*
24 * Skip List impementation based on code from William Pugh.
25 * ftp://ftp.cs.umd.edu/pub/skipLists/
26 *
27 * Skip Lists are a probabilistic alternative to balanced trees, as
28 * described in the June 1990 issue of CACM and were invented by
29 * William Pugh in 1987.
30 *
31 * This file contains source code to implement a dictionary using
32 * skip lists and a test driver to test the routines.
33 *
34 * A couple of comments about this implementation:
35 * The routine randomLevel has been hard-coded to generate random
36 * levels using p=0.25. It can be easily changed.
37 *
38 * The insertion routine has been implemented so as to use the
39 * dirty hack described in the CACM paper: if a random level is
40 * generated that is more than the current maximum level, the
41 * current maximum level plus one is used instead.
42 *
43 * Levels start at zero and go up to MaxLevel (which is equal to
44 * (MaxNumberOfLevels-1).
45 *
46 * The run-time flag SKIPLIST_FLAG_ALLOW_DUPLICATES determines whether or
47 * not duplicates are allowed for a given list. If set, duplicates are
48 * allowed and act in a FIFO manner. If not set, an insertion of a value
49 * already in the list updates the previously existing binding.
50 *
51 * BitsInRandom is defined to be the number of bits returned by a call to
52 * random(). For most all machines with 32-bit integers, this is 31 bits
53 * as currently set.
54 */
55
56
57 #include <zebra.h>
58
59 #include "memory.h"
60 #include "log.h"
61 #include "vty.h"
62 #include "skiplist.h"
63 #include "lib_errors.h"
64
65 DEFINE_MTYPE_STATIC(LIB, SKIP_LIST, "Skip List")
66 DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node")
67
68 #define BitsInRandom 31
69
70 #define MaxNumberOfLevels 16
71 #define MaxLevel (MaxNumberOfLevels-1)
72 #define newNodeOfLevel(l) XCALLOC(MTYPE_SKIP_LIST_NODE, sizeof(struct skiplistnode)+(l)*sizeof(struct skiplistnode *))
73
74 static int randomsLeft;
75 static int randomBits;
76 static struct skiplist *skiplist_last_created; /* debugging hack */
77
78 #if 1
79 #define CHECKLAST(sl) \
80 do { \
81 if ((sl)->header->forward[0] && !(sl)->last) \
82 assert(0); \
83 if (!(sl)->header->forward[0] && (sl)->last) \
84 assert(0); \
85 } while (0)
86 #else
87 #define CHECKLAST(sl)
88 #endif
89
90
91 static int randomLevel()
92 {
93 register int level = 0;
94 register int b;
95
96 do {
97 if (randomsLeft <= 0) {
98 randomBits = random();
99 randomsLeft = BitsInRandom / 2;
100 }
101 b = randomBits & 3;
102 randomBits >>= 2;
103 --randomsLeft;
104
105 if (!b) {
106 level++;
107 if (level >= MaxLevel)
108 return MaxLevel;
109 }
110 } while (!b);
111
112 return level;
113 }
114
115 static int default_cmp(void *key1, void *key2)
116 {
117 if (key1 < key2)
118 return -1;
119 if (key1 > key2)
120 return 1;
121 return 0;
122 }
123
124 unsigned int skiplist_count(struct skiplist *l)
125 {
126 return l->count;
127 }
128
129 struct skiplist *skiplist_new(int flags, int (*cmp)(void *key1, void *key2),
130 void (*del)(void *val))
131 {
132 struct skiplist *new;
133
134 new = XCALLOC(MTYPE_SKIP_LIST, sizeof(struct skiplist));
135 assert(new);
136
137 new->level = 0;
138 new->count = 0;
139 new->header = newNodeOfLevel(MaxNumberOfLevels);
140 new->stats = newNodeOfLevel(MaxNumberOfLevels);
141
142 new->flags = flags;
143 if (cmp)
144 new->cmp = cmp;
145 else
146 new->cmp = default_cmp;
147
148 if (del)
149 new->del = del;
150
151 skiplist_last_created = new; /* debug */
152
153 return new;
154 }
155
156 void skiplist_free(struct skiplist *l)
157 {
158 register struct skiplistnode *p, *q;
159
160 p = l->header;
161
162 do {
163 q = p->forward[0];
164 if (l->del && p != l->header)
165 (*l->del)(p->value);
166 XFREE(MTYPE_SKIP_LIST_NODE, p);
167 p = q;
168 } while (p);
169
170 XFREE(MTYPE_SKIP_LIST_NODE, l->stats);
171 XFREE(MTYPE_SKIP_LIST, l);
172 }
173
174
175 int skiplist_insert(register struct skiplist *l, register void *key,
176 register void *value)
177 {
178 register int k;
179 struct skiplistnode *update[MaxNumberOfLevels];
180 register struct skiplistnode *p, *q;
181
182 CHECKLAST(l);
183
184 /* DEBUG */
185 if (!key) {
186 flog_err(LIB_ERR_DEVELOPMENT, "%s: key is 0, value is %p",
187 __func__, value);
188 }
189
190 p = l->header;
191 k = l->level;
192 do {
193 while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0)
194 p = q;
195 update[k] = p;
196 } while (--k >= 0);
197
198 if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) && q
199 && ((*l->cmp)(q->key, key) == 0)) {
200
201 return -1;
202 }
203
204 k = randomLevel();
205 if (k > l->level) {
206 k = ++l->level;
207 update[k] = l->header;
208 }
209
210 q = newNodeOfLevel(k);
211 q->key = key;
212 q->value = value;
213 #if SKIPLIST_0TIMER_DEBUG
214 q->flags = SKIPLIST_NODE_FLAG_INSERTED; /* debug */
215 #endif
216
217 ++(l->stats->forward[k]);
218 #if SKIPLIST_DEBUG
219 zlog_debug("%s: incremented stats @%p:%d, now %ld", __func__, l, k,
220 l->stats->forward[k] - (struct skiplistnode *)NULL);
221 #endif
222
223 do {
224 p = update[k];
225 q->forward[k] = p->forward[k];
226 p->forward[k] = q;
227 } while (--k >= 0);
228
229 /*
230 * If this is the last item in the list, update the "last" pointer
231 */
232 if (!q->forward[0]) {
233 l->last = q;
234 }
235
236 ++(l->count);
237
238 CHECKLAST(l);
239
240 return 0;
241 }
242
243 int skiplist_delete(register struct skiplist *l, register void *key,
244 register void *value) /* used only if duplicates allowed */
245 {
246 register int k, m;
247 struct skiplistnode *update[MaxNumberOfLevels];
248 register struct skiplistnode *p, *q;
249
250 CHECKLAST(l);
251
252 /* to make debugging easier */
253 for (k = 0; k < MaxNumberOfLevels; ++k)
254 update[k] = NULL;
255
256 p = l->header;
257 k = m = l->level;
258 do {
259 while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0)
260 p = q;
261 update[k] = p;
262 } while (--k >= 0);
263
264 if (l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) {
265 while (q && ((*l->cmp)(q->key, key) == 0)
266 && (q->value != value)) {
267 int i;
268 for (i = 0; i <= l->level; ++i) {
269 if (update[i]->forward[i] == q)
270 update[i] = q;
271 }
272 q = q->forward[0];
273 }
274 }
275
276 if (q && (*l->cmp)(q->key, key) == 0) {
277 if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES)
278 || (q->value == value)) {
279
280 /*
281 * found node to delete
282 */
283 #if SKIPLIST_0TIMER_DEBUG
284 q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED;
285 #endif
286 /*
287 * If we are deleting the last element of the list,
288 * update the list's "last" pointer.
289 */
290 if (l->last == q) {
291 if (update[0] == l->header)
292 l->last = NULL;
293 else
294 l->last = update[0];
295 }
296
297 for (k = 0; k <= m && (p = update[k])->forward[k] == q;
298 k++) {
299 p->forward[k] = q->forward[k];
300 }
301 --(l->stats->forward[k - 1]);
302 #if SKIPLIST_DEBUG
303 zlog_debug("%s: decremented stats @%p:%d, now %ld",
304 __func__, l, k - 1,
305 l->stats->forward[k - 1]
306 - (struct skiplistnode *)NULL);
307 #endif
308 if (l->del)
309 (*l->del)(q->value);
310 XFREE(MTYPE_SKIP_LIST_NODE, q);
311 while (l->header->forward[m] == NULL && m > 0)
312 m--;
313 l->level = m;
314 CHECKLAST(l);
315 --(l->count);
316 return 0;
317 }
318 }
319
320 CHECKLAST(l);
321 return -1;
322 }
323
324 /*
325 * Obtain first value matching "key". Unless SKIPLIST_FLAG_ALLOW_DUPLICATES
326 * is set, this will also be the only value matching "key".
327 *
328 * Also set a cursor for use with skiplist_next_value.
329 */
330 int skiplist_first_value(register struct skiplist *l, /* in */
331 register void *key, /* in */
332 void **valuePointer, /* out */
333 void **cursor) /* out */
334 {
335 register int k;
336 register struct skiplistnode *p, *q;
337
338 p = l->header;
339 k = l->level;
340
341 do {
342 while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0)
343 p = q;
344
345 } while (--k >= 0);
346
347 if (!q || (*l->cmp)(q->key, key))
348 return -1;
349
350 if (valuePointer)
351 *valuePointer = q->value;
352
353 if (cursor)
354 *cursor = q;
355
356 return 0;
357 }
358
359 int skiplist_search(register struct skiplist *l, register void *key,
360 void **valuePointer)
361 {
362 return skiplist_first_value(l, key, valuePointer, NULL);
363 }
364
365
366 /*
367 * Caller supplies key and value of an existing item in the list.
368 * Function returns the value of the next list item that has the
369 * same key (useful when SKIPLIST_FLAG_ALLOW_DUPLICATES is set).
370 *
371 * Returns 0 on success. If the caller-supplied key and value
372 * do not correspond to a list element, or if they specify the
373 * last element with the given key, -1 is returned.
374 */
375 int skiplist_next_value(register struct skiplist *l, /* in */
376 register void *key, /* in */
377 void **valuePointer, /* in/out */
378 void **cursor) /* in/out */
379 {
380 register int k, m;
381 register struct skiplistnode *p, *q;
382
383 CHECKLAST(l);
384
385 if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES)) {
386 return -1;
387 }
388
389 if (!cursor || !*cursor) {
390 p = l->header;
391 k = m = l->level;
392
393 /*
394 * Find matching key
395 */
396 do {
397 while (q = p->forward[k],
398 q && (*l->cmp)(q->key, key) < 0)
399 p = q;
400 } while (--k >= 0);
401
402 /*
403 * Find matching value
404 */
405 while (q && ((*l->cmp)(q->key, key) == 0)
406 && (q->value != *valuePointer)) {
407 q = q->forward[0];
408 }
409
410 if (!q || ((*l->cmp)(q->key, key) != 0)
411 || (q->value != *valuePointer)) {
412 /*
413 * No matching value
414 */
415 CHECKLAST(l);
416 return -1;
417 }
418 } else {
419 q = (struct skiplistnode *)*cursor;
420 }
421
422 /*
423 * Advance cursor
424 */
425 q = q->forward[0];
426
427 /*
428 * If we reached end-of-list or if the key is no longer the same,
429 * then return error
430 */
431 if (!q || ((*l->cmp)(q->key, key) != 0))
432 return -1;
433
434 *valuePointer = q->value;
435 if (cursor)
436 *cursor = q;
437 CHECKLAST(l);
438 return 0;
439 }
440
441 int skiplist_first(register struct skiplist *l, void **keyPointer,
442 void **valuePointer)
443 {
444 register struct skiplistnode *p;
445
446 CHECKLAST(l);
447 p = l->header->forward[0];
448 if (!p)
449 return -1;
450
451 if (keyPointer)
452 *keyPointer = p->key;
453
454 if (valuePointer)
455 *valuePointer = p->value;
456
457 CHECKLAST(l);
458
459 return 0;
460 }
461
462 int skiplist_last(register struct skiplist *l, void **keyPointer,
463 void **valuePointer)
464 {
465 CHECKLAST(l);
466 if (l->last) {
467 if (keyPointer)
468 *keyPointer = l->last->key;
469 if (valuePointer)
470 *valuePointer = l->last->value;
471 return 0;
472 }
473 return -1;
474 }
475
476 /*
477 * true = empty
478 */
479 int skiplist_empty(register struct skiplist *l)
480 {
481 CHECKLAST(l);
482 if (l->last)
483 return 0;
484 return 1;
485 }
486
487 /*
488 * Use this to walk the list. Caller sets *cursor to NULL to obtain
489 * first element. Return value of 0 indicates valid cursor/element
490 * returned, otherwise NULL cursor arg or EOL.
491 */
492 int skiplist_next(register struct skiplist *l, /* in */
493 void **keyPointer, /* out */
494 void **valuePointer, /* out */
495 void **cursor) /* in/out */
496 {
497 struct skiplistnode *p;
498
499 if (!cursor)
500 return -1;
501
502 CHECKLAST(l);
503
504 if (!*cursor) {
505 p = l->header->forward[0];
506 } else {
507 p = *cursor;
508 p = p->forward[0];
509 }
510 *cursor = p;
511
512 if (!p)
513 return -1;
514
515 if (keyPointer)
516 *keyPointer = p->key;
517
518 if (valuePointer)
519 *valuePointer = p->value;
520
521 CHECKLAST(l);
522
523 return 0;
524 }
525
526 int skiplist_delete_first(register struct skiplist *l)
527 {
528 register int k;
529 register struct skiplistnode *p, *q;
530 int nodelevel = 0;
531
532 CHECKLAST(l);
533
534 p = l->header;
535 q = l->header->forward[0];
536
537 if (!q)
538 return -1;
539
540 for (k = l->level; k >= 0; --k) {
541 if (p->forward[k] == q) {
542 p->forward[k] = q->forward[k];
543 if ((k == l->level) && (p->forward[k] == NULL)
544 && (l->level > 0))
545 --(l->level);
546 if (!nodelevel)
547 nodelevel = k;
548 }
549 }
550
551 #if SKIPLIST_0TIMER_DEBUG
552 q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED;
553 #endif
554 /*
555 * If we are deleting the last element of the list,
556 * update the list's "last" pointer.
557 */
558 if (l->last == q) {
559 l->last = NULL;
560 }
561
562 --(l->stats->forward[nodelevel]);
563 #if SKIPLIST_DEBUG
564 zlog_debug("%s: decremented stats @%p:%d, now %ld", __func__, l,
565 nodelevel,
566 l->stats->forward[nodelevel] - (struct skiplistnode *)NULL);
567 #endif
568
569 if (l->del)
570 (*l->del)(q->value);
571
572 XFREE(MTYPE_SKIP_LIST_NODE, q);
573
574 CHECKLAST(l);
575
576 --(l->count);
577
578 return 0;
579 }
580
581 void skiplist_debug(struct vty *vty, struct skiplist *l)
582 {
583 int i;
584
585 if (!l)
586 l = skiplist_last_created;
587 vty_out(vty, "Skiplist %p has max level %d\n", l, l->level);
588 for (i = l->level; i >= 0; --i)
589 vty_out(vty, " @%d: %ld\n", i,
590 (long)((l->stats->forward[i])
591 - (struct skiplistnode *)NULL));
592 }
593
594 static void *scramble(int i)
595 {
596 uintptr_t result;
597
598 result = (unsigned)(i & 0xff) << 24;
599 result |= (unsigned)i >> 8;
600
601 return (void *)result;
602 }
603
604 #define sampleSize 65536
605 void skiplist_test(struct vty *vty)
606 {
607 struct skiplist *l;
608 register int i, k;
609 void *keys[sampleSize];
610 void *v;
611
612 zlog_debug("%s: entry", __func__);
613
614 l = skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES, NULL, NULL);
615
616 zlog_debug("%s: skiplist_new returned %p", __func__, l);
617
618 for (i = 0; i < 4; i++) {
619
620 for (k = 0; k < sampleSize; k++) {
621 if (!(k % 1000)) {
622 zlog_debug("%s: (%d:%d)", __func__, i, k);
623 }
624 // keys[k] = (void *)random();
625 keys[k] = (void *)scramble(k);
626 if (skiplist_insert(l, keys[k], keys[k]))
627 zlog_debug("error in insert #%d,#%d", i, k);
628 }
629
630 zlog_debug("%s: inserts done", __func__);
631
632 for (k = 0; k < sampleSize; k++) {
633
634 if (!(k % 1000))
635 zlog_debug("[%d:%d]", i, k);
636 if (skiplist_search(l, keys[k], &v))
637 zlog_debug("error in search #%d,#%d", i, k);
638
639 if (v != keys[k])
640 zlog_debug("search returned wrong value");
641 }
642
643
644 for (k = 0; k < sampleSize; k++) {
645
646 if (!(k % 1000))
647 zlog_debug("<%d:%d>", i, k);
648 if (skiplist_delete(l, keys[k], keys[k]))
649 zlog_debug("error in delete");
650 keys[k] = (void *)scramble(k ^ 0xf0f0f0f0);
651 if (skiplist_insert(l, keys[k], keys[k]))
652 zlog_debug("error in insert #%d,#%d", i, k);
653 }
654
655 for (k = 0; k < sampleSize; k++) {
656
657 if (!(k % 1000))
658 zlog_debug("{%d:%d}", i, k);
659 if (skiplist_delete_first(l))
660 zlog_debug("error in delete_first");
661 }
662 }
663
664 skiplist_free(l);
665 }