summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cache.c63
-rw-r--r--src/cache.h2
-rw-r--r--src/defs.h21
-rw-r--r--src/io.c30
-rw-r--r--src/main.c4
5 files changed, 96 insertions, 24 deletions
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 <rin/diagnostic.h>
#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;
}