/* SPDX-License-Identifier: LGPL-2.1-only */ /* Copyright (C) 2020 Gediminas Jakutis */ #include #include #include #include #include #include #include "io.h" #include "defs.h" #include "cache.h" #include "datagen.h" static struct settings settings = {0}; static int parseargs(int argc, char **argv, struct settings * settings); int load_io_functions(struct settings const * const s, struct stream * const in); void printhelp(const char * const name); struct entry_l *stub_getnext(struct stream * const restrict in); static int stub_put(struct stream * const restrict in, struct entry_l const * const data); static int stub_split(struct stream * const in, struct stream * const a, struct stream * const b); static int stub_flush(struct stream * const in); /* these need to go AFTER the stub declarations */ static struct stream file_in = {stream_blank, .type = stream_in}; static struct stream file_out = {stream_blank, .type = stream_out}; static struct stream file_tmp = {stream_blank, .type = stream_outlite}; int main(int argc, char **argv) { int ret = 0; rin_diag_init(); try_s((ret = parseargs(argc, argv, &settings)), early_out); if (settings.opmode == mode_generate) { file_in.type = stream_randread; file_in.n = settings.to; } else { file_in.name = settings.filein; } load_io_functions(&settings, &file_in); file_out.name = settings.fileout ? settings.fileout : settings.filein; try_s((ret = stream_open(&file_in)), out); file_out.n = file_in.n - settings.ss; try_s((ret = stream_open(&file_out)), out); load_io_functions(&settings, &file_out); if (settings.access == cached) { try_s((ret = cache_create(&file_in)), out); try_s((ret = cache_populate(&file_in)), out); switch (settings.opmode) { case mode_fetch: if (settings.format == array) { try_s((ret = cache_block_copy(&file_in, &file_out)), out); } else { /* settings.format == list */ try_s((ret = cache_list_copy(&file_in, &file_out)), out); } break; case mode_generate: try_s((ret = cache_transfer(&file_in, &file_out)), out); break; case mode_normal: /* TODO */ ; } } else { /* uncached */ /* TODO */ } stream_close(&file_in); stream_close(&file_out); while (0) { out: stream_close(&file_in); file_out.type = stream_invalid; /* in case of error-exit, just close, don't link */ stream_close(&file_out); stream_close(&file_tmp); } early_out: return ret; } static int parseargs(int argc, char **argv, struct settings * settings) { struct settings s = {0}; ssize_t i; int ret = 0; if (argc < 2) { goto err; } for (i = 1; i < argc - 1; ++i) { if (!(strcmp(argv[i], "--sort"))) { s.opmode = mode_normal; } else if (!(strcmp(argv[i], "--fetch"))) { s.opmode = mode_fetch; } else if (!(strcmp(argv[i], "--generate"))) { s.opmode = mode_generate; } else if (!(strcmp(argv[i], "--array"))) { s.format = array; } else if (!(strcmp(argv[i], "--list"))) { s.format = list; } else if (!(strcmp(argv[i], "--cache"))) { s.access = cached; } else if (!(strcmp(argv[i], "--no-cache"))) { s.access = direct; } else if (!(strncmp(argv[i], "--position=", 11))) { if (strlen(argv[i]) > 11) { s.ss = strtoul(argv[i] + 11, NULL, 10); } else { goto err; } } else if (!(strncmp(argv[i], "--num=", 6))) { if (strlen(argv[i]) > 6) { s.to = strtoul(argv[i] + 6, NULL, 10); } else { goto err; } } else if (!(strncmp(argv[i], "--out=", 6))) { if (strlen(argv[i]) > 6) { s.fileout = argv[i] + 6; } else { goto err; } } else { goto err; } } if (!strncmp(argv[i], "--", 2)) { goto err; } else { s.filein = argv[i]; } if (!s.fileout) { s.fileout = s.filein; } if (s.opmode == mode_generate) { /* we always generate in-memory for PERFORMANCE */ s.access = cached; } else if (s.opmode == mode_fetch) { s.to = s.ss + s.to; } s.stride = s.format == list ? sizeof(struct entry_l) : sizeof(struct entry); *settings = s; while (0) { err: ret = EINVAL; printhelp(*argv); } return ret; } int load_io_functions(struct settings const * const s, struct stream * const in) { int ret = 0; if (in->type == stream_out) { if (s->format == array) { /* TODO */ } else { /* TODO */ } } else if (in->type == stream_in) { /* reading streams do not support dumping */ if (s->format == array) { /* TODO */ } else { /* TODO */ } } else if (in->type == stream_randread) { /* data generation streams do not support dumping nor any cache I/O beyond initial data generation */ if (s->format == array) { in->get_next_element_direct = gen_get_array; in->place_next_element_cache = cached_put_array; } else { in->get_next_element_direct = gen_get_list; in->place_next_element_cache = cached_put_list; } } else { ret = EINVAL; } return ret; } void printhelp(const char * const name) { printf( "This is a mergesort program and such\n" "\n" "usage:\t%s [OPTION]... FILE" "\n" "Options:\n" " --sort sort mode (default)\n" " --fetch do not sort, fetch element(s) instead\n" " --generate generate an input dataset\n" " --array use an array data format (default)\n" " --list use a linked list data format\n" " --[no]-cache cache data in memory (default) or process data in-place\n" " --position= fetch element from position \n" " --num= of elements to fetch/generate\n" " --out= write output to file\n" "\n" "In case more than one same option is provided, the last one take precedence\n" "\n", name); return; } struct entry_l *stub_getnext(struct stream * const restrict in) { struct entry_l *ret = NULL; (void) in; rin_warn("stub!"); return ret; } static int stub_put(struct stream * const restrict in, struct entry_l const * const data) { int ret = ENOSYS; (void) in; (void) data; rin_warn("stub!"); return ret; } static int stub_split(struct stream * const in, struct stream * const a, struct stream * const b) { int ret = ENOSYS; (void) in; (void) a; (void) b; rin_warn("stub!"); return ret; } static int stub_flush(struct stream * const in) { int ret = ENOSYS; (void) in; rin_warn("stub!"); return ret; }