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; + +/* 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"); + 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); + INODE_SET_VID_RANGE(inode, start, (start + count - 1), vid); ret = sd_inode_write(sheep_bnode_writer, inode, 0, false, false); if (ret != SD_RES_SUCCESS) { -- 1.7.12.4 |