From 7df1cbe4d58dd82f9ea323647bedf18e62ddb965 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 6 Sep 2016 23:45:17 -0400 Subject: [PATCH] plugin: Add a new type of timeseries-fetcher plugins. The new type (soon to replace the old) bundles a DESCRIBE callback along with the actual fetch callback. DESCRIBE can be used to retrieve information about a timeseries. --- src/core/plugin.c | 75 +++++++++++++++++++++++++++++++++++ src/include/core/plugin.h | 14 ++++--- src/include/core/timeseries.h | 22 ++++++++++ 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/src/core/plugin.c b/src/core/plugin.c index 44ea48a..8d836cc 100644 --- a/src/core/plugin.c +++ b/src/core/plugin.c @@ -114,6 +114,14 @@ typedef struct { } reader_t; #define READER(obj) ((reader_t *)(obj)) +typedef struct { + callback_t super; /* cb_callback will always be NULL */ +#define ts_user_data super.cb_user_data +#define ts_ctx super.cb_ctx + sdb_timeseries_fetcher_t impl; +} ts_fetcher_t; +#define TS_FETCHER(obj) ((ts_fetcher_t *)(obj)) + /* * private variables */ @@ -134,6 +142,7 @@ static sdb_llist_t *cname_list = NULL; static sdb_llist_t *shutdown_list = NULL; static sdb_llist_t *log_list = NULL; static sdb_llist_t *ts_fetcher_list = NULL; +static sdb_llist_t *timeseries_fetcher_list = NULL; static sdb_llist_t *writer_list = NULL; static sdb_llist_t *reader_list = NULL; @@ -148,6 +157,7 @@ static struct { { "shutdown", &shutdown_list }, { "log", &log_list }, { "timeseries fetcher", &ts_fetcher_list }, + { "timeseries fetcher", ×eries_fetcher_list }, { "store writer", &writer_list }, { "store reader", &reader_list }, }; @@ -505,6 +515,52 @@ static sdb_type_t reader_type = { plugin_reader_destroy }; +static int +plugin_ts_fetcher_init(sdb_object_t *obj, va_list ap) +{ + sdb_timeseries_fetcher_t *impl; + sdb_object_t *ud; + + if (! plugin_init_ok(obj, ap)) + return -1; + + impl = va_arg(ap, sdb_timeseries_fetcher_t *); + ud = va_arg(ap, sdb_object_t *); + assert(impl); + + if ((! impl->describe) || (! impl->fetch)) { + sdb_log(SDB_LOG_ERR, "core: timeseries fetcher callback '%s' " + "does not fully implement the interface.", + obj->name); + return -1; + } + + /* ctx may be NULL if the callback was not registered by a plugin */ + + TS_FETCHER(obj)->impl = *impl; + TS_FETCHER(obj)->ts_ctx = ctx_get(); + sdb_object_ref(SDB_OBJ(TS_FETCHER(obj)->ts_ctx)); + + sdb_object_ref(ud); + TS_FETCHER(obj)->ts_user_data = ud; + return 0; +} /* plugin_ts_fetcher_init */ + +static void +plugin_ts_fetcher_destroy(sdb_object_t *obj) +{ + assert(obj); + sdb_object_deref(TS_FETCHER(obj)->ts_user_data); + sdb_object_deref(SDB_OBJ(TS_FETCHER(obj)->ts_ctx)); +} /* plugin_ts_fetcher_destroy */ + +static sdb_type_t ts_fetcher_type = { + sizeof(ts_fetcher_t), + + plugin_ts_fetcher_init, + plugin_ts_fetcher_destroy +}; + static int module_init(const char *name, lt_dlhandle lh, sdb_plugin_info_t *info) { @@ -1020,6 +1076,14 @@ sdb_plugin_register_ts_fetcher(const char *name, name, callback, user_data); } /* sdb_plugin_register_ts_fetcher */ +int +sdb_plugin_register_timeseries_fetcher(const char *name, + sdb_timeseries_fetcher_t *fetcher, sdb_object_t *user_data) +{ + return plugin_add_impl(×eries_fetcher_list, ts_fetcher_type, "time-series fetcher", + name, fetcher, user_data); +} /* sdb_plugin_register_timeseries_fetcher */ + int sdb_plugin_register_writer(const char *name, sdb_store_writer_t *writer, sdb_object_t *user_data) @@ -1481,6 +1545,8 @@ sdb_plugin_fetch_timeseries(const char *type, const char *id, { callback_t *plugin; sdb_plugin_fetch_ts_cb callback; + + ts_fetcher_t *fetcher; sdb_timeseries_t *ts; ctx_t *old_ctx; @@ -1488,6 +1554,15 @@ sdb_plugin_fetch_timeseries(const char *type, const char *id, if ((! type) || (! id) || (! opts)) return NULL; + fetcher = TS_FETCHER(sdb_llist_search_by_name(timeseries_fetcher_list, type)); + if (fetcher) { + old_ctx = ctx_set(fetcher->ts_ctx); + ts = fetcher->impl.fetch(id, opts, fetcher->ts_user_data); + ctx_set(old_ctx); + return ts; + } + + /* fallback code */ plugin = CB(sdb_llist_search_by_name(ts_fetcher_list, type)); if (! plugin) { sdb_log(SDB_LOG_ERR, "core: Cannot fetch time-series of type %s: " diff --git a/src/include/core/plugin.h b/src/include/core/plugin.h index 6c4a2e1..5a26c39 100644 --- a/src/include/core/plugin.h +++ b/src/include/core/plugin.h @@ -240,11 +240,12 @@ sdb_plugin_register_log(const char *name, sdb_plugin_log_cb callback, sdb_object_t *user_data); /* - * sdb_plugin_register_ts_fetcher: - * Register a "time-series fetcher" function to be called whenever retrieving - * a time-series from a data-store. The callback will receive an identifier - * describing where to retrieve the data from (e.g. a filename or some kind of - * URL) and options which further describe the query. + * sdb_plugin_register_timeseries_fetcher: + * Register a "time-series fetcher" to be called whenever retrieving a + * time-series from a data-store or information about it. The fetch callback + * will receive an identifier describing where to retrieve the data from (e.g. + * a filename or some kind of URL) and options which further describe the + * query. * * The name is used literally (without prepending the plugin name) to look up * the appropriate fetcher callback. @@ -258,6 +259,9 @@ sdb_plugin_register_log(const char *name, sdb_plugin_log_cb callback, int sdb_plugin_register_ts_fetcher(const char *name, sdb_plugin_fetch_ts_cb callback, sdb_object_t *user_data); +int +sdb_plugin_register_timeseries_fetcher(const char *name, + sdb_timeseries_fetcher_t *fetcher, sdb_object_t *user_data); /* * sdb_plugin_register_writer: diff --git a/src/include/core/timeseries.h b/src/include/core/timeseries.h index ce4f0d2..3a50dc6 100644 --- a/src/include/core/timeseries.h +++ b/src/include/core/timeseries.h @@ -29,6 +29,7 @@ #define SDB_CORE_TIMESERIES_H 1 #include "sysdb.h" +#include "core/object.h" #include "core/time.h" #include "utils/strbuf.h" @@ -118,6 +119,27 @@ sdb_timeseries_create(size_t data_names_len, const char * const *data_names, void sdb_timeseries_destroy(sdb_timeseries_t *ts); +/* + * A timeseries fetcher fetches data from a timeseries data-store. + */ +typedef struct { + /* + * describe: + * Retrieve information about the timeseries from the data-store. The + * returned timeseries info object must be freeable using + * sdb_timeseries_info_destroy. + */ + sdb_timeseries_info_t *(*describe)(const char *id, sdb_object_t *user_data); + + /* + * fetch: + * Read timeseries data from the data-store. The returned timeseries + * object must be freeable using sdb_timeseries_destroy. + */ + sdb_timeseries_t *(*fetch)(const char *id, + sdb_timeseries_opts_t *opts, sdb_object_t *user_data); +} sdb_timeseries_fetcher_t; + /* * sdb_timeseries_tojson: * Serialize a time-series to JSON written to the specified string buffer. -- 2.30.2