示例#1
0
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);
	}
}
示例#2
0
/*
 * 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);
	}
}
示例#3
0
    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);
      }
    }
示例#4
0
文件: dm-btree.c 项目: janfj/dd-wrt
/*
 * 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;
}
示例#5
0
    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);
}
示例#9
0
    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);
      }
    }
示例#10
0
    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));
	}
}
示例#14
0
 operator const key_type&()const
 {
   if(value_ptr)return key_from_value(*value_ptr);
   else         return *key_ptr();
 }
示例#15
0
 ~rep_type()
 {
   if(!value_ptr)       key_ptr()->~key_type();
   else if(value_cted())value_ptr->~value_type();
 }
示例#16
0
 rep_type(const rep_type& x):value_ptr(x.value_ptr)
 {
   if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr());
 }