void Inventory::add_item(InventoryType::Id invtype, int16_t slot, int32_t item_id, bool cash, int64_t expire, uint16_t count, const std::string& owner, int16_t flags) { items.emplace( std::piecewise_construct, std::forward_as_tuple(add_slot(invtype, slot, item_id, count, cash)), std::forward_as_tuple(item_id, expire, owner, flags) ); }
void Inventory::add_pet(InventoryType::Id invtype, int16_t slot, int32_t item_id, bool cash, int64_t expire, const std::string& name, int8_t level, int16_t closeness, int8_t fullness) { pets.emplace( std::piecewise_construct, std::forward_as_tuple(add_slot(invtype, slot, item_id, 1, cash)), std::forward_as_tuple(item_id, expire, name, level, closeness, fullness) ); }
void Inventory::add_equip(InventoryType::Id invtype, int16_t slot, int32_t item_id, bool cash, int64_t expire, uint8_t slots, uint8_t level, const EnumMap<Equipstat::Id, uint16_t>& stats, const std::string& owner, int16_t flag, uint8_t ilevel, uint16_t iexp, int32_t vicious) { equips.emplace( std::piecewise_construct, std::forward_as_tuple(add_slot(invtype, slot, item_id, 1, cash)), std::forward_as_tuple(item_id, expire, owner, flag, slots, level, stats, ilevel, iexp, vicious) ); }
/* * rot_left * * A C * / \ / \ * B C ===> A E * / \ / \ * D E B D * */ static void rot_left(node_t *root, node_t *nodeA, vtree_slot_t *slotA, vtree_pthread_data_t *vtree_data) { node_t *nodeC, *nodeD, *parent; vtree_slot_t *slotC; int slotC_old; nodeC = slotA->child[1]; if ((slotC = get_slot_from_rec_new(nodeC, vtree_data)) == NULL) { slotC_old = 1; slotC = read_slot(nodeC, vtree_data); } else slotC_old = 0; if ((nodeD = slotC->child[0]) != NULL) add_or_change_slot_parent(nodeD, nodeA, vtree_data); parent = get_node_parent(slotA->parent); if (!parent) add_or_change_slot(root, nodeC, NULL, NULL, vtree_data); else add_or_change_slot_child(parent, nodeA, nodeC, vtree_data); if (get_slot_from_rec_new(nodeA, vtree_data) == NULL) { add_slot(nodeA, slotA->child[0], nodeD, change_node_parent(slotA->parent, nodeC), vtree_data); } else { slotA->child[1] = nodeD; slotA->parent = change_node_parent(slotA->parent, nodeC); } if (slotC_old) { add_slot(nodeC, nodeA, slotC->child[1], change_node_parent(slotC->parent, parent), vtree_data); } else { slotC->child[0] = nodeA; slotC->parent = change_node_parent(slotC->parent, parent); } }
/* * rot_right * * A B * / \ / \ * B C ===> D A * / \ / \ * D E E C * */ static void rot_right(node_t *root, node_t *nodeA, vtree_slot_t *slotA, vtree_pthread_data_t *vtree_data) { node_t *nodeB, *nodeE, *parent; vtree_slot_t *slotB; int slotB_old; nodeB = slotA->child[0]; if ((slotB = get_slot_from_rec_new(nodeB, vtree_data)) == NULL) { slotB_old = 1; slotB = read_slot(nodeB, vtree_data); } else slotB_old = 0; if ((nodeE = slotB->child[1]) != NULL) add_or_change_slot_parent(nodeE, nodeA, vtree_data); parent = get_node_parent(slotA->parent); if (!parent) add_or_change_slot(root, nodeB, NULL, NULL, vtree_data); else add_or_change_slot_child(parent, nodeA, nodeB, vtree_data); if (get_slot_from_rec_new(nodeA, vtree_data) == NULL) { add_slot(nodeA, nodeE, slotA->child[1], change_node_parent(slotA->parent, nodeB), vtree_data); } else { slotA->child[0] = nodeE; slotA->parent = change_node_parent(slotA->parent, nodeB); } if (slotB_old) { add_slot(nodeB, slotB->child[0], nodeA, change_node_parent(slotB->parent, parent), vtree_data); } else { slotB->child[1] = nodeA; slotB->parent = change_node_parent(slotB->parent, parent); } }
static inline void add_or_change_slot_child(node_t *node, node_t *old_child, node_t *new_child, vtree_pthread_data_t *vtree_data) { vtree_slot_t *slot; slot = get_slot_from_rec_new(node, vtree_data); if (slot) { if (slot->child[0] == old_child) slot->child[0] = new_child; else slot->child[1] = new_child; }else { slot = read_slot(node, vtree_data); if (slot->child[0] == old_child) add_slot(node, new_child, slot->child[1], slot->parent, vtree_data); else add_slot(node, slot->child[0], new_child, slot->parent, vtree_data); } }
static inline void add_or_change_slot(node_t *node, node_t *left, node_t *right, node_t *parent, vtree_pthread_data_t *vtree_data) { vtree_slot_t *slot; slot = get_slot_from_rec_new(node, vtree_data); if (slot) { slot->child[0] = left; slot->child[1] = right; slot->parent = parent; } else { add_slot(node, left, right, parent, vtree_data); } }
static inline void add_or_change_slot_parent(node_t *node, node_t *parent, vtree_pthread_data_t *vtree_data) { vtree_slot_t *slot; slot = get_slot_from_rec_new(node, vtree_data); if (slot) slot->parent = change_node_parent(slot->parent, parent); else { slot = read_slot(node, vtree_data); add_slot(node, slot->child[0], slot->child[1], change_node_parent(slot->parent, parent), vtree_data); } }
void operator()(const Key& aKey, Sink& aSink, SinkFunction aSinkFunction) { add_slot(aKey, aSink, aSinkFunction); }
void operator()(Sink& aSink, SinkFunction aSinkFunction) { typename LockingPolicy::scope_lock sl(*this); add_slot(aSink, aSinkFunction); }
void isa8_device::add_slot(const char *tag) { device_t *dev = subdevice(tag); //printf(tag); add_slot(dynamic_cast<device_slot_interface *>(dev)); }
int list_del(int key, pthread_data_t *data) { vtree_tree_t *tree = (vtree_tree_t *)data->list; vtree_pthread_data_t *vtree_data = (vtree_pthread_data_t *)data->ds_data; node_t *prev, *node, *succ, *succ_prev, *succ_right, *node_child, *rebalance_node; vtree_slot_t *slot, *prev_slot, *succ_slot, *succ_prev_slot, *node_child_slot, *rebalance_slot, *tmp_slot; int direction, rebalance_direction, ret, val; vtree_write_cs_enter(vtree_data); do { data->nr_txn++; prev = tree->root; slot = read_slot(prev, vtree_data); node = slot->child[0]; rbtree_check(node, NULL, RB_RED, vtree_data); direction = 0; while (node != NULL) { val = node->value; if (val > key) { slot = read_slot(node, vtree_data); direction = 0; prev = node; node = slot->child[0]; } else if (val < key) { slot = read_slot(node, vtree_data); direction = 1; prev = node; node = slot->child[1]; } else break; } ret = (node != NULL); if (!ret) goto out; prev_slot = slot; slot = read_slot(node, vtree_data); rebalance_node = NULL; if (slot->child[0] == NULL) { if ((succ = slot->child[1]) != NULL) { // only right, right is red and node is black, no rebalance required rebalance_node = NULL; succ_slot = read_slot(succ, vtree_data); add_slot(succ, succ_slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } else { if (get_node_color(slot->parent) == RB_BLACK && prev != tree->root) rebalance_node = prev; else rebalance_node = NULL; } } else { if ((succ = slot->child[1]) != NULL) { // both left and right succ_prev = NULL; succ_prev_slot = NULL; succ_slot = read_slot(succ, vtree_data); node_child = succ; node_child_slot = succ_slot; while (succ_slot->child[0]) { succ_prev = succ; succ_prev_slot = succ_slot; succ = succ_slot->child[0]; succ_slot = read_slot(succ, vtree_data); } if (succ_prev) { // move succ to node add_slot(succ, slot->child[0], slot->child[1], slot->parent, vtree_data); succ_right = succ_slot->child[1]; // succ has no left child, if succ is red, no rebalance is required if (get_node_color(succ_slot->parent) == RB_BLACK) { rebalance_node = succ_prev; rebalance_direction = 0; } if (succ_prev != node_child) { add_slot(node_child, node_child_slot->child[0], node_child_slot->child[1], change_node_parent(node_child_slot->parent, succ), vtree_data); rebalance_slot = add_slot(succ_prev, succ_right, succ_prev_slot->child[1], succ_prev_slot->parent, vtree_data); } else { rebalance_slot = add_slot(succ_prev, succ_right, succ_prev_slot->child[1], change_node_parent(succ_prev_slot->parent, succ), vtree_data); } if (succ_right != NULL) { // if succ has right, it must be a red node with no child add_slot(succ_right, NULL, NULL, set_node_red(succ_prev), vtree_data); } } else { // succ is right child of node if (get_node_color(succ_slot->parent) == RB_BLACK) { rebalance_node = succ; rebalance_direction = 1; } rebalance_slot = add_slot(succ, slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } node_child = slot->child[0]; node_child_slot = read_slot(node_child, vtree_data); add_slot(node_child, node_child_slot->child[0], node_child_slot->child[1], change_node_parent(node_child_slot->parent, succ), vtree_data); } else { // only left, left is red and node is black, no rebalance required succ = slot->child[0]; rebalance_node = NULL; succ_slot = read_slot(succ, vtree_data); add_slot(succ, succ_slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } } if (prev == tree->root) { add_slot(tree->root, succ, NULL, NULL, vtree_data); } else { if (direction == 0) { tmp_slot = add_slot(prev, succ, prev_slot->child[1], prev_slot->parent, vtree_data); } else { tmp_slot = add_slot(prev, prev_slot->child[0], succ, prev_slot->parent, vtree_data); } if (rebalance_node == prev) { rebalance_slot = tmp_slot; rebalance_direction = direction; } } add_slot(node, node, node, node, vtree_data); if (rebalance_node) vtree_rebalance(tree->root, rebalance_node, rebalance_slot, rebalance_direction, vtree_data); out: ; } while (vtree_write_cs_exit(vtree_data)); if (ret == 1) vtree_free_node_later(node, vtree_data); vtree_maybe_quiescent(vtree_data); return ret; }
static void vtree_rebalance(node_t *root, node_t *prev, vtree_slot_t *prev_slot, int direction, vtree_pthread_data_t *vtree_data) { node_t *node, *sib_node, *tmp1_node, *tmp2_node; vtree_slot_t *sib_slot, *tmp1_slot, *tmp2_slot; node = NULL; loop: /* * loop invariants: * - node is black (or NULL on 1st iteration) * - node is not roiot (parent is not NULL) * -ALL leaf paths going through parent and node have * black node count is 1 lower than other leaf path */ sib_node = prev_slot->child[!direction]; if ((sib_slot = get_slot_from_rec_new(sib_node, vtree_data)) == NULL) sib_slot = read_slot(sib_node, vtree_data); if (get_node_color(sib_slot->parent) == RB_RED) { if (direction == 0) { tmp1_node = sib_slot->child[0]; rot_left(root, prev, prev_slot, vtree_data); } else { tmp1_node = sib_slot->child[1]; rot_right(root, prev, prev_slot, vtree_data); } tmp1_slot = get_slot_from_rec_new(tmp1_node, vtree_data); prev_slot->parent = set_node_red(prev_slot->parent); sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = set_node_black(sib_slot->parent); sib_node = tmp1_node; sib_slot = tmp1_slot; } // now node and sib are both black tmp1_node = sib_slot->child[!direction]; if (tmp1_node != NULL) if ((tmp1_slot = get_slot_from_rec_new(tmp1_node, vtree_data)) == NULL) tmp1_slot = read_slot(tmp1_node, vtree_data); if (tmp1_node == NULL || get_node_color(tmp1_slot->parent) == RB_BLACK) { tmp2_node = sib_slot->child[direction]; if (tmp2_node != NULL) if ((tmp2_slot = get_slot_from_rec_new(tmp2_node, vtree_data)) == NULL) tmp2_slot = read_slot(tmp2_node, vtree_data); if (tmp2_node == NULL || get_node_color(tmp2_slot->parent) == RB_BLACK) { // sibling color flip to red // this violate rbtree variant, flip parent to black if it was red, or recurse add_or_change_slot(sib_node, sib_slot->child[0], sib_slot->child[1], set_node_red(sib_slot->parent), vtree_data); if (get_node_color(prev_slot->parent) == RB_RED) prev_slot->parent = set_node_black(prev_slot->parent); else { node = prev; prev = get_node_parent(prev_slot->parent); if (prev) { if ((prev_slot = get_slot_from_rec_new(prev, vtree_data)) == NULL) { prev_slot = read_slot(prev, vtree_data); prev_slot = add_slot(prev, prev_slot->child[0], prev_slot->child[1], prev_slot->parent, vtree_data); } direction = (prev_slot->child[1] == node); goto loop; } } goto out; } if (direction == 0) { rot_right(root, sib_node, sib_slot, vtree_data); } else { rot_left(root, sib_node, sib_slot, vtree_data); } sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = set_node_red(sib_slot->parent); tmp2_slot = get_slot_from_rec_new(tmp2_node, vtree_data); tmp2_slot->parent = set_node_black(tmp2_slot->parent); tmp1_node = sib_node; tmp1_slot = sib_slot; sib_node = tmp2_node; } if (direction == 0) { rot_left(root, prev, prev_slot, vtree_data); } else { rot_right(root, prev, prev_slot, vtree_data); } sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = change_node_parent(prev_slot->parent, get_node_parent(sib_slot->parent)); prev_slot->parent = set_node_black(prev_slot->parent); add_or_change_slot(tmp1_node, tmp1_slot->child[0], tmp1_slot->child[1], set_node_black(tmp1_slot->parent), vtree_data); out: return; }
int list_ins(int key, pthread_data_t *data) { vtree_tree_t *tree = (vtree_tree_t *)data->list; vtree_pthread_data_t *vtree_data = (vtree_pthread_data_t *)data->ds_data; node_t *prev, *cur, *node, *new_node, *gprev, *prev_sib; vtree_slot_t *slot, *prev_slot, *gprev_slot, *prev_sib_slot; int prev_direction, direction, ret, val; new_node = vtree_new_node(key); assert(new_node != NULL); vtree_write_cs_enter(vtree_data); do { data->nr_txn++; prev = tree->root; prev_slot = read_slot(prev, vtree_data); cur = prev_slot->child[0]; rbtree_check(cur, NULL, RB_RED, vtree_data); direction = 0; while (cur != NULL) { val = cur->value; if (val > key) { prev_slot = read_slot(cur, vtree_data); direction = 0; prev = cur; cur = prev_slot->child[0]; } else if (val < key) { prev_slot = read_slot(cur, vtree_data); direction = 1; prev = cur; cur = prev_slot->child[1]; } else break; } ret = (cur == NULL); if (!ret) goto out; node = new_node; if (direction == 0) prev_slot = add_slot(prev, node, prev_slot->child[1], prev_slot->parent, vtree_data); else prev_slot = add_slot(prev, prev_slot->child[0], node, prev_slot->parent, vtree_data); if (prev == tree->root) { slot = add_slot(node, NULL, NULL, set_node_black(NULL), vtree_data); goto out; } // newly inserted node is red to maintain invariant slot = add_slot(node, NULL, NULL, set_node_red(prev), vtree_data); loop: if (prev == NULL) { // we can always set root to black slot->parent = set_node_black(slot->parent); goto out; } if (get_node_color(prev_slot->parent) == RB_BLACK) { // parent is black, no invariant violated goto out; } // now both node and parent are red, check grandparent, // since parent is red, there must be grandparent and it is black gprev = get_node_parent(prev_slot->parent); gprev_slot = read_slot(gprev, vtree_data); prev_direction = (gprev_slot->child[1] == prev); prev_sib = gprev_slot->child[!prev_direction]; if (prev_sib) { prev_sib_slot = read_slot(prev_sib, vtree_data); if (get_node_color(prev_sib_slot->parent) == RB_RED) { // if sib is red, change parent and sib to black // and move upwards prev_slot->parent = set_node_black(prev_slot->parent); add_slot(prev_sib, prev_sib_slot->child[0], prev_sib_slot->child[1], set_node_black(prev_sib_slot->parent), vtree_data); prev = get_node_parent(gprev_slot->parent); slot = add_slot(gprev, gprev_slot->child[0], gprev_slot->child[1], set_node_red(prev), vtree_data); node = gprev; if (prev) { prev_slot = read_slot(prev, vtree_data); direction = (prev_slot->child[1] == node); prev_slot = add_slot(prev, prev_slot->child[0], prev_slot->child[1], prev_slot->parent, vtree_data); } goto loop; } } // now, either there is no sib of parent or it is black if (prev_direction == 0) { if (direction == 1) { rot_left(tree->root, prev, prev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); prev = node; prev_slot = get_slot_from_rec_new(node, vtree_data); } rot_right(tree->root, gprev, gprev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } else { if (direction == 0) { rot_right(tree->root, prev, prev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); prev = node; prev_slot = get_slot_from_rec_new(node, vtree_data); } rot_left(tree->root, gprev, gprev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } out: ; } while (vtree_write_cs_exit(vtree_data)); if (ret == 0) vtree_free_node_later(new_node, vtree_data); vtree_maybe_quiescent(vtree_data); return ret; }
//obj_x.txt need newline at the end! int set_obj_with_line(Object * o, char *line) { char *first = line; char *second = line + char_pos_ith(line, ' ', 0) + 1; int len = str_len_char(second, '\r'); char buf[32]; memset(buf, 0, sizeof(char) * 32); if (same_until_char(first, "type ", ' ')) { strncpy(o->type, second, len); o->type[len] = 0; return 1; } if (same_until_char(first, "shape.str ", ' ')) { strncpy(o->shape.str, second, len); o->shape.str[len] = 0; return 1; } if (same_until_char(first, "timer ", ' ')) { strncpy(buf, second, len); o->timer = atoi(buf); return 1; } if (same_until_char(first, "shape.layer ", ' ')) { strncpy(buf, second, len); o->shape.layer = atoi(buf); return 1; } if (same_until_char(first, "shape.fg_color ", ' ')) { strncpy(buf, second, len); o->shape.fg_color = atoi(buf); return 1; } if (same_until_char(first, "shape.bg_color ", ' ')) { strncpy(buf, second, len); o->shape.bg_color = atoi(buf); return 1; } if (same_until_char(first, "shape.block ", ' ')) { strncpy(buf, second, len); o->shape.block = atoi(buf); return 1; } if (same_until_char(first, "hp ", ' ')) { strncpy(buf, second, len); o->hp = atoi(buf); return 1; } if (same_until_char(first, "max_hp ", ' ')) { strncpy(buf, second, len); o->max_hp = atoi(buf); return 1; } if (same_until_char(first, "mp ", ' ')) { strncpy(buf, second, len); o->mp = atoi(buf); return 1; } if (same_until_char(first, "max_mp ", ' ')) { strncpy(buf, second, len); o->max_mp = atoi(buf); return 1; } if (same_until_char(first, "power ", ' ')) { strncpy(buf, second, len); o->power = atoi(buf); return 1; } if (same_until_char(first, "item ", ' ')) { strncpy(buf, second, len); add_slot(o, "item", buf); return 1; } if (same_until_char(first, "skill ", ' ')) { strncpy(buf, second, len); add_slot(o, "skill", buf); return 1; } if (same_until_char(first, "debug ", ' ')) { strncpy(buf, second, len); add_slot(o, "debug", buf); return 1; } if (same_until_char(first, "offset_x ", ' ')) { strncpy(buf, second, len); obj_move(o->world, o, atoi(buf), 0); return 1; } if (same_until_char(first, "offset_y ", ' ')) { strncpy(buf, second, len); obj_move(o->world, o, 0, atoi(buf)); return 1; } if (same_until_char(first, "fn_tick ", ' ')) { strncpy(buf, second, len); fnptr fn = table_obj_fn_by_long_name(table_tick_obj_fn, buf); o->tick_fn = fn; if (fn == 0) return 0; return 1; } if (same_until_char(first, "fn_overlap ", ' ')) { strncpy(buf, second, len); fnptr fn = table_obj_fn_by_long_name(table_overlap_obj_fn, buf); o->overlap_fn = fn; if (fn == 0) return 0; return 1; } //ignore unknown things //if you want to inspect unknown string use return 0; return 1; }
int handle_op_records_put(RecordsPutOp * const put_op, HttpHandlerContext * const context) { yajl_gen json_gen; PanDB *pan_db; if (get_pan_db_by_layer_name(context, put_op->layer_name->val, AUTOMATICALLY_CREATE_LAYERS, &pan_db) < 0) { release_key(put_op->layer_name); release_key(put_op->key); free_slip_map(&put_op->properties); free_slip_map(&put_op->special_properties); return HTTP_NOTFOUND; } release_key(put_op->layer_name); int status; KeyNode *key_node; status = get_key_node_from_key(pan_db, put_op->key, 1, &key_node); release_key(put_op->key); if (key_node == NULL) { assert(status <= 0); free_slip_map(&put_op->properties); free_slip_map(&put_op->special_properties); return HTTP_NOTFOUND; } assert(status > 0); const Rectangle2D * const qbounds = &pan_db->qbounds; if (put_op->position_set != 0 && !(put_op->position.latitude >= qbounds->edge0.latitude && put_op->position.longitude >= qbounds->edge0.longitude && put_op->position.latitude < qbounds->edge1.latitude && put_op->position.longitude < qbounds->edge1.longitude)) { put_op->position_set = 0; } if (status > 0 && put_op->position_set != 0 && key_node->slot != NULL) { #if PROJECTION const Position2D * const previous_position = &key_node->slot->real_position; #else const Position2D * const previous_position = &key_node->slot->position; #endif if (previous_position->latitude == put_op->position.latitude && previous_position->longitude == put_op->position.longitude) { put_op->position_set = 0; } else { remove_entry_from_key_node(pan_db, key_node, 0); assert(key_node->slot != NULL); key_node->slot = NULL; } } if (put_op->position_set != 0) { Slot slot; Slot *new_slot; init_slot(&slot); slot = (Slot) { #if PROJECTION .real_position = put_op->position, #endif .position = put_op->position, .key_node = key_node }; if (add_slot(pan_db, &slot, &new_slot) != 0) { RB_REMOVE(KeyNodes_, &pan_db->key_nodes, key_node); key_node->slot = NULL; free_key_node(pan_db, key_node); free_slip_map(&put_op->properties); free_slip_map(&put_op->special_properties); return HTTP_SERVUNAVAIL; } key_node->slot = new_slot; assert(new_slot != NULL); } if (put_op->special_properties != NULL) { RecordsPutApplySpecialPropertiesCBContext cb_context = { .target_map_pnt = &key_node->properties }; slip_map_foreach(&put_op->special_properties, records_put_apply_special_properties_cb, &cb_context); free_slip_map(&put_op->special_properties); } if (key_node->properties == NULL) { key_node->properties = put_op->properties; } else { RecordsPutMergePropertiesCBContext cb_context = { .target_map_pnt = &key_node->properties }; slip_map_foreach(&put_op->properties, records_put_merge_properties_cb, &cb_context); free_slip_map(&put_op->properties); } Expirable *expirable = key_node->expirable; if (put_op->expires_at != (time_t) 0) { if (expirable == NULL) { Expirable new_expirable = { .ts = put_op->expires_at, .key_node = key_node }; expirable = add_entry_to_slab(&context->expirables_slab, &new_expirable); key_node->expirable = expirable; add_expirable_to_tree(pan_db, expirable); } else { if (expirable->ts != put_op->expires_at) { remove_expirable_from_tree(pan_db, expirable); expirable->ts = put_op->expires_at; add_expirable_to_tree(pan_db, expirable); } } assert(expirable->key_node == key_node); } else if (expirable != NULL) {