diff --git a/Makefile.am b/Makefile.am index 3a0ff9c..725c5a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ else EXAMPLES = endif -SUBDIRS = include tdata sxt sexpr sxmp ydaemon tools man $(EXAMPLES) +SUBDIRS = include tdata sxt sexpr sxmp tools man $(EXAMPLES) libsxmpdocdir = ${prefix}/doc/libsxmp libsxmpdoc_DATA = \ diff --git a/configure.ac b/configure.ac index dd96757..ccb8607 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,6 @@ AC_INIT(libsxmp, m4_esyscmd([tr -d '\n' < VERSION.sxmp])) AC_SUBST([LIBSXT_VERSION], m4_esyscmd([tr -d '\n' < sxt/VERSION])) AC_SUBST([LIBTDATA_VERSION], m4_esyscmd([tr -d '\n' < tdata/VERSION])) AC_SUBST([LIBSEXPR_VERSION], m4_esyscmd([tr -d '\n' < sexpr/VERSION])) -AC_SUBST([LIBYDAEMON_VERSION], m4_esyscmd([tr -d '\n' < ydaemon/VERSION])) AC_CONFIG_HEADERS([config.h]) @@ -111,8 +110,6 @@ sexpr/Makefile sexpr/libsexpr.pc tdata/Makefile tdata/libtdata.pc -ydaemon/Makefile -ydaemon/libydaemon.pc include/Makefile man/Makefile tools/Makefile diff --git a/include/Makefile.am b/include/Makefile.am index e60f8f6..4d7be31 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,6 +3,5 @@ nobase_include_HEADERS = sxmp/sxmp.h sxmp/errno.h sxmp/limits.h sxmp/version.h \ sexpr/sexp_memory.h sexpr/sexp_ops.h sexpr/sexp_vis.h \ tdata/bitwise.h tdata/idx_allocator.h tdata/macro.h tdata/tree.h \ tdata/usrtc.h tdata/list.h tdata/ctrie.h \ - ydaemon/ydaemon.h ydaemon/cache.h ydaemon/dataobject.h \ sxt/sxtkey.h sxt/lcrypt.h sxt/fe25519.h sxt/ge25519.h \ sxt/sc25519.h diff --git a/include/ydaemon/cache.h b/include/ydaemon/cache.h deleted file mode 100644 index 02990e0..0000000 --- a/include/ydaemon/cache.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#ifndef __YDATA_CACHE_H__ -#define __YDATA_CACHE_H__ - -#include - -#define YD_CACHE_SPACER_MAGIC 0xbeafbeef - -/* item flags */ -#define YDC_INVALIDATE (1 << 1) -#define YDC_UNUSED (1 << 2) -#define YDC_DIRTY (1 << 3) - -typedef struct __ydata_cache_item_type { - oid_t oid; - uint32_t idx; - uint8_t attr; - usrtc_node_t idxnode; - list_node_t listnode; -} ydata_cache_item_t; - -#define yd_item_idx(item) (item)->idx -#define yd_item_setoid(it, id) (it)->oid = id - -typedef struct __ydata_qitem_type { - ydata_cache_item_t *item; - list_node_t node; -} ydata_qitem_t; - -#define YDC_SYNCTHRESHOLD 64 -#define YDC_SYNCDELTASEC 30 - -typedef struct __ydata_cache_t { - usrtc_t idx_tree; - list_head_t free_poll; - list_head_t dirty_poll; - list_head_t pending_poll; - void *cache; - size_t object_size; - size_t objects_amount; - size_t cache_size; - size_t dirties; - pthread_t syncthread; - pthread_rwlock_t rwlock; - pthread_mutex_t dirtlock; -} ydata_cache_t; - -#define yd_cache_rdlock(c) pthread_rwlock_rdlock(&(c)->rwlock) -#define yd_cache_wrlock(c) pthread_rwlock_wrlock(&(c)->rwlock) -#define yd_cache_unlock(c) pthread_rwlock_unlock(&(c)->rwlock) - -#define yd_cache_ptrbyidx(c, n) (char *)(c)->cache + n*((c)->object_size + sizeof(uint32_t)) - -/* API, mostly internally used, but might be useful */ -ydata_cache_t *yd_cache_init(dataobject_t *, size_t); - -void *yd_cache_alloc_item(ydata_cache_t *, ydata_cache_item_t **); - -void yd_cache_discard_alloc_item(ydata_cache_t *, ydata_cache_item_t *); - -void yd_cache_confirm_alloc_item(ydata_cache_t *, ydata_cache_item_t *, oid_t); - -void *yd_cache_lookup(ydata_cache_t *, oid_t); - -list_head_t *yd_cache_getrslist(ydata_cache_t *, uint8_t); - -void yd_cache_qitems_pullback(ydata_cache_t *, list_head_t *); - -void yd_cache_item_dirtyoid(ydata_cache_t *, oid_t); - -void yd_cache_item_invalidateoid(ydata_cache_t *, oid_t); - -int yd_cache_start_thread(domx_t *); - -#endif /* __YDATA_CACHE_H__ */ diff --git a/include/ydaemon/dataobject.h b/include/ydaemon/dataobject.h deleted file mode 100644 index a69b4be..0000000 --- a/include/ydaemon/dataobject.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#ifndef __DM_DATAOBJECT_H__ -#define __DM_DATAOBJECT_H__ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MAX_ITEM_NAME 32 -#define MAX_ITEMS 255 - -typedef uint64_t oid_t; - -enum { - U8 = 0, - S8, - U16, - S16, - U32, - S32, - U64, - S64, - CSTR, - TBLOB, - TACRT, -}; - -struct typelen { - uint8_t type; - uint64_t len; -}; - -typedef struct __access_rights_type { - uint32_t ouid; - uint32_t ogid; - uint8_t domainid; - uint8_t sal; - uint8_t amask; - uint8_t reserve; -}__attribute__((packed)) acc_right_t; - -typedef struct __dataacc_pemctx_type { - acc_right_t *uobj; - uint32_t gids[16]; -} dataacc_pemctx_t; - -#ifdef DMUX_USE -static struct typelen tltable[] = { - {.type = U8, .len = 1}, - {.type = S8, .len = 1}, - {.type = U16, .len = 2}, - {.type = S16, .len = 2}, - {.type = U32, .len = 4}, - {.type = S32, .len = 4}, - {.type = U64, .len = 8}, - {.type = S64, .len = 8}, - {.type = CSTR, .len = 0}, - {.type = TBLOB, .len = 0}, - {.type = TACRT, .len = sizeof(acc_right_t) }, -}; -#endif - -typedef struct __dataobject_item_type { - uint8_t id; - uint8_t type; - uint64_t len; - char name[MAX_ITEM_NAME]; - list_node_t node; -}__attribute__ ((packed)) dataobject_item_t; - -typedef struct __item_idx_type { - void *key; - dataobject_item_t *dtr; - usrtc_node_t node; -} item_idx_t; - -typedef struct __dataobject_type { - char name[MAX_ITEMS]; - list_head_t description; /* description of the data */ - usrtc_t id_index; - usrtc_t name_index; -} dataobject_t; - -/* API */ -dataobject_t *dotr_create(const char *name); - -int dotr_set_item(dataobject_t *dotr, uint8_t type, uint64_t len, const char *name); - -uint8_t dotr_item_type(dataobject_t *obj, const char *name, uint64_t *len); - -char *dotr_item_nameptr(dataobject_t *obj, const char *name); - -int dotr_item_nameidx(dataobject_t *obj, const char *name); - -void dotr_destroy(dataobject_t *dotr); - -/* dataobject misc operations */ -int dtocmp(const dataobject_t *src, const dataobject_t *dst); - -size_t dtolen(const dataobject_t *src); - -/* - * Filtering used for access to the data stream. - */ -typedef enum { - YDM_NO_FILTER = 0, /* no access right filter */ - YDM_DOMAIN_FILTER, /* filter only by domain */ - YDM_USERDAC_FILTER, /* filter by domain and user with DAC */ - YDM_FULL_FILTER, /* all above filter plus additional filtering */ -} ydm_access_filter_t; - -typedef struct __sxmp_ch_entry_type { - char instance[32]; - uint16_t chtid; - ydm_access_filter_t filter; - list_node_t node; -} sxmp_ch_entry_t; - -struct __domx_dsbe_type; - -/* some intermodular structures */ -typedef struct __domx_type { - dataobject_t *dox; - char *name; - list_head_t sxmp_channels; - struct __domx_dsbe_type *be; - void *cache; -} domx_t; - -/* initialization */ -int domx_init(domx_t *dt, dataobject_t *dodesc); -int domx_set_be(domx_t *dt, void *be, const char *key); -int domx_set_cache(domx_t *dt, size_t size); -int domx_set_sxmpchannel(domx_t *dt, const char *instance, int typeid, int access); - -/* data operations */ -int domx_get(domx_t *dt, uint64_t oid, void **refdata); -int domx_set(domx_t *dt, uint64_t oid, const void *refdata); -int domx_remove(domx_t *dt, uint64_t oid); -int domx_creat(domx_t *dt, uint64_t *oid, const void *refdata); - -/* cache ops for backends */ -int domx_cache_invalidate(domx_t *dt, uint64_t oid); -int domx_cache_invalidate_list(domx_t *dt, list_head_t *oids); -int domx_cache_getdirtylist(domx_t *dt, uint16_t amount, list_head_t **list); -int domx_cache_freelist(domx_t *dt, list_head_t *list); -int domx_cache_freeitems(domx_t *dt, uint16_t amount); - -/* data filters */ -typedef enum { - YDEQUAL = 0, - YDNOTEQUAL, - YDGREATER, - YDLESS, - YDEQOGREATER, - YDEQOLESS, - YDINRANGE, - YDINLIST, -} filt_t; - -typedef struct __yd_inlist_item_type { - union { - uint64_t val; - char *dta; - }; - list_node_t node; -}__attribute__((packed)) yd_inlist_item_t; - -typedef struct __yd_filter_item_type { - char *name; /* dataobject item name ptr */ - filt_t ftype; /* filtering type */ - union { - struct { - uint64_t vf; /* first value */ - uint64_t vc; /* second value if applicable */ - }; - struct { - char *cstr; - list_head_t *inlist; - }; - }; - list_node_t node; -}__attribute__((packed)) yd_filter_item_t; - -typedef struct __yd_filter_type { - domx_t *domx; - list_head_t filter; -} yd_filter_t; - -yd_filter_t *yd_filter_create(domx_t *refobj); -void yd_filter_destroy(yd_filter_t *f); -int yd_filter_add_sf(yd_filter_t *f, const char *name, filt_t ftype, - uint64_t vf, uint64_t vc); -int yd_filter_add_str(yd_filter_t *f, const char *name, const char *value, int eq); -int yd_filter_add_inlist(yd_filter_t *f, const char *name, int length, void **array); - -#define YD_CHUNK_AMOUNT 128 - -typedef struct __yd_wlist_node_type { - oid_t oid; - list_node_t node; -} yd_wlist_node_t; - -typedef struct __yd_index_stream_type { - yd_filter_t *filter; - uint32_t offset; - uint8_t amount; - list_head_t entries_wlist; - void *priv; -} yd_idx_stream_t; - -#define yd_index_stream_setfilter(sw, filt) (sw)->filter = (filt) -#define yd_index_stream_setpriv(sw, prv) (sw)->priv = prv -#define yd_index_stream_getpriv(sw) (sw)->priv - -yd_idx_stream_t *yd_index_stream_init(void); -void yd_index_stream_destroy(yd_idx_stream_t *); -void yd_index_stream_emptylist(yd_idx_stream_t *); - -typedef struct __yd_index_stream_window_type { - uint8_t amount; - list_head_t *wlist; -} yd_idx_stream_win_t; - -#define yd_idx_stream_win_size(sw) (sw)->amount - -/* domx stream operations */ -yd_idx_stream_t *domx_idxl_open(domx_t *dt, ydm_access_filter_t afilter, - dataacc_pemctx_t *dacc, yd_filter_t *datafilter); - -void domx_idxl_close(domx_t *dt, yd_idx_stream_t *idxl); - -yd_idx_stream_win_t *domx_idxl_read(domx_t *dt, yd_idx_stream_t *idxl); - -struct be_ops; - -#define BEMAGIC 0xffffbeef - -typedef struct __domx_dsbe_type { - domx_t *domx; - void *priv; - struct be_ops *f; -} domx_dsbe_t; - -struct be_ops { - uint32_t be_magic; - /* initialization part */ - int (*init)(domx_dsbe_t *, const char *); - /* data manipulation */ - int (*get)(domx_dsbe_t *, oid_t, void *); - int (*set)(domx_dsbe_t *, oid_t, void *); - oid_t (*creat)(domx_dsbe_t *, const void *); - int (*remove)(domx_dsbe_t *, oid_t); - /* list requesting */ - yd_idx_stream_t* (*create_idx_stream)(domx_dsbe_t *, ydm_access_filter_t, - dataacc_pemctx_t *, yd_filter_t *); - void (*destroy_idx_stream)(yd_idx_stream_t *); - yd_idx_stream_win_t* (*getportion_idx_stream)(yd_idx_stream_t *); -}; - -#endif /* __YD_DATAOBJECT_H__ */ diff --git a/include/ydaemon/ydaemon.h b/include/ydaemon/ydaemon.h deleted file mode 100644 index c05bbe6..0000000 --- a/include/ydaemon/ydaemon.h +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#ifndef __YDAEMON_YDAEMON_H__ -#define __YDAEMON_YDAEMON_H__ - -#include -#include -#include -#include - -#include -#include -#include - -/* some syntax */ - -/** - * --values (variables) - */ -#define VAR_CREATE_GROUP "create-var-group" -#define VAR_SET "var-set" -/** - * --modules - * (%MODULE_ADD_SX ' ) -- add a module to the list of available modules - * (%MODULE_SET_SX ' (:%MODULE_PREFIX|%MODULE_PATHNAME|%MODULE_CNFPATH *)) - * *value might be the following: - * a. in case of double or single quote - will be taken as is - * b. without quotes will be interpreted as variable (must be defined before this expression) - */ -#define MODULE_ADD_SX "module-add" -#define MODULE_SET_SX "module-set" /** { */ -/* module config values for _SET_SX */ -#define MODULE_PREFIX "prefix" -#define MODULE_PATHNAME "pathname" -#define MODULE_CNFPATH "config-path" -/** } */ -#define MODULE_LOAD_SX "module-load" -#define MODULE_RUN_SX "module-run" -/* internal functions */ -#define SCMOBJECT "object" -/* functions for the logs */ -#define YDOPENLOGS "yd-open-logfile" - -/* limits */ -#define MAX_SCM_FUNCTIONS 16384 - -#define MAX_SERVICES 8192 -#define MAX_MODULES 4096 - -enum { - SCINT = 0, - SCCSTR, - SCOBJECTPTR, - SCUNDEFINED, -}; - -typedef struct __scm_ret { - uint8_t serr; - uint8_t type; - uint32_t len; - union { - void *ret; - struct { - int32_t ec; - uint32_t ru32; - }; - }; -} scret_t; - -#define RETURN_SRET_SERR(r, e) (r).serr = e; return r -#define RETURN_SRET_IRES(r, e) (r).serr = 0; (r).type = SCINT; (r).ec = e; \ - return r -#define RETURN_SRET_ORES(r, e) (r).serr = 0; (r).type = SCOBJECTPTR; (r).ret = (e); \ - return r - -struct __ydaemon_context_type; - -/** - * @brief Type used to describe scm function - * - * It contains name i.e. keyword, pointer to the - * function itself and optional pointer to the - * implementation specific data. It packs to usrtc - * search structure. - */ -typedef struct __scm_func { - char *name; - scret_t (*call)(struct __ydaemon_context_type *, sexp_t *, void *); - void *priv; - usrtc_node_t node; -} scm_function_t; - -/** - * @brief Type used to describe a tree of scm functions - * - * It contains a search structure with packed - * scm_function_t set and also contain special - * private pointer that might be optionally used - * by implementation. - */ -typedef struct __scm_func_tree { - usrtc_t functions; - void *priv; -} scm_function_tree_t; - -/** - * @brief Values types - * - * Describes the type of value - * @see zdc_conf_val_t - */ -typedef enum { - STRING = 0, - INT, - UINT, - LONG, - ULONG, - BLOB, - SEXPR, - CUSTOM, -} ydc_val_type_t; - -/** - * @brief configuration event - * - * Type used to describe events occured with values - */ -typedef enum { - YC_EVENT_ADD, - YC_EVENT_MODIFY, - YC_EVENT_DESTROY, - YC_EVENT_ATTACH, -} ydc_event_t; - -/** - * @brief Type used to fit all required parameters - * - * It contain mode, system settings and a lot of other - * config defined parameters. - */ -typedef struct __ym_conf { - /* parameters groups */ - usrtc_t p_groups; /**< Parameters groups */ - /* functions tree */ - void *init_funcs; - /* locking */ - pthread_rwlock_t grp_lock; /**< Locking for groups */ - pthread_mutex_t conf_lock; /**< Locking for state change, function ops, system io */ -} ydc_conf_t; - -/** - * @brief Type of the parameters group - * - * Store values. - */ -typedef struct __ym_pgroup { - usrtc_t values; - usrtc_node_t unode; - char *name; - pthread_rwlock_t val_lock; -} ydc_pgroup_t; - -/** - * @brief Type used to describe value - * - * Used to store value. - */ -typedef struct __ym_conf_value { - usrtc_node_t unode; - ydc_val_type_t type; - int len; - char *name; - void *value; - void (*on_eventv)(struct __ym_conf_value *, - struct __ym_conf_value *, - ydc_conf_t *, ydc_event_t); - void *priv; -} ydc_conf_val_t; - -typedef struct __ydaemon_log_type { - FILE *logstream; - int verbose_level; - int se; -} yd_log_t; - -typedef struct __ydaemon_context_type { - usrtc_t *services; - usrtc_t *modules; - scm_function_tree_t *func; /** < functions for configuration and processing */ - ydc_conf_t *values; /** < values stored by the groups */ - yd_log_t *logcontext; - int flags; - pthread_rwlock_t modlock; - pthread_mutex_t looplock; - int daemon; -} yd_context_t; - -#define yd_mod_ctx_wrlock(n) pthread_rwlock_wrlock(&(n)->modlock) -#define yd_mod_ctx_rdlock(n) pthread_rwlock_rdlock(&(n)->modlock) -#define yd_mod_ctx_unlock(n) pthread_rwlock_unlock(&(n)->modlock) - -typedef enum { - YD_SERVICE_MUX = 0, - YD_SXMP_MOD, - YD_DATASTORE_MOD, - YD_OTHER, -} yd_mod_type_t; - -typedef struct __ydaemon_module { - char *name; - char *pathname; - char *cnfname; - char *prefix; - void *dlhandle; - void *(*getobject)(void *, const char *); - int (*shutdown)(yd_context_t *); - int (*preinit)(yd_context_t *); - int (*init)(yd_context_t *); - int (*run)(yd_context_t *); - yd_mod_type_t type; - int flags; - usrtc_node_t node; -} yd_mod_t; - -/* functions defines for modules */ -#define def_shutdown(PREFIX) int PREFIX ## _shutdown(yd_context_t *ctx) -#define def_preinit(PREFIX) int PREFIX ## _preinit(yd_context_t *ctx) -#define def_init(PREFIX) int PREFIX ## _init(yd_context_t *ctx) -#define def_run(PREFIX) int PREFIX ## _run(yd_context_t *ctx) -#define def_getobject(PREFIX) void* PREFIX ## _getobject(void *priv, const char *oname) -/* function arguments macros */ -#define def_ctx ctx -#define defpriv priv -#define defoname oname - -#define yd_mod_set_prefix(n, p) (n)->prefix = (p) -#define yd_mod_set_pathname(n, p) (n)->pathname = (p) -#define yd_mod_set_cfgpath(n, p) (n)->cnfname = (p) - -#define yd_mod_preinit(n) \ - { memset((n), 0, sizeof(yd_mod_t)); usrtc_node_init((n)->node, (n)); } - -int yd_mod_init(yd_context_t *, yd_mod_t *); - -int yd_mod_get(yd_context_t *, const char *, yd_mod_t **); - -int yd_mod_load(yd_context_t *, yd_mod_t *); - -int yd_mod_run(yd_context_t *, yd_mod_t *); - -int yd_mod_shutdown(yd_context_t *, yd_mod_t *); - -void *yd_mod_getobject(yd_context_t *, yd_mod_t *, void *, const char *); - -void *yd_mod_getsym(yd_context_t *, yd_mod_t *, const char *); - -typedef struct __ydaemon_service { - char *name; /* name of the service */ - void *ops; /* the subject to think about ... */ - void *connection; /* as backends private data */ - void *conf; /* special configuration */ - usrtc_node_t node; -} yd_service_t; - -#define yd_ctx_values(c) (c)->values - -int yd_init_ctx(yd_context_t *); - -int yd_eval_ctx(yd_context_t *, const char *); - -scret_t yd_eval_sexp(yd_context_t *, sexp_t *); - -int yd_mainloop(yd_context_t *); - -void yd_mainloop_exit(yd_context_t *); - -int yd_set_daemonize(yd_context_t *, int); - -/* modules related functions */ -int yd_mod_add(yd_context_t *, const char *, yd_mod_type_t); - -/* internal functions API */ -void scm_func_tree_free(scm_function_tree_t *pt); - -int scm_func_tree_init(scm_function_tree_t **pt, void *priv); - -int scm_func_tree_insert(yd_context_t *zdx, const char *name, - scret_t (*call)(yd_context_t *, sexp_t *, void *), - void *priv); - -int scm_func_tree_insert_t(yd_context_t *zdx, scm_function_t *f); - -scret_t scm_func_tree_call(yd_context_t *zdx, void *cnf, sexp_t *sx, - char *name); - -int scm_func_tree_delete(yd_context_t *zdx, char *name); - -/* variables related functions */ -int ydc_conf_init(ydc_conf_t *); - -int ydc_conf_create_pgroup(ydc_conf_t *, char *); - -int ydc_conf_get_val(ydc_conf_t *, const char *, ydc_conf_val_t **); - -int ydc_conf_add_val_p(ydc_conf_t *, const char *, int); - -/* some internal stuff */ -#define UNIT_TESTS 1 -#ifdef UNIT_TESTS -#define blub printf("%d at %s\n", __LINE__, __FUNCTION__) -#endif - -/* logging */ -enum { - YL_DEBUG = 0, - YL_INFO, - YL_WARN, - YL_ERROR, -}; - -void ydlog(yd_context_t *ctx, int olvl, const char *fmt, ...); - -void yddaemon(yd_context_t *ctx); - -/* object storage */ - -#define MAX_OBJECTS 65535 - -typedef struct __ostore_type { - usrtc_t objects; - pthread_rwlock_t rwlock; -} obj_store_t; - -typedef struct __ostore_node_type { - char *name; - void *objdata; - usrtc_node_t node; -} obj_store_node_t; - -int obj_store_init(obj_store_t *); - -int obj_store_set(obj_store_t *, const char *, void *); - -int obj_store_get(obj_store_t *, const char *, void **); - -int obj_store_remove(obj_store_t *, const char *); - -#endif /* __YDAEMON_YDAEMON_H__ */ diff --git a/ydaemon/Makefile.am b/ydaemon/Makefile.am deleted file mode 100644 index 87b22b6..0000000 --- a/ydaemon/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -## Process this file with automake to produce Makefile.in - -AM_CPPFLAGS = \ - -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ - -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ - -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ - $(LIBYDAEMON_CFLAGS) -I../include - -AM_CFLAGS =\ - -Wall\ - -g - -lib_LTLIBRARIES = libydaemon.la - - -libydaemon_la_SOURCES = \ - values.c functions.c log.c module.c \ - daemon.c context.c data.c cache.c \ - domx.c filter.c idxstream.c - -libydaemon_la_LDFLAGS = -Wl,--export-dynamic - -# where to find other libs ... -LIBTDATA_LIBSLA = ../tdata/.libs/libtdata.la -LIBSEXPR_LIBSLA = ../sexpr/.libs/libsexpr.la - -libydaemon_la_LIBADD = -lpthread -lcrypto -ldl $(LIBTDATA_LIBSLA) $(LIBSEXPR_LIBSLA) - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libydaemon.pc - -EXTRA_DIST = \ - libydaemon.pc.in - diff --git a/ydaemon/VERSION b/ydaemon/VERSION deleted file mode 100644 index 64b3f4a..0000000 --- a/ydaemon/VERSION +++ /dev/null @@ -1,3 +0,0 @@ -0.0.1 - - diff --git a/ydaemon/cache.c b/ydaemon/cache.c deleted file mode 100644 index fc931a4..0000000 --- a/ydaemon/cache.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include - -#include -#include - -static long __cmp_oids(const void *a, const void *b) -{ - return (long)(*(oid_t *)a - *(oid_t *)b); -} - -static ydata_cache_item_t *__alloc_ydcitem(uint32_t idx) -{ - ydata_cache_item_t *out = malloc(sizeof(ydata_cache_item_t)); - - if(out) { - memset(out, 0, sizeof(ydata_cache_item_t)); - out->idx = idx; - out->attr |= YDC_UNUSED; - list_init_node(&out->listnode); - usrtc_node_init(&out->idxnode, out); - } - - return out; -} - -static void *__sync_thread(void *p); - -int yd_cache_start_thread(domx_t *domx) -{ - ydata_cache_t *cc; - - if(!domx || !(cc = (ydata_cache_t *)domx->cache)) return EINVAL; - - return pthread_create(&cc->syncthread, NULL, __sync_thread, (void *)domx); -} - -static void *__sync_thread(void *p) -{ - domx_t *domx = (domx_t *)p; - ydata_cache_t *cc; - domx_dsbe_t *be; - list_node_t *iter, *siter; - ydata_cache_item_t *citem; - struct timespec tio; - int r, c, o; - - /* check up, we shouldn't falls to segmentation */ - if(!p || !(cc = (ydata_cache_t *)domx->cache)) goto __fini; - if(!(be = domx->be)) goto __fini; - - /* everyday life is here */ - while(1) { - /* get our tio, yes it's not so green ... but it works */ - tio.tv_sec = time(NULL) + YDC_SYNCDELTASEC; - /* lock on mutex for a time being or will wake up on request */ - r = pthread_mutex_timedlock(&cc->dirtlock, &tio); - - __retrywolock: - yd_cache_rdlock(cc); - if(!cc->dirties) { - yd_cache_unlock(cc); - goto __again; - } - yd_cache_unlock(cc); - - yd_cache_wrlock(cc); - c = 0; - list_for_each_safe(&cc->dirty_poll, iter, siter) { - citem = container_of(iter, ydata_cache_item_t, listnode); - list_del(&citem->listnode); - - if(citem->attr & YDC_INVALIDATE) { /* invalidated item, just pullback it */ - citem->attr = 0; - citem->attr |= YDC_UNUSED; - list_add2tail(&cc->free_poll, &citem->listnode); - usrtc_delete(&cc->idx_tree, &citem->idxnode); - } else { - o = be->f->set(be, citem->oid, yd_cache_ptrbyidx(cc, citem->idx)); - if(o != 0) { /* invalidate */ - citem->attr = 0; - citem->attr |= YDC_UNUSED; - list_add2tail(&cc->free_poll, &citem->listnode); - usrtc_delete(&cc->idx_tree, &citem->idxnode); - } else citem->attr &= ~YDC_DIRTY; /* just remove this flag */ - } - cc->dirties--; - c++; - if(c >= YDC_SYNCTHRESHOLD) break; - } - yd_cache_unlock(cc); - - if(c >= YDC_SYNCTHRESHOLD) { - usleep(100); /* looks like a huge load, let's wait and retry without lock */ - goto __retrywolock; - } - - __again: - if(r != ETIMEDOUT) pthread_mutex_lock(&cc->dirtlock); /* acquire lock again */ - } - - __fini: - return NULL; -} - -ydata_cache_t *yd_cache_init(dataobject_t *object, size_t cache_size) -{ - ydata_cache_t *cache = NULL; - char *iter; - ydata_cache_item_t *zcitem; - list_node_t *it, *sit; - int r = 0; - size_t i; - - if(!object || !cache_size) { - errno = EINVAL; - goto __fail; - } - - /* allocate and zero structure */ - if(!(cache = malloc(sizeof(ydata_cache_t)))) { - errno = ENOMEM; - goto __fail; - } else memset(cache, 0, sizeof(ydata_cache_t)); - - /* map a memory buffer */ - cache->cache = mmap(NULL, cache_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if(cache->cache == MAP_FAILED) { - errno = ENOMEM; - goto __fail; - } - - /* allocate all the locks */ - if((r = pthread_rwlock_init(&cache->rwlock, NULL))) { - errno = r; - goto __fail; - } - if((r = pthread_mutex_init(&cache->dirtlock, NULL))) { - pthread_rwlock_destroy(&cache->rwlock); - errno = r; - goto __fail; - } - - /* init other values */ - cache->cache_size = cache_size; - cache->object_size = dtolen(object); - - /* some paranoic check up */ - if(!cache->object_size) { - pthread_rwlock_destroy(&cache->rwlock); - pthread_mutex_destroy(&cache->dirtlock); - errno = EINVAL; - goto __fail; - } - /* well, able to continue ... */ - cache->objects_amount = cache->cache_size/(cache->object_size + sizeof(uint32_t)); - - /* init structures */ - usrtc_init(&cache->idx_tree, USRTC_SPLAY, cache->objects_amount, __cmp_oids); /* indexing one */ - list_init_head(&cache->free_poll); - list_init_head(&cache->dirty_poll); - list_init_head(&cache->pending_poll); - - /* mark i.e. format our memory buffer, also it will populate the pages */ - for(i = 0, iter = (char *)cache->cache; i < cache->objects_amount; - i++, iter += cache->object_size + sizeof(uint32_t)) { - /* mark with spacer */ - *(uint32_t *)iter = YD_CACHE_SPACER_MAGIC; - zcitem = __alloc_ydcitem(i); - if(!zcitem) { errno = ENOMEM; goto __failall; } - - list_add2tail(&cache->free_poll, &zcitem->listnode); - } - - /* lock the mutex */ - pthread_mutex_lock(&cache->dirtlock); - - return cache; - - __failall: - pthread_rwlock_destroy(&cache->rwlock); - pthread_mutex_destroy(&cache->dirtlock); - - __fail: - /* failcase freeing */ - if(cache) { - /* memory buffer */ - if(cache->cache != MAP_FAILED || cache->cache != NULL) { - /* if we have a buffer, we might have some items already allocated ... */ - list_for_each_safe(&cache->free_poll, it, sit) { - zcitem = container_of(it, ydata_cache_item_t, listnode); - list_del(&zcitem->listnode); - free(zcitem); - } - - munmap(cache->cache, cache_size); - } - - free(cache); - } - - return NULL; /* sadly ... */ -} - -/* allocating is quite simple: - * we're trying to get a free item, if it - * exists, we're moving this the the pending poll, - * otherwise return nil. - */ -void *yd_cache_alloc_item(ydata_cache_t *cache, ydata_cache_item_t **item) -{ - char *data = NULL; - list_node_t *listnode; - ydata_cache_item_t *zcitem; - - yd_cache_rdlock(cache); - listnode = list_node_first(&cache->free_poll); - if(listnode) { - yd_cache_unlock(cache); /* retake locks */ - yd_cache_wrlock(cache); - zcitem = container_of(listnode, ydata_cache_item_t, listnode); - list_del(&zcitem->listnode); /* delete from free poll */ - list_add2tail(&cache->pending_poll, &zcitem->listnode); /* add to the pending poll */ - /* do the magic */ - data = yd_cache_ptrbyidx(cache, zcitem->idx); - /* mark it invalidate - since we don't know what will be in future */ - zcitem->attr |= YDC_INVALIDATE; - *item = zcitem; - } - yd_cache_unlock(cache); - - /* ok. we'll do some automagically check for the near items safety */ - if(data && *(uint32_t *)data != YD_CACHE_SPACER_MAGIC ) { /* currupted - mark near elements invalidated ! */ - /* TODO: do it */ - } - - if(data) { - data += sizeof(uint32_t); /* bypass magic spacer */ - - return (void *)data; - } - - return NULL; -} - -void yd_cache_discard_alloc_item(ydata_cache_t *cache, ydata_cache_item_t *item) -{ - if(!(item->attr & YDC_INVALIDATE)) return; /* some shit happens */ - - yd_cache_wrlock(cache); - list_del(&item->listnode); /* delete from panding poll - guess, u can use API ugly and dirty */ - list_add2tail(&cache->free_poll, &item->listnode); /* add to the pending poll */ - item->attr &= ~YDC_INVALIDATE; /* clear the invalidate bit */ - yd_cache_unlock(cache); - - return; -} - -void yd_cache_confirm_alloc_item(ydata_cache_t *cache, ydata_cache_item_t *item, oid_t oid) -{ - if(!(item->attr & YDC_INVALIDATE)) return; /* some shit happens */ - - yd_cache_wrlock(cache); - list_del(&item->listnode); /* delete from pending poll - guess, u can use API ugly and dirty */ - item->attr &= ~YDC_INVALIDATE; /* clear the invalidate bit */ - item->attr &= ~YDC_UNUSED; /* clear the use bit */ - yd_item_setoid(item, oid); - usrtc_insert(&cache->idx_tree, &item->idxnode, (void *)&item->oid); /* now it will be in the splay tree of the active cached data */ - yd_cache_unlock(cache); - - return; -} - -void *yd_cache_lookup(ydata_cache_t *cache, oid_t oid) -{ - usrtc_node_t *node; - ydata_cache_item_t *item; - void *ret = NULL; - - yd_cache_rdlock(cache); - node = usrtc_lookup(&cache->idx_tree, &oid); - if(node) { - item = (ydata_cache_item_t *)usrtc_node_getdata(node); - if(!(item->attr & YDC_INVALIDATE)) ret = yd_cache_ptrbyidx(cache, yd_item_idx(item)); - else if(item->attr & YDC_INVALIDATE) { /* invalidated item */ - yd_cache_unlock(cache); /* retake lock */ - yd_cache_wrlock(cache); - usrtc_delete(&cache->idx_tree, &item->idxnode); - if(item->attr & YDC_DIRTY) { list_del(&item->listnode); /* it was dirty - but invalidated, remove it */ - cache->dirties--; - } - item->attr = 0; /* clear attributes */ - item->attr |= YDC_UNUSED; - list_add2tail(&cache->free_poll, &item->listnode); - ret = NULL; - } - } - yd_cache_unlock(cache); - - if(ret && *(uint32_t *)ret != YD_CACHE_SPACER_MAGIC ) { /* currupted - mark near elements invalidated ! */ - /* TODO: do it */ - } - - if(ret) ret += sizeof(uint32_t); - - return ret; -} - -static inline ydata_qitem_t *__quickitem_alloc(ydata_cache_item_t *zitem) -{ - ydata_qitem_t *itm = malloc(sizeof(ydata_qitem_t)); - - if(itm) { - list_init_node(&itm->node); - itm->item = zitem; - } - - return itm; -} - -list_head_t *yd_cache_getrslist(ydata_cache_t *cache, uint8_t amount) -{ - list_head_t *head = malloc(sizeof(list_head_t)); - usrtc_node_t *node; - list_node_t *_i, *_si; - ydata_qitem_t *itm; - ydata_cache_item_t *zitem; - int i; - - if(!head) return NULL; - if(!cache || !amount) goto __failcase; /* little bit of paranoic check */ - - yd_cache_wrlock(cache); - for(i = 0, node = usrtc_last(&cache->idx_tree); - i < amount; - i++, node = usrtc_last(&cache->idx_tree)) { - if(!node) break; /* pfff */ - zitem = (ydata_cache_item_t *)usrtc_node_getdata(node); - /* create an quick entry */ - if(!(itm = __quickitem_alloc(zitem))) goto __failcase_hasent; - - /* delete from the index tree */ - usrtc_delete(&cache->idx_tree, &zitem->idxnode); - list_add2tail(head, &itm->node); - } - yd_cache_unlock(cache); - - return head; - - __failcase_hasent: - if(head) { - list_for_each_safe(head, _i, _si) { - itm = container_of(_i, ydata_qitem_t, node); - zitem = itm->item; - if(zitem->attr & YDC_INVALIDATE) { /* oops, invalidated item found ! */ - if(zitem->attr & YDC_DIRTY) { - list_del(&zitem->listnode); - cache->dirties--; - } - list_add2tail(&cache->free_poll, &zitem->listnode); - zitem->attr = 0; - zitem->attr |= YDC_UNUSED; - } else /* return back */ - usrtc_insert(&cache->idx_tree, &zitem->idxnode, (void *)&zitem->oid); - - list_del(&itm->node); - free(itm); - } - yd_cache_unlock(cache); - } - - __failcase: - if(head) free(head); - return NULL; -} - -void yd_cache_qitems_pullback(ydata_cache_t *cache, list_head_t *list) -{ - list_node_t *iter, *siter; - ydata_qitem_t *itm; - ydata_cache_item_t *zitem; - - yd_cache_wrlock(cache); - list_for_each_safe(list, iter, siter) { - itm = container_of(iter, ydata_qitem_t, node); - zitem = itm->item; - if(zitem->attr & YDC_DIRTY) { - list_del(&zitem->listnode); - cache->dirties--; - } - zitem->attr = 0; /* reset flags */ - zitem->attr |= YDC_UNUSED; - list_add2tail(&cache->free_poll, &zitem->listnode); - - /* free it at all */ - list_del(&itm->node); - free(itm); - } - yd_cache_unlock(cache); - - free(list); - - return; -} - -void yd_cache_item_dirtyoid(ydata_cache_t *cache, oid_t oid) -{ - usrtc_node_t *node; - ydata_cache_item_t *zitem; - - yd_cache_wrlock(cache); - node = usrtc_lookup(&cache->idx_tree, &oid); - if(node) { - zitem = (ydata_cache_item_t *)usrtc_node_getdata(node); - if(!(zitem->attr & YDC_DIRTY)) { - list_add2tail(&cache->dirty_poll, &zitem->listnode); - zitem->attr |= YDC_DIRTY; - cache->dirties++; - /* schedule sync thread, since threshold of dirty items occured */ - if(cache->dirties >= YDC_SYNCTHRESHOLD) pthread_mutex_unlock(&cache->dirtlock); - } - } - yd_cache_unlock(cache); - - return; -} - -void yd_cache_item_invalidateoid(ydata_cache_t *cache, oid_t oid) -{ - usrtc_node_t *node; - ydata_cache_item_t *zitem; - - yd_cache_wrlock(cache); - node = usrtc_lookup(&cache->idx_tree, &oid); - if(node) { - zitem = (ydata_cache_item_t *)usrtc_node_getdata(node); - if(!(zitem->attr & YDC_INVALIDATE)) zitem->attr |= YDC_INVALIDATE; - } - yd_cache_unlock(cache); - - return; -} diff --git a/ydaemon/context.c b/ydaemon/context.c deleted file mode 100644 index 836e119..0000000 --- a/ydaemon/context.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static long __cmp_cstr(const void *a, const void *b) -{ - return strcmp((const char *)a, (const char *)b); -} - -/* config entries */ -static scret_t __ymconf_create_pgroup(yd_context_t *cnf, sexp_t *sx, void *priv) -{ - char *grp_name; - scret_t rets; - int r = EINVAL; - - /* get the group name */ - sx->list = sx->list->next; - if(!(sx->list)) { RETURN_SRET_IRES(rets, r); } - else grp_name = sx->list->val; - - /* now we will add this */ - r = ydc_conf_create_pgroup(cnf->values, (char *)grp_name); - RETURN_SRET_IRES(rets, r); -} - -static scret_t __module_add(yd_context_t *ctx, sexp_t *sx, void *priv) -{ - char *mod_name, *mod_type; - yd_mod_type_t type; - scret_t rets; - int r = 0; - - /* get the name */ - sx->list = sx->list->next; - if(!(sx->list)) { r = EINVAL; goto __fail; } - else mod_name = sx->list->val; - - sx->list = sx->list->next; - if(!(sx->list)) { r = EINVAL; goto __fail; } - else mod_type = sx->list->val; - - if(!strcmp(mod_type, "service")) type = YD_SERVICE_MUX; - else if(!strcmp(mod_type, "sxmp")) type = YD_SXMP_MOD; - else if(!strcmp(mod_type, "datastore")) type = YD_DATASTORE_MOD; - else if(!strcmp(mod_type, "other")) type = YD_OTHER; - else r = EINVAL; - - if(!r) r = yd_mod_add(ctx, mod_name, type); - - __fail: - RETURN_SRET_IRES(rets, r); -} - -static scret_t __object(yd_context_t *ctx, sexp_t *sx, void *priv) -{ - char *mod_name, *mod_obj; - yd_mod_t *lmod; - scret_t rets; - int r = 0; - void *fdata; - - /* get the name */ - sx->list = sx->list->next; - if(!(sx->list)) { r = EINVAL; goto __fail; } - else mod_name = sx->list->val; - - sx->list = sx->list->next; - if(!(sx->list)) { r = EINVAL; goto __fail; } - else mod_obj = sx->list->val; - - r = yd_mod_get(ctx, mod_name, &lmod); - if(r) { - RETURN_SRET_SERR(rets, r); - } else fdata = yd_mod_getobject(ctx, lmod, NULL, mod_obj); - - if(!fdata) { - r = ENOENT; - goto __fail; - } - - RETURN_SRET_ORES(rets, fdata); - - __fail: - RETURN_SRET_IRES(rets, r); -} - -static scret_t __module_load(yd_context_t *ctx, sexp_t *sx, void *priv) -{ - register int state = 0; - register int idx; - yd_mod_t *lmod; - sexp_t *isx; - int r = EINVAL; - scret_t rets; - - SEXP_ITERATE_LIST(sx, isx, idx) { - if(isx->ty == SEXP_LIST) goto __fail; - else { - if(!state) { - if(strcmp(isx->val, MODULE_LOAD_SX)) goto __fail; - else state++; - } else { /* find module */ - if(isx->aty != SEXP_SQUOTE) goto __fail; - - r = yd_mod_get(ctx, (const char *)isx->val, &lmod); - if(r) goto __fail; - - /* load it */ - r = yd_mod_load(ctx, lmod); - } - } - } - - __fail: - RETURN_SRET_IRES(rets, r); -} - -static scret_t __module_run(yd_context_t *ctx, sexp_t *sx, void *priv) -{ - register int state = 0; - register int idx; - yd_mod_t *lmod; - sexp_t *isx; - int r = EINVAL; - scret_t rets; - - SEXP_ITERATE_LIST(sx, isx, idx) { - if(isx->ty == SEXP_LIST) goto __fail; - else { - if(!state) { - if(strcmp(isx->val, MODULE_RUN_SX)) goto __fail; - else state++; - } else { /* find module */ - if(isx->aty != SEXP_SQUOTE) goto __fail; - - r = yd_mod_get(ctx, (const char *)isx->val, &lmod); - if(r) goto __fail; - - /* load it */ - r = yd_mod_run(ctx, lmod); - } - } - } - - __fail: - RETURN_SRET_IRES(rets, r); -} - -static scret_t __module_set(yd_context_t *ctx, sexp_t *sx, void *priv) -{ - register int state = 0; /* states - 0 begin, 1 - rpc function checked, 2 - module found */ - register int pst = 0; /* 0 - nothing, 1 - name set */ - char *pname, *pval, *pss; - yd_mod_t *lmod; - int r = 0, idx, pidx; - sexp_t *isx, *pisx; - ydc_conf_val_t *rval; - scret_t rets; - - r = EINVAL; /* invalid syntax */ - SEXP_ITERATE_LIST(sx, isx, idx) { - if(isx->ty == SEXP_LIST) { - r = EINVAL; - if(state < 2) goto __err_fail; - pst = 0; - SEXP_ITERATE_LIST(isx, pisx, pidx) { - if(pisx->ty != SEXP_VALUE) { /* values are not acceptable */ - goto __err_fail; - } - - if(!pst && *(pisx->val) != ':') goto __err_fail; /* syntax error */ - - if(!pst) { - pname = pisx->val + sizeof(char); pst++; - } else { - if(pisx->aty == SEXP_DQUOTE || pisx->aty == SEXP_SQUOTE) pval = pisx->val; - else if((pisx->aty == SEXP_BASIC) && (pss = strchr((const char *)pisx->val, '/'))) { - /* it's a variable */ - r = ydc_conf_get_val(ctx->values, (const char *)pisx->val, &rval); - if(r) goto __err_fail; - - if(rval->type != STRING) goto __err_fail; - else pval = (char *)rval->value; - } else goto __err_fail; - - /* set the right part of the module */ - if(!strcmp(pname, MODULE_PREFIX)) yd_mod_set_prefix(lmod, pval); - else if(!strcmp(pname, MODULE_PATHNAME)) yd_mod_set_pathname(lmod, pval); - else if(!strcmp(pname, MODULE_CNFPATH)) yd_mod_set_cfgpath(lmod, pval); - else goto __err_fail; - } - } - } else if(isx->ty == SEXP_VALUE) { /* got the value */ - switch(state) { - case 0: - if(strcmp((const char *)isx->val, MODULE_SET_SX)) goto __err_fail; - else state++; - break; - case 1: - if(isx->aty != SEXP_SQUOTE) goto __err_fail; - else { - r = yd_mod_get(ctx, (const char *)isx->val, &lmod); - if(r) goto __err_fail; - else state++; - } - break; - default: - goto __err_fail; - } - } - } - - r = 0; - - __err_fail: - - RETURN_SRET_IRES(rets, r); -} - -static scret_t __ymconf_set_cv(yd_context_t *cnf, sexp_t *sx, void *priv) -{ - char *value_expression, *value; - char *buf = priv; - scret_t rets; - int r = EINVAL; - int cstr = 0; - - /* skip keyword */ - sx->list = sx->list->next; - /* check out this */ - if(sx->ty != SEXP_LIST) { RETURN_SRET_IRES(rets, r); } - else sx = sx->list; - value_expression = sx->list->val; - sx->list = sx->list->next; - //if(sx->ty == SEXP_LIST) return -EINVAL; - value = sx->list->val; - /* check for the forcing of cstring */ - if(sx->list->aty == SEXP_DQUOTE) cstr = 1; - - snprintf(buf, sizeof(char)*4096, "%s:%s", value_expression, value); - - r = ydc_conf_add_val_p(cnf->values, (const char *)buf, cstr); - - RETURN_SRET_IRES(rets, r); -} - -static scret_t __ymconf_uselogfile(yd_context_t *cnf, sexp_t *sx, void *priv) -{ - char *logfile; - FILE *ls; - ydc_conf_val_t *rval; - scret_t rets; - int r = EINVAL; - - r = ydc_conf_get_val(cnf->values, "daemon/logfile", &rval); - if(r) goto __fini; - if(rval->type != STRING) goto __fini; - else logfile = (char *)rval->value; - - ls = fopen(logfile, "a+"); - if(!ls) r = errno; - else { - cnf->logcontext->logstream = ls; - setbuf(ls, NULL); - r = 0; - } - - if(cnf->daemon && !r) { - fclose(stdout); - fclose(stderr); - stdout = fopen(logfile, "a+"); - stderr = fopen(logfile, "a+"); - setbuf(stdout, NULL); - setbuf(stderr, NULL); - } - - __fini: - RETURN_SRET_IRES(rets, r); -} - -int yd_init_ctx(yd_context_t *ctx) -{ - int r = 0; - usrtc_t *services = malloc(sizeof(usrtc_t)); - usrtc_t *modules = malloc(sizeof(usrtc_t)); - scm_function_tree_t *ft = NULL; - ydc_conf_t *c = malloc(sizeof(ydc_conf_t)); - yd_log_t *zdl = malloc(sizeof(yd_log_t)); - char *pbuf = malloc(sizeof(char)*4096); - - if(!ctx) return EINVAL; - else memset(ctx, 0, sizeof(yd_context_t)); - - if((r = pthread_rwlock_init(&ctx->modlock, NULL))) goto __fini; - if((r = pthread_mutex_init(&ctx->looplock, NULL))) { - pthread_rwlock_destroy(&ctx->modlock); - goto __fini; - } - - if(!zdl) goto __fail; - /* init trees */ - if(!services || !modules) goto __fail; - else { - usrtc_init(services, USRTC_SPLAY, MAX_SERVICES, __cmp_cstr); - usrtc_init(modules, USRTC_SPLAY, MAX_MODULES, __cmp_cstr); - ctx->services = services; - ctx->modules = modules; - ctx->daemon = 0; - ctx->logcontext = zdl; - zdl->logstream = stdout; - zdl->verbose_level = YL_INFO; - zdl->se = 1; - } - - r = scm_func_tree_init(&ft, ctx); - if(r) goto __fail; - else { /* fill up with default functions */ - if(!pbuf) goto __fail; - if(!c) goto __fail; /* let's init config */ - r = ydc_conf_init(c); - if(r) goto __fail; - else { - ctx->values = c; - ctx->func = ft; - } - - /* defaults ones */ - scm_func_tree_insert(ctx, VAR_CREATE_GROUP, - __ymconf_create_pgroup, NULL); - scm_func_tree_insert(ctx, VAR_SET, - __ymconf_set_cv, pbuf); - scm_func_tree_insert(ctx, MODULE_ADD_SX, - __module_add, NULL); - scm_func_tree_insert(ctx, MODULE_SET_SX, - __module_set, NULL); - scm_func_tree_insert(ctx, MODULE_LOAD_SX, - __module_load, NULL); - scm_func_tree_insert(ctx, MODULE_RUN_SX, - __module_run, NULL); - scm_func_tree_insert(ctx, SCMOBJECT, - __object, NULL); - scm_func_tree_insert(ctx, YDOPENLOGS, - __ymconf_uselogfile, NULL); - - } - - if(!r) pthread_mutex_lock(&ctx->looplock); - - __fini: - return r; - - __fail: - pthread_rwlock_destroy(&ctx->modlock); - pthread_mutex_destroy(&ctx->looplock); - if(c) free(c); - if(zdl) free(zdl); - if(pbuf) free(pbuf); - if(services) free(services); - if(modules) free(modules); - if(ft) scm_func_tree_free(ft); - - return r; -} - -scret_t yd_eval_sexp(yd_context_t *ctx, sexp_t *sx) -{ - scret_t rets; - int r; - char *keyw; - char ibuf[64]; - - if(sx->ty == SEXP_LIST) keyw = sx->list->val; - else { - r = EINVAL; - RETURN_SRET_SERR(rets, r); - } - - rets = scm_func_tree_call(ctx, ctx, sx, keyw); - - if(rets.type == SCINT && rets.ec != 0) { - r = rets.ec; - print_sexp(ibuf, 63, sx); - if(strlen(ibuf) >= 63) ydlog(ctx, YL_WARN, "%s... return %d (%s)\n", ibuf, r, strerror(r)); - else ydlog(ctx, YL_WARN, "%s return %d (%s)\n", ibuf, r, strerror(r)); - } - - return rets; -} - -int yd_eval_ctx(yd_context_t *ctx, const char *confpath) -{ - sexp_t *sx; - sexp_iowrap_t *iow; - int fd, r = 0; - char *keyw; - scret_t ret; - char ibuf[64]; - - /* try to open it */ - if((fd = open(confpath, O_RDONLY)) < 0) { - r = errno; - return r; - } - - if(!(iow = init_iowrap(fd))) { - r = errno; - close(fd); - return r; - } - - /* now load the configuration scenario */ - while((sx = read_one_sexp(iow)) != NULL) { - if(sx->ty == SEXP_LIST) keyw = sx->list->val; - else keyw = sx->val; - - ret = scm_func_tree_call(ctx, ctx, sx, keyw); - /* not found */ - if(ret.serr) { - close(fd); - ydlog(ctx, YL_ERROR, "%s: unknown keyword ``%s''\n", __FUNCTION__, keyw); - return r; - } - /* more information */ - if(ret.type == SCINT && ret.ec != 0) { - r = ret.ec; - print_sexp(ibuf, 63, sx); - if(strlen(ibuf) >= 63) ydlog(ctx, YL_WARN, "%s... return %d (%s)\n", ibuf, r, strerror(r)); - else ydlog(ctx, YL_WARN, "%s return %d (%s)\n", ibuf, r, strerror(r)); - } - } - - r = 0; - - close(fd); - - return r; -} - diff --git a/ydaemon/daemon.c b/ydaemon/daemon.c deleted file mode 100644 index a1c38a7..0000000 --- a/ydaemon/daemon.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -int yd_mainloop(yd_context_t *ctx) -{ - usrtc_node_t *node = NULL; - yd_mod_t *mod; - - /* we will locked here */ - pthread_mutex_lock(&ctx->looplock); - - /* if we're here ... somebody decide to end the loop */ - yd_mod_ctx_wrlock(ctx); - for(node = usrtc_last(ctx->modules); ;node = usrtc_prev(ctx->modules, node)) { - mod = (yd_mod_t *)usrtc_node_getdata(node); - mod->shutdown(ctx); - - /* for() */ - if(node == usrtc_first(ctx->modules)) break; - } - yd_mod_ctx_unlock(ctx); - - return 0; -} - -void yd_mainloop_exit(yd_context_t *ctx) -{ - pthread_mutex_unlock(&ctx->looplock); - - return; -} - -/* - * daemon workout - */ - -void yddaemon(yd_context_t *ctx) -{ - pid_t pid; - ydc_conf_val_t *rval; - - /* fork the first time to detach the controlling terminal - * and avoid to be a group leader. - */ - pid = fork(); - if(pid < 0) exit(EXIT_FAILURE); /* something goes wrong ... */ - if(pid > 0) exit(EXIT_SUCCESS); /* parent can take a rest */ - - /* try to become a session leader */ - if(setsid() < 0) exit(EXIT_FAILURE); /* something goes wrong ... */ - - /* ignore fucking signals */ - signal(SIGCHLD, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - - /* fork the second time, to avoid be a session leader - the goal is - * regain a terminal control never. - */ - pid = fork(); - if(pid < 0) exit(EXIT_FAILURE); /* something goes wrong ... */ - if(pid > 0) exit(EXIT_SUCCESS); /* parent can take a rest */ - - /* reset mask */ - umask(0); - - /* change working directory to root */ - // chdir("/"); -#if 0 - /* test and change if set */ - if(!ydc_conf_get_val(ctx->zvalues, "daemon/workingdir", &rval)) { - if(rval->type == STRING) chdir((const char *)rval->value); - } -#endif - - /* let's a deal */ - fclose(stdin); - fclose(stderr); - fclose(stdout); - - /* if oe - mean we allowing to write a lof file thru standard prints ... */ - stdin = fopen("/dev/null", "r"); -#if 0 - if(ctx->logcontext->se && !ydc_conf_get_val(ctx->zvalues, "daemon/logfile", &rval)) { - if(rval->type == STRING) { - stdout = fopen((char *)rval->value, "a"); - stderr = fopen((char *)rval->value, "a"); - } - } else { -#endif - stdout = fopen("/dev/null", "a"); - stderr = fopen("/dev/null", "a"); -#if 0 - } -#endif - ctx->daemon = 1; - - return; -} diff --git a/ydaemon/data.c b/ydaemon/data.c deleted file mode 100644 index 6ec5efd..0000000 --- a/ydaemon/data.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include - -static long __cmp_uint8(const void *a, const void *b) -{ - return *(uint8_t *)a - *(uint8_t *)b; -} - -static long __cmp_cstr(const void *a, const void *b) -{ - return strcmp((const char *)a, (const char *)b); -} - -dataobject_t *dotr_create(const char *name) -{ - dataobject_t *dtr = malloc(sizeof(dataobject_t)); - - if(!dtr) return NULL; - else memset(dtr, 0, sizeof(dataobject_t)); - - /* init name, indexes etc ... */ - strncpy(dtr->name, name, MAX_ITEM_NAME - sizeof(char)); - - list_init_head(&dtr->description); - usrtc_init(&dtr->id_index, USRTC_REDBLACK, MAX_ITEMS, __cmp_uint8); - usrtc_init(&dtr->name_index, USRTC_REDBLACK, MAX_ITEMS, __cmp_cstr); - - return dtr; -} - -int dotr_set_item(dataobject_t *dotr, uint8_t type, uint64_t len, - const char *name) -{ - dataobject_item_t *ditem = malloc(sizeof(dataobject_item_t)); - char *indexes = malloc(2*sizeof(item_idx_t)); - item_idx_t *iidx, *nidx; - - if(!ditem || !indexes) { - if(ditem) free(ditem); - if(indexes) free(indexes); - return ENOMEM; - } else { - iidx = (item_idx_t *)indexes; - nidx = (item_idx_t *)(indexes + sizeof(item_idx_t)); - } - - /* init items */ - strncpy(ditem->name, name, MAX_ITEM_NAME - sizeof(char)); - ditem->id = usrtc_count(&dotr->id_index); - ditem->type = type; - ditem->len = len; - list_init_node(&ditem->node); - - iidx->key = &ditem->id; - iidx->dtr = ditem; - usrtc_node_init(&iidx->node, iidx); - - nidx->key = ditem->name; - nidx->dtr = ditem; - usrtc_node_init(&nidx->node, nidx); - - /* now insert all */ - list_add2tail(&dotr->description, &ditem->node); - usrtc_insert(&dotr->id_index, &iidx->node, iidx->key); - usrtc_insert(&dotr->name_index, &nidx->node, nidx->key); - - return 0; -} - -void dotr_destroy(dataobject_t *dotr) -{ - usrtc_t *tree = &dotr->id_index; - usrtc_node_t *node = NULL; - item_idx_t *idx; - list_node_t *iter, *save; - dataobject_item_t *ditem; - - if(usrtc_count(tree)) { /* we can free only index, since it was allocated as one memory chunk */ - for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) { - idx = (item_idx_t *)usrtc_node_getdata(node); - usrtc_delete(tree, node); - free(idx); - } - - /* free description */ - list_for_each_safe(&dotr->description, iter, save) { - ditem = container_of(iter, dataobject_item_t, node); - list_del(&ditem->node); - free(ditem); - } - } - - free(dotr); - - return; -} - -uint8_t dotr_item_type(dataobject_t *obj, const char *name, uint64_t *len) -{ - usrtc_node_t *node = usrtc_lookup(&obj->name_index, name); - item_idx_t *idxnode; - dataobject_item_t *dtr = NULL; - - if(!node) { /* not found ! */ - __failed: - *len = 0; - return 0; - } - - idxnode = (item_idx_t *)usrtc_node_getdata(node); - if(!idxnode) goto __failed; - else dtr = idxnode->dtr; - - if(!dtr) goto __failed; - - *len = dtr->len; - return dtr->type; -} - -char *dotr_item_nameptr(dataobject_t *obj, const char *name) -{ - usrtc_node_t *node = usrtc_lookup(&obj->name_index, name); - item_idx_t *idxnode; - dataobject_item_t *dtr = NULL; - - if(!node) /* not found ! */ return NULL; - - idxnode = (item_idx_t *)usrtc_node_getdata(node); - if(!idxnode) return NULL; - else dtr = idxnode->dtr; - - if(!dtr) return NULL; - - return dtr->name; -} - -int dotr_item_nameidx(dataobject_t *obj, const char *name) -{ - usrtc_node_t *node = usrtc_lookup(&obj->name_index, name); - item_idx_t *idxnode; - dataobject_item_t *dtr = NULL; - - if(!node) /* not found ! */ return -1; - - idxnode = (item_idx_t *)usrtc_node_getdata(node); - if(!idxnode) return -1; - else dtr = idxnode->dtr; - - if(!dtr) return -1; - - return dtr->id; -} - -static inline int __itemcmp(const dataobject_item_t *s1, - const dataobject_item_t *s2) -{ - int r = 0; - if((r = strcmp(s1->name, s2->name))) return r; - if((r = s1->len - s2->len)) return r; - if((r = s1->type - s2->type)) return r; - - return 0; -} - -int dtocmp(const dataobject_t *src, const dataobject_t *dst) -{ - int r = 0; - list_node_t *iter, *siter; - dataobject_item_t *ditem, *sitem; - usrtc_node_t *unode; - item_idx_t *iidx; - - /* check name */ - if((r = strcmp(src->name, dst->name))) return r; - /* check amount of items */ - if((r = usrtc_count((usrtc_t *)&src->id_index) - usrtc_count((usrtc_t *)&dst->id_index))) - return r; - - /* check items itself */ - list_for_each_safe(&src->description, iter, siter) { - ditem = container_of(iter, dataobject_item_t, node); - if(!(unode = usrtc_lookup((usrtc_t *)&dst->id_index, (const void *)&ditem->id))) - return 100*ditem->id; - - iidx = (item_idx_t *)usrtc_node_getdata(unode); - sitem = iidx->dtr; - - if((r = __itemcmp(ditem, sitem))) return r*ditem->id; - } - - return 0; -} - -size_t dtolen(const dataobject_t *src) -{ - size_t len = 0; - list_node_t *iter, *siter; - dataobject_item_t *ditem; - - list_for_each_safe(&src->description, iter, siter) { - ditem = container_of(iter, dataobject_item_t, node); - len += ditem->len; - } - - return len; -} diff --git a/ydaemon/domx.c b/ydaemon/domx.c deleted file mode 100644 index 4b654b1..0000000 --- a/ydaemon/domx.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include - -int domx_init(domx_t *dt, dataobject_t *dodesc) -{ - if(!dt || !dodesc) return EINVAL; - - /* init first values */ - dt->dox = dodesc; - dt->name = dodesc->name; - dt->be = dt->cache = NULL; - - /* init list for sntls lists */ - list_init_head(&dt->sxmp_channels); - - return 0; -} - -int domx_set_be(domx_t *dt, void *be, const char *key) -{ - struct be_ops *f = (struct be_ops *)be; - domx_dsbe_t *dbe; - - if(!dt) return EINVAL; - if(!f || f->be_magic != BEMAGIC) return EINVAL; - - if(!(dbe = malloc(sizeof(domx_dsbe_t)))) return ENOMEM; - - dbe->domx = dt; - dbe->priv = NULL; - dbe->f = f; - dt->be = dbe; - - return dbe->f->init(dbe, key); -} - -int domx_set_cache(domx_t *dt, size_t size) -{ - int r = 0; - - /* paranoic check */ - if(!dt || !dt->dox) return EINVAL; - - if(!(dt->cache = (void *)yd_cache_init(dt->dox, size))) - r = errno; - else r = yd_cache_start_thread(dt); - - return r; -} - -int domx_set_sxmpchannel(domx_t *dt, const char *instance, int typeid, int access) -{ - sxmp_ch_entry_t *sentry = NULL; - - if(!dt || !instance) return EINVAL; - - if(!(sentry = malloc(sizeof(sxmp_ch_entry_t)))) return ENOMEM; - - /* init sntl channel entry */ - strncpy(sentry->instance, instance, 31); - sentry->chtid = (uint16_t)typeid; - sentry->filter = (ydm_access_filter_t)access; - list_init_node(&sentry->node); - - /* add this entry */ - list_add2tail(&dt->sxmp_channels, &sentry->node); - - return 0; -} - -#define __ITEMSTOFREED 32 - -int domx_get(domx_t *dt, uint64_t oid, void **refdata) -{ - void *data; - ydata_cache_item_t *itm; - ydata_qitem_t *qitem; - domx_dsbe_t *be; - list_head_t *rsitemslist = NULL; - list_node_t *iter, *siter; - int r = 0; - - /* paranoic check up */ - if(!dt || !dt->cache) return EINVAL; - if(!(be = dt->be)) return EINVAL; - - __retry: /* yep, that's here, because anybody can inject our data while we're trying to refresh cache */ - data = yd_cache_lookup((ydata_cache_t *)dt->cache, oid); - - if(data) *refdata = data; - else { /* cache miss occured */ - /* first allocate the required item within the cache */ - data = yd_cache_alloc_item((ydata_cache_t *)dt->cache, &itm); - if(data) { /* we have a free entries ! */ - if((r = be->f->get(be, oid, data))) yd_cache_discard_alloc_item((ydata_cache_t *)dt->cache, itm); - else {/* all is fine - confirm cache insertion */ - yd_cache_confirm_alloc_item((ydata_cache_t *)dt->cache, itm, oid); - *refdata = data; - } - } else { /* we don't have free entries */ - if(!(rsitemslist = yd_cache_getrslist((ydata_cache_t *)dt->cache, __ITEMSTOFREED))) - { r = ENOMEM; goto __fini; } - /* ok, now we're ready to do something - we have unplugged items clean it up then */ - list_for_each_safe(rsitemslist, iter, siter) { - qitem = container_of(iter, ydata_qitem_t, node); - itm = qitem->item; - if(itm->attr & YDC_DIRTY) /* if dirty - sync, but we don't care result here - if corrupted - data is totally corrupteed*/ - be->f->set(be, itm->oid, (yd_cache_ptrbyidx((ydata_cache_t *)dt->cache, itm->idx)) + sizeof(uint32_t)); - } - /* now we need to return there list back to the cache and retry */ - yd_cache_qitems_pullback((ydata_cache_t *)dt->cache, rsitemslist); - goto __retry; - } - } - - __fini: - return r; -} - -int domx_set(domx_t *dt, uint64_t oid, const void *refdata) -{ - domx_dsbe_t *be; - void *data; - ydata_cache_t *cc; - int r = 0; - - /* paranoic check up */ - if(!dt || !dt->cache) return EINVAL; - if(!(be = dt->be)) return EINVAL; - - cc = (ydata_cache_t *)dt->cache; - - data = yd_cache_lookup(cc, oid); - __again: - if(data) { /* we have those object with this oid in cache */ - memcpy(data, refdata, cc->object_size); /* copy object data */ - yd_cache_item_dirtyoid(cc, oid); /* just point to the cache - dirty */ - } else { /* we're trying to set invalidated data */ - r = domx_get(dt, oid, &data); - if(!r) goto __again; - } - - return r; -} - -int domx_remove(domx_t *dt, uint64_t oid) -{ - domx_dsbe_t *be; - void *data; - ydata_cache_t *cc; - - /* paranoic check up */ - if(!dt || !dt->cache) return EINVAL; - if(!(be = dt->be)) return EINVAL; - - cc = (ydata_cache_t *)dt->cache; - - data = yd_cache_lookup(cc, oid); - if(data) yd_cache_item_invalidateoid(cc, oid); - - return be->f->remove(be, oid); -} - -int domx_creat(domx_t *dt, uint64_t *oid, const void *refdata) -{ - domx_dsbe_t *be; - oid_t r = 0; - - /* paranoic check up */ - if(!dt || !dt->cache) return EINVAL; - if(!(be = dt->be)) return EINVAL; - - /* here we just create this one and nothing */ - r = be->f->creat(be, refdata); - - if(!r) return errno; - - *oid = r; - - return 0; -} - -yd_idx_stream_t *domx_idxl_open(domx_t *dt, ydm_access_filter_t afilter, - dataacc_pemctx_t *dacc, yd_filter_t *datafilter) -{ - domx_dsbe_t *be; - - /* paranoic check up */ - if(!dt || !dt->cache) { - __einval: - errno = EINVAL; - return NULL; - } - if(!(be = dt->be)) goto __einval; - - return be->f->create_idx_stream(be, afilter, dacc, datafilter); -} - -void domx_idxl_close(domx_t *dt, yd_idx_stream_t *idxl) -{ - domx_dsbe_t *be; - - /* paranoic check up */ - if(!dt || !dt->cache) { - __einval: - errno = EINVAL; - return; - } - if(!(be = dt->be) || !idxl) goto __einval; - - be->f->destroy_idx_stream(idxl); -} - -yd_idx_stream_win_t *domx_idxl_read(domx_t *dt, yd_idx_stream_t *idxl) -{ - domx_dsbe_t *be; - - /* paranoic check up */ - if(!dt || !dt->cache) { - __einval: - errno = EINVAL; - return NULL; - } - if(!(be = dt->be) || !idxl) goto __einval; - - return be->f->getportion_idx_stream(idxl); -} - diff --git a/ydaemon/filter.c b/ydaemon/filter.c deleted file mode 100644 index fef27a0..0000000 --- a/ydaemon/filter.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#define DMUX_USE 1 -#include - -yd_filter_t *yd_filter_create(domx_t *refobj) -{ - yd_filter_t *f = malloc(sizeof(yd_filter_t)); - - if(f) { - f->domx = refobj; - list_init_head(&f->filter); - } - - return f; -} - -void yd_filter_destroy(yd_filter_t *f) -{ - list_head_t *lhead; - list_node_t *iter, *siter, *liter, *lsiter; - yd_filter_item_t *filter_item; - yd_inlist_item_t *inl_item; - dataobject_t *obj; - uint64_t len; - uint8_t type; - - if(!f) return; - else { - lhead = &f->filter; - obj = f->domx->dox; - } - - list_for_each_safe(lhead, iter, siter) { - filter_item = container_of(iter, yd_filter_item_t, node); - type = dotr_item_type(obj, filter_item->name, &len); - if(type && len) { - switch(filter_item->ftype) { - case YDEQUAL: - case YDNOTEQUAL: - if(type == CSTR || type == TBLOB) free(filter_item->cstr); - break; - case YDINLIST: - /* we must destroy the list */ - list_for_each_safe(filter_item->inlist, liter, lsiter) { - inl_item = container_of(liter, yd_inlist_item_t, node); - if(type == CSTR || type == TBLOB) free(inl_item->dta); - list_del(&inl_item->node); - free(inl_item); - } - free(filter_item->inlist); - break; - default: break; /* nothing to do */ - } - } - - /* free struct itself */ - list_del(&filter_item->node); - free(filter_item); - } - - free(f); - - return; -} - -static yd_filter_item_t *__alloc_init_fitem(filt_t ftype, char *name) -{ - yd_filter_item_t *fitem = NULL; - - if(name && (fitem = malloc(sizeof(yd_filter_item_t)))) { - memset(fitem, 0, sizeof(yd_filter_item_t)); - fitem->name = name; - fitem->ftype = ftype; - list_init_node(&fitem->node); - } - - return fitem; -} - -int yd_filter_add_sf(yd_filter_t *f, const char *name, filt_t ftype, - uint64_t vf, uint64_t vc) -{ - yd_filter_item_t *fitem; - dataobject_t *obj; - uint64_t len; - uint8_t type; - - if(!f || !name) return EINVAL; - - /* lookup for existing entry and check it */ - obj = f->domx->dox; - type = dotr_item_type(obj, name, &len); - if(!type && !len) return EINVAL; - - /* check validity */ - if((type < CSTR) && (len > tltable[type].len)) return EINVAL; /* we cannot filter by array here */ - if(type > S64) return EINVAL; /* we're adding a simple filter rule */ - if(ftype == YDINLIST) return EINVAL; /* we're not working with that in this function */ - - fitem = __alloc_init_fitem(ftype, dotr_item_nameptr(obj, name)); - if(!fitem) return ENOMEM; - - fitem->vf = vf; - if(ftype == YDINLIST) fitem->vc = vc; - - /* add this entry */ - list_add2tail(&f->filter, &fitem->node); - - return 0; -} - -int yd_filter_add_str(yd_filter_t *f, const char *name, const char *value, int eq) -{ - yd_filter_item_t *fitem; - dataobject_t *obj; - filt_t ftype; - uint64_t len; - uint8_t type; - - if(!f || !name) return EINVAL; - - /* lookup for existing entry and check it */ - obj = f->domx->dox; - type = dotr_item_type(obj, name, &len); - if(!type && !len) return EINVAL; - - if(type != CSTR) return EINVAL; /* cannot do it, invalid */ - - if(!eq) ftype = YDNOTEQUAL; - else ftype = YDEQUAL; - - fitem = __alloc_init_fitem(ftype, dotr_item_nameptr(obj, name)); - if(!fitem) return ENOMEM; - - if(!(fitem->cstr = strndup(value, len - sizeof(char)))) { - free(fitem); - return ENOMEM; - } - - /* add this entry */ - list_add2tail(&f->filter, &fitem->node); - - return 0; -} - -int yd_filter_add_inlist(yd_filter_t *f, const char *name, int length, void **array) -{ - yd_filter_item_t *fitem; - yd_inlist_item_t *list_item; - dataobject_t *obj; - list_node_t *iter, *siter; - uint64_t len; - int i; - uint8_t type; - - if(!f || !name) return EINVAL; - if(!length || !array) return EINVAL; - - /* lookup for existing entry and check it */ - obj = f->domx->dox; - type = dotr_item_type(obj, name, &len); - if(!type && !len) return EINVAL; - - fitem = __alloc_init_fitem(YDINLIST, dotr_item_nameptr(obj, name)); - if(!fitem) return ENOMEM; - - if(!(fitem->inlist = malloc(sizeof(list_head_t)))) { - __enomem: - free(fitem); - return ENOMEM; - } - - /* fill the list */ - for(i = 0; i < length; i++) { - if(!(list_item = malloc(sizeof(yd_inlist_item_t)))) { - __deep_enomem: - list_for_each_safe(fitem->inlist, iter, siter) { - list_item = container_of(iter, yd_inlist_item_t, node); - if(type == CSTR || type == TBLOB) free(list_item->dta); - list_del(&list_item->node); - free(list_item); - } - /* free the list */ - free(fitem->inlist); - goto __enomem; - } - if(type < CSTR) list_item->val = *(uint64_t *)array[i]; - else if(!(list_item->dta = strndup((const char *)array[i], len - sizeof(char)))) goto __deep_enomem; - - list_init_node(&list_item->node); - list_add2tail(fitem->inlist, &list_item->node); - } - - /* add this entry */ - list_add2tail(&f->filter, &fitem->node); - - return 0; -} - diff --git a/ydaemon/functions.c b/ydaemon/functions.c deleted file mode 100644 index e7d5487..0000000 --- a/ydaemon/functions.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static long __cmp_cstrs(const void *a, const void *b) -{ - return (long)(strcmp((const char *)a, (const char *)b)); -} - -static void __scm_func_tree_init(scm_function_tree_t *pt, void *priv) -{ - usrtc_t *foost = (usrtc_t *)&(pt->functions); - - usrtc_init(foost, USRTC_SPLAY, MAX_SCM_FUNCTIONS, __cmp_cstrs); - return; -} - -static scm_function_tree_t *__scm_func_tree_alloc(void *priv) -{ - scm_function_tree_t *t = malloc(sizeof(scm_function_tree_t)); - - if(!t) goto __fail; - else __scm_func_tree_init(t, priv); - - __fail: - return t; -} - -void scm_func_tree_free(scm_function_tree_t *pt) -{ - usrtc_t *ftree = &(pt->functions); - usrtc_node_t *node = NULL; - scm_function_t *sf; - - if(usrtc_count(ftree)) { - for(node = usrtc_first(ftree); node != NULL; node = usrtc_first(ftree)) { - sf = (scm_function_t *)usrtc_node_getdata(node); - /* remove from the tree first */ - usrtc_delete(ftree, node); - /* free all */ - free(sf->name); - free(sf); - } - } - - free(pt); - - return; -} - -/* external API */ -int scm_func_tree_init(scm_function_tree_t **pt, void *priv) -{ - scm_function_tree_t *nt = __scm_func_tree_alloc(priv); - - if(!nt) return ENOENT; - else *pt = nt; - - return 0; -} - -int scm_func_tree_insert(yd_context_t *zdx, const char *name, - scret_t (*call)(yd_context_t *, sexp_t *, void *), - void *priv) -{ - scm_function_tree_t *pt = zdx->func; - usrtc_t *ftree = &(pt->functions); - scm_function_t *n_func = malloc(sizeof(scm_function_t)); - usrtc_node_t *node = NULL; - int e = 0; - - /* just check existence */ - if(!n_func) return ENOMEM; - if(usrtc_count(ftree) >= MAX_SCM_FUNCTIONS) { - e = ENOMEM; - goto __end; - } - if((node = usrtc_lookup(ftree, (const void *)name))) { - e = EEXIST; - goto __end; - } - - /* init structure */ - if(!(n_func->name = strdup(name))) { - free(n_func); - return ENOMEM; - } - n_func->call = call; - n_func->priv = priv; - node = &(n_func->node); - usrtc_node_init(node, n_func); - - /* insert to the tree */ - usrtc_insert(ftree, node, (const void *)name); - - __end: - if(e) free(n_func); - - return e; -} - -int scm_func_tree_insert_t(yd_context_t *zdx, scm_function_t *f) -{ - scm_function_tree_t *pt = zdx->func; - usrtc_t *ftree = &(pt->functions); - usrtc_node_t *node = usrtc_lookup(ftree, (const void *)f->name); - - if(node) return EEXIST; - else node = &(f->node); - if(usrtc_count(ftree) >= MAX_SCM_FUNCTIONS) return ENOMEM; - - usrtc_node_init(node, f); - usrtc_insert(ftree, node, (const void *)f->name); - - return 0; -} - -scret_t scm_func_tree_call(yd_context_t *zdx, void *cnf, sexp_t *sx, - char *name) -{ - scm_function_tree_t *pt = zdx->func; - usrtc_t *ftree = &(pt->functions); - usrtc_node_t *node = usrtc_lookup(ftree, (const void *)name); - scm_function_t *fn; - - if(!node) { - scret_t rets; - RETURN_SRET_SERR(rets, ENOENT); - } else fn = (scm_function_t *)usrtc_node_getdata(node); - - cnf = zdx; - - return fn->call(cnf, sx, fn->priv); -} - -int scm_func_tree_delete(yd_context_t *zdx, char *name) -{ - scm_function_tree_t *pt = zdx->func; - usrtc_t *ftree = &(pt->functions); - usrtc_node_t *node = usrtc_lookup(ftree, (const void *)name); - scm_function_t *fn; - - if(!node) return ENOENT; - else fn = (scm_function_t *)usrtc_node_getdata(node); - - /* remove from tree first */ - usrtc_delete(ftree, node); - - /* free */ - free(fn->name); - free(fn); - - return 0; -} diff --git a/ydaemon/idxstream.c b/ydaemon/idxstream.c deleted file mode 100644 index 9986620..0000000 --- a/ydaemon/idxstream.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include - -yd_idx_stream_t *yd_index_stream_init(void) -{ - yd_idx_stream_t *is = malloc(sizeof(yd_idx_stream_t)); - - if(!is) return NULL; - else memset(is, 0, sizeof(yd_idx_stream_t)); - - list_init_head(&is->entries_wlist); - - return is; -} - -static inline void __empty_list(list_head_t *list) -{ - list_node_t *iter, *siter; - yd_wlist_node_t *wlistnode; - - list_for_each_safe(list, iter, siter){ - wlistnode = container_of(iter, yd_wlist_node_t, node); - list_del(&wlistnode->node); - free(wlistnode); - } - - return; -} - -void yd_index_stream_destroy(yd_idx_stream_t *is) -{ - if(!is) return; - else __empty_list(&is->entries_wlist); - - free(is); - - return; -} - -void yd_index_stream_emptylist(yd_idx_stream_t *is) -{ - if(!is) return; - else __empty_list(&is->entries_wlist); - - return; -} - diff --git a/ydaemon/libydaemon.pc.in b/ydaemon/libydaemon.pc.in deleted file mode 100644 index 3f544d1..0000000 --- a/ydaemon/libydaemon.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -includedir=@includedir@ - -Name: libydaemon -Description: yet another library for daemons -Version: @LIBYDAEMON_VERSION@ -Requires: -Libs: -L${libdir} -lydaemon -Cflags: -I${includedir} diff --git a/ydaemon/log.c b/ydaemon/log.c deleted file mode 100644 index 8f8ee59..0000000 --- a/ydaemon/log.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -void ydlog(yd_context_t *ctx, int olvl, const char *fmt, ...) -{ - yd_log_t *log = ctx->logcontext; - FILE *logstr = NULL; - char tbuf[32]; - struct tm tmb; - time_t ctime; - va_list args; - - if(!log) return; - if(!(logstr = log->logstream)) return; - - if(olvl >= log->verbose_level) { /* we can output this */ - /* take a time and output this */ - time(&ctime); - localtime_r(&ctime, &tmb); - asctime_r(&tmb, tbuf); - /* remove trailing \n */ - tbuf[strlen(tbuf) - 1] = '\0'; - fprintf(logstr, "[%s] ", tbuf); - switch(olvl) { /* out prefix */ - case YL_DEBUG: fprintf(logstr, "[DEBUG] "); break; - case YL_INFO: fprintf(logstr, "[INFO] "); break; - case YL_WARN: fprintf(logstr, "[WARNING] "); break; - case YL_ERROR: fprintf(logstr, "[ERROR] "); break; - default: return; - } - - va_start(args, fmt); - vfprintf(logstr, fmt, args); - va_end(args); - } - - return; -} diff --git a/ydaemon/module.c b/ydaemon/module.c deleted file mode 100644 index ab1bba2..0000000 --- a/ydaemon/module.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -int yd_mod_add(yd_context_t *ctx, const char *name, yd_mod_type_t type) -{ - yd_mod_t *mod = malloc(sizeof(yd_mod_t)); - usrtc_node_t *node = NULL; - int r = 0; - - if(!mod) return ENOMEM; - else if(!(mod->name = strdup(name))) { - free(mod); - return ENOMEM; - } - mod->type = type; - usrtc_node_init(&mod->node, mod); - - yd_mod_ctx_wrlock(ctx); - node = usrtc_lookup(ctx->modules, mod->name); - if(node) r = EEXIST; - else usrtc_insert(ctx->modules, &mod->node, mod->name); - yd_mod_ctx_unlock(ctx); - - return r; -} - -int yd_mod_load(yd_context_t *ctx, yd_mod_t *mod) -{ - char buf[256]; - int r = 0; - - /* let's try to find it and load */ - if(!mod->pathname || !mod->name) return EINVAL; - - if(!(mod->dlhandle = dlopen(mod->pathname, RTLD_LAZY|RTLD_GLOBAL))) - return ENOENT; - - /* ok now we can resolve all symbols */ - snprintf(buf, 256, "%s_preinit", mod->prefix); - mod->preinit = dlsym(mod->dlhandle, buf); - if(!mod->preinit) { - __einval: - dlclose(mod->dlhandle); - return EINVAL; - } - - snprintf(buf, 256, "%s_init", mod->prefix); - if(!(mod->init = dlsym(mod->dlhandle, buf))) goto __einval; - snprintf(buf, 256, "%s_run", mod->prefix); - if(!(mod->run = dlsym(mod->dlhandle, buf))) goto __einval; - snprintf(buf, 256, "%s_shutdown", mod->prefix); - if(!(mod->shutdown = dlsym(mod->dlhandle, buf))) goto __einval; - snprintf(buf, 256, "%s_getobject", mod->prefix); - if(!(mod->getobject = dlsym(mod->dlhandle, buf))) goto __einval; - - if((r = mod->preinit(ctx))) { - blub; - __fail: - dlclose(mod->dlhandle); - return r; - } - - if(mod->cnfname) { - blub; - r = yd_eval_ctx(ctx, (const char *)mod->cnfname); - if(r) goto __fail; - } - - if((r = mod->init(ctx))) goto __fail; - - if(mod->type == YD_SERVICE_MUX) { - if((r = mod->run(ctx))) goto __fail; - } - - return 0; -} - -int yd_mod_get(yd_context_t *ctx, const char *name, yd_mod_t **rmod) -{ - int r = 0; - usrtc_node_t *node; - - yd_mod_ctx_rdlock(ctx); - node = usrtc_lookup(ctx->modules, name); - if(!node) r = ENOENT; - else *rmod = (yd_mod_t *)usrtc_node_getdata(node); - yd_mod_ctx_unlock(ctx); - - return r; -} - -int yd_mod_run(yd_context_t *ctx, yd_mod_t *mod) -{ - return mod->run(ctx); -} - -int yd_mod_shutdown(yd_context_t *ctx, yd_mod_t *mod) -{ - return mod->shutdown(ctx); -} - -void *yd_mod_getobject(yd_context_t *ctx, yd_mod_t *mod, - void *priv, const char *name) -{ - return mod->getobject(priv, name); -} - -void *yd_mod_getsym(yd_context_t *ctx, yd_mod_t *mod, const char *name) -{ - return dlsym(mod->dlhandle, name); -} - -/* object store */ - -static long __cmp_cstr(const void *a, const void *b) -{ - return strcmp((const char *)a, (const char *)b); -} - -#define __obs_wrlock(s) pthread_rwlock_wrlock(&((s)->rwlock)) -#define __obs_rdlock(s) pthread_rwlock_rdlock(&((s)->rwlock)) -#define __obs_unlock(s) pthread_rwlock_unlock(&((s)->rwlock)) -#define __obs_tree(s) &((s)->objects) - -int obj_store_init(obj_store_t *st) -{ - usrtc_t *tree = &st->objects; - - if(pthread_rwlock_init(&(st->rwlock), NULL)) return ENOMEM; - else usrtc_init(tree, USRTC_SPLAY, MAX_OBJECTS, __cmp_cstr); - - return 0; -} - -int obj_store_set(obj_store_t *st, const char *nm, void *od) -{ - usrtc_node_t *node = NULL; - obj_store_node_t *onode = NULL; - - __obs_rdlock(st); - node = usrtc_lookup(__obs_tree(st), nm); - __obs_unlock(st); - - if(!node) { - if(!(onode = malloc(sizeof(obj_store_node_t)))) return ENOMEM; - else memset(onode, 0, sizeof(obj_store_node_t)); - - if(!(onode->name = strdup(nm))) { - free(onode); - return ENOMEM; - } - - onode->objdata = od; - node = &(onode->node); - usrtc_node_init(node, onode); - - __obs_wrlock(st); - usrtc_insert(__obs_tree(st), node, (const void *)onode->name); - __obs_unlock(st); - } else { - onode = (obj_store_node_t *)usrtc_node_getdata(node); - - __obs_wrlock(st); - onode->objdata = od; - __obs_unlock(st); - } - - return 0; -} - -int obj_store_get(obj_store_t *st, const char *nm, void **rod) -{ - usrtc_node_t *node = NULL; - obj_store_node_t *onode = NULL; - - __obs_rdlock(st); - node = usrtc_lookup(__obs_tree(st), nm); - __obs_unlock(st); - - if(!node) return ENOENT; - else onode = (obj_store_node_t *)usrtc_node_getdata(node); - - *rod = onode->objdata; - - return 0; -} - -int obj_store_remove(obj_store_t *st, const char *nm) -{ - usrtc_node_t *node = NULL; - obj_store_node_t *onode = NULL; - - __obs_rdlock(st); - node = usrtc_lookup(__obs_tree(st), nm); - __obs_unlock(st); - - if(!node) return ENOENT; - else { - __obs_wrlock(st); - usrtc_delete(__obs_tree(st), node); - __obs_unlock(st); - - onode = (obj_store_node_t *)usrtc_node_getdata(node); - if(onode->name) free(onode->name); - free(onode); - } - - return 0; -} - diff --git a/ydaemon/values.c b/ydaemon/values.c deleted file mode 100644 index 58f6f7b..0000000 --- a/ydaemon/values.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Yet another daemon library especially designed to be used - * with libsxmp based daemons. - * - * (c) Alexander Vdolainen 2016 - * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libsxmp is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see ."; - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define _MAX_GROUPS 256 -#define _MAX_VALUES 4096 - -/* - * TODO: - * - Optimize where it possible - */ - -static long __cmp_strs(const void *a, const void *b) -{ - return strcmp((const char *)a, (const char *)b); -} - -static void __destroy_val(ydc_conf_val_t *val) -{ - if(val->on_eventv != NULL) - val->on_eventv(val, NULL, NULL, YC_EVENT_DESTROY); - - /* ok, let's begin to free all memory */ - if(val->type == SEXPR) sexp_t_deallocate((sexp_t *)val->priv); - - free(val->value); - free(val->name); - - return; -} - -static int __ydc_conf_get_val_f(ydc_conf_t *c, const char *phvar, ydc_conf_val_t **rval, - ydc_pgroup_t **rgrp) -{ - int err = 0; - int len = 0; - usrtc_t *ptree = &(c->p_groups), *tree = NULL; - usrtc_node_t *node; - char *group_name = NULL, *var_name = NULL; - ydc_conf_val_t *val = NULL; - ydc_pgroup_t *pgroup = NULL; - - /* ok, first try to understand what to do */ - if(!(var_name = strchr(phvar, '/'))) { - err = EINVAL; - goto __failure; - } else { - len = strlen(phvar) - strlen(var_name); - if(!(group_name = strndup(phvar, len))) { - err = ENOMEM; - goto __failure; - } - if(!(node = usrtc_lookup(ptree, (const void *)group_name))) { - err = ENOENT; - goto __failure; - } else { - pgroup = (ydc_pgroup_t *)usrtc_node_getdata(node); - pthread_rwlock_rdlock(&(pgroup->val_lock)); - } - } - free(group_name); - /* we should know the value name now */ - var_name += sizeof(char); - - tree = &(pgroup->values); - if(!(node = usrtc_lookup(tree, (const void *)var_name))) { - err = ENOENT; - goto __failure_1; - } - val = (ydc_conf_val_t *)usrtc_node_getdata(node); - - /* fill this */ - if(rval) *rval = val; - if(rgrp) *rgrp = pgroup; - - __failure_1: - pthread_rwlock_unlock(&(pgroup->val_lock)); - __failure: - return err; -} - -int ydc_conf_init(ydc_conf_t *c) -{ - int err = ENOMEM; - usrtc_t *tree = &(c->p_groups); - - /* zero all to keep it simple as possible */ - memset(c, 0, sizeof(ydc_conf_t)); - /* init locking */ - if(pthread_rwlock_init(&(c->grp_lock), NULL)) goto __fail_0; - if(pthread_mutex_init(&(c->conf_lock), NULL)) goto __fail_0_1; - - /* initialize tree structure */ - usrtc_init(tree, USRTC_SPLAY, _MAX_GROUPS, __cmp_strs); - - return 0; - - __fail_0_1: - pthread_rwlock_destroy(&(c->grp_lock)); - __fail_0: - return err; -} - -int ydc_conf_create_pgroup(ydc_conf_t *c, char *nm) -{ - int err = ENOMEM; - ydc_pgroup_t *pg = malloc(sizeof(ydc_pgroup_t)); - usrtc_t *tree = NULL, *ptree = &(c->p_groups); - usrtc_node_t *node = NULL; - - /* initialize */ - if(!pg) { - err = ENOMEM; - goto __failure; - } else if(!(pg->name = strdup(nm))){ - err = ENOMEM; - goto __failure_1; - } - /* check availability */ - /* from here we will lock conf */ - pthread_rwlock_wrlock(&(c->grp_lock)); - if((node = usrtc_lookup(ptree, (const void *)nm))) { - err = EEXIST; - goto __failure_2; - } - if(usrtc_count(ptree) >= _MAX_GROUPS) { - err = ENOMEM; - goto __failure_2; - } - /* init rwlock */ - if(pthread_rwlock_init(&(pg->val_lock), NULL)) { - err = ENOMEM; - goto __failure_2; - } - - /* init tree structures */ - tree = &(pg->values); - node = &(pg->unode); - usrtc_init(tree, USRTC_SPLAY, _MAX_VALUES, __cmp_strs); - usrtc_node_init(node, pg); - /* insert */ - usrtc_insert(ptree, node, pg->name); - - pthread_rwlock_unlock(&(c->grp_lock)); - - return 0; - - __failure_2: - pthread_rwlock_unlock(&(c->grp_lock)); - __failure_1: - free(pg); - __failure: - return err; -} - -int ydc_conf_destroy_pgroup(ydc_conf_t *c, char *nm, int force) -{ - int err = 0; - usrtc_t *ptree = &(c->p_groups), *tree; - usrtc_node_t *node = NULL, *nn = NULL; - ydc_pgroup_t *pg = NULL; - ydc_conf_val_t *val = NULL; - - /* take an rwlock for write due to the our sirection to write somethings */ - pthread_rwlock_wrlock(&(c->grp_lock)); - node = usrtc_lookup(ptree, (const void *)nm); - if(!node) { - pthread_rwlock_unlock(&(c->grp_lock)); - return ENOENT; - } else { - pg = (ydc_pgroup_t *)usrtc_node_getdata(node); - tree = &(pg->values); - pthread_rwlock_rdlock(&(pg->val_lock)); - } - - if(!force && usrtc_count(tree)) { - pthread_rwlock_unlock(&(c->grp_lock)); - pthread_rwlock_unlock(&(pg->val_lock)); - return ENOTEMPTY; /* auuhh ... */ - } - /* let's retake lock */ - pthread_rwlock_unlock(&(pg->val_lock)); - pthread_rwlock_wrlock(&(pg->val_lock)); - - /* remove from the tree */ - usrtc_delete(ptree, node); - pthread_rwlock_unlock(&(c->grp_lock)); - - for(nn = usrtc_first(tree); nn != NULL; nn = usrtc_first(tree)) { - val = usrtc_node_getdata(nn); - __destroy_val(val); - usrtc_delete(tree, nn); - } - - /* free all */ - pthread_rwlock_unlock(&(pg->val_lock)); - pthread_rwlock_destroy(&(pg->val_lock)); - free(pg->name); - free(pg); - - return err; -} - -int ydc_conf_add_val_p(ydc_conf_t *c, const char *phvar, int cstr) -{ - int err = 0; - int len = 0, p1 = 0, p2 = 0; - unsigned long siv = 0; unsigned long uiv = 0; - usrtc_t *ptree = &(c->p_groups), *tree = NULL; - usrtc_node_t *node; - char *grp_name, *val_name, *value; - ydc_pgroup_t *pg = NULL; - ydc_conf_val_t *val = malloc(sizeof(ydc_conf_val_t)), *oldval = NULL; - - if(!val) return ENOMEM; - else memset(val, 0, sizeof(ydc_conf_val_t)); - - /* take the path, group name first */ - if(!(val_name = strchr(phvar, '/'))) { - err = EINVAL; - goto __failure; - } else { - grp_name = val_name; - len = strlen(phvar) - strlen(grp_name); - if(!(grp_name = strndup(phvar, len))) { /* we got it */ - err = ENOMEM; - goto __failure; - } else { - /* looking for existence of the group */ - pthread_rwlock_rdlock(&(c->grp_lock)); - node = usrtc_lookup(ptree, (const void *)grp_name); free(grp_name); - pthread_rwlock_unlock(&(c->grp_lock)); - if(!node) { - err = ENOENT; goto __failure; - } else { - pg = (ydc_pgroup_t *)usrtc_node_getdata(node); - pthread_rwlock_wrlock(&(pg->val_lock)); /* we apologize to change something */ - } - tree = &(pg->values); - - /* get the value name */ - if(!(value = strchr(val_name, ':'))) { - err = EINVAL; goto __failure_0; - } else { - len = (strlen(val_name) - strlen(value)) - sizeof(char); - if(!(val_name = strndup(val_name + sizeof(char), len))) { /* gotcha ! */ - err = ENOMEM; goto __failure_0; - } else if(!(value = strdup(value + sizeof(char)))) { /* take the value itself */ - free(val_name); err = ENOMEM; goto __failure_0; - } - - /* check out if we're have one */ - if((node = usrtc_lookup(tree, (const void *)val_name))) { /* oops, then remove */ - oldval = (ydc_conf_val_t *)usrtc_node_getdata(node); - usrtc_delete(tree, node); - } - if(usrtc_count(tree) >= _MAX_VALUES) { /* know your limits (c) British ale and beer stickers */ - err = ENOMEM; - goto __failure_1; - } - /* ok, here we can create a new value */ - /* detect the type */ - len = strlen(value); - /* first for long values */ - if(isdigit(value[0]) || (isdigit(value[1]) && (value[0] == '-'))) { /* looks like a digit */ - if(value[0] == '-') { /* signed should be used */ - if(len > 9) val->type = LONG; - else val->type = INT; - } else { - if(len > 9) val->type = ULONG; - else val->type = UINT; - } - } else if(value[0] == '(' && value[len - 1] == ')') { /* might be a sexp */ - /* first, we must count parentes */ - for(grp_name = strchr(value, '('); grp_name != NULL; - grp_name = strchr(grp_name + sizeof(char), '(')) - p1++; - for(grp_name = strchr(value, ')'); grp_name != NULL; - grp_name = strchr(grp_name + sizeof(char), ')')) - p2++; - - if(p1 != p2) val->type = STRING; /* looks like string */ - else if((grp_name = strchr(value, ' '))) val->type = SEXPR; /* should be at least one space */ - else val->type = STRING; - } else - val->type = STRING; - - /* if forced cstring */ - if(cstr) val->type = STRING; - - /* let's decide what to do */ - switch(val->type) { - case STRING: - val->len = len + sizeof(char); - val->value = (void *)value; - break; - case INT: - case LONG: - val->len = sizeof(unsigned long); - if(!(val->value = malloc(sizeof(unsigned long)))) { - err = ENOMEM; - goto __failure_2; - } - siv = strtoll(value, NULL, 0); - *(long *)val->value = siv; -#if 0 /* FIXME: */ - if((siv != MAXINT64) || (siv != G_MININT64)) { - *(gint64 *)val->value = siv; - } else { - g_free(val->value); - err = EINVAL; - goto __failure_2; - } -#endif - free(value); - break; - case UINT: - case ULONG: - val->len = sizeof(unsigned long); - if(!(val->value = malloc(sizeof(unsigned long)))) { - err = ENOMEM; - goto __failure_2; - } - uiv = strtoull(value, NULL, 0); - *(unsigned long *)val->value = uiv; -#if 0 - if(uiv != G_MAXUINT64) { - *(guint64 *)val->value = uiv; - } else { - g_free(val->value); - err = EINVAL; - goto __failure_2; - } -#endif - free(value); - break; - case SEXPR: - val->len = len; - val->value = value; - if(!(val->priv = (void *)parse_sexp(value, len))) { - errno = EINVAL; - goto __failure_2; - } - break; - default: /* just to keep gcc happy */ - break; - } - - val->name = val_name; - /* well, init tree and other stuff */ - node = &(val->unode); - usrtc_node_init(node, val); - usrtc_insert(tree, node, (const void *)val->name); - if(oldval) { - if(oldval->on_eventv) { - oldval->on_eventv(val, oldval, c, YC_EVENT_MODIFY); - val->on_eventv = oldval->on_eventv; - } - __destroy_val(oldval); - free(oldval); - } - } - } - - } - - pthread_rwlock_unlock(&(pg->val_lock)); - - return 0; - - __failure_2: - if(oldval) { - node = &(oldval->unode); - usrtc_insert(tree, node, (const void *)oldval->name); - } - __failure_1: - free(val_name); - free(value); - __failure_0: - pthread_rwlock_unlock(&(pg->val_lock)); - __failure: - free(val); - return err; -} - -int ydc_conf_rm_val(ydc_conf_t *c, const char *phvar) -{ - int err = 0; - usrtc_node_t *node; - usrtc_t *tree; - ydc_conf_val_t *val = NULL; - ydc_pgroup_t *pgroup = NULL; - - pthread_rwlock_rdlock(&(c->grp_lock)); - if((err = __ydc_conf_get_val_f(c, phvar, &val, &pgroup))) goto __failure; - - /* delete it */ - pthread_rwlock_wrlock(&(pgroup->val_lock)); - tree = &(pgroup->values); - node = &(val->unode); - usrtc_delete(tree, node); - pthread_rwlock_unlock(&(pgroup->val_lock)); - __destroy_val(val); - free(val); - - __failure: - pthread_rwlock_unlock(&(c->grp_lock)); - return err; -} - -int ydc_conf_get_val(ydc_conf_t *c, const char *phvar, ydc_conf_val_t **rval) -{ - int err = 0; - ydc_conf_val_t *val = NULL; - - pthread_rwlock_rdlock(&(c->grp_lock)); - if((err = __ydc_conf_get_val_f(c, phvar, &val, NULL))) goto __failure; - - /* fill this */ - *rval = val; - - __failure: - pthread_rwlock_unlock(&(c->grp_lock)); - return err; -} - -/* more code, but faster than double search */ -void ydc_conf_destroy(ydc_conf_t *c) -{ - usrtc_t *ptree = &(c->p_groups), *tree; - usrtc_node_t *node, *nnode; - ydc_pgroup_t *grp; - ydc_conf_val_t *val; - - /* lock for all operations */ - pthread_mutex_lock(&(c->conf_lock)); - pthread_rwlock_wrlock(&(c->grp_lock)); - - if(!usrtc_count(ptree)) goto __e_out; /* all is clean*/ - /* well let's clean all groups */ - for(node = usrtc_first(ptree); node != NULL; node = usrtc_first(ptree)) { - grp = (ydc_pgroup_t *)usrtc_node_getdata(node); - pthread_rwlock_wrlock(&(grp->val_lock)); - - tree = &(grp->values); - if(usrtc_count(tree)) { - for(nnode = usrtc_first(tree); nnode != NULL; nnode = usrtc_first(tree)) { - val = (ydc_conf_val_t *)usrtc_node_getdata(nnode); - __destroy_val(val); - usrtc_delete(tree, nnode); - free(val); - } - } - usrtc_delete(ptree, node); - pthread_rwlock_destroy(&(grp->val_lock)); - free(grp->name); - free(grp); - } - - __e_out: - pthread_mutex_destroy(&(c->conf_lock)); - pthread_rwlock_destroy(&(c->grp_lock)); - - /* secure */ - memset(c, 0, sizeof(ydc_conf_t)); - - free(c); - return; -} - -int ydc_conf_val_attach_event(ydc_conf_t *c, const char *phvar, - void (*on_eventv)(struct __ym_conf_value *, - struct __ym_conf_value *, - ydc_conf_t *, ydc_event_t)) -{ - int err = 0; - ydc_conf_val_t *val = NULL; - ydc_pgroup_t *grp; - - pthread_rwlock_rdlock(&(c->grp_lock)); - if((err = __ydc_conf_get_val_f(c, phvar, &val, &grp))) goto __failure; - - pthread_rwlock_wrlock(&(grp->val_lock)); - /* attach callback */ - val->on_eventv = on_eventv; - val->on_eventv(val, NULL, c, YC_EVENT_ATTACH); /* yep, it's an event */ - - pthread_rwlock_unlock(&(grp->val_lock)); - - __failure: - pthread_rwlock_unlock(&(c->grp_lock)); - return err; -} - -int ydc_conf_modify_val(ydc_conf_t *c, const char *phvar, void *data, int len) -{ - ydc_conf_val_t *val; - ydc_pgroup_t *grp; - char *t = NULL; - void *tb = NULL; - sexp_t *nsexp = NULL; - int err = 0; - - pthread_rwlock_rdlock(&(c->grp_lock)); - if((err = __ydc_conf_get_val_f(c, phvar, &val, &grp))) goto __failure; - pthread_rwlock_unlock(&(c->grp_lock)); - - /* take group lock */ - pthread_rwlock_wrlock(&(grp->val_lock)); - - switch(val->type) { - case STRING: - t = val->value; - if(!(val->value = strndup((const char *)data, len))) { - err = ENOMEM; - val->value = t; - goto __failure_1; - } else free(t); - break; - case INT: - case LONG: - *(long *)val->value = *(long *)data; - break; - case ULONG: - case UINT: - *(unsigned long *)val->value = *(unsigned long *)data; - break; - case CUSTOM: /* that means we must call event callback before data change also */ - if(val->on_eventv) - val->on_eventv(val, val, c, YC_EVENT_MODIFY); /* oldval is val, since it pre call */ - case BLOB: - tb = val->value; - if(!(val->value = malloc(len))) { - err = ENOMEM; - val->value = tb; - goto __failure_1; - } else memcpy(data, val->value, len); - free(tb); - break; - case SEXPR: - t = val->value; - if(!(val->value = strndup((const char *)data, len))) { - err = ENOMEM; - val->value = t; - goto __failure_1; - } - if(!(nsexp = parse_sexp(val->value, len))) { - err = EINVAL; - val->value = t; - goto __failure_1; - } else { /* change it */ - free(t); - sexp_t_deallocate((sexp_t *)val->priv); - val->priv = (void *)nsexp; - } - break; - } - - /* well, run callback if exists */ - if(val->on_eventv) - val->on_eventv(val, NULL, c, YC_EVENT_MODIFY); /* oldval is nil, incdicate - * post event for CUSTOM type - */ - __failure_1: - pthread_rwlock_unlock(&(grp->val_lock)); - return err; - - __failure: - pthread_rwlock_unlock(&(c->grp_lock)); - return err; -} - -int ydc_conf_clone_val(ydc_conf_val_t *s, ydc_conf_val_t *c) -{ - int e = 0; - - /* zeroing for our clone */ - memset(c, 0, sizeof(ydc_conf_val_t)); - - /* clone name and data */ - if((c->name = strdup(s->name))) { - e = ENOMEM; goto __fail; - } - if(!(c->value = malloc(s->len))) { - free(c->name); e = ENOMEM; goto __fail; - } else - memcpy(c->value, s->value, s->len); - /* clone others */ - c->type = s->type; - c->priv = s->priv; - - __fail: - return e; -} - -void ydc_conf_val_destroy_clone(ydc_conf_val_t *c) -{ - free(c->name); - free(c->value); - - /* this function will not free structure itself, instead we will - * zero all stuff within structure, since we don't know how it was allocated, - * it's better to be sure about cloned data */ - memset(c, 0, sizeof(ydc_conf_val_t)); - - return; -}