Commit b63c5aa1 authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

Merge branch 'dev-bedrock-26' into 'master'

Bedrock bindings and json configuration

See merge request !19
parents c0677770 ca8a206d
......@@ -7,7 +7,7 @@ distversion:
#
# Easy way to build unit tests without running them
#
#
.phony: tests
tests: $(check_PROGRAMS)
......@@ -6,7 +6,7 @@ bin_SCRIPTS =
noinst_PROGRAMS =
noinst_HEADERS =
TESTS =
XFAIL_TESTS =
XFAIL_TESTS =
check_PROGRAMS =
EXTRA_PROGRAMS =
CLEANFILES = $(bin_SCRIPTS)
......@@ -23,7 +23,7 @@ include_HEADERS = include/bake.h\
TESTS_ENVIRONMENT =
EXTRA_DIST += \
prepare.sh
prepare.sh
AM_CPPFLAGS = -I$(top_srcdir)/include
......@@ -36,6 +36,10 @@ AM_CXXFLAGS = $(AM_CFLAGS)
lib_LTLIBRARIES = src/libbake-client.la src/libbake-server.la
src_libbake_client_la_SOURCES =
src_libbake_server_la_SOURCES =
if ENABLE_BEDROCK
lib_LTLIBRARIES += src/libbake-bedrock.la
src_libbake_bedrock_la_SOURCES =
endif
LDADD = src/libbake-client.la src/libbake-server.la
......
......@@ -86,6 +86,12 @@ LIBS="$UUID_LIBS $LIBS"
CPPFLAGS="$UUID_CFLAGS $CPPFLAGS"
CFLAGS="$UUID_CFLAGS $CFLAGS"
PKG_CHECK_MODULES([JSONC],[json-c],[],
[AC_MSG_ERROR([Could not find working json-c installation!])])
LIBS="$JSONC_LIBS $LIBS"
CPPFLAGS="$JSONC_CFLAGS $CPPFLAGS"
CFLAGS="$JSONC_CFLAGS $CFLAGS"
AC_ARG_ENABLE(remi,
[AS_HELP_STRING([--enable-remi],[Enable REMI (migration) support @<:@default=no@:>@])],
[case "${enableval}" in
......@@ -111,6 +117,27 @@ fi
AC_SUBST(USE_REMI)
AC_SUBST(REMI_PKG)
AC_ARG_ENABLE(bedrock,
[AS_HELP_STRING([--enable-bedrock],[Enable bedrock library support @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_bedrock="yes" ;;
no) enable_bedrock="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-bedrock) ;;
esac],
[enable_bedrock="no"]
)
AM_CONDITIONAL(ENABLE_BEDROCK, test x$enable_bedrock = xyes)
if test "$enable_bedrock" = "yes"; then
PKG_CHECK_MODULES(BEDROCK, bedrock-server)
AC_DEFINE(USE_BEDROCK, 1, [BEDROCK support enabled.])
USE_BEDROCK=1
CPPFLAGS="$BEDROCK_CFLAGS $CPPFLAGS"
CFLAGS="$BEDROCK_CFLAGS $CFLAGS"
else
USE_BEDROCK=0
fi
AC_SUBST(USE_BEDROCK)
AC_ARG_ENABLE(benchmark,
[AS_HELP_STRING([--enable-benchmark],[Build Bake benchmark @<:@default=no@:>@])],
[case "${enableval}" in
......
{
"margo" : {
"argobots": {
"pools" : [
{
"name" : "io_pool"
}
],
"xstreams" : [
{
"name" : "io1",
"scheduler" : {
"type" : "basic_wait",
"pools" : [ "io_pool" ]
}
},
{
"name" : "io2",
"scheduler" : {
"type" : "basic_wait",
"pools" : [ "io_pool" ]
}
},
{
"name" : "io3",
"scheduler" : {
"type" : "basic_wait",
"pools" : [ "io_pool" ]
}
},
{
"name" : "io4",
"scheduler" : {
"type" : "basic_wait",
"pools" : [ "io_pool" ]
}
}
]
}
},
"abt_io" : [
{
"name" : "bake_abt_io",
"pool" : "io_pool"
}
],
"libraries" : {
"bake" : "libbake-bedrock.so"
},
"providers" : [
{
"name" : "my_bake_provider",
"type" : "bake",
"provider_id" : 1,
"pool" : "__primary__",
"config" : {
"pipeline_enable":true,
"pipeline_npools":4,
"pipeline_nbuffers_per_pool":32,
"pipeline_first_buffer_size":65536,
"pipeline_multiplier":4,
"file_backend":{
"targets":[
"./file-target-A.dat"
],
"alignment":4096
},
"pmem_backend":{
"targets":[
"./pmem-target-A.dat"
]
}
},
"dependencies" : {
"abt_io" : "bake_abt_io"
}
}
]
}
......@@ -7,6 +7,7 @@
#ifndef __BAKE_SERVER_H
#define __BAKE_SERVER_H
#include <abt-io.h>
#include <margo.h>
#include <libpmemobj.h>
#include <bake.h>
......@@ -15,24 +16,28 @@
extern "C" {
#endif
#define BAKE_ABT_POOL_DEFAULT ABT_POOL_NULL
#define BAKE_PROVIDER_ID_DEFAULT 0
#define BAKE_PROVIDER_IGNORE NULL
typedef struct bake_provider* bake_provider_t;
/**
* Creates a BAKE pool to use for backend PMEM storage.
*
* NOTE: This function must be called on a pool before the pool
* can be passed to 'bake_provider_register'.
*
* @param[in] pool_name path to PMEM backend file
* @param[in] pool_size size of the created pool
* @param[in] pool_mode mode of the created pool
* @returns 0 on success, -1 otherwise
* The bake_provider_init_info structure can be passed in to the
* bake_provider_register() function to configure the provider. The struct
* can be memset to zero to use default values.
*/
int bake_makepool(const char* pool_name, size_t pool_size, mode_t pool_mode);
struct bake_provider_init_info {
const char* json_config; /* optional JSON-formatted string */
ABT_pool rpc_pool; /* optional pool on which to run RPC handlers */
abt_io_instance_id aid; /* optional abt-io instance, used by file backend */
void* remi_provider; /* optional REMI provider */
void* remi_client; /* optional REMI client */
};
#define BAKE_PROVIDER_INIT_INFO_INITIALIZER \
{ \
NULL, ABT_POOL_NULL, ABT_IO_INSTANCE_NULL, NULL, NULL \
}
/**
* Initializes a BAKE provider.
......@@ -44,35 +49,49 @@ int bake_makepool(const char* pool_name, size_t pool_size, mode_t pool_mode);
* @param[out] provider resulting provider
* @returns 0 on success, -1 otherwise
*/
int bake_provider_register(margo_instance_id mid,
uint16_t provider_id,
ABT_pool pool,
bake_provider_t* provider);
int bake_provider_register(margo_instance_id mid,
uint16_t provider_id,
const struct bake_provider_init_info* args,
bake_provider_t* provider);
/**
* @brief Deregisters and destroys the provider.
* @brief Deregisters the provider.
*
* @param provider Provider to deregister and destroy.
* @param provider Provider to deregister.
*
* @return 0 on success, -1 otherwise.
*/
int bake_provider_destroy(bake_provider_t provider);
int bake_provider_deregister(bake_provider_t provider);
/**
* Makes the provider start managing a target.
* The target must have been previously created with bake_makepool,
* and it should not be managed by another provider (whether in this
* proccess or another).
* Makes the provider start managing a target. The target must have already
* been created in the past.
*
* @param provider Bake provider
* @param target_name path to pmem target
* @param target_id resulting id identifying the target
*
* @return 0 on success, -1 on failure
* @return BAKE_SUCCESS or BAKE_ERR*
*/
int bake_provider_attach_target(bake_provider_t provider,
const char* target_name,
bake_target_id_t* target_id);
/**
* Create a new target that did not yet exist and begin managing it.
*
* @param provider Bake provider
* @param target_name path to pmem target
* @param[in] size size of the created target (may be ignored for target
* types that can be extended or use a fixed size physical device)
* @param target_id resulting id identifying the target
*
* @return BAKE_SUCCESS or BAKE_ERR*
*/
int bake_provider_add_storage_target(bake_provider_t provider,
const char* target_name,
bake_target_id_t* target_id);
int bake_provider_create_target(bake_provider_t provider,
const char* target_name,
size_t size,
bake_target_id_t* target_id);
/**
* Makes the provider stop managing a target.
......@@ -82,8 +101,8 @@ int bake_provider_add_storage_target(bake_provider_t provider,
*
* @return 0 on success, -1 on failure
*/
int bake_provider_remove_storage_target(bake_provider_t provider,
bake_target_id_t target_id);
int bake_provider_detach_target(bake_provider_t provider,
bake_target_id_t target_id);
/**
* Removes all the targets associated with a provider.
......@@ -92,7 +111,7 @@ int bake_provider_remove_storage_target(bake_provider_t provider,
*
* @return 0 on success, -1 on failure
*/
int bake_provider_remove_all_storage_targets(bake_provider_t provider);
int bake_provider_detach_all_targets(bake_provider_t provider);
/**
* Returns the number of targets that this provider manages.
......@@ -102,13 +121,13 @@ int bake_provider_remove_all_storage_targets(bake_provider_t provider);
*
* @return 0 on success, -1 on failure
*/
int bake_provider_count_storage_targets(bake_provider_t provider,
uint64_t* num_targets);
int bake_provider_count_targets(bake_provider_t provider,
uint64_t* num_targets);
/**
* List the target ids of the targets managed by this provider.
* The targets array must be pre-allocated with at least enough
* space to hold all the targets (use bake_provider_count_storage_targets
* space to hold all the targets (use bake_provider_count_targets
* to know how many storage targets are managed).
*
* @param provider Bake provider
......@@ -116,41 +135,29 @@ int bake_provider_count_storage_targets(bake_provider_t provider,
*
* @return 0 on success, -1 on failure
*/
int bake_provider_list_storage_targets(bake_provider_t provider,
bake_target_id_t* targets);
/* TODO: the following configuration management functions would ideally be
* split off into a dedicated component. Treating this as a prototype for
* now.
*/
int bake_provider_list_targets(bake_provider_t provider,
bake_target_id_t* targets);
/**
* @brief Set configuration parameters as string key/value pairs
*
* @param provider Bake provider
* @param key Configuration key
* @param value Configuratiion value
* Retrieves complete configuration of bake provider, encoded as json
*
* @return 0 on success, -1 on failure
* @param [in] provider bake provider
* @returns null terminated string that must be free'd by caller
*/
int bake_provider_set_conf(bake_provider_t provider,
const char* key,
const char* value);
char* bake_provider_get_config(bake_provider_t provider);
/**
* @brief Set configuration parameters for a target.
* Creates a raw storage target, not connected to a provider. This would
* mainly be used by external utilities, not a server daemon itself.
*
* @param provider Bake provider
* @param tid Bake target id
* @param key Configuration key
* @param value Configuration value
* @param[in] path path to storage target (could be a file, directory, or
* device depending on the backend type)
* @param[in] size size of the created target (may be ignored for target
* types that can be extended or use a fixed size physical device)
*
* @return 0 on success, -1 on failure
* @returns 0 on success, -1 otherwise
*/
int bake_target_set_conf(bake_provider_t provider,
bake_target_id_t tid,
const char* key,
const char* value);
int bake_create_raw_target(const char* path, size_t size);
#ifdef __cplusplus
}
......
/*
* (C) 2019 The University of Chicago
*
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __BAKE_SERVER_HPP
......@@ -12,7 +12,7 @@
#include <bake-server.h>
#define _CHECK_RET(__ret) \
if(__ret != BAKE_SUCCESS) throw exception(__ret)
if (__ret != BAKE_SUCCESS) throw exception(__ret)
namespace bake {
......@@ -23,11 +23,9 @@ namespace bake {
* @param pool_size Pool size.
* @param pool_mode Mode.
*/
inline void makepool(
const std::string& pool_name,
size_t pool_size,
mode_t pool_mode) {
int ret = bake_makepool(pool_name.c_str(), pool_size, pool_mode);
inline void create_raw_target(const std::string& path, size_t size)
{
int ret = bake_create_raw_target(path.c_str(), size);
_CHECK_RET(ret);
}
......@@ -36,39 +34,68 @@ inline void makepool(
*/
class provider {
margo_instance_id m_mid = MARGO_INSTANCE_NULL;
bake_provider_t m_provider = NULL;
margo_instance_id m_mid = MARGO_INSTANCE_NULL;
bake_provider_t m_provider = NULL;
provider(
margo_instance_id mid,
uint16_t provider_id = 0,
ABT_pool pool = ABT_POOL_NULL)
: m_mid(mid) {
int ret = bake_provider_register(mid, provider_id, pool, &m_provider);
provider(margo_instance_id mid,
uint16_t provider_id,
const bake_provider_init_info* args)
: m_mid(mid)
{
int ret = bake_provider_register(mid, provider_id, args, &m_provider);
_CHECK_RET(ret);
}
static void finalize_callback(void* args) {
static void finalize_callback(void* args)
{
auto* p = static_cast<provider*>(args);
delete p;
}
public:
public:
/**
* @brief Factory method to create an instance of provider.
*
* @param mid Margo instance id.
* @param provider_id Provider id.
* @param pool Argobots pool.
* @param config JSON config.
* @param abtid ABT-IO instance.
* @param remi REMI provider.
*
* @return Pointer to newly created provider.
*/
static provider* create(margo_instance_id mid,
uint16_t provider_id = 0,
ABT_pool pool = ABT_POOL_NULL,
const std::string& config = "",
abt_io_instance_id abtio = ABT_IO_INSTANCE_NULL,
void* remi_provider = NULL,
void* remi_client = NULL)
{
bake_provider_init_info args = BAKE_PROVIDER_INIT_INFO_INITIALIZER;
args.json_config = config.c_str();
args.rpc_pool = pool;
args.aid = abtio;
args.remi_provider = remi_provider;
args.remi_client = remi_client;
return create(mid, provider_id, &args);
}
/**
* @brief Factory method to create an instance of provider.
*
* @param mid Margo instance id.
* @param provider_id Provider id.
* @param args bake_provider_init_info structure.
*
* @return Pointer to newly created provider.
*/
static provider* create(margo_instance_id mid,
uint16_t provider_id = 0,
ABT_pool pool = BAKE_ABT_POOL_DEFAULT) {
auto p = new provider(mid, provider_id, pool);
static provider* create(margo_instance_id mid,
uint16_t provider_id,
const bake_provider_init_info* args = nullptr)
{
auto p = new provider(mid, provider_id, args);
margo_provider_push_finalize_callback(mid, p, &finalize_callback, p);
return p;
}
......@@ -96,9 +123,10 @@ class provider {
/**
* @brief Destructor.
*/
~provider() {
~provider()
{
margo_provider_pop_finalize_callback(m_mid, this);
bake_provider_destroy(m_provider);
bake_provider_deregister(m_provider);
}
/**
......@@ -109,12 +137,28 @@ class provider {
*
* @return a target object.
*/
target add_storage_target(const std::string& target_name) {
target attach_target(const std::string& target_name)
{
target t;
int ret = bake_provider_add_storage_target(
m_provider,
target_name.c_str(),
&(t.m_tid));
int ret = bake_provider_attach_target(m_provider, target_name.c_str(),
&(t.m_tid));
_CHECK_RET(ret);
return t;
}
/**
* @brief Create a storage target and attach it to the provider.
*
* @param target_name Path to the target.
* @param size Target size.
*
* @return a target object.
*/
target create_target(const std::string& target_name, size_t size)
{
target t;
int ret = bake_provider_create_target(m_provider, target_name.c_str(),
size, &(t.m_tid));
_CHECK_RET(ret);
return t;
}
......@@ -126,16 +170,18 @@ class provider {
*
* @param t target to remove.
*/
void remove_storage_target(const target& t) {
int ret = bake_provider_remove_storage_target(m_provider, t.m_tid);
void detach_target(const target& t)
{
int ret = bake_provider_detach_target(m_provider, t.m_tid);
_CHECK_RET(ret);
}
/**
* @brief Removes all the storage targets managed by the provider.
*/
void remove_all_storage_targets() {
int ret = bake_provider_remove_all_storage_targets(m_provider);
void detach_all_targets()
{
int ret = bake_provider_detach_all_targets(m_provider);
_CHECK_RET(ret);
}
......@@ -144,9 +190,10 @@ class provider {
*
* @return number of storage targets.
*/
uint64_t count_storage_targets() const {
uint64_t count_targets() const
{
uint64_t count;
int ret = bake_provider_count_storage_targets(m_provider, &count);
int ret = bake_provider_count_targets(m_provider, &count);
_CHECK_RET(ret);
return count;
}
......@@ -156,25 +203,28 @@ class provider {
*
* @return Vector of targets.
*/
std::vector<target> list_storage_targets() const {
uint64_t count = count_storage_targets();
std::vector<target> result(count);
std::vector<target> list_targets() const
{
uint64_t count = count_targets();
std::vector<target> result(count);
std::vector<bake_target_id_t> tgts(count);
int ret = bake_provider_list_storage_targets(m_provider, tgts.data());
int ret = bake_provider_list_targets(m_provider, tgts.data());
_CHECK_RET(ret);
for(unsigned i=0; i < count; i++) {
result[i].m_tid = tgts[i];
}
for (unsigned i = 0; i < count; i++) { result[i].m_tid = tgts[i]; }
return result;
}
void set_config(const std::string& key, const std::string& value) {
int ret = bake_provider_set_conf(m_provider, key.c_str(), value.c_str());
_CHECK_RET(ret);
std::string get_config() const
{
char* cfg = bake_provider_get_config(m_provider);
if (!cfg) return std::string();
auto str_cfg = std::string(cfg);
free(cfg);
return str_cfg;
}
};
}
} // namespace bake
#undef _CHECK_RET
......
......@@ -14,6 +14,15 @@
extern "C" {
#endif
#define BAKE_TRACE(_mid, _format, f...) margo_trace(_mid, "bake: " _format, ##f)
#define BAKE_DEBUG(_mid, _format, f...) margo_debug(_mid, "bake: " _format, ##f)
#define BAKE_INFO(_mid, _format, f...) margo_info(_mid, "bake: " _format, ##f)
#define BAKE_WARNING(_mid, _format, f...) \
margo_warning(_mid, "bake: " _format, ##f)
#define BAKE_ERROR(_mid, _format, f...) margo_error(_mid, "bake: " _format, ##f)
#define BAKE_CRITICAL(_mid, _format, f...) \
margo_critical(_mid, "bake: " _format, ##f)
typedef struct {
uuid_t id;
} bake_target_id_t;
......@@ -29,8 +38,9 @@ typedef struct {
#define BAKE_SUCCESS 0 /* Success */
#define BAKE_ERR_ALLOCATION (-1) /* Error allocating something */
#define BAKE_ERR_INVALID_ARG (-2) /* An argument is invalid */
#define BAKE_ERR_MERCURY (-3) /* An error happened calling a Mercury function \
*/
#define BAKE_ERR_MERCURY \
(-3) /* An error happened calling a Mercury function \
*/
#define BAKE_ERR_ARGOBOTS \
(-4) /* An error happened calling an Argobots function */
#define BAKE_ERR_PMEM (-5) /* An error happened calling a pmem function */
......@@ -45,7 +55,10 @@ typedef struct {
#define BAKE_ERR_FORBIDDEN (-12) /* Forbidden operation */
#define BAKE_ERR_BACKEND_TYPE (-13) /* Unknown backend type */
#define BAKE_ERR_IO (-14) /* Back-end I/O error */
#define BAKE_ERR_END (-15) /* End of valid bake error codes */
#define BAKE_ERR_NOENT (-15) /* entry does not exist */