Skip to content

Commit

Permalink
Merge pull request #316 from dice-group/feature/new-c-interface
Browse files Browse the repository at this point in the history
Feature: new c interface
  • Loading branch information
KIwabuchi committed Feb 2, 2024
2 parents a62a322 + e0a73ea commit 571ac94
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 111 deletions.
43 changes: 30 additions & 13 deletions example/c_api.c
Expand Up @@ -4,48 +4,65 @@
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

#include <assert.h>
#include <stdint.h>
#include <metall/c_api/metall.h>

int main(void) {
// Basic allocation
{
metall_open(METALL_CREATE_ONLY, "/tmp/metall1");
metall_manager* manager = metall_create("/tmp/metall1");

uint64_t *x = metall_malloc(sizeof(uint64_t));
uint64_t* x = metall_malloc(manager, sizeof(uint64_t));
x[0] = 1;

metall_free(x);

metall_close();
metall_free(manager, x);
metall_close(manager);
metall_remove("/tmp/metall1");
}

// Allocate named object
{
metall_open(METALL_CREATE_ONLY, "/tmp/metall2");
metall_manager* manager = metall_create("/tmp/metall2");

uint64_t *array = metall_named_malloc("array", sizeof(uint64_t) * 10);
uint64_t* array = metall_named_malloc(manager, "array",
sizeof(uint64_t) * 10);

array[0] = 0;

metall_flush();
metall_flush(manager);

array[1] = 1;

metall_close();
metall_snapshot(manager, "/tmp/metall2-snap");
metall_close(manager);
}

// Retrieve named object
{
metall_open(METALL_OPEN_ONLY, "/tmp/metall2");
metall_manager* manager = metall_open("/tmp/metall2");

uint64_t *array = metall_find("array");
uint64_t* array = metall_find(manager, "array");

assert(array[0] == 0);
assert(array[1] == 1);

metall_named_free("array");
metall_named_free(manager, "array");
metall_close(manager);
metall_remove("/tmp/metall2");
}

// Retrieve object snapshot
{
metall_manager* manager = metall_open("/tmp/metall2-snap");

uint64_t* array = metall_find(manager, "array");

assert(array[0] == 0);
assert(array[1] == 1);

metall_close();
metall_named_free(manager, "array");
metall_close(manager);
metall_remove("/tmp/metall2-snap");
}

return 0;
Expand Down
176 changes: 111 additions & 65 deletions include/metall/c_api/metall.h
@@ -1,80 +1,126 @@
// Copyright 2019 Lawrence Livermore National Security, LLC and other Metall
// Copyright 2024 Lawrence Livermore National Security, LLC and other Metall
// Project Developers. See the top-level COPYRIGHT file for details.
//
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

#ifndef METALL_C_API_METALL_H
#define METALL_C_API_METALL_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/// \brief Tag to create the segment always.
/// The existing segment with the same name is over written.
#define METALL_CREATE_ONLY 1

/// \brief Tag to open an already created segment.
#define METALL_OPEN_ONLY 2

/// \brief Tag to open an already created segment as read only.
#define METALL_OPEN_READ_ONLY 3

/// \brief Constructs a Metall manager object
/// \param mode Open mode
/// \param path A path to the backing data store
/// \return On success, returns 0. On error, returns -1.
extern int metall_open(int mode, const char *path);

/// \brief Destructs Metall manager object
extern void metall_close();

/// \brief Flush data to persistent memory
extern void metall_flush();

/// \brief Allocates nbytes bytes.
/// \param nbytes The Number of bytes to allocate
/// \return Returns a pointer to the allocated memory
extern void *metall_malloc(uint64_t nbytes);

/// \brief Frees the allocated memory
/// \param ptr A pointer to the allocated memory to be free
extern void metall_free(void *ptr);

/// \brief Allocates nbytes bytes and save the address of the allocated memory
/// with name \param name A name of the allocated memory \param nbytes A size to
/// allocate \return Returns a pointer to the allocated memory
extern void *metall_named_malloc(const char *name, uint64_t nbytes);

/// \brief Finds a saved memory
/// \param name A name of the allocated memory to find
/// \return Returns a pointer to the allocated memory if it exist. Otherwise,
/// returns NULL.
extern void *metall_find(char *name);

/// \brief Frees memory with the name
/// \param name A name of the allocated memory to free
extern void metall_named_free(const char *name);

/// \brief Snapshot the entire data.
/// \param destination_path The path to store a snapshot.
/// \return On success, returns 0. On error, returns -1.
extern int snapshot(const char *destination_path);

/// \brief Copies backing files synchronously.
/// \param source_path Source data store path.
/// \param destination_path Destination data store path.
/// \return On success, returns 0. On error, returns -1.
extern int copy(const char *source_path, const char *destination_path);

/// \brief Check if the backing data store is consistent,
/// i.e. it was closed properly.
/// \param path A path to the backing data store.
/// \return Returns a oon-zero integer if the data store is consistent;
/// otherwise, returns 0.
extern int consistent(const char *path);
/**
* \brief Opaque struct representing a metall manager
* \note this type is internally represented by `::metall::manager` therefore pointers
* to `::metall_manager` may be reinterpret-casted to pointers to `::metall::manager`
*/
typedef struct metall_manager metall_manager;

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

/**
* \brief Attempts to create a metall datastore at path
* \param path path at which to create a datastore
* \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(const char* path);

/**
* \brief Creates a snapshot of the metall datastore of manager and places it at dst_path
* \param manager manager to perform snapshot
* \param dst_path path where to place the snapshot
* \return true if the snapshot was successfully created otherwise false.
*/
bool metall_snapshot(metall_manager* manager, const char* dst_path);

/**
* \brief Flushes the given manager
* \param manager manager to flush
*/
void metall_flush(metall_manager* manager);

/**
* \brief Closes a metall manager
*/
void metall_close(metall_manager* manager);

/**
* \brief Removes the metall datastore at path
* \param path path to datastore to remove
* \return true on successful removal, false otherwise. On failure, sets errno to one of the following values:
* - EADDRINUSE if there is a metall manager open for the given path
*
* \warning Behaviour is undefined if there is still a metall manager for path open
*/
bool metall_remove(const char* path);

/**
* \brief Allocates size bytes
* \param manager manager to allocate with
* \param size number of bytes to allocate
* \return pointer to allocated memory if successful otherwise returns NULL and sets errno to one of the following values
* - EINVAL
*/
void* metall_malloc(metall_manager* manager, size_t size);

/**
* \brief Frees memory previously allocated by metall_malloc
* \param manager manager from which to free
* \param ptr memory to free
*/
void metall_free(metall_manager* manager, void* ptr);

/**
* \brief Allocates size bytes and associates the allocated memory with a name
* \param manager manager to allocate with
* \param name A name of the allocated memory
* \param size number of bytes to allocate
* \return pointer to the allocated memory if sucessful otherwise returns NULL and sets errno to one of the following values
* - EINVAL if the given path does not have a metall datastore open
* - ENOMEM if the memory could not be allocated
*/
void* metall_named_malloc(metall_manager* manager, const char* name,
size_t size);

/**
* \brief Finds memory that was previously allocated using metall_named_alloc
* \param manager manager to find the object in
* \param name name of the allocated memory to find
* \return pointer to the allocated memory if found. Otherwise, returns NULL and sets errno to one of the following values
* - EINVAL if the given path does not have a metall datastore open
* - ENOTENT if the object could not be found
*/
void* metall_find(metall_manager* manager, const char* name);

/**
* \brief Frees memory previously allocated by metall_named_malloc
* \param manager manager from which to free
* \param name name of the allocated memory to free
* \return true if sucessfully freed, otherwise returns false and sets errno to one of the following values
* - EINVAL if the given path does not have a metall datastore open
* - ENOENT if the referred to object does not exist
*/
bool metall_named_free(metall_manager* manager, const char* name);

#ifdef __cplusplus
}
Expand Down

0 comments on commit 571ac94

Please sign in to comment.