diff --git a/conanfile.py b/conanfile.py index 5fbec4c..df9b73c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -50,7 +50,7 @@ def _configure_cmake(self): if self._cmake: return self._cmake self._cmake = CMake(self) - self._cmake.configure(variables={"USE_CONAN": False}) + self._cmake.configure() return self._cmake diff --git a/src/dice/ffi/metall.cpp b/src/dice/ffi/metall.cpp index cb8edcb..59841f1 100644 --- a/src/dice/ffi/metall.cpp +++ b/src/dice/ffi/metall.cpp @@ -1,6 +1,8 @@ #include #include +#include + using metall_manager_t = dice::metall_ffi::internal::metall_manager; template @@ -22,22 +24,15 @@ metall_manager *open_impl(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) { +template +metall_manager *create_impl(char const *path, Create &&create) { if (std::filesystem::exists(path)) { // prevent accidental overwrite errno = EEXIST; return nullptr; } - auto *manager = new metall_manager_t{metall::create_only, path}; + auto *manager = std::invoke(std::forward(create), path); if (!manager->check_sanity()) { delete manager; errno = ENOTRECOVERABLE; @@ -47,6 +42,26 @@ metall_manager *metall_create(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) { + return create_impl(path, [](char const *path) { + return new metall_manager_t{metall::create_only, path}; + }); +} + +metall_manager *metall_create_with_capacity_limit(char const *path, size_t capacity) { + return create_impl(path, [capacity](char const *path) { + return new metall_manager_t{metall::create_only, path, capacity}; + }); +} + bool metall_is_read_only(metall_manager const *manager) { return reinterpret_cast(manager)->read_only(); } diff --git a/src/dice/ffi/metall.h b/src/dice/ffi/metall.h index 7689efd..0981db1 100644 --- a/src/dice/ffi/metall.h +++ b/src/dice/ffi/metall.h @@ -30,6 +30,7 @@ typedef enum metall_log_level { } metall_log_level; #endif + typedef struct metall_manager metall_manager; /** @@ -57,6 +58,16 @@ metall_manager *metall_open_read_only(char const *path); */ metall_manager *metall_create(char const *path); +/** + * @brief Attempts to create a metall datastore at path + * @param path path at which to create a datastore + * @param capacity maximum capacity for metall manager + * @return true on success, false on failure. On failure, sets errno to one of the following values: + * - EEXIST if the given path already exists + * - ENOTRECOVERABLE if the datastore could not be created for some other reason + */ +metall_manager *metall_create_with_capacity_limit(char const *path, size_t capacity); + /** * @brief Returns true if the metall manager was opened as read-only * @param manager manager to check diff --git a/tests/tests_Sanity.cpp b/tests/tests_Sanity.cpp index eefb935..8eecee5 100644 --- a/tests/tests_Sanity.cpp +++ b/tests/tests_Sanity.cpp @@ -114,4 +114,18 @@ TEST_SUITE("metall-ffi") { metall_close(manager); CHECK(metall_remove(path.c_str())); } + + TEST_CASE("capacity limit") { + std::string const path = "/tmp/" + std::to_string(std::random_device{}()); + metall_manager *manager = metall_create_with_capacity_limit(path.c_str(), 1); + if (manager == nullptr) { + FAIL("failed to create datastore: ", strerror(errno)); + } + + auto ret = metall_malloc(manager, "aaa", 1'000'000'000); + if (ret != nullptr) { + metall_free(manager, "aaa"); + FAIL("Did not refuse to allocate"); + } + } }