diff --git a/ufoaltrep/src/altrep_ufo_files.c b/ufoaltrep/src/altrep_ufo_files.c deleted file mode 100644 index 5ae9cb8..0000000 --- a/ufoaltrep/src/altrep_ufo_files.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include -#include - -#include "altrep_ufo_vectors.h" - -/** - * Translates the type of UFO vector to the size of its element in bytes. - * - * @param vector_type The type of the vector as specified by the ufo_vector_type - * enum. - * @return Returns the size of the element vector or dies in case of an - * unrecognized vector type. - */ -size_t __get_element_size(SEXPTYPE vector_type) { - switch (vector_type) { - case CHARSXP: - return sizeof(Rbyte); - case LGLSXP: - return sizeof(Rboolean); - case INTSXP: - return sizeof(int); - case REALSXP: - return sizeof(double); - case CPLXSXP: - return sizeof(Rcomplex); - case RAWSXP: - return sizeof(Rbyte); - default: - Rf_error("Unrecognized vector type: %d\n", vector_type); - } -} - -int __extract_boolean_or_die(SEXP/*STRSXP*/ sexp) { - if (TYPEOF(sexp) != LGLSXP) { - Rf_error("Invalid type for boolean vector: %d\n", TYPEOF(sexp)); - } - - if (LENGTH(sexp) == 0) { - Rf_error("Provided a zero length vector for boolean vector\n"); - } - - if (LENGTH(sexp) > 1) { - Rf_warning("Provided multiple values for boolean vector, " - "using the first one only\n"); - } - - int element = LOGICAL_ELT(sexp, 0); - return element == 1; -} - -/** - * Check if the path provided via this SEXP makes sense: - * - it contains strings, - * - it's has at least one element, - * - preferably it has only one element. - * - * If the number of elements in the path vector is too large the function exits - * but prints a warning in the R interpreter. If the other requirements are not - * met the function dies and shows a message to the R interpreter. - * - * If the path makes sense, it is is extracted into a C string. - * - * @param path A SEXP containing the file path to validate. - * @return - */ -const char* __extract_path_or_die(SEXP/*STRSXP*/ path) { - if (TYPEOF(path) != STRSXP) { - Rf_error("Invalid type for paths: %d\n", TYPEOF(path)); - } - - if (LENGTH(path) == 0) { - Rf_error("Provided a zero length string for path\n"); - } - - if (TYPEOF(STRING_ELT(path, 0)) != CHARSXP) { - Rf_error("Invalid type for path: %d\n", TYPEOF(STRING_ELT(path, 0))); - } - - if (LENGTH(path) > 2) { - Rf_warning("Provided multiple string values for path, " - "using the first one only\n"); - } - - return CHAR(STRING_ELT(path, 0)); -} - - -long __get_vector_length_from_file_or_die(const char *path, size_t element_size) { - - // FIXME concurrency - FILE* file = fopen(path, "rb"); - if (file == NULL) { - Rf_error("Could not open file.\n"); - } - - int seek_status = fseek(file, 0L, SEEK_END); - if (seek_status < 0) { - // Could not seek in from file. - fclose(file); - Rf_error("Could not seek to the end of file.\n"); - } - - long file_size_in_bytes = ftell(file); - fclose(file); - - if (file_size_in_bytes % element_size != 0) { - Rf_error("File size not divisible by element size.\n"); - } - - return file_size_in_bytes / element_size; -} - -int __load_from_file(int debug, uint64_t start, uint64_t end, char const *path, size_t element_size, size_t vector_size, char* target) { - - if (debug) { - Rprintf("__load_from_file\n"); - Rprintf(" start index: %li\n", start); - Rprintf(" end index: %li\n", end); - Rprintf(" target memory: %p\n", (void *) target); - Rprintf(" source file: %s\n", path); -// Rprintf(" vector type: %d\n", data->vector_type); - Rprintf(" vector size: %li\n", vector_size); - Rprintf(" element size: %li\n", element_size); - } - - // FIXME concurrency - FILE* file = fopen(path, "rb"); - - if (!file) { - fprintf(stderr, "Could not open file.\n"); - return -1; - } - - int initial_seek_status = fseek(file, 0L, SEEK_END); - if (initial_seek_status < 0) { - // Could not seek in from file. - fprintf(stderr, "Could not seek to the end of file.\n"); - return 1; - } - - long file_size_in_bytes = ftell(file); - //fprintf(stderr, "file_size=%li\n", file_size_in_bytes); - - long start_reading_from = element_size * start; - //fprintf(stderr, "start_reading_from=%li\n", start_reading_from); - if (start_reading_from > file_size_in_bytes) { - // Start index out of bounds of the file. - fprintf(stderr, "Start index out of bounds of the file.\n"); - return 42; - } - - long end_reading_at = element_size * end; - //fprintf(stderr, "end_reading_at=%li\n", end_reading_at); - if (end_reading_at > file_size_in_bytes) { - // End index out of bounds of the file. - fprintf(stderr, "End index out of bounds of the file.\n"); - return 43; - } - - int rewind_seek_status = fseek(file, start_reading_from, SEEK_SET); - if (rewind_seek_status < 0) { - // Could not seek in the file to position at start index. - fprintf(stderr, "Could not seek in the file to position at start index.\n"); - return 2; - } - - size_t read_status = fread(target, element_size, end - start, file); - if (debug) { - Rprintf(" read status: %li\n", element_size); - } - if (read_status < end - start || read_status == 0) { - // Read failed. - fprintf(stderr, "Read failed. Read %li out of %li elements.\n", read_status, end - start); - return 44; - } - - fclose(file); - return 0; -} - -// TODO this does not actually implement anything in userfaultCore.h yet -//int __save_to_file(uint64_t start, uint64_t end, ufPopulateCallout cf, -// ufUserData user_data, void* target) { -// ufo_file_source_data_t* data = (ufo_file_source_data_t*) user_data; -// FILE* file = fopen(data->path, "wb"); -// -// if (file) { -// // TODO "allocate" if necessary. -// int seek_status = fseek(file, data->element_size * start, SEEK_SET); -// if (seek_status < 0) { -// return 42; -// } -// size_t write_status = fwrite(target, data->element_size, end-start, file); -// if (write_status < end-start || write_status == 0) { -// return 47; -// } -// } -// -// fclose(file); -// return 0; -//} - -void __write_bytes_to_disk(const char *path, size_t size, const char *bytes) { - //fprintf(stderr, "__write_bytes_to_disk(%s,%li,...)\n", path, size); - - FILE* file = fopen(path, "wb"); - - if (!file) { - fclose(file); - Rf_error("Error opening file '%s'.", path); - } - - size_t write_status = fwrite(bytes, sizeof(const char), size, file); - if (write_status < size || write_status == 0) { - fclose(file); - Rf_error("Error writing to file '%s'. Written: %i out of %li", - path, write_status, size); - } - - fclose(file); -} \ No newline at end of file diff --git a/ufoaltrep/src/altrep_ufo_files.h b/ufoaltrep/src/altrep_ufo_files.h deleted file mode 100644 index 11e623c..0000000 --- a/ufoaltrep/src/altrep_ufo_files.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "Rinternals.h" - -size_t __get_element_size(SEXPTYPE vector_type); -long __get_vector_length_from_file_or_die(const char * path, size_t element_size); -int __extract_boolean_or_die(SEXP/*LGLSXP*/ sexp); -const char* __extract_path_or_die(SEXP/*STRSXP*/ path); -int __load_from_file(int debug, uint64_t start, uint64_t end, char const *path, size_t element_size, size_t vector_size, char* target); \ No newline at end of file diff --git a/ufoaltrep/src/altrep_ufo_vectors.c b/ufoaltrep/src/altrep_ufo_vectors.c index a4903a6..3c66ebc 100644 --- a/ufoaltrep/src/altrep_ufo_vectors.c +++ b/ufoaltrep/src/altrep_ufo_vectors.c @@ -7,21 +7,17 @@ #include #include -#include "altrep_ufo_files.h" #include "altrep_ufo_vectors.h" int altrep_ufo_debug_mode = 0; -SEXP/*NILSXP*/ altrep_ufo_vectors_set_debug_mode(SEXP/*LGLSXP*/ debug) { - altrep_ufo_debug_mode = __extract_boolean_or_die(debug); - return R_NilValue; -} - typedef struct { - char const *path; - size_t element_size; - size_t vector_size; - SEXPTYPE type; + char const* path; + size_t element_size; + size_t vector_size; + SEXPTYPE type; + FILE* file_handle; + size_t file_cursor; } altrep_ufo_config_t; static R_altrep_class_t ufo_integer_altrep; @@ -47,41 +43,194 @@ R_altrep_class_t __get_class_from_type(SEXPTYPE type) { } } -// ALTREP Methods -//static SEXP ufo_integer_Duplicate(SEXP x, Rboolean deep); -//static SEXP ufo_numeric_Duplicate(SEXP x, Rboolean deep); -//static SEXP ufo_logical_Duplicate(SEXP x, Rboolean deep); -//static SEXP ufo_raw_Duplicate(SEXP x, Rboolean deep); -//static SEXP ufo_complex_Duplicate(SEXP x, Rboolean deep); +/** + * Translates the type of UFO vector to the size of its element in bytes. + * + * @param vector_type The type of the vector as specified by the ufo_vector_type + * enum. + * @return Returns the size of the element vector or dies in case of an + * unrecognized vector type. + */ +size_t __get_element_size(SEXPTYPE vector_type) { + switch (vector_type) { + case CHARSXP: + return sizeof(Rbyte); + case LGLSXP: + return sizeof(Rboolean); + case INTSXP: + return sizeof(int); + case REALSXP: + return sizeof(double); + case CPLXSXP: + return sizeof(Rcomplex); + case RAWSXP: + return sizeof(Rbyte); + default: + Rf_error("Unrecognized vector type: %d\n", vector_type); + } +} + +int __extract_boolean_or_die(SEXP/*STRSXP*/ sexp) { + if (TYPEOF(sexp) != LGLSXP) { + Rf_error("Invalid type for boolean vector: %d\n", TYPEOF(sexp)); + } -//static Rboolean ufo_integer_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)); -//static Rboolean ufo_numeric_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)); -//static Rboolean ufo_logical_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)); -//static Rboolean ufo_raw_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)); -//static Rboolean ufo_complex_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)); + if (LENGTH(sexp) == 0) { + Rf_error("Provided a zero length vector for boolean vector\n"); + } -//static R_xlen_t ufo_integer_Length(SEXP x); -//static R_xlen_t ufo_numeric_Length(SEXP x); -//static R_xlen_t ufo_logical_Length(SEXP x); -//static R_xlen_t ufo_raw_Length(SEXP x); -//static R_xlen_t ufo_complex_Length(SEXP x); + if (LENGTH(sexp) > 1) { + Rf_warning("Provided multiple values for boolean vector, " + "using the first one only\n"); + } -// ALTVEC Methods -//static void *ufo_integer_Dataptr(SEXP x, Rboolean writeable); -//static void *ufo_numeric_Dataptr(SEXP x, Rboolean writeable); -//static void *ufo_logical_Dataptr(SEXP x, Rboolean writeable); -//static void *ufo_raw_Dataptr(SEXP x, Rboolean writeable); -//static void *ufo_complex_Dataptr(SEXP x, Rboolean writeable); + int element = LOGICAL_ELT(sexp, 0); + return element == 1; +} -//static const void *ufo_integer_Dataptr_or_null(SEXP x); -//static const void *ufo_numeric_Dataptr_or_null(SEXP x); -//static const void *ufo_logical_Dataptr_or_null(SEXP x); -//static const void *ufo_raw_Dataptr_or_null(SEXP x); -//static const void *ufo_complex_Dataptr_or_null(SEXP x); +const char* __extract_path_or_die(SEXP/*STRSXP*/ path) { + if (TYPEOF(path) != STRSXP) { + Rf_error("Invalid type for paths: %d\n", TYPEOF(path)); + } -// ALTINTEGER Methods -//static int ufo_integer_Elt(SEXP x, R_xlen_t i); -//static R_xlen_t ufo_integer_Get_region(SEXP x, R_xlen_t i, R_xlen_t n, int *buf); + if (LENGTH(path) == 0) { + Rf_error("Provided a zero length string for path\n"); + } + + if (TYPEOF(STRING_ELT(path, 0)) != CHARSXP) { + Rf_error("Invalid type for path: %d\n", TYPEOF(STRING_ELT(path, 0))); + } + + if (LENGTH(path) > 2) { + Rf_warning("Provided multiple string values for path, " + "using the first one only\n"); + } + + return CHAR(STRING_ELT(path, 0)); +} + + +long __get_vector_length_from_file_or_die(const char *path, size_t element_size) { + + // FIXME concurrency + FILE* file = fopen(path, "rb"); + if (file == NULL) { + Rf_error("Could not open file.\n"); + } + + int seek_status = fseek(file, 0L, SEEK_END); + if (seek_status < 0) { + // Could not seek in from file. + fclose(file); + Rf_error("Could not seek to the end of file.\n"); + } + + long file_size_in_bytes = ftell(file); + fclose(file); + + if (file_size_in_bytes % element_size != 0) { + Rf_error("File size not divisible by element size.\n"); + } + + return file_size_in_bytes / element_size; +} + +int __load_from_file(int debug, uint64_t start, uint64_t end, altrep_ufo_config_t* cfg, char* target) { + + if (debug) { + Rprintf("__load_from_file\n"); + Rprintf(" start index: %li\n", start); + Rprintf(" end index: %li\n", end); + Rprintf(" target memory: %p\n", (void *) target); + Rprintf(" source file: %s\n", cfg->path); + // Rprintf(" vector type: %d\n", data->vector_type); + Rprintf(" vector size: %li\n", cfg->vector_size); + Rprintf(" element size: %li\n", cfg->element_size); + } + + int initial_seek_status = fseek(cfg->file_handle, 0L, SEEK_END); + if (initial_seek_status < 0) { + // Could not seek in from file. + fprintf(stderr, "Could not seek to the end of file.\n"); + return 1; + } + + long file_size_in_bytes = ftell(cfg->file_handle); + //fprintf(stderr, "file_size=%li\n", file_size_in_bytes); + + long start_reading_from = cfg->element_size * start; + //fprintf(stderr, "start_reading_from=%li\n", start_reading_from); + if (start_reading_from > file_size_in_bytes) { + // Start index out of bounds of the file. + fprintf(stderr, "Start index out of bounds of the file.\n"); + return 42; + } + + long end_reading_at = cfg->element_size * end; + //fprintf(stderr, "end_reading_at=%li\n", end_reading_at); + if (end_reading_at > file_size_in_bytes) { + // End index out of bounds of the file. + fprintf(stderr, "End index out of bounds of the file.\n"); + return 43; + } + + int rewind_seek_status = fseek(cfg->file_handle, start_reading_from, SEEK_SET); + if (rewind_seek_status < 0) { + // Could not seek in the file to position at start index. + fprintf(stderr, "Could not seek in the file to position at start index.\n"); + return 2; + } + + size_t read_status = fread(target, cfg->element_size, end - start, cfg->file_handle); + if (debug) { + Rprintf(" read status: %li\n", cfg->element_size); + } + if (read_status < end - start || read_status == 0) { + // Read failed. + fprintf(stderr, "Read failed. Read %li out of %li elements.\n", read_status, end - start); + return 44; + } + + return 0; +} + +void __write_bytes_to_disk(const char *path, size_t size, const char *bytes) { + //fprintf(stderr, "__write_bytes_to_disk(%s,%li,...)\n", path, size); + + FILE* file = fopen(path, "wb"); + + if (!file) { + fclose(file); + Rf_error("Error opening file '%s'.", path); + } + + size_t write_status = fwrite(bytes, sizeof(const char), size, file); + if (write_status < size || write_status == 0) { + fclose(file); + Rf_error("Error writing to file '%s'. Written: %i out of %li", + path, write_status, size); + } + + fclose(file); +} + +FILE *__open_file_or_die(char const *path) { + FILE * file = fopen(path, "rb"); + if (!file) { + Rf_error("Could not open file.\n"); + } + return file; +} + +SEXP/*NILSXP*/ altrep_ufo_vectors_set_debug_mode(SEXP/*LGLSXP*/ debug) { + altrep_ufo_debug_mode = __extract_boolean_or_die(debug); + return R_NilValue; +} + +void ufo_vector_finalize_altrep(SEXP wrapper) { + altrep_ufo_config_t *cfg = (altrep_ufo_config_t *) EXTPTR_PTR(wrapper); + fclose(cfg->file_handle); +} // UFO constructors SEXP ufo_vector_new_altrep(SEXPTYPE type, char const *path) { @@ -93,12 +242,23 @@ SEXP ufo_vector_new_altrep(SEXPTYPE type, char const *path) { cfg->path = path; cfg->element_size = __get_element_size(type); cfg->vector_size = __get_vector_length_from_file_or_die(cfg->path, cfg->element_size); + cfg->file_handle = __open_file_or_die(cfg->path); + cfg->file_cursor = 0; SEXP wrapper = allocSExp(EXTPTRSXP); EXTPTR_PTR(wrapper) = (void *) cfg; EXTPTR_TAG(wrapper) = Rf_install("ALTREP UFO CFG"); - return R_new_altrep(__get_class_from_type(type), wrapper, R_NilValue); + SEXP ans = R_new_altrep(__get_class_from_type(type), wrapper, R_NilValue); + EXTPTR_PROT(wrapper) = ans; + + // FIXME finalizer + + /* Finalizer */ + //SEXP extptr = PROTECT(R_MakeExternalPtr(NULL, R_NilValue, ans)); + R_MakeWeakRefC(wrapper, R_NilValue, ufo_vector_finalize_altrep, TRUE); + + return ans; } SEXP/*INTSXP*/ altrep_ufo_vectors_intsxp_bin(SEXP/*STRSXP*/ path) { return ufo_vector_new_altrep(INTSXP, __extract_path_or_die(path)); @@ -116,7 +276,7 @@ SEXP/*RAWSXP*/ altrep_ufo_vectors_rawsxp_bin(SEXP/*STRSXP*/ path) { return ufo_vector_new_altrep(RAWSXP, __extract_path_or_die(path)); } -static SEXP ufo_vector_Duplicate(SEXP x, Rboolean deep) { +static SEXP ufo_vector_duplicate(SEXP x, Rboolean deep) { altrep_ufo_config_t *new_cfg = (altrep_ufo_config_t *) malloc(sizeof(altrep_ufo_config_t)); @@ -149,7 +309,7 @@ static SEXP ufo_vector_Duplicate(SEXP x, Rboolean deep) { } } -static Rboolean ufo_vector_Inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)) { +static Rboolean ufo_vector_inspect(SEXP x, int pre, int deep, int pvec, void (*inspect_subtree)(SEXP, int, int, int)) { if (R_altrep_data1(x) == R_NilValue) { Rprintf(" ufo_integer_altrep %s\n", type2char(TYPEOF(x))); @@ -168,7 +328,7 @@ static Rboolean ufo_vector_Inspect(SEXP x, int pre, int deep, int pvec, void (*i return FALSE; } -static R_xlen_t ufo_vector_Length(SEXP x) { +static R_xlen_t ufo_vector_length(SEXP x) { if (altrep_ufo_debug_mode) { Rprintf("ufo_vector_Length\n"); Rprintf(" SEXP: %p\n", x); @@ -188,14 +348,12 @@ static void __materialize_data(SEXP x) { PROTECT(x); SEXP payload = allocVector(INTSXP, cfg->vector_size); int *data = INTEGER(payload); - __load_from_file(altrep_ufo_debug_mode, 0, cfg->vector_size, - cfg->path, cfg->element_size, cfg->vector_size, - (char *) data); + __load_from_file(altrep_ufo_debug_mode, 0, cfg->vector_size, cfg, (char *) data); R_set_altrep_data2(x, payload); UNPROTECT(1); } -static void *ufo_vector_Dataptr(SEXP x, Rboolean writeable) { +static void *ufo_vector_dataptr(SEXP x, Rboolean writeable) { if (altrep_ufo_debug_mode) { Rprintf("ufo_vector_Dataptr\n"); Rprintf(" SEXP: %p\n", x); @@ -212,7 +370,7 @@ static void *ufo_vector_Dataptr(SEXP x, Rboolean writeable) { } } -static const void *ufo_vector_Dataptr_or_null(SEXP x) { +static const void *ufo_vector_dataptr_or_null(SEXP x) { if (altrep_ufo_debug_mode) { Rprintf("ufo_vector_Dataptr_or_null\n"); Rprintf(" SEXP: %p\n", x); @@ -232,9 +390,7 @@ static void ufo_vector_element(SEXP x, R_xlen_t i, void *target) { altrep_ufo_config_t *cfg = (altrep_ufo_config_t *) EXTPTR_PTR(R_altrep_data1(x)); - __load_from_file(altrep_ufo_debug_mode, i, i+1, - cfg->path, cfg->element_size, cfg->vector_size, - (char *) target); + __load_from_file(altrep_ufo_debug_mode, i, i+1, cfg, (char *) target); } static int ufo_integer_element(SEXP x, R_xlen_t i) { @@ -287,9 +443,7 @@ static R_xlen_t ufo_vector_get_region(SEXP x, R_xlen_t i, R_xlen_t n, void *buf) } altrep_ufo_config_t *cfg = (altrep_ufo_config_t *) EXTPTR_PTR(R_altrep_data1(x)); - return __load_from_file(altrep_ufo_debug_mode, i, i+n, - cfg->path, cfg->element_size, cfg->vector_size, - (char *) buf); + return __load_from_file(altrep_ufo_debug_mode, i, i+n, cfg, (char *) buf); } static R_xlen_t ufo_integer_get_region(SEXP x, R_xlen_t i, R_xlen_t n, int *buf) { @@ -322,6 +476,8 @@ static R_xlen_t ufo_logical_get_region(SEXP x, R_xlen_t i, R_xlen_t n, int *buf) return ufo_vector_get_region(x, i, n, buf); } + + // UFO Inits void init_ufo_integer_altrep_class(DllInfo * dll) { R_altrep_class_t cls = R_make_altinteger_class("ufo_integer_altrep", @@ -329,13 +485,13 @@ void init_ufo_integer_altrep_class(DllInfo * dll) { ufo_integer_altrep = cls; /* Override ALTREP methods */ - R_set_altrep_Duplicate_method(cls, ufo_vector_Duplicate); - R_set_altrep_Inspect_method(cls, ufo_vector_Inspect); - R_set_altrep_Length_method(cls, ufo_vector_Length); + R_set_altrep_Duplicate_method(cls, ufo_vector_duplicate); + R_set_altrep_Inspect_method(cls, ufo_vector_inspect); + R_set_altrep_Length_method(cls, ufo_vector_length); /* Override ALTVEC methods */ - R_set_altvec_Dataptr_method(cls, ufo_vector_Dataptr); - R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_Dataptr_or_null); + R_set_altvec_Dataptr_method(cls, ufo_vector_dataptr); + R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_dataptr_or_null); /* Override ALTINTEGER methods */ R_set_altinteger_Elt_method(cls, ufo_integer_element); @@ -348,13 +504,13 @@ void init_ufo_numeric_altrep_class(DllInfo * dll) { ufo_numeric_altrep = cls; /* Override ALTREP methods */ - R_set_altrep_Duplicate_method(cls, ufo_vector_Duplicate); - R_set_altrep_Inspect_method(cls, ufo_vector_Inspect); - R_set_altrep_Length_method(cls, ufo_vector_Length); + R_set_altrep_Duplicate_method(cls, ufo_vector_duplicate); + R_set_altrep_Inspect_method(cls, ufo_vector_inspect); + R_set_altrep_Length_method(cls, ufo_vector_length); /* Override ALTVEC methods */ - R_set_altvec_Dataptr_method(cls, ufo_vector_Dataptr); - R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_Dataptr_or_null); + R_set_altvec_Dataptr_method(cls, ufo_vector_dataptr); + R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_dataptr_or_null); /* Override ALTREAL methods */ R_set_altreal_Elt_method(cls, ufo_numeric_element); @@ -367,13 +523,13 @@ void init_ufo_logical_altrep_class(DllInfo * dll) { ufo_logical_altrep = cls; /* Override ALTREP methods */ - R_set_altrep_Duplicate_method(cls, ufo_vector_Duplicate); - R_set_altrep_Inspect_method(cls, ufo_vector_Inspect); - R_set_altrep_Length_method(cls, ufo_vector_Length); + R_set_altrep_Duplicate_method(cls, ufo_vector_duplicate); + R_set_altrep_Inspect_method(cls, ufo_vector_inspect); + R_set_altrep_Length_method(cls, ufo_vector_length); /* Override ALTVEC methods */ - R_set_altvec_Dataptr_method(cls, ufo_vector_Dataptr); - R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_Dataptr_or_null); + R_set_altvec_Dataptr_method(cls, ufo_vector_dataptr); + R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_dataptr_or_null); /* Override ALTLOGICAL methods */ R_set_altlogical_Elt_method(cls, ufo_logical_element); @@ -386,13 +542,13 @@ void init_ufo_complex_altrep_class(DllInfo * dll) { ufo_complex_altrep = cls; /* Override ALTREP methods */ - R_set_altrep_Duplicate_method(cls, ufo_vector_Duplicate); - R_set_altrep_Inspect_method(cls, ufo_vector_Inspect); - R_set_altrep_Length_method(cls, ufo_vector_Length); + R_set_altrep_Duplicate_method(cls, ufo_vector_duplicate); + R_set_altrep_Inspect_method(cls, ufo_vector_inspect); + R_set_altrep_Length_method(cls, ufo_vector_length); /* Override ALTVEC methods */ - R_set_altvec_Dataptr_method(cls, ufo_vector_Dataptr); - R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_Dataptr_or_null); + R_set_altvec_Dataptr_method(cls, ufo_vector_dataptr); + R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_dataptr_or_null); /* Override ALTCOMPLEX methods */ R_set_altcomplex_Elt_method(cls, ufo_complex_element); @@ -405,13 +561,13 @@ void init_ufo_raw_altrep_class(DllInfo * dll) { ufo_raw_altrep = cls; /* Override ALTREP methods */ - R_set_altrep_Duplicate_method(cls, ufo_vector_Duplicate); - R_set_altrep_Inspect_method(cls, ufo_vector_Inspect); - R_set_altrep_Length_method(cls, ufo_vector_Length); + R_set_altrep_Duplicate_method(cls, ufo_vector_duplicate); + R_set_altrep_Inspect_method(cls, ufo_vector_inspect); + R_set_altrep_Length_method(cls, ufo_vector_length); /* Override ALTVEC methods */ - R_set_altvec_Dataptr_method(cls, ufo_vector_Dataptr); - R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_Dataptr_or_null); + R_set_altvec_Dataptr_method(cls, ufo_vector_dataptr); + R_set_altvec_Dataptr_or_null_method(cls, ufo_vector_dataptr_or_null); /* Override ALTRAW methods */ R_set_altraw_Elt_method(cls, ufo_raw_element); diff --git a/ufoaltrep/src/init.c b/ufoaltrep/src/init.c index d33cf5e..d91786c 100644 --- a/ufoaltrep/src/init.c +++ b/ufoaltrep/src/init.c @@ -33,3 +33,7 @@ void attribute_visible R_init_ufoaltrep(DllInfo *dll) { R_forceSymbols(dll, TRUE); } +void attribute_visible R_unload_ufoaltrep(DllInfo *dll) { + printf("goodnight sweet prince\n"); +} + diff --git a/ufovectors/CMakeLists.txt b/ufovectors/CMakeLists.txt index 8cbe6e0..5b641ac 100644 --- a/ufovectors/CMakeLists.txt +++ b/ufovectors/CMakeLists.txt @@ -5,7 +5,6 @@ SET(EX_PLATFORM 64) SET(EX_PLATFORM_NAME "x64") add_definitions(-Wall -O2) - # -Wall -g file(GLOB_RECURSE SRC "src/*.c" "src/*.h") diff --git a/ufovectors/src/ufo_vectors.c b/ufovectors/src/ufo_vectors.c index 79301af..bc684a2 100644 --- a/ufovectors/src/ufo_vectors.c +++ b/ufovectors/src/ufo_vectors.c @@ -11,6 +11,8 @@ typedef struct { ufo_vector_type_t vector_type; size_t element_size; /* in bytes */ size_t vector_size; + FILE* file_handle; + size_t file_cursor; } ufo_file_source_data_t; int ufo_initialized = 0; @@ -107,22 +109,14 @@ int __load_from_file(uint64_t start, uint64_t end, ufPopulateCallout cf, Rprintf(" element size: %li\n", data->element_size); } - // FIXME concurrency - FILE* file = fopen(data->path, "rb"); - - if (!file) { - fprintf(stderr, "Could not open file.\n"); //TODO use proper channels - return -1; - } - - int initial_seek_status = fseek(file, 0L, SEEK_END); + int initial_seek_status = fseek(data->file_handle, 0L, SEEK_END); if (initial_seek_status < 0) { // Could not seek in from file. fprintf(stderr, "Could not seek to the end of file.\n"); //TODO use proper channels return 1; } - long file_size_in_bytes = ftell(file); + long file_size_in_bytes = ftell(data->file_handle); //fprintf(stderr, "file_size=%li\n", file_size_in_bytes); long start_reading_from = data->element_size * start; @@ -141,27 +135,28 @@ int __load_from_file(uint64_t start, uint64_t end, ufPopulateCallout cf, return 43; } - int rewind_seek_status = fseek(file, start_reading_from, SEEK_SET); + int rewind_seek_status = fseek(data->file_handle, start_reading_from, SEEK_SET); if (rewind_seek_status < 0) { // Could not seek in the file to position at start index. fprintf(stderr, "Could not seek in the file to position at start index.\n"); //TODO use proper channels return 2; } - size_t read_status = fread(target, data->element_size, end - start, file); + size_t read_status = fread(target, data->element_size, end - start, data->file_handle); if (read_status < end - start || read_status == 0) { // Read failed. fprintf(stderr, "Read failed. Read %li out of %li elements.\n", read_status, end - start); //TODO use proper channels return 44; } - fclose(file); + //fclose(file); return 0; } // TODO this does not actually implement anything in userfaultCore.h yet int __save_to_file(uint64_t start, uint64_t end, ufPopulateCallout cf, ufUserData user_data, void* target) { + // FIXME ufo_file_source_data_t* data = (ufo_file_source_data_t*) user_data; FILE* file = fopen(data->path, "wb"); @@ -237,31 +232,50 @@ void __check_file_path_or_die(const char * path) { } -ufo_source_t* __make_source(ufo_vector_type_t type, const char* path) { +void __destroy(ufUserData *user_data) { + ufo_file_source_data_t *data = (ufo_file_source_data_t*) user_data; + if (ufo_debug_mode) { + Rprintf("__destroy\n"); + Rprintf(" source file: %s\n", data->path); + Rprintf(" vector type: %d\n", data->vector_type); + Rprintf(" vector size: %li\n", data->vector_size); + Rprintf(" element size: %li\n", data->element_size); + } + fclose(data->file_handle); +} + +FILE *__open_file_or_die(char const *path) { + FILE * file = fopen(path, "rb"); + if (!file) { + Rf_error("Could not open file.\n"); + } + return file; +} + +ufo_source_t* __make_source_or_die(ufo_vector_type_t type, const char* path) { __check_file_path_or_die(path); ufo_file_source_data_t *data = (ufo_file_source_data_t*) malloc(sizeof(ufo_file_source_data_t)); ufo_source_t* source = (ufo_source_t*) malloc(sizeof(ufo_source_t)); source->population_function = &__load_from_file; + source->destructor_function = &__destroy; source->data = (ufUserData*) data; source->vector_type = type; source->element_size = __get_element_size(type); source->vector_size = __get_vector_length_from_file_or_die(path, source->element_size); -// fprintf(stderr, "source->vector_type=%i\n",source->vector_type); -// fprintf(stderr, "source->element_size=%li\n",source->element_size); -// fprintf(stderr, "source->vector_size=%li\n",source->vector_size); - data->path = path; data->vector_type = source->vector_type; data->vector_size = source->vector_size; data->element_size = source->element_size; + data->file_handle = __open_file_or_die(path); + data->file_cursor = 0; + return source; } - SEXP/*NILSXP*/ ufo_vectors_shutdown() { if (ufo_initialized != 0) { ufo_shutdown_t ufo_shutdown = @@ -283,7 +297,7 @@ void ufo_vectors_initialize_if_necessary() { SEXP __make_vector(ufo_vector_type_t type, SEXP sexp) { const char *path = __extract_path_or_die(sexp); - ufo_source_t *source = __make_source(type, path); + ufo_source_t *source = __make_source_or_die(type, path); ufo_vectors_initialize_if_necessary(); ufo_new_t ufo_new = (ufo_new_t) R_GetCCallable("ufos", "ufo_new"); return ufo_new(source);