commit 691beeb817d3454ace5b68ccc1ea32f6c753d7ae
parent 12513286b9fbfc7364afda7b995bfe46e6ff5546
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 16 Oct 2023 11:52:27 +0200
Make memory mapping optional
By default, data is now loaded into memory. Memory mapping becomes an
option of the load functions. As a consequence, this commit introduces
API breaks. But we're taking advantage of this update to group the
input arguments in a specific structure. Future maintenance of the
calling code should therefore be simplified when adding a new optional
argument if the said structure is initialized with its default value.
When refactoring, we added the path of the loaded file or the name of
the loaded stream as a data item in the sars structure. This allows us
to avoid passing this name as an argument to internal load functions,
since they can retrieve it from this structure. We have also added a
public sars_get_name function to obtain this name.
Diffstat:
| M | src/sars.c | | | 359 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
| M | src/sars.h | | | 27 | ++++++++++++++++++++++++--- |
| M | src/sars_c.h | | | 16 | ++++++++++++++++ |
| M | src/test_sars_load.c | | | 73 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
4 files changed, 398 insertions(+), 77 deletions(-)
diff --git a/src/sars.c b/src/sars.c
@@ -22,6 +22,7 @@
#include "sars_log.h"
#include <rsys/algorithm.h>
+#include <rsys/cstr.h>
#include <rsys/hash.h>
#include <unistd.h> /* sysconf support */
@@ -39,6 +40,20 @@ check_sars_create_args(const struct sars_create_args* args)
return args ? RES_OK : RES_BAD_ARG;
}
+static INLINE res_T
+check_sars_load_args(const struct sars_load_args* args)
+{
+ if(!args || !args->path) return RES_BAD_ARG;
+ return RES_OK;
+}
+
+static INLINE res_T
+check_sars_load_stream_args(const struct sars_load_stream_args* args)
+{
+ if(!args || !args->stream || !args->name) return RES_BAD_ARG;
+ return RES_OK;
+}
+
static void
reset_sars(struct sars* sars)
{
@@ -52,20 +67,20 @@ static res_T
read_band
(struct sars* sars,
struct band* band,
- FILE* stream,
- const char* stream_name)
+ FILE* stream)
{
size_t iband;
res_T res = RES_OK;
- ASSERT(sars && band && stream_name);
+ ASSERT(sars && band);
+ band->sars = sars;
iband = (size_t)(band - darray_band_cdata_get(&sars->bands));
/* Read band definition */
#define READ(Var, Name) { \
if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
log_err(sars, "%s: band %lu: could not read the %s.\n", \
- stream_name, (unsigned long)iband, (Name)); \
+ sars_get_name(sars), (unsigned long)iband, (Name)); \
res = RES_IO_ERR; \
goto error; \
} \
@@ -78,7 +93,7 @@ read_band
if(band->low < 0 || band->low >= band->upp) {
log_err(sars,
"%s: band %lu: invalid band range [%g, %g[.\n",
- stream_name, (unsigned long)iband, band->low, band->upp);
+ sars_get_name(sars), (unsigned long)iband, band->low, band->upp);
res = RES_BAD_ARG;
goto error;
}
@@ -89,23 +104,223 @@ error:
goto exit;
}
+static res_T
+map_data
+ (struct sars* sars,
+ const int fd, /* File descriptor */
+ const size_t filesz, /* Overall filesize */
+ const char* data_name,
+ const off_t offset, /* Offset of the data into file */
+ const size_t map_len,
+ void** out_map) /* Lenght of the data to map */
+{
+ void* map = NULL;
+ res_T res = RES_OK;
+ ASSERT(sars && filesz && data_name && map_len && out_map);
+ ASSERT(IS_ALIGNED((size_t)offset, (size_t)sars->pagesize));
+
+ if((size_t)offset + map_len > filesz) {
+ log_err(sars, "%s: the %s to map exceed the file size\n",
+ sars_get_name(sars), data_name);
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ map = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, offset);
+ if(map == MAP_FAILED) {
+ log_err(sars, "%s: could not map the %s -- %s\n",
+ sars_get_name(sars), data_name, strerror(errno));
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+exit:
+ *out_map = map;
+ return res;
+error:
+ if(map == MAP_FAILED) map = NULL;
+ goto exit;
+}
static res_T
-load_stream(struct sars* sars, FILE* stream, const char* stream_name)
+map_file(struct sars* sars, FILE* stream)
{
+ size_t filesz;
size_t map_len;
size_t iband;
+ size_t nbands;
+ off_t offset;
+ res_T res = RES_OK;
+ ASSERT(sars && stream);
+
+ /* Compute the length in bytes of the k to map for each band/quadrature point */
+ map_len = ALIGN_SIZE(sars->nnodes * sizeof(float)*2, sars->pagesize);
+
+ /* Compute the offset toward the 1st list of radiative coefficients */
+ offset = ftell(stream);
+ offset = (off_t)ALIGN_SIZE((uint64_t)offset, sars->pagesize);
+
+ /* Retrieve the overall filesize */
+ fseek(stream, 0, SEEK_END);
+ filesz = (size_t)ftell(stream);
+
+ nbands = sars_get_bands_count(sars);
+ FOR_EACH(iband, 0, nbands) {
+ struct band* band = NULL;
+
+ band = darray_band_data_get(&sars->bands) + iband;
+ band->map_len = map_len;
+
+ /* Mapping per band radiative coefficients */
+ res = map_data(sars, fileno(stream), filesz, "radiative coefficients",
+ offset, band->map_len, (void**)&band->k_list);
+ if(res != RES_OK) {
+ log_err(sars,
+ "%s: data mapping error for band %lu\n",
+ sars_get_name(sars), (unsigned long)iband);
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ offset = (off_t)((size_t)offset + map_len);
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+read_padding(FILE* stream, const size_t padding)
+{
+ char chunk[1024];
+ size_t remaining_nbytes = padding;
+
+ while(remaining_nbytes) {
+ const size_t nbytes = MMIN(sizeof(chunk), remaining_nbytes);
+ if(fread(chunk, 1, nbytes, stream) != nbytes) return RES_IO_ERR;
+ remaining_nbytes -= nbytes;
+ }
+ return RES_OK;
+}
+
+/* Return the size in bytes of the data layout and band descriptors */
+static INLINE size_t
+compute_sizeof_header(struct sars* sars)
+{
+ size_t sizeof_header = 0;
+ ASSERT(sars);
+
+ sizeof_header =
+ sizeof(uint64_t) /* pagesize */
+ + sizeof(uint64_t) /* #bands */
+ + sizeof(uint64_t) /* #nodes */
+ + sizeof(double[2]) * sars_get_bands_count(sars); /* Bands */
+ return sizeof_header;
+}
+
+static res_T
+load_data
+ (struct sars* sars,
+ FILE* stream,
+ const char* data_name,
+ float** out_data)
+{
+ float* data = NULL;
+ res_T res = RES_OK;
+ ASSERT(sars && stream && data_name && out_data);
+
+ data = MEM_ALLOC(sars->allocator, sizeof(float[2]/*ka and ks*/)*sars->nnodes);
+ if(!data) {
+ res = RES_MEM_ERR;
+ log_err(sars, "%s: could not allocate the %s -- %s\n",
+ sars_get_name(sars), data_name, res_to_cstr(res));
+ goto error;
+ }
+
+ if(fread(data, sizeof(float[2]), sars->nnodes, stream) != sars->nnodes) {
+ res = RES_IO_ERR;
+ log_err(sars, "%s: could not read the %s -- %s\n",
+ sars_get_name(sars), data_name, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ *out_data = data;
+ return res;
+error:
+ if(data) { MEM_RM(sars->allocator, data); data = NULL; }
+ goto exit;
+}
+
+static res_T
+load_file(struct sars* sars, FILE* stream)
+{
+ size_t sizeof_header;
+ size_t sizeof_k_list;
+ size_t padding_bytes;
+ size_t iband;
+ size_t nbands;
+ res_T res = RES_OK;
+ ASSERT(sars && stream);
+
+ sizeof_header = compute_sizeof_header(sars);
+ sizeof_k_list = sizeof(float[2])*sars->nnodes;
+
+ padding_bytes = ALIGN_SIZE(sizeof_header, sars->pagesize) - sizeof_header;
+ if((res = read_padding(stream, padding_bytes)) != RES_OK) goto error;
+
+ /* Calculate the padding between the lists of radiative coefficients. Note
+ * that this padding is the same between each list */
+ padding_bytes = ALIGN_SIZE(sizeof_k_list, sars->pagesize) - sizeof_k_list;
+
+ nbands = sars_get_bands_count(sars);
+ FOR_EACH(iband, 0, nbands) {
+ struct band* band = NULL;
+
+ band = darray_band_data_get(&sars->bands) + iband;
+ ASSERT(!band->k_list && band->sars == sars);
+
+ /* Loading per band scattering coefficients */
+ res = load_data(sars, stream, "radiative coefficients", &band->k_list);
+ if(res != RES_OK) {
+ log_err(sars,
+ "%s: data loading error for band %lu\n",
+ sars_get_name(sars), (unsigned long)iband);
+ goto error;
+ }
+
+ if((res = read_padding(stream, padding_bytes)) != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+load_stream(struct sars* sars, const struct sars_load_stream_args* args)
+{
+ size_t iband;
uint64_t nbands;
- off_t offset = 0;
res_T res = RES_OK;
- ASSERT(sars && stream && stream_name);
+ ASSERT(sars && check_sars_load_stream_args(args) == RES_OK);
reset_sars(sars);
+ res = str_set(&sars->name, args->name);
+ if(res != RES_OK) {
+ log_err(sars, "%s: unable to duplicate path to loaded data or stream name\n",
+ args->name);
+ goto error;
+ }
+
/* Read file header */
#define READ(Var, Name) { \
- if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
- log_err(sars, "%s: could not read the %s.\n", stream_name, (Name)); \
+ if(fread((Var), sizeof(*(Var)), 1, args->stream) != 1) { \
+ log_err(sars, "%s: could not read the %s.\n", sars_get_name(sars), (Name));\
res = RES_IO_ERR; \
goto error; \
} \
@@ -120,7 +335,7 @@ load_stream(struct sars* sars, FILE* stream, const char* stream_name)
log_err(sars,
"%s: invalid page size %lu. The page size attribute must be aligned on "
"the page size of the operating system (%lu).\n",
- stream_name,
+ sars_get_name(sars),
(unsigned long)sars->pagesize,
(unsigned long)sars->pagesize_os);
res = RES_BAD_ARG;
@@ -128,13 +343,13 @@ load_stream(struct sars* sars, FILE* stream, const char* stream_name)
}
if(!nbands) {
log_err(sars, "%s: invalid number of bands %lu.\n",
- stream_name, (unsigned long)nbands);
+ sars_get_name(sars), (unsigned long)nbands);
res = RES_BAD_ARG;
goto error;
}
if(!sars->nnodes) {
log_err(sars, "%s: invalid number of nodes %lu.\n",
- stream_name, (unsigned long)sars->nnodes);
+ sars_get_name(sars), (unsigned long)sars->nnodes);
res = RES_BAD_ARG;
goto error;
}
@@ -143,20 +358,20 @@ load_stream(struct sars* sars, FILE* stream, const char* stream_name)
res = darray_band_resize(&sars->bands, nbands);
if(res != RES_OK) {
log_err(sars, "%s: could not allocate the list of bands (#bands=%lu).\n",
- stream_name, (unsigned long)nbands);
+ sars_get_name(sars), (unsigned long)nbands);
goto error;
}
/* Read the band description */
FOR_EACH(iband, 0, nbands) {
struct band* band = darray_band_data_get(&sars->bands) + iband;
- res = read_band(sars, band, stream, stream_name);
+ res = read_band(sars, band, args->stream);
if(res != RES_OK) goto error;
if(iband > 0 && band[0].low < band[-1].upp) {
log_err(sars,
"%s: bands must be sorted in ascending order and must not "
"overlap (band %lu in [%g, %g[ nm; band %lu in [%g, %g[ nm).\n",
- stream_name,
+ sars_get_name(sars),
(unsigned long)(iband-1), band[-1].low, band[-1].upp,
(unsigned long)(iband), band[ 0].low, band[ 0].upp);
res = RES_BAD_ARG;
@@ -164,30 +379,12 @@ load_stream(struct sars* sars, FILE* stream, const char* stream_name)
}
}
- /* Compute the length in bytes of the k to map for each band/quadrature point */
- map_len = ALIGN_SIZE(sars->nnodes * sizeof(float)*2, sars->pagesize);
-
- /* Compute the offset toward the 1st list of radiative coefficients */
- offset = ftell(stream);
- offset = (off_t)ALIGN_SIZE((uint64_t)offset, sars->pagesize);
-
- FOR_EACH(iband, 0, nbands) {
- struct band* band = NULL;
-
- band = darray_band_data_get(&sars->bands) + iband;
- band->map_len = map_len;
-
- /* Map the per band scattering coefficient */
- band->k_list = mmap(NULL, band->map_len, PROT_READ,
- MAP_PRIVATE|MAP_POPULATE, fileno(stream), offset);
- if(band->k_list == MAP_FAILED) {
- log_err(sars,
- "%s: band %lu: could not map the radiative coefficients -- %s\n",
- stream_name, (unsigned long)iband, strerror(errno));
- res = RES_IO_ERR;
- goto error;
- }
- offset = (off_t)((size_t)offset + map_len);
+ if(args->memory_mapping) {
+ res = map_file(sars, args->stream);
+ if(res != RES_OK) goto error;
+ } else {
+ res = load_file(sars, args->stream);
+ if(res != RES_OK) goto error;
}
exit:
@@ -233,6 +430,7 @@ release_sars(ref_T* ref)
ASSERT(ref);
sars = CONTAINER_OF(ref, struct sars, ref);
if(sars->logger == &sars->logger__) logger_release(&sars->logger__);
+ str_release(&sars->name);
darray_band_release(&sars->bands);
MEM_RM(sars->allocator, sars);
}
@@ -273,6 +471,7 @@ sars_create
sars->allocator = allocator;
sars->verbose = args->verbose;
sars->pagesize_os = (size_t)sysconf(_SC_PAGESIZE);
+ str_init(allocator, &sars->name);
darray_band_init(allocator, &sars->bands);
if(args->logger) {
sars->logger = args->logger;
@@ -305,24 +504,27 @@ sars_ref_put(struct sars* sars)
}
res_T
-sars_load(struct sars* sars, const char* path)
+sars_load(struct sars* sars, const struct sars_load_args* args)
{
+ struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL;
FILE* file = NULL;
res_T res = RES_OK;
- if(!sars || !path) {
- res = RES_BAD_ARG;
- goto error;
- }
+ if(!sars) { res = RES_BAD_ARG; goto error; }
+ res = check_sars_load_args(args);
+ if(res != RES_OK) goto error;
- file = fopen(path, "r");
+ file = fopen(args->path, "r");
if(!file) {
- log_err(sars, "%s: error opening file `%s'.\n", FUNC_NAME, path);
+ log_err(sars, "%s: error opening file `%s'.\n", FUNC_NAME, args->path);
res = RES_IO_ERR;
goto error;
}
- res = load_stream(sars, file, path);
+ stream_args.stream = file;
+ stream_args.name = args->path;
+ stream_args.memory_mapping = args->memory_mapping;
+ res = load_stream(sars, &stream_args);
if(res != RES_OK) goto error;
exit:
@@ -333,13 +535,13 @@ error:
}
res_T
-sars_load_stream
- (struct sars* sars,
- FILE* stream,
- const char* stream_name)
+sars_load_stream(struct sars* sars, const struct sars_load_stream_args* args)
{
- if(!sars || !stream) return RES_BAD_ARG;
- return load_stream(sars, stream, stream_name ? stream_name : "<stream>");
+ res_T res = RES_OK;
+ if(!sars) return RES_BAD_ARG;
+ res = check_sars_load_stream_args(args);
+ if(res != RES_OK) return res;
+ return load_stream(sars, args);
}
size_t
@@ -513,6 +715,13 @@ error:
goto exit;
}
+const char*
+sars_get_name(const struct sars* sars)
+{
+ ASSERT(sars);
+ return str_cget(&sars->name);
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
@@ -520,7 +729,47 @@ void
band_release(struct band* band)
{
ASSERT(band);
- if(band->k_list && band->k_list != MAP_FAILED) {
+ if(!band->k_list) return;
+
+ if(!band->map_len) {
+ MEM_RM(band->sars->allocator, band->k_list);
+ } else if(band->k_list != MAP_FAILED) {
munmap(band->k_list, band->map_len);
}
}
+
+res_T
+band_copy(struct band* dst, const struct band* src)
+{
+ ASSERT(dst && src);
+
+ dst->sars = src->sars;
+ dst->low = src->low;
+ dst->upp = dst->upp;
+ dst->map_len = src->map_len;
+ dst->k_list = NULL;
+
+ if(src->map_len) {
+ /* The k are mapped: copy the pointer */
+ dst->k_list = src->k_list;
+ } else if(src->k_list != NULL) {
+ /* The k are loaded: duplicate thable contents */
+ const size_t memsz = sizeof(*dst->k_list)*src->sars->nnodes*2/*ka & ks*/;
+ dst->k_list = MEM_ALLOC(src->sars->allocator, memsz);
+ if(!dst->k_list) return RES_MEM_ERR;
+ memcpy(dst->k_list, src->k_list, memsz);
+ }
+ return RES_OK;
+}
+
+res_T
+band_copy_and_release(struct band* dst, struct band* src)
+{
+ ASSERT(dst && src);
+ dst->sars = src->sars;
+ dst->low = src->low;
+ dst->upp = dst->upp;
+ dst->map_len = src->map_len;
+ dst->k_list = src->k_list;
+ return RES_OK;
+}
diff --git a/src/sars.h b/src/sars.h
@@ -50,6 +50,24 @@ struct sars_create_args {
static const struct sars_create_args SARS_CREATE_ARGS_DEFAULT =
SARS_CREATE_ARGS_DEFAULT__;
+struct sars_load_args {
+ const char* path;
+ int memory_mapping; /* Use memory mapping instead of normal loading */
+};
+#define SARS_LOAD_ARGS_NULL__ {NULL, 0}
+static const struct sars_load_args SARS_LOAD_ARGS_NULL = SARS_LOAD_ARGS_NULL__;
+
+struct sars_load_stream_args {
+ FILE* stream;
+ const char* name; /* Stream name */
+ /* Use memory mapping instead of normal loading. Note that memory mapping
+ * cannot be used on some stream like stdin */
+ int memory_mapping;
+};
+#define SARS_LOAD_STREAM_ARGS_NULL__ {NULL, "stream", 0}
+static const struct sars_load_stream_args SARS_LOAD_STREAM_ARGS_NULL =
+ SARS_LOAD_STREAM_ARGS_NULL__;
+
struct sars_band {
double lower; /* Lower band wavelength in nm (inclusive) */
double upper; /* Upper band wavelength in nm (exclusive) */
@@ -84,13 +102,12 @@ sars_ref_put
SARS_API res_T
sars_load
(struct sars* sars,
- const char* path);
+ const struct sars_load_args* args);
SARS_API res_T
sars_load_stream
(struct sars* sars,
- FILE* stream,
- const char* stream_name); /* Can be NULL */
+ const struct sars_load_stream_args* args);
SARS_API size_t
sars_get_bands_count
@@ -126,6 +143,10 @@ sars_compute_hash
(const struct sars* sars,
hash256_T hash);
+SARS_API const char*
+sars_get_name
+ (const struct sars* sars);
+
static INLINE float
sars_band_get_ka(const struct sars_band* band, const size_t inode)
{
diff --git a/src/sars_c.h b/src/sars_c.h
@@ -19,8 +19,10 @@
#include <rsys/dynamic_array.h>
#include <rsys/logger.h>
#include <rsys/ref_count.h>
+#include <rsys/str.h>
struct band {
+ struct sars* sars;
double low; /* Lower bound in nm (inclusive) */
double upp; /* Upper bound in nm (exclusive) */
size_t map_len;
@@ -32,6 +34,7 @@ band_init(struct mem_allocator* allocator, struct band* band)
{
ASSERT(band);
(void)allocator;
+ band->sars = NULL;
band->low = DBL_MAX;
band->upp =-DBL_MAX;
band->map_len = 0;
@@ -42,11 +45,23 @@ extern LOCAL_SYM void
band_release
(struct band* band);
+extern LOCAL_SYM res_T
+band_copy
+ (struct band* dst,
+ const struct band* src);
+
+extern LOCAL_SYM res_T
+band_copy_and_release
+ (struct band* dst,
+ struct band* src);
+
/* Generate the dynamic array of bands */
#define DARRAY_NAME band
#define DARRAY_DATA struct band
#define DARRAY_FUNCTOR_INIT band_init
#define DARRAY_FUNCTOR_RELEASE band_release
+#define DARRAY_FUNCTOR_COPY band_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE band_copy_and_release
#include <rsys/dynamic_array.h>
struct mem_allocator;
@@ -58,6 +73,7 @@ struct sars {
struct darray_band bands;
size_t pagesize_os;
+ struct str name;
struct mem_allocator* allocator;
struct logger* logger;
diff --git a/src/test_sars_load.c b/src/test_sars_load.c
@@ -19,6 +19,7 @@
#include <rsys/hash.h>
#include <rsys/mem_allocator.h>
#include <math.h>
+#include <string.h>
/*******************************************************************************
* Helper functions
@@ -114,6 +115,9 @@ test_load(struct sars* sars)
hash256_T hash1;
hash256_T band_hash0;
hash256_T band_hash1;
+ struct sars_load_args args = SARS_LOAD_ARGS_NULL;
+ struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL;
+
FILE* fp = NULL;
const char* filename = "test_file.sars";
const uint64_t pagesize = 16384;
@@ -124,13 +128,16 @@ test_load(struct sars* sars)
write_sars(fp, pagesize, nbands, nnodes);
rewind(fp);
- CHK(sars_load_stream(NULL, fp, filename) == RES_BAD_ARG);
- CHK(sars_load_stream(sars, NULL, filename) == RES_BAD_ARG);
- CHK(sars_load_stream(sars, fp, NULL) == RES_OK);
- check_sars_load(sars, nbands, nnodes);
+ stream_args.stream =fp;
+ stream_args.name = filename;
+ CHK(sars_load_stream(NULL, &stream_args) == RES_BAD_ARG);
+ CHK(sars_load_stream(sars, NULL) == RES_BAD_ARG);
+ stream_args.stream = NULL;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_OK);
- rewind(fp);
- CHK(sars_load_stream(sars, fp, filename) == RES_OK);
+ CHK(!strcmp(sars_get_name(sars), filename));
CHK(sars_compute_hash(NULL, hash0) == RES_BAD_ARG);
CHK(sars_compute_hash(sars, NULL) == RES_BAD_ARG);
@@ -145,10 +152,23 @@ test_load(struct sars* sars)
CHK(sars_band_compute_hash(sars, 0, band_hash1) == RES_OK);
CHK(hash256_eq(band_hash0, band_hash1));
- CHK(sars_load(NULL, filename) == RES_BAD_ARG);
+ check_sars_load(sars, nbands, nnodes);
+ rewind(fp);
+
+ stream_args.name = NULL;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
+ stream_args.name = SARS_LOAD_STREAM_ARGS_NULL.name;
+ stream_args.memory_mapping = 1;
+ CHK(sars_load_stream(sars, &stream_args) == RES_OK);
+ CHK(!strcmp(sars_get_name(sars), SARS_LOAD_STREAM_ARGS_NULL.name));
+ check_sars_load(sars, nbands, nnodes);
+
+ args.path = "nop";
+ CHK(sars_load(NULL, &args) == RES_BAD_ARG);
CHK(sars_load(sars, NULL) == RES_BAD_ARG);
- CHK(sars_load(sars, "nop") == RES_IO_ERR);
- CHK(sars_load(sars, filename) == RES_OK);
+ CHK(sars_load(sars, &args) == RES_IO_ERR);
+ args.path = filename;
+ CHK(sars_load(sars, &args) == RES_OK);
check_sars_load(sars, nbands, nnodes);
CHK(sars_compute_hash(sars, hash1) == RES_OK);
@@ -158,7 +178,9 @@ test_load(struct sars* sars)
write_sars(fp, pagesize, nbands+1, nnodes);
rewind(fp);
- CHK(sars_load_stream(sars, fp, filename) == RES_OK);
+ stream_args.stream = fp;
+ stream_args.name = filename;
+ CHK(sars_load_stream(sars, &stream_args) == RES_OK);
CHK(sars_compute_hash(sars, hash1) == RES_OK);
CHK(!hash256_eq(hash0, hash1));
@@ -171,6 +193,7 @@ test_load(struct sars* sars)
static void
test_load_fail(struct sars* sars)
{
+ struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL;
FILE* fp = NULL;
double low;
double upp;
@@ -179,28 +202,32 @@ test_load_fail(struct sars* sars)
CHK(fp = tmpfile());
write_sars(fp, 2048, 1, 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* The pagesize is not a power of two */
CHK(fp = tmpfile());
write_sars(fp, 4100, 1, 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* Wrong #bands */
CHK(fp = tmpfile());
write_sars(fp, 4096, 0, 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* Wrong #nodes */
CHK(fp = tmpfile());
write_sars(fp, 4096, 1, 0);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* Wrong band boundaries */
@@ -212,7 +239,8 @@ test_load_fail(struct sars* sars)
CHK(fwrite(&low, sizeof(low), 1, fp) == 1);
CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* Unsorted bands */
@@ -226,7 +254,8 @@ test_load_fail(struct sars* sars)
CHK(fwrite(&low, sizeof(low), 1, fp) == 1);
CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
/* Bands overlap */
@@ -240,7 +269,8 @@ test_load_fail(struct sars* sars)
CHK(fwrite(&low, sizeof(low), 1, fp) == 1);
CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG);
CHK(fclose(fp) == 0);
}
@@ -251,13 +281,16 @@ test_load_files(struct sars* sars, int argc, char** argv)
CHK(sars);
FOR_EACH(i, 1, argc) {
hash256_T hash;
+ struct sars_load_args args = SARS_LOAD_ARGS_NULL;
size_t nnodes;
size_t nbands;
size_t iband;
printf("Load %s\n", argv[1]);
- CHK(sars_load(sars, argv[i]) == RES_OK);
+ args.path = argv[i];
+ args.memory_mapping = 1;
+ CHK(sars_load(sars, &args) == RES_OK);
nbands = sars_get_bands_count(sars);
nnodes = sars_get_nodes_count(sars);
CHK(nbands);
@@ -291,6 +324,7 @@ test_load_files(struct sars* sars, int argc, char** argv)
static void
test_find(struct sars* sars)
{
+ struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL;
size_t ibands[2];
double range[2];
FILE* fp;
@@ -298,7 +332,8 @@ test_find(struct sars* sars)
CHK(fp = tmpfile());
write_sars(fp, 4096, 10, 1);
rewind(fp);
- CHK(sars_load_stream(sars, fp, NULL) == RES_OK);
+ stream_args.stream = fp;
+ CHK(sars_load_stream(sars, &stream_args) == RES_OK);
range[0] = 0;
range[1] = 10;