From 7859c2d53d0a4f7f125c10db008bd58edaeeef5b Mon Sep 17 00:00:00 2001 From: Konrad Siek Date: Tue, 18 Jun 2019 11:03:13 +0200 Subject: [PATCH] Roughly approximate R packages. Changes from old master branch. --- .gitignore | 4 +- CMakeLists.txt | 22 ---- DESCRIPTION | 10 -- R/ufos.R | 30 ----- src/bin_file_source.h | 10 -- src/init.c | 36 ------ src/userfaultCore_dummy.c | 16 --- ufos/CMakeLists.txt | 53 ++++++++ ufos/DESCRIPTION | 20 +++ NAMESPACE => ufos/NAMESPACE | 0 ufos/R/ufos.R | 2 + README.md => ufos/README.md | 0 {cmake => ufos/cmake}/FindR.cmake | 0 ufos/src/Makevars | 2 + ufos/src/init.c | 25 ++++ {src => ufos/src}/mappedMemory/sparseList.c | 0 {src => ufos/src}/mappedMemory/sparseList.h | 0 .../src}/mappedMemory/sparseListTest.c | 0 {src => ufos/src}/mappedMemory/stride.c | 0 {src => ufos/src}/mappedMemory/ufoTest.c | 0 .../src}/mappedMemory/userFaultCoreInternal.h | 0 .../src}/mappedMemory/userfaultCore.c | 0 .../src}/mappedMemory/userfaultCore.h | 0 .../mappedMemory/userfaultGettersSetters.c | 0 .../src}/mappedMemory/userfaultSpeed.c | 0 {src => ufos/src}/ufo_sources.h | 2 +- {src => ufos/src}/ufos.c | 38 +++--- {src => ufos/src}/ufos.h | 9 +- {src => ufos/src}/unstdLib/errors.h | 0 {src => ufos/src}/unstdLib/math.h | 0 {src => ufos/src}/unstdLib/vars.h | 0 ufovectors/CMakeLists.txt | 20 +++ ufovectors/DESCRIPTION | 17 +++ ufovectors/NAMESPACE | 10 ++ ufovectors/R/ufovectors.R | 46 +++++++ ufovectors/README.md | 5 + ufovectors/cmake/FindR.cmake | 106 ++++++++++++++++ .../include/mappedMemory/userfaultCore.h | 1 + ufovectors/include/ufos.h | 1 + ufovectors/src/Makevars | 2 + ufovectors/src/init.c | 42 +++++++ .../src/ufo_vectors.c | 115 +++++++++++++----- ufovectors/src/ufo_vectors.h | 12 ++ 43 files changed, 476 insertions(+), 180 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 DESCRIPTION delete mode 100644 R/ufos.R delete mode 100644 src/bin_file_source.h delete mode 100644 src/init.c delete mode 100644 src/userfaultCore_dummy.c create mode 100644 ufos/CMakeLists.txt create mode 100644 ufos/DESCRIPTION rename NAMESPACE => ufos/NAMESPACE (100%) create mode 100644 ufos/R/ufos.R rename README.md => ufos/README.md (100%) rename {cmake => ufos/cmake}/FindR.cmake (100%) create mode 100644 ufos/src/Makevars create mode 100644 ufos/src/init.c rename {src => ufos/src}/mappedMemory/sparseList.c (100%) rename {src => ufos/src}/mappedMemory/sparseList.h (100%) rename {src => ufos/src}/mappedMemory/sparseListTest.c (100%) rename {src => ufos/src}/mappedMemory/stride.c (100%) rename {src => ufos/src}/mappedMemory/ufoTest.c (100%) rename {src => ufos/src}/mappedMemory/userFaultCoreInternal.h (100%) rename {src => ufos/src}/mappedMemory/userfaultCore.c (100%) rename {src => ufos/src}/mappedMemory/userfaultCore.h (100%) rename {src => ufos/src}/mappedMemory/userfaultGettersSetters.c (100%) rename {src => ufos/src}/mappedMemory/userfaultSpeed.c (100%) rename {src => ufos/src}/ufo_sources.h (93%) rename {src => ufos/src}/ufos.c (79%) rename {src => ufos/src}/ufos.h (70%) rename {src => ufos/src}/unstdLib/errors.h (100%) rename {src => ufos/src}/unstdLib/math.h (100%) rename {src => ufos/src}/unstdLib/vars.h (100%) create mode 100644 ufovectors/CMakeLists.txt create mode 100644 ufovectors/DESCRIPTION create mode 100644 ufovectors/NAMESPACE create mode 100644 ufovectors/R/ufovectors.R create mode 100644 ufovectors/README.md create mode 100644 ufovectors/cmake/FindR.cmake create mode 120000 ufovectors/include/mappedMemory/userfaultCore.h create mode 120000 ufovectors/include/ufos.h create mode 100644 ufovectors/src/Makevars create mode 100644 ufovectors/src/init.c rename src/bin_file_source.c => ufovectors/src/ufo_vectors.c (57%) create mode 100644 ufovectors/src/ufo_vectors.h diff --git a/.gitignore b/.gitignore index 1eed6ba..5344569 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ !DESCRIPTION !NAMESPACE !CMakeLists.txt -!cmake/FindR.cmake +!Makefile +!Makevars +!*/cmake/FindR.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 37711c4..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -project(ufo) -cmake_minimum_required(VERSION 2.8.7) - -SET( EX_PLATFORM 64 ) -SET( EX_PLATFORM_NAME "x64" ) - -add_definitions( - -Wall -O2 -# -Wall -g -) - -file(GLOB_RECURSE SRC "src/*.c" "src/*.h") - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") - -find_package(R REQUIRED) -message("R libraries: ${R_LIBRARIES}") -message("R include dirs: ${R_INCLUDE_DIR} ${Rcpp_INCLUDE_DIR}") - -add_library(ufos SHARED ${SRC}) -include_directories(ufos ${R_INCLUDE_DIR} ${Rcpp_INCLUDE_DIR}) -target_link_libraries(ufos ${R_LIBRARIES}) \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION deleted file mode 100644 index c5ab621..0000000 --- a/DESCRIPTION +++ /dev/null @@ -1,10 +0,0 @@ -Package: ufos -Type: Package -Title: UFOs: implementation of custom objects masquerading as plain R objects via user faults -Version: 0.1.0 -Author: Colette Kerr , Konrad Siek -Maintainer: Colette Kerr , Konrad Siek -Description: Experiments in making custom objects with complex behavior appearing as ordinary R data structures (data.frames, matrices, etc.) to both R functions and C functions. This uses user faults (memory faults) to capture memory accesses and override them. -License: who knows? -Encoding: UTF-8 -LazyData: true diff --git a/R/ufos.R b/R/ufos.R deleted file mode 100644 index cd34a59..0000000 --- a/R/ufos.R +++ /dev/null @@ -1,30 +0,0 @@ -ufo_bin_file_source <-function(path) { - if (typeof(path) != "character") { - stop(paste0("Path is of type", typeof(path), - ", must be a character vector.")) - } - if (length(path) == 0) { - stop("Path is a 0-length vector") - } - if (length(path) > 1) { - # TODO warning - warning(paste0("Path is a vector containing multiple values, picking the", - "first one, ignoring the rest")); - } - .Call("ufo_bin_file_source", path) -} - -# Create new UFO vector using a specified source. If multiple lengths -# are given, it creates a list of integer vectors that matches the number of -# provided lengths. -ufo_new <- function(lengths, source) { - if (typeof(lengths) != "double" && typeof(lengths) != "integer") - stop(paste0("Vector is of type", typeof(lengths), - ", must be either integer or double.")) - - .Call("ufo_new", as.integer(lengths), source) -} - -ufo_shutdown <- function() { - .Call("ufo_shutdown", source) -} diff --git a/src/bin_file_source.h b/src/bin_file_source.h deleted file mode 100644 index feaf533..0000000 --- a/src/bin_file_source.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "Rinternals.h" - -typedef struct { - const char* path; - size_t element_size; /* in bytes */ -} ufo_file_source_data_t; - -SEXP/*EXTPTRSXP*/ ufo_bin_file_source(SEXP/*STRSXP*/ path); \ No newline at end of file diff --git a/src/init.c b/src/init.c deleted file mode 100644 index 91b4baa..0000000 --- a/src/init.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "ufos.h" -#include "bin_file_source.h" - -#include -#include - -// List of functions provided by the package. -static const R_CallMethodDef CallEntries[] = { - // Creates a new UFO vector. The constructor takes 1 argument which defines - // a source. A source is specifically a EXTPTRSXP that points to a - // ufo_source_t struct. - //{"ufo_new", (DL_FUNC) &ufo_new, 1}, - - // Creates a source that reads data from a binary file into a UFO vector. - // A source is specifically a EXTPTRSXP that points to a ufo_source_t - // struct. The constructor takes 1 argument that defines a path to a - // binary file. - //{"ufo_bin_file_source", (DL_FUNC) &ufo_bin_file_source, 1}, - - // Shut the UFO system down. - {"ufo_shutdown", (DL_FUNC) &ufo_shutdown, 0}, - - // Terminates the function list. Necessary. - {NULL, NULL, 0} -}; - -// Initializes the package and registers the routines with the Rdynload -// library. Name follows the pattern: R_init_ -void attribute_visible R_init_ufos(DllInfo *dll) { - //InitUFOAltRepClass(dll); - //R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - //R_useDynamicSymbols(dll, FALSE); - //R_forceSymbols(dll, TRUE); -} - - diff --git a/src/userfaultCore_dummy.c b/src/userfaultCore_dummy.c deleted file mode 100644 index 701c718..0000000 --- a/src/userfaultCore_dummy.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "mappedMemory/userfaultCore.h" -ufInstance_t ufMakeInstance(){} -int ufInit(ufInstance_t instance){} -void ufShutdown(ufInstance_t instance, bool free){} -void ufAwaitShutdown(ufInstance_t instance){} -uint32_t ufGetPageSize(ufInstance_t instance){} -ufObjectConfig_t _makeObjectConfig(uint64_t ct, uint32_t stride, int32_t minLoadCt){} -void ufSetPopulateFunction(ufObjectConfig_t config, ufPopulateRange populateF){} -void ufSetUserConfig(ufObjectConfig_t config, ufUserData userData){} -int ufCreateObject(ufInstance_t instance, ufObjectConfig_t objectConfig, ufObject_t* object_p){} -int ufDestroyObject(ufObject_t object_p){} -void* ufGetHeaderPointer(ufObject_t object){} -void* ufGetValuePointer(ufObject_t object){} - - - diff --git a/ufos/CMakeLists.txt b/ufos/CMakeLists.txt new file mode 100644 index 0000000..91caffa --- /dev/null +++ b/ufos/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.7) +project(ufos) + +SET(EX_PLATFORM 64) +SET(EX_PLATFORM_NAME "x64") + +add_definitions(-Wall -O2 -D__UFOs_CoreDev__) + #-Wall -g + +set(CMAKE_CXX_STANDARD 11) + +#file(GLOB_RECURSE SRC "src/*.c" "src/*.h") + +set(CORE_SRC src/mappedMemory/userfaultCore.h + src/mappedMemory/sparseList.h + src/mappedMemory/sparseList.c + src/mappedMemory/userfaultCore.c + src/mappedMemory/userFaultCoreInternal.h + src/mappedMemory/userfaultGettersSetters.c) + +set(UNSTDLIB_SRC + src/unstdLib/errors.h + src/unstdLib/math.h + src/unstdLib/vars.h) + +set(R_SRC src/ufos.h + src/ufos.c + src/init.c) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +find_package(R REQUIRED) +message("R libraries: ${R_LIBRARIES}") +message("R include dirs: ${R_INCLUDE_DIR}") + +find_package (Threads) + +add_library(ufos SHARED ${CORE_SRC} ${R_SRC} ${UNSTDLIB_SRC}) +include_directories(ufos ${R_INCLUDE_DIR}) +target_link_libraries(ufos ${R_LIBRARIES}) + +add_executable(ufoTest ${CORE_SRC} ${UNSTDLIB_SRC} src/mappedMemory/ufoTest.c) +target_link_libraries(ufoTest ${CMAKE_THREAD_LIBS_INIT}) + +add_executable(strideTest ${CORE_SRC} src/mappedMemory/stride.c) +target_link_libraries(strideTest ${CMAKE_THREAD_LIBS_INIT}) + +add_executable(sparseListTest ${CORE_SRC} src/mappedMemory/sparseListTest.c) +target_link_libraries(sparseListTest ${CMAKE_THREAD_LIBS_INIT}) + +add_executable(userfaultSpeed ${CORE_SRC} src/mappedMemory/userfaultSpeed.c) +target_link_libraries(userfaultSpeed ${CMAKE_THREAD_LIBS_INIT}) + diff --git a/ufos/DESCRIPTION b/ufos/DESCRIPTION new file mode 100644 index 0000000..3a8074d --- /dev/null +++ b/ufos/DESCRIPTION @@ -0,0 +1,20 @@ +Package: ufos +Type: Package +Title: UserFault Objects: framework for implementing of custom objects + masquerading as plain R objects via user faults +Description: Experiments in making custom objects with complex behavior + appearing as ordinary R data structures (data.frames, matrices, + etc.) to both R functions and C functions. This uses user faults + (memory faults) to capture memory accesses and override them. +Version: 0.1.0 +Authors@R: c(person(given = "Colette", family = "Kerr", role = c("aut"), + email = "colette.m.y.kerr@gmail.com"), + person(given = "Konrad", family = "Siek", role = c("aut", "cre"), + email = "siekkonr@fit.cvut.cz")) +Maintainer: Konrad Siek +License: GPL-2 | GPL-3 +Encoding: UTF-8 +LazyData: true +NeedsCompilation: yes +Suggests: ufovectors + diff --git a/NAMESPACE b/ufos/NAMESPACE similarity index 100% rename from NAMESPACE rename to ufos/NAMESPACE diff --git a/ufos/R/ufos.R b/ufos/R/ufos.R new file mode 100644 index 0000000..2f1642c --- /dev/null +++ b/ufos/R/ufos.R @@ -0,0 +1,2 @@ +# Empty. + diff --git a/README.md b/ufos/README.md similarity index 100% rename from README.md rename to ufos/README.md diff --git a/cmake/FindR.cmake b/ufos/cmake/FindR.cmake similarity index 100% rename from cmake/FindR.cmake rename to ufos/cmake/FindR.cmake diff --git a/ufos/src/Makevars b/ufos/src/Makevars new file mode 100644 index 0000000..faa6e1c --- /dev/null +++ b/ufos/src/Makevars @@ -0,0 +1,2 @@ +PKG_CPPFLAGS = -pthread -D__UFOs_CoreDev__ +PKG_LIBS = -pthread -D__UFOs_CoreDev__ diff --git a/ufos/src/init.c b/ufos/src/init.c new file mode 100644 index 0000000..64fa180 --- /dev/null +++ b/ufos/src/init.c @@ -0,0 +1,25 @@ +#include "ufos.h" + +#include +#include + +// List of functions provided by the package. +static const R_CallMethodDef CallEntries[] = { + // Terminates the function list. Necessary. + {NULL, NULL, 0} +}; + +// Initializes the package and registers the routines with the Rdynload +// library. Name follows the pattern: R_init_ +void attribute_visible R_init_ufos(DllInfo *dll) { + //InitUFOAltRepClass(dll); + //R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + //R_useDynamicSymbols(dll, FALSE); + //R_forceSymbols(dll, TRUE); + + R_RegisterCCallable("ufos", "ufo_initialize", (DL_FUNC) &ufo_initialize); + R_RegisterCCallable("ufos", "ufo_new", (DL_FUNC) &ufo_new); + R_RegisterCCallable("ufos", "ufo_shutdown", (DL_FUNC) &ufo_shutdown); +} + + diff --git a/src/mappedMemory/sparseList.c b/ufos/src/mappedMemory/sparseList.c similarity index 100% rename from src/mappedMemory/sparseList.c rename to ufos/src/mappedMemory/sparseList.c diff --git a/src/mappedMemory/sparseList.h b/ufos/src/mappedMemory/sparseList.h similarity index 100% rename from src/mappedMemory/sparseList.h rename to ufos/src/mappedMemory/sparseList.h diff --git a/src/mappedMemory/sparseListTest.c b/ufos/src/mappedMemory/sparseListTest.c similarity index 100% rename from src/mappedMemory/sparseListTest.c rename to ufos/src/mappedMemory/sparseListTest.c diff --git a/src/mappedMemory/stride.c b/ufos/src/mappedMemory/stride.c similarity index 100% rename from src/mappedMemory/stride.c rename to ufos/src/mappedMemory/stride.c diff --git a/src/mappedMemory/ufoTest.c b/ufos/src/mappedMemory/ufoTest.c similarity index 100% rename from src/mappedMemory/ufoTest.c rename to ufos/src/mappedMemory/ufoTest.c diff --git a/src/mappedMemory/userFaultCoreInternal.h b/ufos/src/mappedMemory/userFaultCoreInternal.h similarity index 100% rename from src/mappedMemory/userFaultCoreInternal.h rename to ufos/src/mappedMemory/userFaultCoreInternal.h diff --git a/src/mappedMemory/userfaultCore.c b/ufos/src/mappedMemory/userfaultCore.c similarity index 100% rename from src/mappedMemory/userfaultCore.c rename to ufos/src/mappedMemory/userfaultCore.c diff --git a/src/mappedMemory/userfaultCore.h b/ufos/src/mappedMemory/userfaultCore.h similarity index 100% rename from src/mappedMemory/userfaultCore.h rename to ufos/src/mappedMemory/userfaultCore.h diff --git a/src/mappedMemory/userfaultGettersSetters.c b/ufos/src/mappedMemory/userfaultGettersSetters.c similarity index 100% rename from src/mappedMemory/userfaultGettersSetters.c rename to ufos/src/mappedMemory/userfaultGettersSetters.c diff --git a/src/mappedMemory/userfaultSpeed.c b/ufos/src/mappedMemory/userfaultSpeed.c similarity index 100% rename from src/mappedMemory/userfaultSpeed.c rename to ufos/src/mappedMemory/userfaultSpeed.c diff --git a/src/ufo_sources.h b/ufos/src/ufo_sources.h similarity index 93% rename from src/ufo_sources.h rename to ufos/src/ufo_sources.h index a447de2..47f56c1 100644 --- a/src/ufo_sources.h +++ b/ufos/src/ufo_sources.h @@ -16,7 +16,7 @@ typedef enum { typedef struct { ufUserData* data; ufPopulateRange population_function; - ufo_vector_type_t vector_type; + ufo_vector_type_t vector_type; //ufUpdateRange update_function; R_xlen_t length; } ufo_source_t; diff --git a/src/ufos.c b/ufos/src/ufos.c similarity index 79% rename from src/ufos.c rename to ufos/src/ufos.c index 6ba2aeb..69d8ee9 100644 --- a/src/ufos.c +++ b/ufos/src/ufos.c @@ -6,9 +6,10 @@ #include #include "ufos.h" -#include "ufo_sources.h" #include "mappedMemory/userfaultCore.h" +#include + ufInstance_t ufo_system; typedef SEXP (*__ufo_specific_vector_constructor)(ufo_source_t*); @@ -33,9 +34,21 @@ void __validate_status_or_die (int status) { void* __ufo_alloc(R_allocator_t *allocator, size_t size) { ufo_source_t* source = (ufo_source_t*) allocator->data; - ufObject_t object; - ufObjectConfig_t cfg = makeObjectConfig(int, size, 1); // FIXME + size_t sexp_header_size = sizeof(struct sxpinfo_struct) + + 2 * sizeof(struct SEXPREC*); + + size_t sexp_metadata_size = sizeof(R_allocator_t); + assert((size - sexp_header_size - sexp_metadata_size) + == (source->length * sizeof(int))); + + //makeObjectConfig(headerBytes, type, ct, minLoadCt) + ufObjectConfig_t cfg = makeObjectConfig(int, + sexp_header_size + sexp_metadata_size, + source->length, + 16); // FIXME + + ufObject_t object; int status = ufCreateObject(ufo_system, cfg, &object); __validate_status_or_die(status); @@ -105,22 +118,9 @@ __ufo_specific_vector_constructor __select_constructor(ufo_vector_type_t type) { } } -void __validate_source_or_die(SEXP/*EXTPTRSXP*/ source) { - if (TYPEOF(source) != EXTPTRSXP) { - Rf_error("Invalid source type: expecting EXTPTRSXP"); - } - //ufo_source_t* source_details = CAR(source); -} - -SEXP __ufo_new(SEXP/*EXTPTRSXP*/ source) { - ufo_source_t* source_details = (ufo_source_t*) CAR(source); +SEXP ufo_new(ufo_source_t* source) { __ufo_specific_vector_constructor constructor = - __select_constructor(source_details->vector_type); - return constructor(source_details); -} - -SEXP ufo_new(SEXP/*EXTPTRSXP*/ source) { - __validate_source_or_die(source); - return __ufo_new(source); + __select_constructor(source->vector_type); + return constructor(source); } diff --git a/src/ufos.h b/ufos/src/ufos.h similarity index 70% rename from src/ufos.h rename to ufos/src/ufos.h index ddaede2..80af563 100644 --- a/src/ufos.h +++ b/ufos/src/ufos.h @@ -18,7 +18,7 @@ typedef struct { ufPopulateRange population_function; ufo_vector_type_t vector_type; //ufUpdateRange update_function; - R_xlen_t length; + uint64_t length; } ufo_source_t; // Initialization and shutdown @@ -26,4 +26,9 @@ void ufo_initialize(); void ufo_shutdown(); // Constructor -SEXP ufo_new(ufo_source_t*); \ No newline at end of file +SEXP ufo_new(ufo_source_t*); + +// Function types for R dynloader. +typedef void (*ufo_initialize_t)(void); +typedef void (*ufo_shutdown_t)(void); +typedef SEXP (*ufo_new_t)(ufo_source_t*); \ No newline at end of file diff --git a/src/unstdLib/errors.h b/ufos/src/unstdLib/errors.h similarity index 100% rename from src/unstdLib/errors.h rename to ufos/src/unstdLib/errors.h diff --git a/src/unstdLib/math.h b/ufos/src/unstdLib/math.h similarity index 100% rename from src/unstdLib/math.h rename to ufos/src/unstdLib/math.h diff --git a/src/unstdLib/vars.h b/ufos/src/unstdLib/vars.h similarity index 100% rename from src/unstdLib/vars.h rename to ufos/src/unstdLib/vars.h diff --git a/ufovectors/CMakeLists.txt b/ufovectors/CMakeLists.txt new file mode 100644 index 0000000..8cbe6e0 --- /dev/null +++ b/ufovectors/CMakeLists.txt @@ -0,0 +1,20 @@ +project(ufovectors) +cmake_minimum_required(VERSION 2.8.7) + +SET(EX_PLATFORM 64) +SET(EX_PLATFORM_NAME "x64") + +add_definitions(-Wall -O2) + # -Wall -g + +file(GLOB_RECURSE SRC "src/*.c" "src/*.h") + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +find_package(R REQUIRED) +message("R libraries: ${R_LIBRARIES}") +message("R include dirs: ${R_INCLUDE_DIR}") + +add_library(ufovectors SHARED ${SRC}) +include_directories(ufovectors ${R_INCLUDE_DIR}) +target_link_libraries(ufovectors ${R_LIBRARIES}) \ No newline at end of file diff --git a/ufovectors/DESCRIPTION b/ufovectors/DESCRIPTION new file mode 100644 index 0000000..2cef6fd --- /dev/null +++ b/ufovectors/DESCRIPTION @@ -0,0 +1,17 @@ +Package: ufovectors +Type: Package +Title: Implementation of R vectors using UserFault Objects +Description: Example implementation of R vectors using UserFault Objects to + materialize data on demand from file sources. +Version: 0.1.0 +Authors@R: c(person(given = "Colette", family = "Kerr", role = c("aut"), + email = "colette.m.y.kerr@gmail.com"), + person(given = "Konrad", family = "Siek", role = c("aut", "cre"), + email = "siekkonr@fit.cvut.cz")) +Maintainer: Konrad Siek +License: GPL-2 | GPL-3 +Encoding: UTF-8 +LazyData: true +Depends: ufos +LinkingTo: ufos +NeedsCompilation: yes diff --git a/ufovectors/NAMESPACE b/ufovectors/NAMESPACE new file mode 100644 index 0000000..d017f86 --- /dev/null +++ b/ufovectors/NAMESPACE @@ -0,0 +1,10 @@ +useDynLib(ufovectors, .registration = TRUE, .fixes = "") + +export(ufo_integer_bin) +#export(ufo_numeric_bin) +#export(ufo_character_bin) +#export(ufo_complex_bin) +#export(ufo_logical_bin) + +export(ufo_init) +export(ufo_shutdown) \ No newline at end of file diff --git a/ufovectors/R/ufovectors.R b/ufovectors/R/ufovectors.R new file mode 100644 index 0000000..25e81d5 --- /dev/null +++ b/ufovectors/R/ufovectors.R @@ -0,0 +1,46 @@ +ufo_init <- function() { + invisible(.Call("ufo_vectors_initialize")) +} + +ufo_integer_bin <- function(path) { + .check_path(path) + .Call("ufo_vectors_intsxp_bin", path) +} + +# ufo_numeric_bin <- function(path) { +# .check_path(path) +# .Call("ufo_vectors_realsxp_bin", path) +# } +# +# ufo_character_bin <- function(path) { +# .check_path(path) +# .Call("ufo_vectors_strsxp_bin", path) +# } +# +# ufo_complex_bin <- function(path) { +# .check_path(path) +# .Call("ufo_vectors_cplxsxp_bin", path) +# } +# +# ufo_logical_bin <- function(path) { +# .check_path(path) +# .Call("ufo_vectors_lglsxp_bin", path) +# } + +ufo_shutdown <- function() { + invisible(.Call("ufo_vectors_shutdown")) +} + +.check_path <- function(path) { + if (typeof(path) != "character") { + stop(paste0("Path is of type", typeof(path), + ", must be a character vector.")) + } + if (length(path) == 0) { + stop("Path is a 0-length vector") + } + if (length(path) > 1) { + warning(paste0("Path is a vector containing multiple values, picking the", + "first one, ignoring the rest")); + } +} \ No newline at end of file diff --git a/ufovectors/README.md b/ufovectors/README.md new file mode 100644 index 0000000..2a226ff --- /dev/null +++ b/ufovectors/README.md @@ -0,0 +1,5 @@ +# UFO Vectors + +## Installation + +## Getting started diff --git a/ufovectors/cmake/FindR.cmake b/ufovectors/cmake/FindR.cmake new file mode 100644 index 0000000..b48f507 --- /dev/null +++ b/ufovectors/cmake/FindR.cmake @@ -0,0 +1,106 @@ + +# +# - This module locates an installed R distribution. +# +# Input: +# R_LIB_ARCH - For windows (i386 or x64) +# +# Defines the following: +# R_COMMAND - Path to R command +# R_HOME - Path to 'R home', as reported by R +# R_INCLUDE_DIR - Path to R include directory +# R_LIBRARY_BASE - Path to R library +# R_LIBRARY_BLAS - Path to Rblas / blas library +# R_LIBRARY_LAPACK - Path to Rlapack / lapack library +# R_LIBRARY_READLINE - Path to readline library +# R_LIBRARIES - Array of: R_LIBRARY_BASE, R_LIBRARY_BLAS, R_LIBRARY_LAPACK, R_LIBRARY_BASE [, R_LIBRARY_READLINE] +# +# VTK_R_HOME - (deprecated, use R_HOME instead) Path to 'R home', as reported by R +# +# Variable search order: +# 1. Attempt to locate and set R_COMMAND +# - If unsuccessful, generate error and prompt user to manually set R_COMMAND +# 2. Use R_COMMAND to set R_HOME +# 3. Locate other libraries in the priority: +# 1. Within a user-built instance of R at R_HOME +# 2. Within an installed instance of R +# 3. Within external system libraries +# + +set(TEMP_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE}) +set(CMAKE_FIND_APPBUNDLE "NEVER") +find_program(R_COMMAND R DOC "R executable.") +set(CMAKE_FIND_APPBUNDLE ${TEMP_CMAKE_FIND_APPBUNDLE}) + +if(NOT R_LIB_ARCH) + set(R_LIB_ARCH "ThisPathNotExists") +endif() + +if(R_COMMAND) + execute_process(WORKING_DIRECTORY . + COMMAND ${R_COMMAND} RHOME + OUTPUT_VARIABLE R_ROOT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + # deprecated + if(VTK_R_HOME) + set(R_HOME ${VTK_R_HOME} CACHE PATH "R home directory obtained from R RHOME") + else(VTK_R_HOME) + set(R_HOME ${R_ROOT_DIR} CACHE PATH "R home directory obtained from R RHOME") + set(VTK_R_HOME ${R_HOME}) + endif(VTK_R_HOME) + # /deprecated + # the following command does nothing currently, but will be used when deprecated code is removed + set(R_HOME ${R_ROOT_DIR} CACHE PATH "R home directory obtained from R RHOME") + + find_path(R_INCLUDE_DIR R.h + HINTS ${R_ROOT_DIR} + PATHS /usr/local/lib /usr/local/lib64 /usr/share + PATH_SUFFIXES include R/include + DOC "Path to file R.h") + if(NOT R_INCLUDE_DIR) + message( + FATAL_ERROR + "R.h file not found. Locations tried:\n" + "/usr/local/lib /usr/local/lib64 /usr/share ${R_ROOT_DIR}" + ) + endif() + + file(GLOB_RECURSE RCPP_HINT "${R_HOME}/*/Rcpp.h") + string(REGEX REPLACE "/Rcpp.h$" "" RCPP_HINT "${RCPP_HINT}") + + find_path(Rcpp_INCLUDE_DIR "Rcpp.h" HINTS "${RCPP_HINT}") + + find_library(R_LIBRARY_BASE R + HINTS ${R_ROOT_DIR}/lib ${R_ROOT_DIR}/bin/${R_LIB_ARCH} + DOC "R library (example libR.a, libR.dylib, etc.).") + if(NOT R_LIBRARY_BASE) + set(R_LIBRARY_BASE "") + message( + "R library not found. Locations tried:\n" + "${R_ROOT_DIR}/lib ${R_ROOT_DIR}/bin/${R_LIB_ARCH}" + ) + if(APPLE) + message(FATAL_ERROR "") + endif() + endif() + + find_library(R_LIBRARY_BLAS NAMES Rblas blas + HINTS ${R_ROOT_DIR}/lib ${R_ROOT_DIR}/bin/${R_LIB_ARCH} + DOC "Rblas library (example libRblas.a, libRblas.dylib, etc.).") + + find_library(R_LIBRARY_LAPACK NAMES Rlapack lapack + HINTS ${R_ROOT_DIR}/lib ${R_ROOT_DIR}/bin/${R_LIB_ARCH} + DOC "Rlapack library (example libRlapack.a, libRlapack.dylib, etc.).") + + find_library(R_LIBRARY_READLINE readline + DOC "(Optional) system readline library. Only required if the R libraries were built with readline support.") + +else(R_COMMAND) + message(SEND_ERROR "FindR.cmake requires the following variables to be set: R_COMMAND") +endif(R_COMMAND) + +# Note: R_LIBRARY_BASE is added to R_LIBRARIES twice; this may be due to circular linking dependencies; needs further investigation +set(R_LIBRARIES ${R_LIBRARY_BASE} ${R_LIBRARY_BLAS} ${R_LIBRARY_LAPACK} ${R_LIBRARY_BASE}) +if(R_LIBRARY_READLINE) + set(R_LIBRARIES ${R_LIBRARIES} ${R_LIBRARY_READLINE}) +endif(R_LIBRARY_READLINE) diff --git a/ufovectors/include/mappedMemory/userfaultCore.h b/ufovectors/include/mappedMemory/userfaultCore.h new file mode 120000 index 0000000..0512f55 --- /dev/null +++ b/ufovectors/include/mappedMemory/userfaultCore.h @@ -0,0 +1 @@ +../../../ufos/src/mappedMemory/userfaultCore.h \ No newline at end of file diff --git a/ufovectors/include/ufos.h b/ufovectors/include/ufos.h new file mode 120000 index 0000000..d5b894e --- /dev/null +++ b/ufovectors/include/ufos.h @@ -0,0 +1 @@ +../../ufos/src/ufos.h \ No newline at end of file diff --git a/ufovectors/src/Makevars b/ufovectors/src/Makevars new file mode 100644 index 0000000..5d76418 --- /dev/null +++ b/ufovectors/src/Makevars @@ -0,0 +1,2 @@ +PKG_CPPFLAGS = -pthread +PKG_LIBS = -pthread diff --git a/ufovectors/src/init.c b/ufovectors/src/init.c new file mode 100644 index 0000000..b3c2f81 --- /dev/null +++ b/ufovectors/src/init.c @@ -0,0 +1,42 @@ +#include "../include/ufos.h" +#include "ufo_vectors.h" + +#include +#include + +// List of functions provided by the package. +static const R_CallMethodDef CallEntries[] = { + + // Initialize the system. + {"ufo_vectors_initialize", (DL_FUNC) &ufo_vectors_initialize, 0}, + + // Vectors that parially materialize on-demand from binary files. + {"ufo_vectors_intsxp_bin", (DL_FUNC) &ufo_vectors_intsxp_bin, 1}, +// {"ufo_vectors_realsxp_bin", (DL_FUNC) &ufo_vectors_realsxp_bin, 1}, +// {"ufo_vectors_strsxp_bin", (DL_FUNC) &ufo_vectors_strsxp_bin, 1}, +// {"ufo_vectors_cplxsxp_bin", (DL_FUNC) &ufo_vectors_cplxsxp_bin, 1}, +// {"ufo_vectors_lglsxp_bin", (DL_FUNC) &ufo_vectors_lglsxp_bin, 1}, + + // Shutdown the system. + {"ufo_vectors_shutdown", (DL_FUNC) &ufo_vectors_shutdown, 0}, + + // Terminates the function list. Necessary. + {NULL, NULL, 0} +}; + +//ufo_initialize_t ufo_initialize; +//ufo_new_t ufo_new; +//ufo_shutdown_t ufo_shutdown; + +// Initializes the package and registers the routines with the Rdynload +// library. Name follows the pattern: R_init_ +void attribute_visible R_init_ufovectors(DllInfo *dll) { +// ufo_new = R_GetCCallable("ufos", "ufo_new"); +// ufo_shutdown = R_GetCCallable("ufos", "ufo_shutdown"); + //InitUFOAltRepClass(dll); + //R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + //R_useDynamicSymbols(dll, FALSE); + //R_forceSymbols(dll, TRUE); +} + + diff --git a/src/bin_file_source.c b/ufovectors/src/ufo_vectors.c similarity index 57% rename from src/bin_file_source.c rename to ufovectors/src/ufo_vectors.c index b5c0e9b..47aedd9 100644 --- a/src/bin_file_source.c +++ b/ufovectors/src/ufo_vectors.c @@ -1,10 +1,15 @@ #include #include -#include -#include "ufo_sources.h" -#include "bin_file_source.h" -#include "mappedMemory/userfaultCore.h" +#include "../include/ufos.h" +#include "ufo_vectors.h" + +#include "../include/mappedMemory/userfaultCore.h" + +typedef struct { + const char* path; + size_t element_size; /* in bytes */ +} ufo_file_source_data_t; /** * Check if the path provided via this SEXP makes sense: @@ -16,9 +21,12 @@ * 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 */ -void __validate_path_or_die(SEXP/*STRSXP*/ path) { +const char* __extract_path_or_die(SEXP/*STRSXP*/ path) { if (TYPEOF(path) != STRSXP) { Rf_error("Invalid type for paths: %d\n", TYPEOF(path)); } @@ -35,6 +43,8 @@ void __validate_path_or_die(SEXP/*STRSXP*/ path) { Rf_warning("Provided multiple string values for path, " "using the first one only\n"); } + + return CHAR(STRING_ELT(path, 0)); } /** @@ -50,26 +60,32 @@ void __validate_path_or_die(SEXP/*STRSXP*/ path) { * file, 44 if reading failed. */ int __load_from_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, "rb"); - - if (file) { - int seek_status = fseek(file, data->element_size * start, SEEK_SET); - if (seek_status < 0) { - return 42; - } - int read_status = fread(target, data->element_size, end-start, file); - if (read_status < end-start || read_status == 0) { - return 44; - } + ufUserData user_data, char* target) { // FIXME ASK COLETTE +// ufo_file_source_data_t* data = (ufo_file_source_data_t*) user_data; +// FILE* file = fopen(data->path, "rb"); +// +// if (file) { +// int seek_status = fseek(file, data->element_size * start, SEEK_SET); +// if (seek_status < 0) { +// return 42; +// } +// int read_status = fread(target, data->element_size, end-start, file); +// if (read_status < end-start || read_status == 0) { +// return 44; +// } +// } +// +// fclose(file); + + int *x = (int *) target; + for(int i = 0; i < end - start; i++) { + x[i] = start + i; } - fclose(file); return 0; } -// TODO not actually implementing anything in userfaultCore.h +// 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; @@ -88,6 +104,8 @@ int __save_to_file(uint64_t start, uint64_t end, ufPopulateCallout cf, } fclose(file); + + return 0; } /** @@ -115,18 +133,7 @@ size_t __get_element_size(ufo_vector_type_t vector_type) { } } -/** - * Create a new binary source for UFO vectors. This source reads/writes data - * to/from a binary file. - * - * @param path - * @return Returns SEXP of type EXTPTR, containing a pointer to a - */ -SEXP/*EXTPTRSXP*/ ufo_bin_file_source(SEXP/*STRSXP*/ sexp) { - __validate_path_or_die(sexp); - - const char* path = CHAR(STRING_ELT(sexp, 0)); - +ufo_source_t* __make_source(ufo_vector_type_t type, const char* path) { ufo_file_source_data_t *data = (ufo_file_source_data_t*) malloc(sizeof(ufo_file_source_data_t)); data->path = path; @@ -134,8 +141,50 @@ SEXP/*EXTPTRSXP*/ ufo_bin_file_source(SEXP/*STRSXP*/ sexp) { ufo_source_t* source = (ufo_source_t*) malloc(sizeof(ufo_source_t)); source->population_function = &__load_from_file; source->data = (ufUserData*) data; + source->vector_type = type; + source->length = 256; //FIXME this should be arbitrary or discovered data->element_size = __get_element_size(source->vector_type); - return R_MakeExternalPtr(source, install("ufo_source"), R_NilValue); + return source; +} + +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_new_t ufo_new = (ufo_new_t) R_GetCCallable("ufos", "ufo_new"); + return ufo_new(source); +} + +SEXP ufo_vectors_intsxp_bin(SEXP/*STRSXP*/ path) { + return __make_vector(UFO_INT, path); +} + +//SEXP ufo_vectors_realsxp_bin(SEXP/*STRSXP*/ path) { +// return __make_vector(UFO_REAL, path); +//} +// +//SEXP ufo_vectors_cplxsxp_bin(SEXP/*STRSXP*/ path) { +// return __make_vector(UFO_CPLX, path); +//} +// +//SEXP ufo_vectors_strsxp_bin(SEXP/*STRSXP*/ path) { +// Rf_error("ufo_vectors_strsxp_bin not implemented"); +// //return __make_vector(UFO_STR, path); +//} +// +//SEXP ufo_vectors_lglsxp_bin(SEXP/*STRSXP*/ path) { +// return __make_vector(UFO_LGL, path); +//} + +SEXP ufo_vectors_initialize() { + ufo_initialize_t ufo_initialize = (ufo_initialize_t) R_GetCCallable("ufos", "ufo_initialize"); + ufo_initialize(); + return R_NilValue; +} + +SEXP ufo_vectors_shutdown() { + ufo_shutdown_t ufo_shutdown = (ufo_shutdown_t) R_GetCCallable("ufos", "ufo_shutdown"); + ufo_shutdown(); + return R_NilValue; } \ No newline at end of file diff --git a/ufovectors/src/ufo_vectors.h b/ufovectors/src/ufo_vectors.h new file mode 100644 index 0000000..8d114bf --- /dev/null +++ b/ufovectors/src/ufo_vectors.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Rinternals.h" + +SEXP ufo_vectors_intsxp_bin(SEXP/*STRSXP*/ path); +//SEXP ufo_vectors_realsxp_bin(SEXP/*STRSXP*/ path); +//SEXP ufo_vectors_cplxsxp_bin(SEXP/*STRSXP*/ path); +//SEXP ufo_vectors_strsxp_bin(SEXP/*STRSXP*/ path); +//SEXP ufo_vectors_lglsxp_bin(SEXP/*STRSXP*/ path); + +SEXP ufo_vectors_initialize(); +SEXP ufo_vectors_shutdown(); \ No newline at end of file