static void node_copy(struct node *left, struct node *right, int shift) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t value_size = le32_to_cpu(left->header.value_size); BUG_ON(value_size != le32_to_cpu(right->header.value_size)); if (shift < 0) { shift = -shift; BUG_ON(nr_left + shift > le32_to_cpu(left->header.max_entries)); memcpy(key_ptr(left, nr_left), key_ptr(right, 0), shift * sizeof(__le64)); memcpy(value_ptr(left, nr_left, value_size), value_ptr(right, 0, value_size), shift * value_size); } else { BUG_ON(shift > le32_to_cpu(right->header.max_entries)); memcpy(key_ptr(right, 0), key_ptr(left, nr_left - shift), shift * sizeof(__le64)); memcpy(value_ptr(right, 0, value_size), value_ptr(left, nr_left - shift, value_size), shift * value_size); } }
/* * Some little utilities for moving node data around. */ static void node_shift(struct node *n, int shift) { uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); uint32_t value_size = le32_to_cpu(n->header.value_size); if (shift < 0) { shift = -shift; BUG_ON(shift > nr_entries); BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size)); memmove(key_ptr(n, 0), key_ptr(n, shift), (nr_entries - shift) * sizeof(__le64)); memmove(value_ptr(n, 0, value_size), value_ptr(n, shift, value_size), (nr_entries - shift) * value_size); } else { BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries)); memmove(key_ptr(n, shift), key_ptr(n, 0), nr_entries * sizeof(__le64)); memmove(value_ptr(n, shift, value_size), value_ptr(n, 0, value_size), nr_entries * value_size); } }
void construct_value()const { if(!value_cted()){ /* value_ptr must be ==0, oherwise copy_value would have been called */ key_type k(*key_ptr()); key_ptr()->~key_type(); value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */ static_cast<value_type*>(spc_ptr())+1; /* next statement throws */ value_ptr=new(spc_ptr())value_type(k); } }
/* * FIXME: We shouldn't use a recursive algorithm when we have limited stack * space. Also this only works for single level trees. */ static int walk_node(struct dm_btree_info *info, dm_block_t block, int (*fn)(void *context, uint64_t *keys, void *leaf), void *context) { int r; unsigned i, nr; struct dm_block *node; struct btree_node *n; uint64_t keys; r = bn_read_lock(info, block, &node); if (r) return r; n = dm_block_data(node); nr = le32_to_cpu(n->header.nr_entries); for (i = 0; i < nr; i++) { if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { r = walk_node(info, value64(n, i), fn, context); if (r) goto out; } else { keys = le64_to_cpu(*key_ptr(n, i)); r = fn(context, &keys, value_ptr(n, i)); if (r) goto out; } } out: dm_tm_unlock(info->tm, node); return r; }
int Document::decrypt(lua_State* L) { // use the provided arg to look up the crypto keys. lua_getglobal(L, "get_crypto_key"); lua_pushvalue(L, -2); lua_call(L, 1, 1); // Get the returned value. nil will cause an error bumping us out. Bson_ro* val = Lunar<Bson_ro>::check(L, -1); std::string key_name(as_string(L, -2)); // Create a copy of the data. It is possible that the pop below // will cause the returned value to GC. lj::bson::Binary_type bt; uint32_t key_sz; const uint8_t* key_data = lj::bson::as_binary(val->node(), &bt, &key_sz); std::unique_ptr<uint8_t[], lj::Wiper<uint8_t[]> > key_ptr(new uint8_t[key_sz]); key_ptr.get_deleter().set_count(key_sz); memcpy(key_ptr.get(), key_data, key_sz); lua_pop(L, 2); try { doc_->decrypt(key_ptr.get(), key_sz, key_name); } catch (lj::Exception& ex) { lua_pushstring(L, ex.str().c_str()); lua_error(L); } return 0; }
/* * We dump as many entries from center as possible into left, then the rest * in right, then rebalance2. This wastes some cpu, but I want something * simple atm. */ static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { uint32_t max_entries = le32_to_cpu(left->header.max_entries); unsigned shift = min(max_entries - nr_left, nr_center); BUG_ON(nr_left + shift > max_entries); node_copy(left, center, -shift); left->header.nr_entries = cpu_to_le32(nr_left + shift); if (shift != nr_center) { shift = nr_center - shift; BUG_ON((nr_right + shift) > max_entries); node_shift(right, shift); node_copy(center, right, shift); right->header.nr_entries = cpu_to_le32(nr_right + shift); } *key_ptr(parent, r->index) = right->keys[0]; delete_at(parent, c->index); r->index--; dm_tm_dec(info->tm, dm_block_location(c->block)); __rebalance2(info, parent, l, r); }
static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *r) { struct btree_node *left = l->n; struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); unsigned threshold = 2 * merge_threshold(left) + 1; if (nr_left + nr_right < threshold) { /* * Merge */ node_copy(left, right, -nr_right); left->header.nr_entries = cpu_to_le32(nr_left + nr_right); delete_at(parent, r->index); /* * We need to decrement the right block, but not it's * children, since they're still referenced by left. */ dm_tm_dec(info->tm, dm_block_location(r->block)); } else { /* * Rebalance. */ unsigned target_left = (nr_left + nr_right) / 2; shift(left, right, nr_left - target_left); *key_ptr(parent, r->index) = right->keys[0]; } }
/* * Delete a specific entry from a leaf node. */ static void delete_at(struct node *n, unsigned index, size_t value_size) { unsigned nr_entries = le32_to_cpu(n->header.nr_entries); unsigned nr_to_copy = nr_entries - (index + 1); if (nr_to_copy) { memmove(key_ptr(n, index), key_ptr(n, index + 1), nr_to_copy * sizeof(__le64)); memmove(value_ptr(n, index, value_size), value_ptr(n, index + 1, value_size), nr_to_copy * value_size); } n->header.nr_entries = cpu_to_le32(nr_entries - 1); }
void construct_value()const { if(!value_cted()){ /* value_ptr must be ==0, oherwise copy_value would have been called */ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) key_type k(std::move(*key_ptr())); #else key_type k(*key_ptr()); #endif key_ptr()->~key_type(); value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */ static_cast<value_type*>(spc_ptr())+1; /* next statement throws */ value_ptr=new(spc_ptr())value_type(k); } }
int Document::encrypt(lua_State* L) { int top = lua_gettop(L); // Every arg except the first is a path to encrypt std::vector<std::string> paths; if (top > 1) { paths.resize(top - 1); while (top > 1) { // This code moves the item at lua index 2 and puts it // in C index 0. paths[top - 2] = as_string(L, -1); lua_pop(L, 1); top = lua_gettop(L); } } // use the provided arg to look up the crypto keys. lua_getglobal(L, "get_crypto_key"); lua_pushvalue(L, -2); lua_call(L, 1, 1); // Get the returned value. nil will cause an error bumping us out. Bson_ro* val = Lunar<Bson_ro>::check(L, -1); std::string key_name(as_string(L, -2)); // Create a copy of the data. It is possible that the pop below // will cause the returned value to GC. lj::bson::Binary_type bt; uint32_t key_sz; const uint8_t* key_data = lj::bson::as_binary(val->node(), &bt, &key_sz); std::unique_ptr<uint8_t[], lj::Wiper<uint8_t[]> > key_ptr(new uint8_t[key_sz]); key_ptr.get_deleter().set_count(key_sz); memcpy(key_ptr.get(), key_data, key_sz); lua_pop(L, 2); try { // XXX Change this to get the server from somewhere. doc_->encrypt(lj::Uuid::k_nil, key_ptr.get(), key_sz, key_name, paths); } catch (lj::Exception& ex) { lua_pushstring(L, ex.str().c_str()); lua_error(L); } return 0; }
/* * Redistributes entries among 3 sibling nodes. */ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { int s; uint32_t max_entries = le32_to_cpu(left->header.max_entries); unsigned target = (nr_left + nr_center + nr_right) / 3; BUG_ON(target > max_entries); if (nr_left < nr_right) { s = nr_left - target; if (s < 0 && nr_center < -s) { /* not enough in central node */ shift(left, center, nr_center); s = nr_center - target; shift(left, right, s); nr_right += s; } else shift(left, center, s); shift(center, right, target - nr_right); } else { s = target - nr_right; if (s > 0 && nr_center < s) { /* not enough in central node */ shift(center, right, nr_center); s = target - nr_center; shift(left, right, s); nr_left -= s; } else shift(center, right, s); shift(left, center, nr_left - target); } *key_ptr(parent, c->index) = center->keys[0]; *key_ptr(parent, r->index) = right->keys[0]; }
static void node_copy(struct node *left, struct node *right, int shift) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); if (shift < 0) { shift = -shift; memcpy(key_ptr(left, nr_left), key_ptr(right, 0), shift * sizeof(__le64)); memcpy(value_ptr(left, nr_left, sizeof(__le64)), value_ptr(right, 0, sizeof(__le64)), shift * sizeof(__le64)); } else { memcpy(key_ptr(right, 0), key_ptr(left, nr_left - shift), shift * sizeof(__le64)); memcpy(value_ptr(right, 0, sizeof(__le64)), value_ptr(left, nr_left - shift, sizeof(__le64)), shift * sizeof(__le64)); } }
/* * Some little utilities for moving node data around. */ static void node_shift(struct node *n, int shift) { uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); if (shift < 0) { shift = -shift; memmove(key_ptr(n, 0), key_ptr(n, shift), (nr_entries - shift) * sizeof(__le64)); memmove(value_ptr(n, 0, sizeof(__le64)), value_ptr(n, shift, sizeof(__le64)), (nr_entries - shift) * sizeof(__le64)); } else { memmove(key_ptr(n, shift), key_ptr(n, 0), nr_entries * sizeof(__le64)); memmove(value_ptr(n, shift, sizeof(__le64)), value_ptr(n, 0, sizeof(__le64)), nr_entries * sizeof(__le64)); } }
operator const key_type&()const { if(value_ptr)return key_from_value(*value_ptr); else return *key_ptr(); }
~rep_type() { if(!value_ptr) key_ptr()->~key_type(); else if(value_cted())value_ptr->~value_type(); }
rep_type(const rep_type& x):value_ptr(x.value_ptr) { if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr()); }