From fb383b792d1044405188e42c4b827858c4a3a038 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Mon, 15 Feb 2021 09:18:31 +0200 Subject: now with generating lists! Signed-off-by: Gediminas Jakutis --- src/cache.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- src/cache.h | 2 +- src/defs.h | 21 ++++++++++++++++----- src/io.c | 30 ++++++++++++++++++++++++++--- src/main.c | 4 ---- 5 files changed, 96 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/cache.c b/src/cache.c index bb41689..fe97fef 100644 --- a/src/cache.c +++ b/src/cache.c @@ -9,6 +9,8 @@ #include #include "defs.h" +static int cache_rewind(struct stream * const in); + int cache_create(struct stream * const in) { int ret = 0; @@ -100,15 +102,23 @@ err: return ret; } -int cache_list_copy(struct stream const * const src, struct stream * const dest) +int cache_list_copy(struct stream * const src, struct stream * const dest) { - int ret = ENOSYS; + int ret = 0; + struct entry_l *tmp; - (void) src; - (void) dest; + try(src->settings->access != cached || dest->settings->access != cached, err, EINVAL, "cannot cache-copy between uncached streams"); + try(!src->cache, err, EINVAL, "no cache to transfer"); + try(!(src->n < dest->settings->to), err, EINVAL, "invalid copy size"); + try(!dest->cache, err, EINVAL, "no cache to transfer to"); - rin_warn("stub!"); + while ((tmp = get(src))) { + put(dest, tmp); + } + + cache_rewind(src); +err: return ret; } @@ -163,7 +173,7 @@ struct entry_l *cached_get_list(struct stream * const in) if (in->index < in->n) { ret = in->cnode; - in->cnode = (struct entry_l *) ret->next; + in->cnode = ret->next; ++in->index; } @@ -172,7 +182,7 @@ struct entry_l *cached_get_list(struct stream * const in) int cached_put_array(struct stream * const in, const struct entry_l * const data) { - int ret = EINVAL; + int ret = 0; if (in->index < in->n) { in->cache_a[in->index].val = data->val; @@ -182,14 +192,45 @@ int cached_put_array(struct stream * const in, const struct entry_l * const data return ret; } +/* This is were fun with the fact mergesort is NOT an in-place algorightm begins. + * Since we only ever need to "put" on a) generating data and b) merging lists, + * we basically have to generate the list anew each and every time. For generating, + * it's a no-brainer, but for lists, while reusing existing nodes COULD be done in + * a chached variant, file variant cannot do this, as cross-file links are not + * something that could be handled without going into pretty insane (and laughably + * inefficient) lenghts either way. + * + * And thus alas, we have no option but to just make a list anew + */ int cached_put_list(struct stream * const restrict in, const struct entry_l * const node) { - int ret = ENOSYS; + int ret = 0; - (void) in; - (void) node; + if (!in->cnode) { /* if this is the very first one */ + in->pnode = NULL; + in->cnode = in->cache_l; + in->cnode->val = node->val; + in->cnode->next = NULL; + in->index = 0; + } else { + in->pnode = in->cnode; + in->cnode = in->cnode + 1; /* lol says librin, lmao */ + in->pnode->next = in->cnode; + in->cnode->val = node->val; + in->cnode->next = NULL; + ++in->index; + } - rin_warn("stub!"); + return ret; +} + +int cache_rewind(struct stream * const in) +{ + int ret = 0; + + in->pnode = NULL; + in->cnode = in->cnode ? in->cache_l : NULL; + in->index = 0; return ret; } diff --git a/src/cache.h b/src/cache.h index 055a686..63f5560 100644 --- a/src/cache.h +++ b/src/cache.h @@ -16,7 +16,7 @@ int cache_destroy(struct stream * const in); /* BLOCKMANIP */ int cache_transfer(struct stream * const src, struct stream * const dest); int cache_block_copy(struct stream const * const src, struct stream * const dest); -int cache_list_copy(struct stream const * const src, struct stream * const dest); +int cache_list_copy(struct stream * const src, struct stream * const dest); int cache_block_split(struct stream * const src, struct stream * const A, struct stream * const B); int cache_list_split(struct stream * const src, struct stream * const A, struct stream * const B); diff --git a/src/defs.h b/src/defs.h index 39960d9..f6a7f91 100644 --- a/src/defs.h +++ b/src/defs.h @@ -30,6 +30,18 @@ .get_next_element_cache = stub_getnext, .place_next_element_direct = stub_put, \ .place_next_element_cache = stub_put, .split = stub_split, .flush = stub_flush +union nextoff { + struct entry_l *next; + ptrdiff_t offset; + int64_t spacer; /* make sure it is 8-byte-alligned on 32 bit pointer systems */ +}; + +union cachewrap { + char *cache; + struct entry *cache_a; + struct entry_l *cache_l; +}; + /* for array implementation */ struct entry { uint64_t val; @@ -38,7 +50,7 @@ struct entry { /* for linked list implementation */ struct entry_l { struct entry; - int64_t next; /* """pointer""" to the next element. */ + union nextoff; }; enum opmode { @@ -73,11 +85,10 @@ struct stream { char *name; size_t stride; size_t index; - struct entry_l *cnode; - char *cache; + struct entry_l *pnode; /* "previous" node */ + struct entry_l *cnode; /* "current" node */ + union cachewrap; struct settings *settings; - struct entry *cache_a; - struct entry_l *cache_l; struct entry_l *(*get_next_element_direct)(struct stream * const); struct entry_l *(*get_next_element_cache)(struct stream * const); int (*place_next_element_direct)(struct stream * const, struct entry_l const * const); diff --git a/src/io.c b/src/io.c index 41c5880..9dae2e1 100644 --- a/src/io.c +++ b/src/io.c @@ -218,11 +218,35 @@ err: int stream_flush_list(struct stream * const in) { - int ret = ENOSYS; + ssize_t ret = 0; + size_t remaining; + ssize_t written; + size_t i; + + /* adjust pointers to have a base starting at 0, to cater to disk storage format. + * File offsets are otherwise 1:1 to memory addresses, which is neat. + * Just don't process the last offset, as that is always NULL/zero. + * */ - (void) in; + for (i = 0; i < (in->n - 1); ++i) { + in->cache_l[i].offset = (char *) in->cache_l[i].next - in->cache; + } - rin_warn("stub!"); + /* dump the bloody list */ + written = 0; + remaining = in->n * in->settings->stride; + do { + ret = write(in->fd, in->cache + written, remaining); + if (ret < 0) { + try(errno != EAGAIN, err, errno, "Writing to stream failed with %zi", ret); + } else { + written += ret; + remaining -= ret; + ret = 0; + } + } while (remaining); + +err: return ret; } diff --git a/src/main.c b/src/main.c index 1733f84..e3455d1 100644 --- a/src/main.c +++ b/src/main.c @@ -155,10 +155,6 @@ static int parseargs(int argc, char **argv, struct settings * settings) if (s.opmode == mode_generate) { /* we always generate in-memory for PERFORMANCE */ s.access = cached; - if (s.format == list) { - /* we need to generate the empty header, too */ - ++s.to; - } } else if (s.opmode == mode_fetch) { s.to = s.ss + s.to; } -- cgit v1.2.3