/* actual insert: returns true -> insert ok or key found, false -> alloc failure */ bool cbtree_insert(struct CBTree *tree, void *obj) { const void *key, *old_key; unsigned newbit, klen, old_klen; void *old_obj; if (!tree->root) return insert_first(tree, obj); /* current key */ klen = get_key(tree, obj, &key); /* nearest key in tree */ old_obj = raw_lookup(tree, key, klen); old_klen = get_key(tree, old_obj, &old_key); /* first differing bit is the target position */ newbit = find_crit_bit(key, klen, old_key, old_klen); if (newbit == SAME_KEY) return true; return insert_at(tree, newbit, key, klen, obj); }
/** * Insert or update the given value under the given key. * * The map takes ownership of the value. * * @param key The key to insert under. * @param value The value to be inserted. * * @return 0 on success, negative values on error. */ int insert(key_type key, value_type value) { auto dest_entry = root; while (dest_entry->inode != nullptr) { auto n = dest_entry->inode; dest_entry = n->entries[BIT_IS_SET(key, n->diff)]; } entry e(key, value); auto pop = nvobj::pool_by_vptr(this); nvobj::transaction::exec_tx(pop, [&] { if (dest_entry->key == 0 || dest_entry->key == key) { nvobj::delete_persistent<T>(dest_entry->value); *dest_entry = e; } else { insert_leaf(&e, find_crit_bit(dest_entry->key, key)); } }); return 0; }
/* * ctree_insert -- inserts a new key into the tree */ int ctree_insert(struct ctree *t, uint64_t key) { void **dst = &t->root; struct node *a = NULL; int err; if ((err = pthread_mutex_lock(&t->lock)) != 0) return err; /* descend the path until a best matching key is found */ while (NODE_IS_INTERNAL(*dst)) { a = NODE_INTERNAL_GET(*dst); dst = &a->slots[BIT_IS_SET(key, a->diff)]; } uint64_t *dstkeyp = *dst; uint64_t *kp = Malloc(sizeof (uint64_t)); /* allocate leaf node */ if (kp == NULL) { err = ENOMEM; goto error_leaf_malloc; } *kp = key; if (dstkeyp == NULL) { /* root */ *dst = kp; goto out; } uint64_t dstkey = *dstkeyp; struct node *n = Malloc(sizeof (*n)); /* internal node */ if (n == NULL) { err = ENOMEM; goto error_internal_Malloc; } if (dstkey == key) { err = EINVAL; goto error_duplicate; } n->diff = find_crit_bit(dstkey, key); /* insert the node at the direction based on the critical bit */ int d = BIT_IS_SET(key, n->diff); n->slots[d] = kp; /* find the appropriate position in the tree to insert the node */ dst = &t->root; while (NODE_IS_INTERNAL(*dst)) { a = NODE_INTERNAL_GET(*dst); /* the critical bits have to be sorted */ if (a->diff < n->diff) break; dst = &a->slots[BIT_IS_SET(key, a->diff)]; } /* insert the found destination in the other slot */ n->slots[!d] = *dst; NODE_INTERNAL_SET(*dst, n); out: if ((errno = pthread_mutex_unlock(&t->lock)) != 0) ERR("!pthread_mutex_unlock"); return err; error_internal_Malloc: Free(kp); error_duplicate: Free(n); error_leaf_malloc: if ((errno = pthread_mutex_unlock(&t->lock)) != 0) ERR("!pthread_mutex_unlock"); return err; }