Skip to content

Commit

Permalink
complete interface rework to prevent early destruction
Browse files Browse the repository at this point in the history
  • Loading branch information
Clueliss committed Sep 19, 2023
1 parent a88058c commit 6133662
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 109 deletions.
93 changes: 18 additions & 75 deletions src/dice/ffi/metall.cpp
Original file line number Diff line number Diff line change
@@ -1,120 +1,63 @@
#include <dice/ffi/metall.h>
#include <dice/ffi/metall_internal.hpp>

namespace dice::metall_ffi::internal {
dice::sparse_map::sparse_map<std::string, std::unique_ptr<metall_manager>> metall_managers;
} // dice::metall_ffi::internal

using namespace dice::metall_ffi::internal;

bool metall_open(char const *path) {
if (auto it = metall_managers.find(path); it != metall_managers.end()) {
return true;
}
using metall_manager_t = dice::metall_ffi::internal::metall_manager;

metall_manager *metall_open(char const *path) {
if (!metall::manager::consistent(path)) {
errno = ENOTRECOVERABLE;
return false;
return nullptr;
}

metall_managers.emplace(path, std::make_unique<metall_manager>(metall::open_only, path));
return true;
return reinterpret_cast<metall_manager *>(new metall_manager_t{metall::open_only, path});
}

bool metall_create(char const *path) {
if (auto it = metall_managers.find(path); it != metall_managers.end()) {
return true;
}

metall_manager *metall_create(char const *path) {
if (std::filesystem::exists(path)) {
errno = EEXIST;
return false;
return nullptr;
}

metall_managers.emplace(path, std::make_unique<metall_manager>(metall::create_only, path));
return true;
}

bool metall_is_open(char const *path) {
return metall_managers.find(path) != metall_managers.end();
return reinterpret_cast<metall_manager *>(new metall_manager_t{metall::create_only, path});
}

bool metall_is_consistent(char const *path) {
if (metall_is_open(path)) {
return true;
}

return metall::manager::consistent(path);
}

bool metall_snapshot(char const *src_path, char const *dst_path) {
auto it = metall_managers.find(src_path);
if (it == metall_managers.end()) {
errno = EINVAL;
return false;
}

return it->second->snapshot(dst_path);
bool metall_snapshot(metall_manager *manager, char const *dst_path) {
return reinterpret_cast<metall_manager_t *>(manager)->snapshot(dst_path);
}

bool metall_close(char const *path) {
auto it = metall_managers.find(path);
if (it == metall_managers.end()) {
errno = EINVAL;
return false;
}

metall_managers.erase(it);
return true;
void metall_close(metall_manager *manager) {
delete reinterpret_cast<metall_manager_t *>(manager);
}

bool metall_remove(char const *path) {
if (auto it = metall_managers.find(path); it != metall_managers.end()) {
errno = EADDRINUSE;
return false;
}

return metall::manager::remove(path);
}

void *metall_malloc(char const *path, char const *name, size_t size) {
auto it = metall_managers.find(path);
if (it == metall_managers.end()) {
errno = EINVAL;
return nullptr;
}

auto *ptr = it->second->construct<char>(name)[size]();
void *metall_malloc(metall_manager *manager, char const *name, size_t size) {
auto *ptr = reinterpret_cast<metall_manager_t *>(manager)->construct<char>(name)[size]();
if (ptr == nullptr) {
errno = ENOMEM;
return nullptr;
}

return ptr;
}

void *metall_find(char const *path, char const *name) {
auto it = metall_managers.find(path);
if (it == metall_managers.end()) {
errno = EINVAL;
return nullptr;
}

auto *ptr = it->second->find<char>(name).first;
void *metall_find(metall_manager *manager, char const *name) {
auto *ptr = reinterpret_cast<metall_manager_t *>(manager)->find<char>(name).first;
if (ptr == nullptr) {
errno = ENOENT;
}

return ptr;
}

bool metall_free(char const *path, char const *name) {
auto it = metall_managers.find(path);
if (it == metall_managers.end()) {
errno = EINVAL;
return false;
}

auto const res = it->second->destroy<char>(name);
bool metall_free(metall_manager *manager, char const *name) {
auto const res = reinterpret_cast<metall_manager_t *>(manager)->destroy<char>(name);
if (!res) {
errno = ENOENT;
}
Expand Down
22 changes: 9 additions & 13 deletions src/dice/ffi/metall.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,21 @@
extern "C" {
#endif

typedef struct metall_manager metall_manager;

/**
* @brief Attempts to open the metall datastore at path
* @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
*/
bool metall_open(char const *path);
metall_manager *metall_open(char const *path);

/**
* @brief Attempts to create a metall datastore at path
* @return true on success, false on failure. On failure, sets errno to one of the following values:
* - EEXIST if the given path already exists
*/
bool metall_create(char const *path);

/**
* @brief Checks if a metall manager is open for the given path
* @return true if open otherwise false
*/
bool metall_is_open(char const *path);
metall_manager *metall_create(char const *path);

/**
* @brief checks if the datastore at the given path is in consistent state.
Expand All @@ -39,14 +35,14 @@ bool metall_is_consistent(char const *path);
* @return true if the snapshot was successfully created otherwise false. On failure sets errno to one of the following values:
* - EINVAL if there is no metall datastore open at src_path
*/
bool metall_snapshot(char const *src_path, char const *dst_path);
bool metall_snapshot(metall_manager *manager, char const *dst_path);

/**
* @brief Attempts to close the metall datastore opened at path
* @return true on success, false on failure. On failure, sets errno to one of the following values:
* - EINVAL if the given path does not have a metall datastore open
*/
bool metall_close(char const *path);
void metall_close(metall_manager *manager);

/**
* @brief Removes the metall datastore at path
Expand All @@ -65,7 +61,7 @@ bool metall_remove(char const *path);
* - EINVAL if the given path does not have a metall datastore open
* - ENOMEM if the memory could not be allocated
*/
void *metall_malloc(char const *path, char const *name, size_t size);
void *metall_malloc(metall_manager *manager, char const *name, size_t size);

/**
* @brief Finds memory that was previously allocated using metall_named_alloc
Expand All @@ -75,7 +71,7 @@ void *metall_malloc(char const *path, char const *name, size_t size);
* - EINVAL if the given path does not have a metall datastore open
* - ENOTENT if the object could not be found
*/
void *metall_find(char const *path, char const *name);
void *metall_find(metall_manager *manager, char const *name);

/**
* @brief Frees memory previously allocated by metall_named_malloc
Expand All @@ -85,7 +81,7 @@ void *metall_find(char const *path, char const *name);
* - EINVAL if the given path does not have a metall datastore open
* - ENOENT if the referred to object does not exist
*/
bool metall_free(char const *path, char const *name);
bool metall_free(metall_manager *manager, char const *name);

#ifdef __cplusplus
}
Expand Down
3 changes: 0 additions & 3 deletions src/dice/ffi/metall_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
#include <metall/metall.hpp>

namespace dice::metall_ffi::internal {

using metall_manager = metall::basic_manager<uint32_t, (1ULL << 28ULL)>;
extern dice::sparse_map::sparse_map<std::string, std::unique_ptr<metall_manager>> metall_managers;

} // namespace

#endif//DICE_METALLFFI_METALLINTERNAL_HPP
28 changes: 10 additions & 18 deletions tests/tests_Sanity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,46 @@ TEST_CASE("sanity check") {
std::string const snap_path = path + "-snap";

{
if (!metall_create(path.c_str())) {
metall_manager *manager = metall_create(path.c_str());
if (manager == nullptr) {
FAIL("failed to create: ", strerror(errno));
}
CHECK(metall_is_open(path.c_str()));

auto *ptr = static_cast<size_t *>(metall_malloc(path.c_str(), 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);

if (!metall_snapshot(path.c_str(), snap_path.c_str())) {
if (!metall_snapshot(manager, snap_path.c_str())) {
FAIL("failed to snapshot: ", strerror(errno));
}

if (!metall_close(path.c_str())) {
FAIL("failed to close: ", strerror(errno));
}

CHECK(!metall_is_open(path.c_str()));
metall_close(manager);
}

auto check = [obj_name](auto const &path) {
CHECK(metall_is_consistent(path.c_str()));

if (!metall_open(path.c_str())) {
metall_manager *manager = metall_open(path.c_str());
if (manager == nullptr) {
FAIL("failed to open: ", strerror(errno));
}

CHECK(metall_is_open(path.c_str()));

auto *ptr = static_cast<size_t *>(metall_find(path.c_str(), obj_name));
auto *ptr = static_cast<size_t *>(metall_find(manager, obj_name));
if (ptr == nullptr) {
FAIL("failed to load: ", strerror(errno));
}

CHECK_EQ(*ptr, 55);

if (!metall_free(path.c_str(), obj_name)) {
if (!metall_free(manager, obj_name)) {
FAIL("failed to dealloc: ", strerror(errno));
}

if (!metall_close(path.c_str())) {
FAIL("failed to close: ", strerror(errno));
}
metall_close(manager);

CHECK(!metall_is_open(path.c_str()));
CHECK(metall_remove(path.c_str()));
CHECK(!metall_open(path.c_str()));
};
Expand Down

0 comments on commit 6133662

Please sign in to comment.