[sheepdog] [PATCH v2 3/3] lib: add cache version of writer and reader
Liu Yuan
namei.unix at gmail.com
Mon Feb 17 12:29:59 CET 2014
On Mon, Feb 17, 2014 at 07:07:17PM +0800, Robin Dong wrote:
> From: Robin Dong <sanbai at taobao.com>
>
> Add new functions to repleace default writer and reader so it can cache
> entire ext-node when set_vid_for_btree() need to access ext-node.
>
> Signed-off-by: Robin Dong <sanbai at taobao.com>
> ---
> lib/sd_inode.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> sheep/http/oalloc.c | 4 +-
> 2 files changed, 111 insertions(+), 2 deletions(-)
>
> diff --git a/lib/sd_inode.c b/lib/sd_inode.c
> index 53035b0..a02d472 100644
> --- a/lib/sd_inode.c
> +++ b/lib/sd_inode.c
> @@ -216,6 +216,106 @@ static void dump_btree(read_node_fn reader, struct sd_inode *inode)
> }
>
> /*
> + * This is the cache for inode and ext-node (B-tree), so we name it 'icache'.
> + * Cache of the same inode and ext-node dose not support concurrent operations
> + * so it could only be used in sd_inode_set_vid() which will be protected by
> + * distributed lock and should be released in the end of sd_inode_set_vid().
> + */
> +static write_node_fn raw_writer;
> +static read_node_fn raw_reader;
raw_{reader, writer} -> caller_{reader, writer} is easier to understand.
> +
> +/* no rationale */
> +#define NUMBER_OF_CACHE 4
> +
> +struct inode_cache {
> + uint64_t oid;
> + unsigned char mem[SD_INODE_DATA_INDEX_SIZE];
> +} cache_array[NUMBER_OF_CACHE];
> +static int cache_idx;
> +
> +static void icache_init(void)
> +{
> + cache_idx = 0;
> +}
> +
> +static void icache_writeout(write_node_fn writer, int copies, int policy)
> +{
> + int i;
> + for (i = 0; i < cache_idx; i++) {
> + writer(cache_array[i].oid, cache_array[i].mem,
> + SD_INODE_DATA_INDEX_SIZE, 0, 0, copies, policy,
> + false, false);
> + }
> +}
> +
> +static void icache_release(write_node_fn writer, int copies, int policy)
> +{
> + icache_writeout(writer, copies, policy);
> + icache_init();
> +}
> +
> +static void icache_insert(write_node_fn writer, int copies, int policy,
> + uint64_t oid, void *mem)
> +{
> + int i;
> + for (i = 0; i < cache_idx; i++) {
> + if (oid == cache_array[i].oid) {
> + memcpy(cache_array[i].mem, mem,
> + SD_INODE_DATA_INDEX_SIZE);
> + return;
> + }
> + }
> +
> + if (cache_idx == (NUMBER_OF_CACHE - 1)) {
> + sd_info("cache for B-tree is full, so write all out");
why user should bother with this information? I think sd_debug is good enough.
> + icache_release(writer, copies, policy);
> + }
> +
> + /* insert new cache */
> + cache_array[cache_idx].oid = oid;
> + memcpy(cache_array[cache_idx].mem, mem, SD_INODE_DATA_INDEX_SIZE);
> + cache_idx++;
> +}
> +
> +static void *icache_find(uint64_t oid)
> +{
> + int i;
> + for (i = 0; i < cache_idx; i++) {
> + if (cache_array[i].oid == oid)
> + return cache_array[i].mem;
> + }
> + return NULL;
> +}
> +
> +static int icache_writer(uint64_t id, void *mem, unsigned int len,
> + uint64_t offset, uint32_t flags, int copies,
> + int copy_policy, bool create, bool direct)
> +{
> + /* Only try to cache entire ext-node */
> + if (!offset && !create && !direct && len == SD_INODE_DATA_INDEX_SIZE) {
> + icache_insert(raw_writer, copies, copy_policy, id, mem);
> + return SD_RES_SUCCESS;
> + }
> + return raw_writer(id, mem, len, offset, flags, copies, copy_policy,
> + create, direct);
> +}
> +
> +static int icache_reader(uint64_t id, void **mem, unsigned int len,
> + uint64_t offset)
> +{
> + void *data;
> +
> + if (!offset && len == SD_INODE_DATA_INDEX_SIZE) {
> + data = icache_find(id);
> + if (data) {
> + memcpy(*mem, data, len);
> + return SD_RES_SUCCESS;
> + }
> + }
> + return raw_reader(id, mem, len, offset);
> +}
> +
> +/*
> * Search for the key in a B-tree node. If can't find it, return the position
> * for insert operation. So we can't just use xbsearch().
> */
> @@ -626,6 +726,13 @@ void sd_inode_set_vid(write_node_fn writer, read_node_fn reader,
> struct sd_extent_header *header;
> int idx;
>
> + /* save default writer and reader */
> + raw_writer = writer;
> + raw_reader = reader;
> + /* use cache version of writer and reader */
> + writer = icache_writer;
> + reader = icache_reader;
> +
> for (idx = idx_start; idx <= idx_end; idx++) {
> if (inode->store_policy == 0)
> inode->data_vdi_id[idx] = vdi_id;
> @@ -641,6 +748,8 @@ void sd_inode_set_vid(write_node_fn writer, read_node_fn reader,
> }
> if (inode->store_policy != 0)
> dump_btree(reader, inode);
> +
> + icache_release(raw_writer, inode->nr_copies, inode->copy_policy);
> }
>
> /*
> diff --git a/sheep/http/oalloc.c b/sheep/http/oalloc.c
> index b3d9583..3f3fb8b 100644
> --- a/sheep/http/oalloc.c
> +++ b/sheep/http/oalloc.c
> @@ -178,8 +178,8 @@ int oalloc_new_finish(uint32_t vid, uint64_t start, uint64_t count)
> goto out;
> }
>
> - for (uint64_t i = 0; i < count; i++)
> - INODE_SET_VID(inode, start + i, vid);
> + sd_info("start %"PRIu64" end %"PRIu64, start, start + count - 1);
ditto.
Thanks
Yuan
More information about the sheepdog
mailing list