diff --git a/src/dice/ffi/metall.cpp b/src/dice/ffi/metall.cpp index 745ffb5..b209504 100644 --- a/src/dice/ffi/metall.cpp +++ b/src/dice/ffi/metall.cpp @@ -3,7 +3,8 @@ using metall_manager_t = dice::metall_ffi::internal::metall_manager; -metall_manager *metall_open(char const *path) { +template +metall_manager *open_impl(char const *path) { if (!metall::manager::consistent(path)) { // prevents opening the same datastore twice // (because opening removes the properly_closed_mark and this checks for it) @@ -11,7 +12,7 @@ metall_manager *metall_open(char const *path) { return nullptr; } - auto *manager = new metall_manager_t{metall::open_only, path}; + auto *manager = new metall_manager_t{open_mode, path}; if (!manager->check_sanity()) { delete manager; errno = ENOTRECOVERABLE; @@ -21,6 +22,14 @@ metall_manager *metall_open(char const *path) { return reinterpret_cast(manager); } +metall_manager *metall_open(char const *path) { + return open_impl(path); +} + +metall_manager *metall_open_read_only(char const *path) { + return open_impl(path); +} + metall_manager *metall_create(char const *path) { if (std::filesystem::exists(path)) { // prevent accidental overwrite diff --git a/src/dice/ffi/metall.h b/src/dice/ffi/metall.h index a7581b6..8fb232a 100644 --- a/src/dice/ffi/metall.h +++ b/src/dice/ffi/metall.h @@ -18,6 +18,14 @@ typedef struct metall_manager metall_manager; */ metall_manager *metall_open(char const *path); +/** + * @brief Attempts to open the metall datastore at path in read only mode + * @param path path to datastore + * @return true on success, false on failure. On failure, sets errno to one of the following values: + * - ENOTRECOVERABLE if the given metall datastore is inconsistent + */ +metall_manager *metall_open_read_only(char const *path); + /** * @brief Attempts to create a metall datastore at path * @param path path at which to create a datastore diff --git a/tests/tests_Sanity.cpp b/tests/tests_Sanity.cpp index 1da3b06..691adcb 100644 --- a/tests/tests_Sanity.cpp +++ b/tests/tests_Sanity.cpp @@ -18,12 +18,30 @@ TEST_SUITE("metall-ffi") { FAIL("failed to create: ", strerror(errno)); } - auto *ptr = static_cast(metall_malloc(manager, obj_name, sizeof(size_t))); + { + auto *ptr = static_cast(metall_malloc(manager, obj_name, sizeof(size_t))); + CHECK_NE(ptr, nullptr); + CHECK_EQ(reinterpret_cast(ptr) % alignof(size_t), 0); + + *ptr = 55; + CHECK_EQ(*ptr, 55); + } + + metall_close(manager); + } + + { + metall_manager *manager = metall_open(path.c_str()); + if (manager == nullptr) { + FAIL("failed to create: ", strerror(errno)); + } + + auto *ptr = static_cast(metall_find(manager, obj_name)); CHECK_NE(ptr, nullptr); CHECK_EQ(reinterpret_cast(ptr) % alignof(size_t), 0); - *ptr = 55; - CHECK_EQ(*ptr, 55); + *ptr = 66; + CHECK_EQ(*ptr, 66); if (!metall_snapshot(manager, snap_path.c_str())) { FAIL("failed to snapshot: ", strerror(errno)); @@ -33,26 +51,39 @@ TEST_SUITE("metall-ffi") { } auto check = [obj_name](auto const &path) { - metall_manager *manager = metall_open(path.c_str()); - if (manager == nullptr) { - FAIL("failed to open: ", strerror(errno)); - } + { + metall_manager *manager = metall_open_read_only(path.c_str()); + if (manager == nullptr) { + FAIL("failed to open: ", strerror(errno)); + } - auto *ptr = static_cast(metall_find(manager, obj_name)); - if (ptr == nullptr) { - FAIL("failed to load: ", strerror(errno)); - } + auto *ptr = static_cast(metall_find(manager, obj_name)); + if (ptr == nullptr) { + FAIL("failed to load: ", strerror(errno)); + } - CHECK_EQ(*ptr, 55); + CHECK_EQ(*ptr, 66); - if (!metall_free(manager, obj_name)) { - FAIL("failed to dealloc: ", strerror(errno)); + CHECK_FALSE(metall_free(manager, obj_name)); + + metall_close(manager); } - metall_close(manager); + { + metall_manager *manager = metall_open(path.c_str()); + if (manager == nullptr) { + FAIL("failed to open: ", strerror(errno)); + } + + if (!metall_free(manager, obj_name)) { + FAIL("failed to dealloc: ", strerror(errno)); + } - CHECK(metall_remove(path.c_str())); - CHECK(!metall_open(path.c_str())); + metall_close(manager); + + CHECK(metall_remove(path.c_str())); + CHECK(!metall_open(path.c_str())); + } }; check(snap_path);