Skip to content

Commit

Permalink
implement read only open (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
liss-h authored Sep 25, 2023
1 parent 5ea2906 commit 31963c5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 19 deletions.
13 changes: 11 additions & 2 deletions src/dice/ffi/metall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@

using metall_manager_t = dice::metall_ffi::internal::metall_manager;

metall_manager *metall_open(char const *path) {
template<auto open_mode>
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)
errno = ENOTRECOVERABLE;
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;
Expand All @@ -21,6 +22,14 @@ metall_manager *metall_open(char const *path) {
return reinterpret_cast<metall_manager *>(manager);
}

metall_manager *metall_open(char const *path) {
return open_impl<metall::open_only>(path);
}

metall_manager *metall_open_read_only(char const *path) {
return open_impl<metall::open_read_only>(path);
}

metall_manager *metall_create(char const *path) {
if (std::filesystem::exists(path)) {
// prevent accidental overwrite
Expand Down
8 changes: 8 additions & 0 deletions src/dice/ffi/metall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 48 additions & 17 deletions tests/tests_Sanity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,30 @@ TEST_SUITE("metall-ffi") {
FAIL("failed to create: ", strerror(errno));
}

auto *ptr = static_cast<size_t *>(metall_malloc(manager, obj_name, sizeof(size_t)));
{
auto *ptr = static_cast<size_t *>(metall_malloc(manager, obj_name, sizeof(size_t)));
CHECK_NE(ptr, nullptr);
CHECK_EQ(reinterpret_cast<uintptr_t>(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<size_t *>(metall_find(manager, obj_name));
CHECK_NE(ptr, nullptr);
CHECK_EQ(reinterpret_cast<uintptr_t>(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));
Expand All @@ -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<size_t *>(metall_find(manager, obj_name));
if (ptr == nullptr) {
FAIL("failed to load: ", strerror(errno));
}
auto *ptr = static_cast<size_t *>(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);
Expand Down

0 comments on commit 31963c5

Please sign in to comment.