summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Gediminas Jakutis <gediminas@varciai.lt> 2020-03-27 14:40:33 +0200
committerGravatar Gediminas Jakutis <gediminas@varciai.lt> 2020-03-27 14:40:33 +0200
commit7754455c48c50764ad7291ea508109c53b60517f (patch)
treef8b3f0fe7ad2509ff8c40a998cde91f8f7353f80 /src
parent8b4c2c3194dbf9b18ecf475597d257ee7125a1e1 (diff)
downloadalgos-ld1-7754455c48c50764ad7291ea508109c53b60517f.tar.gz
algos-ld1-7754455c48c50764ad7291ea508109c53b60517f.tar.bz2
algos-ld1-7754455c48c50764ad7291ea508109c53b60517f.zip
cache I/O implementation and fixes.
Signed-off-by: Gediminas Jakutis <gediminas@varciai.lt>
Diffstat (limited to 'src')
-rw-r--r--src/cache.c92
-rw-r--r--src/cache.h7
-rw-r--r--src/datagen.c7
-rw-r--r--src/datagen.h3
-rw-r--r--src/defs.h9
-rw-r--r--src/io.c10
-rw-r--r--src/io.h6
-rw-r--r--src/main.c73
8 files changed, 190 insertions, 17 deletions
diff --git a/src/cache.c b/src/cache.c
index ebe1047..de182ec 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -6,11 +6,14 @@
#include <stdlib.h>
#include "defs.h"
+static off_t cache_walker(struct stream * const restrict in, ssize_t idx);
+
int cache_create(struct stream * const restrict in, const struct settings * const restrict s)
{
int ret;
void *cache;
+ try(!in->cached, err, EINVAL, "cannot create cache: stream is uncached");
try(!(cache = calloc(in->n, s->stride)), err, ENOMEM, "out of memory");
in->cache = cache;
@@ -21,7 +24,9 @@ err:
int cache_populate(struct stream * const restrict in)
{
int ret = 0;
- ssize_t i;
+ size_t i;
+
+ try(!in->cached, err, EINVAL, "cannot populate cache: stream is uncached");
for (i = 0; i < in->n && !ret; ++i) {
ret = in->get_element(in, i, in->cache + i);
@@ -34,7 +39,10 @@ err:
int cache_flush(struct stream * const in)
{
int ret;
- ssize_t i;
+ size_t i;
+
+ try(!in->cached, err, EINVAL, "no cache to flush: stream is uncached");
+ try(in->out != 1, err, EINVAL, "cannot flush a non-output cache");
for (i = 0; i < in->n && !ret; ++i) {
ret = in->put_element(in, i, in->cache + i);
@@ -48,9 +56,87 @@ int cache_destroy(struct stream * const in)
{
int ret;
- try(!in->cache, err, EINVAL, "trying to destroy cache of uncached streadm");
+ try(!in->cached, err, EINVAL, "no cache to destroy: stream uncached");
free(in->cache);
in->cache = NULL;
err:
return ret;
}
+
+int cache_transfer(struct stream * const from, struct stream * const to)
+{
+ int ret;
+
+ try(!from->cached || !to->cached, err, EINVAL, "cannot transfer caches of uncached streams");
+ try(!from->cache, err, EINVAL, "no cache to transfer");
+ try(!to->cache, err, EINVAL, "cannot transfer cache: recipient cache already exists");
+
+ to->cache = from->cache;
+ from->cache = NULL;
+err:
+ return ret;
+}
+
+int cached_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data)
+{
+ int ret = 0;
+ const struct entry * const cache = in->cache;
+
+ data->val = cache[idx].val;
+
+ return ret;
+}
+
+int cached_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data)
+{
+ int ret = 0;
+ off_t offset;
+
+ offset = cache_walker(in, idx);
+ *data = in->cache[offset];
+
+ return ret;
+}
+
+int cached_put_array(struct stream * const in, ssize_t idx, const struct entry_l * const data)
+{
+ int ret = 0;
+ struct entry * const cache = in->cache;
+
+ cache[idx].val = data->val;
+
+ return ret;
+}
+
+int cached_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data)
+{
+ int ret = 0;
+ off_t offset;
+
+ offset = cache_walker(in, idx);
+ in->cache[offset] = *data;
+
+ return ret;
+}
+
+static off_t cache_walker(struct stream * const restrict in, ssize_t idx)
+{
+ size_t i;
+ off_t ret = in->prev_off;
+
+ if (in->prev_idx < idx) { /* previous index smaller, walk forward */
+ for (i = labs(idx - in->prev_idx); i; --i) {
+ ret = in->cache[ret].next;
+ }
+
+ } else if (in->prev_idx > idx) { /* previous index larger, walk backwards */
+ for (i = in->prev_idx - idx; i; --i) {
+ ret = in->cache[ret].prev;
+ }
+ } /* ...or we're standing on it already, if neither */
+
+ in->prev_idx = idx;
+ in->prev_off = ret;
+
+ return ret;
+}
diff --git a/src/cache.h b/src/cache.h
index 0607112..45215d4 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -12,5 +12,12 @@ int cache_create(struct stream * const restrict in, const struct settings * cons
int cache_populate(struct stream * const restrict in);
int cache_flush(struct stream * const in);
int cache_destroy(struct stream * const in);
+int cache_transfer(struct stream * const from, struct stream * const to);
+
+int cached_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data);
+int cached_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+
+int cached_put_array(struct stream * const in, ssize_t idx, const struct entry_l * const data);
+int cached_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
#endif /* ALGOS_CACHE_H_INCLUDED */
diff --git a/src/datagen.c b/src/datagen.c
index d4c8bab..25002e2 100644
--- a/src/datagen.c
+++ b/src/datagen.c
@@ -10,7 +10,7 @@
#include "datagen.h"
#include "defs.h"
-int gen_get_array(struct stream * const restrict in, ssize_t idx, struct entry_l * const data)
+int gen_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data)
{
int ret = 0;
(void) idx;
@@ -40,8 +40,3 @@ int gen_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l
return ret;
}
-
-int gen_put(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data)
-{
- return ENOSYS;
-}
diff --git a/src/datagen.h b/src/datagen.h
index 63b3461..0b8aa35 100644
--- a/src/datagen.h
+++ b/src/datagen.h
@@ -7,8 +7,7 @@
#include "defs.h"
-int gen_get_array(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+int gen_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data);
int gen_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
-int gen_put(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
#endif /* ALGOS_DATAGEN_H_INCLUDED */
diff --git a/src/defs.h b/src/defs.h
index ff19102..f3eb48f 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -57,15 +57,16 @@ enum dataformat {
struct stream {
size_t n;
ssize_t prev_idx;
+ off_t prev_off;
int fd;
int out;
int cached;
char *name;
struct entry_l *cache;
- int (*get_element)(struct stream * const restrict, size_t, struct entry_l *);
- int (*put_element)(struct stream * const restrict, size_t, struct entry_l *);
- int (*get_element_cache)(struct stream * const restrict, size_t, struct entry_l *);
- int (*put_element_cache)(struct stream * const restrict, size_t, struct entry_l *);
+ int (*get_element)(struct stream * const, ssize_t, struct entry_l * const);
+ int (*put_element)(struct stream * const restrict, ssize_t, struct entry_l const * const);
+ int (*get_element_cache)(struct stream * const, ssize_t, struct entry_l * const);
+ int (*put_element_cache)(struct stream * const restrict, ssize_t, struct entry_l const * const);
};
struct settings {
diff --git a/src/io.c b/src/io.c
index 9fdad38..688ec35 100644
--- a/src/io.c
+++ b/src/io.c
@@ -45,7 +45,7 @@ int stream_close(struct stream * const in)
try(!in || in->fd < 0, early_err, EINVAL, "invalid argunent");
- if (!in->out) {
+ if (in->out != 1) {
goto out;
}
@@ -135,9 +135,15 @@ static int stream_open_special(struct stream * const in)
int ret = 0;
try(stat(in->name, &st), err, errno, "stat failed: %s", strerror(ret));
- in->fd = open(in->name, O_RDONLY | O_NOATIME);
+ in->fd = open(in->name, O_RDONLY);
try(in->fd < 0, err, errno, "failed opening input file: %s", strerror(ret));
err:
return ret;
}
+
+int direct_get_array(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+int direct_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+
+int direct_put_array(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
+int direct_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
diff --git a/src/io.h b/src/io.h
index 792ebd2..eca6aec 100644
--- a/src/io.h
+++ b/src/io.h
@@ -10,4 +10,10 @@
int stream_open(struct stream * const in, const struct settings * const s);
int stream_close(struct stream * const in);
+int direct_get_array(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+int direct_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+
+int direct_put_array(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
+int direct_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data);
+
#endif /* ALGOS_IO_H_INCLUDED */
diff --git a/src/main.c b/src/main.c
index ddae024..1050741 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,6 +10,8 @@
#include <rin/diagnostic.h>
#include "io.h"
#include "defs.h"
+#include "cache.h"
+#include "datagen.h"
static char randfile[] = "/dev/urandom";
@@ -19,7 +21,10 @@ static struct stream file_in = {.prev_idx = -1, .fd = -1};
static struct stream file_out = {.prev_idx = -1, .fd = -1, .out = 1};
static int parseargs(int argc, char **argv, struct settings * settings);
+int prime_io_functions(struct settings const * const s, struct stream * const in);
void printhelp(const char * const name);
+static int stub_get(struct stream * const restrict in, ssize_t idx, struct entry_l * const data);
+static int stub_put(struct stream * const restrict in, ssize_t idx, struct entry_l const * const data);
int main(int argc, char **argv)
{
@@ -36,6 +41,9 @@ int main(int argc, char **argv)
file_in.name = settings.filein;
}
+ ret = prime_io_functions(&settings, &file_in);
+ ret = prime_io_functions(&settings, &file_out);
+
file_out.name = settings.fileout ? settings.fileout : settings.filein;
try_s((ret = stream_open(&file_in, &settings)), out);
file_out.n = file_in.n;
@@ -131,6 +139,51 @@ err:
return ret;
}
+int prime_io_functions(struct settings const * const s, struct stream * const in)
+{
+ int ret = 0;
+
+ if (in->out == 1) {
+ if (s->format == array) {
+ in->get_element = stub_get;
+ in->put_element = stub_put;
+ in->get_element_cache = cached_get_array;
+ in->put_element_cache = cached_put_array;
+ } else {
+ in->get_element = stub_get;
+ in->put_element = stub_put;
+ in->get_element_cache = cached_get_list;
+ in->put_element_cache = cached_put_list;
+ }
+ } else if (!in->out) { /* reading streams do not support dumping */
+ if (s->format == array) {
+ in->get_element = stub_get;
+ in->put_element = stub_put;
+ in->get_element_cache = stub_get;
+ in->put_element_cache = stub_put;
+ } else {
+ in->get_element = stub_get;
+ in->put_element = stub_put;
+ in->get_element_cache = stub_get;
+ in->put_element_cache = stub_put;
+ }
+ } else { /* data generation streams do not support dumping nor any cache I/O beyond initial data generation */
+ if (s->format == array) {
+ in->get_element = gen_get_array;
+ in->put_element = stub_put;
+ in->get_element_cache = stub_get;
+ in->put_element_cache = stub_put;
+ } else {
+ in->get_element = gen_get_list;
+ in->put_element = stub_put;
+ in->get_element_cache = stub_get;
+ in->put_element_cache = stub_put;
+ }
+ }
+
+ return ret;
+}
+
void printhelp(const char * const name)
{
printf( "This is a mergesort program and such\n"
@@ -153,3 +206,23 @@ void printhelp(const char * const name)
name);
return;
}
+
+static int stub_get(struct stream * const restrict in, ssize_t idx, struct entry_l * const data)
+{
+ (void) in;
+ (void) idx;
+ (void) data;
+
+ rin_warn("stub!");
+ return ENOSYS;
+}
+
+static int stub_put(struct stream * const restrict in, ssize_t idx, struct entry_l const * const data)
+{
+ (void) in;
+ (void) idx;
+ (void) data;
+
+ rin_warn("stub!");
+ return ENOSYS;
+}