From a5e0f06c63440b07d43e678684d6190b2bed758a Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 24 Sep 2012 22:57:38 +0400 Subject: [PATCH] Populate cache on READ command when DNET_IO_FLAGS_CACHE ioflag is set --- cache/cache.cpp | 5 +---- library/dnet.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- library/elliptics.h | 2 +- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/cache/cache.cpp b/cache/cache.cpp index f7d0c4f..fe4df6a 100644 --- a/cache/cache.cpp +++ b/cache/cache.cpp @@ -320,7 +320,7 @@ class cache_t { using namespace ioremap::cache; -int dnet_cmd_cache_io(struct dnet_net_state *st, struct dnet_cmd *cmd, char *data) +int dnet_cmd_cache_io(struct dnet_net_state *st, struct dnet_cmd *cmd, struct dnet_io_attr *io, char *data) { struct dnet_node *n = st->n; int err = -ENOTSUP; @@ -331,11 +331,8 @@ int dnet_cmd_cache_io(struct dnet_net_state *st, struct dnet_cmd *cmd, char *dat cache_t *cache = (cache_t *)n->cache; try { - struct dnet_io_attr *io = (struct dnet_io_attr *)data; boost::shared_ptr d; - data += sizeof(struct dnet_io_attr); - switch (cmd->cmd) { case DNET_CMD_WRITE: cache->write(io->id, io->start, data, io->size, !!(io->flags & DNET_IO_FLAGS_CACHE_REMOVE_FROM_DISK)); diff --git a/library/dnet.c b/library/dnet.c index d4e6e93..7cd9501 100644 --- a/library/dnet.c +++ b/library/dnet.c @@ -630,7 +630,7 @@ int dnet_process_cmd_raw(struct dnet_net_state *st, struct dnet_cmd *cmd, void * * Always check cache when reading! */ if ((io->flags & DNET_IO_FLAGS_CACHE) || (cmd->cmd != DNET_CMD_WRITE)) { - err = dnet_cmd_cache_io(st, cmd, data); + err = dnet_cmd_cache_io(st, cmd, io, data + sizeof(struct dnet_io_attr)); if (io->flags & DNET_IO_FLAGS_CACHE_ONLY) break; @@ -846,6 +846,47 @@ err_out_exit: return err; } +static int dnet_populate_cache(struct dnet_node *n, struct dnet_cmd *cmd, struct dnet_io_attr *io, + void *data, int fd, size_t fd_offset, size_t size) +{ + void *orig_data = data; + ssize_t err; + + if (!data && fd >= 0) { + ssize_t tmp_size = size; + + if (size >= n->cache_size) + return -ENOMEM; + + orig_data = data = malloc(size); + if (!data) + return -ENOMEM; + + while (tmp_size > 0) { + err = pread(fd, data, tmp_size, fd_offset); + if (err <= 0) { + dnet_log_err(n, "%s: failed to populate cache: pread: offset: %zd, size: %zd", + dnet_dump_id(&cmd->id), fd_offset, size); + goto err_out_free; + } + + data += err; + tmp_size -= err; + fd_offset += err; + } + } + + cmd->cmd = DNET_CMD_WRITE; + err = dnet_cmd_cache_io(n->st, cmd, io, orig_data); + cmd->cmd = DNET_CMD_READ; + +err_out_free: + if (data != orig_data) + free(orig_data); + + return err; +} + int dnet_send_read_data(void *state, struct dnet_cmd *cmd, struct dnet_io_attr *io, void *data, int fd, uint64_t offset, int close_on_exit) { @@ -890,6 +931,11 @@ int dnet_send_read_data(void *state, struct dnet_cmd *cmd, struct dnet_io_attr * dnet_dump_id(&c->id), dnet_cmd_string(c->cmd), (unsigned long long)io->offset, (unsigned long long)io->size); + /* only populate data which has zero offset and from column 0 */ + if ((io->flags & DNET_IO_FLAGS_CACHE) && !io->offset && (io->type == 0)) { + err = dnet_populate_cache(st->n, c, rio, data, fd, offset, io->size); + } + dnet_convert_cmd(c); dnet_convert_io_attr(rio); diff --git a/library/elliptics.h b/library/elliptics.h index 97ef058..c2992ef 100644 --- a/library/elliptics.h +++ b/library/elliptics.h @@ -720,7 +720,7 @@ int dnet_cmd_exec_raw(struct dnet_net_state *st, struct dnet_cmd *cmd, struct sp int dnet_cache_init(struct dnet_node *n); void dnet_cache_cleanup(struct dnet_node *n); -int dnet_cmd_cache_io(struct dnet_net_state *st, struct dnet_cmd *cmd, char *data); +int dnet_cmd_cache_io(struct dnet_net_state *st, struct dnet_cmd *cmd, struct dnet_io_attr *io, char *data); int __attribute__((weak)) dnet_remove_local(struct dnet_node *n, struct dnet_id *id); -- 2.11.4.GIT