From 1b97e7b8d9759144b38ea3c732afefe0a24f2a17 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Sat, 23 Mar 2024 11:00:49 -0400 Subject: [PATCH] snapshot v2/p4; _insert done --- include/sl.h | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/include/sl.h b/include/sl.h index 48589d1..705aa07 100644 --- a/include/sl.h +++ b/include/sl.h @@ -463,9 +463,49 @@ level = __skip_toss_##decl(slist->max - 1); \ n->field.sle.gen = slist->gen; \ n->field.sle.height = level; \ - /* preserve nodes for snapshots if necessary */ \ + \ + /* preserve nodes for snapshots if necessary \ + * \ + * ALGORITHM: \ + * Foreach node in `path`, if the generation in that element \ + * is less than the current generation for the list then \ + * that node must be preserved before being mutated for this \ + * insert. So we: \ + * a) allocate a new node and copy this node into it without \ + * copying the user-supplied additional memory (that will \ + * happen iff an _update() is called on the node). \ + * b) zero out the next sle.prev/next[] pointers \ + * c) determine if this is a duplicate, if so we set the \ + * sle.next[1] field to 0x1 as a reminder to re-insert \ + * this element as a duplicate in the restore function. \ + * d) ignore the head and the tail nodes in path[] \ + */ \ for (i = 0; i < len; i++) { \ - if (path[i]->field.sle.gen >= slist->max_gen) { \ + if (path[i]->field.sle.gen < slist->gen) { \ + if (path[i] == slist->slh_head || path[i] == slist->slh_tail) \ + continue; \ + int rc; \ + decl##_node_t *src = node, *dest, *this; \ + size_t amt = sizeof(src); \ + char *d = NULL; \ + const char *s = (const char *)src; \ + rc = prefix##skip_alloc_node_##decl(slist, &dest); \ + if (rc) \ + return rc; \ + d = (char *)dest; \ + for (size_t i = 0; i < amt; i++) \ + d[i] = s[i]; \ + \ + this = dest; \ + this->field.sle.prev = NULL; \ + __SKIP_NEXT_ENTRIES_B2T(field, this) \ + { \ + this->field.sle.next[lvl] = NULL; \ + } \ + \ + if (__skip_key_compare_##decl(slist, dest, dest->field.sle.next[0], slist->aux) == 0 || \ + __skip_key_compare_##decl(slist, dest, dest->field.sle.prev, slist->aux) == 0) \ + dest->field.sle.next[0] = (decl##_node_t *)0x1; \ } \ } \ \