mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Define memhead list inside bbf context structure
This commit is contained in:
parent
72ad1ac91a
commit
b0614ecfd3
12 changed files with 390 additions and 105 deletions
|
|
@ -45,9 +45,10 @@ extern struct list_head json_memhead;
|
|||
|
||||
LIST_HEAD(head_registered_service);
|
||||
|
||||
static void register_periodic_timers(struct ubus_context *ctx);
|
||||
static void cancel_periodic_timers(struct ubus_context *ctx);
|
||||
static void run_schema_updater(struct bbfdm_context *u);
|
||||
static void periodic_instance_updater(struct uloop_timeout *t);
|
||||
static void register_instance_refresh_timer(struct ubus_context *ctx, int start_sec);
|
||||
|
||||
// Global variables
|
||||
static void *deamon_lib_handle = NULL;
|
||||
|
|
@ -583,6 +584,7 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
cancel_periodic_timers(ctx);
|
||||
trans_id = transaction_start(&data, "INT_SET", 0);
|
||||
if (trans_id == 0) {
|
||||
WARNING("Failed to get the lock for the transaction");
|
||||
|
|
@ -595,6 +597,7 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
register_instance_refresh_timer(ctx, 100);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
|
|
@ -703,6 +706,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
cancel_periodic_timers(ctx);
|
||||
trans_id = transaction_start(&data, "INT_ADD", 0);
|
||||
if (trans_id == 0) {
|
||||
ERR("Failed to get the lock for the transaction");
|
||||
|
|
@ -717,6 +721,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to abort the changes
|
||||
register_instance_refresh_timer(ctx, 0);
|
||||
transaction_abort(NULL, trans_id);
|
||||
}
|
||||
|
||||
|
|
@ -735,6 +740,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to abort the changes
|
||||
register_instance_refresh_timer(ctx, 0);
|
||||
transaction_abort(NULL, trans_id);
|
||||
}
|
||||
|
||||
|
|
@ -751,6 +757,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
register_instance_refresh_timer(ctx, 100);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
|
|
@ -826,6 +833,7 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
cancel_periodic_timers(ctx);
|
||||
trans_id = transaction_start(&data, "INT_DEL", 0);
|
||||
if (trans_id == 0) {
|
||||
WARNING("Failed to get the lock for the transaction");
|
||||
|
|
@ -838,6 +846,7 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
register_instance_refresh_timer(ctx, 100);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
|
|
@ -915,11 +924,11 @@ static int bbfdm_transaction_handler(struct ubus_context *ctx, struct ubus_objec
|
|||
transaction_status(&data.bb);
|
||||
}
|
||||
} else if (is_str_eq(trans_cmd, "commit")) {
|
||||
register_periodic_timers(ctx);
|
||||
register_instance_refresh_timer(ctx, 100);
|
||||
ret = transaction_commit(&data, data.trans_id, is_service_restart);
|
||||
blobmsg_add_u8(&data.bb, "status", (ret == 0));
|
||||
} else if (is_str_eq(trans_cmd, "abort")) {
|
||||
register_periodic_timers(ctx);
|
||||
register_instance_refresh_timer(ctx, 0);
|
||||
ret = transaction_abort(&data, data.trans_id);
|
||||
blobmsg_add_u8(&data.bb, "status", (ret == 0));
|
||||
} else if (is_str_eq(trans_cmd, "status")) {
|
||||
|
|
@ -1185,7 +1194,6 @@ static void update_instances_list(struct list_head *inst)
|
|||
bbf_cleanup(&bbf_ctx);
|
||||
}
|
||||
|
||||
static void periodic_instance_updater(struct uloop_timeout *t);
|
||||
static void instance_fork_done(struct uloop_process *p, int ret)
|
||||
{
|
||||
struct bbfdm_async_req *r = container_of(p, struct bbfdm_async_req, process);
|
||||
|
|
@ -1251,6 +1259,7 @@ static int fork_instance_checker(struct bbfdm_context *u)
|
|||
}
|
||||
child = fork();
|
||||
if (child == 0) {
|
||||
INFO("{fork} Instances checker entry");
|
||||
prctl(PR_SET_NAME, (unsigned long) "bbfdm_instance");
|
||||
// child initialise signal to prevent segfaults
|
||||
signal_init();
|
||||
|
|
@ -1262,10 +1271,10 @@ static int fork_instance_checker(struct bbfdm_context *u)
|
|||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
|
||||
DEBUG("subprocess instances checker");
|
||||
instance_compare_publish(u);
|
||||
bbfdm_cleanup(u);
|
||||
closelog();
|
||||
INFO("{fork} Instances checker exit");
|
||||
/* write result and exit */
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
@ -1306,17 +1315,30 @@ static void periodic_instance_updater(struct uloop_timeout *t)
|
|||
return;
|
||||
}
|
||||
|
||||
if (list_empty(&u->instances)) {
|
||||
if (!list_empty(&u->old_instances)) {
|
||||
list_splice_init(&u->old_instances, &u->instances);
|
||||
} else {
|
||||
update_instances_list(&u->instances);
|
||||
DEBUG("Creating timer for instance update checker, init instances");
|
||||
u->instance_timer.cb = periodic_instance_updater;
|
||||
uloop_timeout_set(&u->instance_timer, u->config.refresh_time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
free_path_list(&u->old_instances);
|
||||
list_splice_init(&u->instances, &u->old_instances);
|
||||
update_instances_list(&u->instances);
|
||||
|
||||
if (list_empty(&u->instances)) {
|
||||
update_instances_list(&u->instances);
|
||||
DEBUG("Creating timer for instance update checker, init instances");
|
||||
WARNING("Failed to get current instances, restart the timer");
|
||||
u->instance_timer.cb = periodic_instance_updater;
|
||||
uloop_timeout_set(&u->instance_timer, u->config.refresh_time);
|
||||
return;
|
||||
}
|
||||
|
||||
list_splice_init(&u->instances, &u->old_instances);
|
||||
update_instances_list(&u->instances);
|
||||
|
||||
// fork a process and send it to compare, when process completes
|
||||
// delete the old instances and add a new timer
|
||||
fork_instance_checker(u);
|
||||
|
|
@ -1569,9 +1591,10 @@ static void cancel_periodic_timers(struct ubus_context *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void register_periodic_timers(struct ubus_context *ctx)
|
||||
static void register_instance_refresh_timer(struct ubus_context *ctx, int start_in)
|
||||
{
|
||||
struct bbfdm_context *u;
|
||||
unsigned refresh_time = 0;
|
||||
|
||||
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
|
||||
if (u == NULL) {
|
||||
|
|
@ -1579,10 +1602,16 @@ static void register_periodic_timers(struct ubus_context *ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
DEBUG("Register instance_timer %d", u->config.refresh_time);
|
||||
if (start_in <= 0) {
|
||||
refresh_time = u->config.refresh_time;
|
||||
} else {
|
||||
refresh_time = start_in;
|
||||
}
|
||||
|
||||
DEBUG("Register instance refresh timer in %d ms...", refresh_time);
|
||||
if (u->config.refresh_time != 0) {
|
||||
u->instance_timer.cb = periodic_instance_updater;
|
||||
uloop_timeout_set(&u->instance_timer, u->config.refresh_time);
|
||||
uloop_timeout_set(&u->instance_timer, refresh_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1716,12 +1745,13 @@ int main(int argc, char **argv)
|
|||
ubus_add_uloop(&bbfdm_ctx.ubus_ctx);
|
||||
ubus_init_done = true;
|
||||
|
||||
periodic_instance_updater(&bbfdm_ctx.instance_timer);
|
||||
err = bbfdm_regiter_ubus(&bbfdm_ctx.ubus_ctx);
|
||||
if (err != UBUS_STATUS_OK)
|
||||
goto exit;
|
||||
|
||||
run_schema_updater(&bbfdm_ctx);
|
||||
register_instance_refresh_timer(&bbfdm_ctx.ubus_ctx, 1000);
|
||||
|
||||
if (is_micro_service == false) { // It's not a micro-service instance
|
||||
err = register_events_to_ubus(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers);
|
||||
if (err != 0)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "plugin/json_plugin.h"
|
||||
|
||||
extern struct list_head global_memhead;
|
||||
static LIST_HEAD(plugin_mem);
|
||||
|
||||
int load_dotso_plugin(void **lib_handle, const char *file_path,
|
||||
DMOBJ **main_entry,
|
||||
|
|
@ -34,13 +34,15 @@ int load_dotso_plugin(void **lib_handle, const char *file_path,
|
|||
return -1;
|
||||
}
|
||||
|
||||
dm_dynamic_initmem(&plugin_mem);
|
||||
|
||||
*lib_handle = handle;
|
||||
|
||||
//Dynamic Object
|
||||
DM_MAP_OBJ *dynamic_obj = NULL;
|
||||
*(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj");
|
||||
if (dynamic_obj) {
|
||||
char *node_obj = dm_dynamic_strdup(&global_memhead, dynamic_obj[0].path);
|
||||
char *node_obj = dm_dynamic_strdup(&plugin_mem, dynamic_obj[0].path);
|
||||
unsigned int len = strlen(node_obj);
|
||||
|
||||
if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') {
|
||||
|
|
@ -48,7 +50,7 @@ int load_dotso_plugin(void **lib_handle, const char *file_path,
|
|||
return -1;
|
||||
}
|
||||
|
||||
DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&global_memhead, 2, sizeof(DMOBJ));
|
||||
DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&plugin_mem, 2, sizeof(DMOBJ));
|
||||
if (dm_entryobj == NULL) {
|
||||
ERR("No Memory exists\n");
|
||||
return -1;
|
||||
|
|
@ -91,6 +93,7 @@ int free_dotso_plugin(void *lib_handle)
|
|||
if (lib_handle)
|
||||
dlclose(lib_handle);
|
||||
|
||||
dm_dynamic_cleanmem(&plugin_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ struct dmctx {
|
|||
int (*checkobj)(DMOBJECT_ARGS);
|
||||
int (*checkleaf)(DMOBJECT_ARGS);
|
||||
struct list_head list_parameter;
|
||||
struct list_head *memhead;
|
||||
DMOBJ *dm_entryobj;
|
||||
DM_MAP_VENDOR *dm_vendor_extension[2];
|
||||
DM_MAP_VENDOR_EXCLUDE *dm_vendor_extension_exclude;
|
||||
|
|
|
|||
|
|
@ -183,18 +183,6 @@ enum option_type_enum {
|
|||
if ((dir = opendir(path)) == NULL) return 0; \
|
||||
while ((ent = readdir(dir)) != NULL) \
|
||||
|
||||
#define sysfs_foreach_file_sorted(path,max_num_files) \
|
||||
struct dirent *ent = NULL; \
|
||||
DIR *dir = NULL; \
|
||||
if ((dir = opendir(path)) == NULL) return 0; \
|
||||
int num_files = 0; \
|
||||
char *files[max_num_files]; \
|
||||
while ((ent = readdir(dir)) != NULL && num_files < max_num_files) \
|
||||
files[num_files++] = dmstrdup(ent->d_name); \
|
||||
closedir(dir); \
|
||||
qsort(files, num_files, sizeof(char*), compare_strings); \
|
||||
for (int i = 0; i < num_files; i++)
|
||||
|
||||
struct dmmap_sect {
|
||||
struct list_head list;
|
||||
char *section_name;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj,
|
|||
ctx->dm_vendor_extension[0] = tVendorExtension ? tVendorExtension[0] : NULL;
|
||||
ctx->dm_vendor_extension[1] = tVendorExtension ? tVendorExtension[1] : NULL;
|
||||
ctx->dm_vendor_extension_exclude = tVendorExtensionExclude;
|
||||
bbfdm_init_mem(ctx);
|
||||
dm_uci_init();
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ void bbf_ctx_clean(struct dmctx *ctx)
|
|||
|
||||
dm_uci_exit();
|
||||
dmubus_free();
|
||||
dmcleanmem();
|
||||
bbfdm_clean_mem(ctx);
|
||||
}
|
||||
|
||||
void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj,
|
||||
|
|
@ -251,6 +252,7 @@ int bbf_entry_method(struct dmctx *ctx, int cmd)
|
|||
|
||||
void bbf_global_init(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, const char *plugin_path)
|
||||
{
|
||||
dm_dynamic_initmem(&global_memhead);
|
||||
load_plugins(dm_entryobj, dm_VendorExtension,dm_VendorExtensionExclude, plugin_path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,28 +9,70 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "dmbbf.h"
|
||||
#include "dmmem.h"
|
||||
|
||||
LIST_HEAD(memhead);
|
||||
#define CHECK_MEM_LIST(mem_list) \
|
||||
do { \
|
||||
if (mem_list == NULL) { \
|
||||
TRACE("mem_list is not initialized !!!"); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
inline void *__dmmalloc(struct list_head *mem_list, size_t size)
|
||||
struct dmmem {
|
||||
struct list_head list;
|
||||
char mem[0];
|
||||
};
|
||||
|
||||
void __dminitmem(struct list_head *mem_list)
|
||||
{
|
||||
INIT_LIST_HEAD(mem_list);
|
||||
}
|
||||
|
||||
void __dmcleanmem(struct list_head *mem_list)
|
||||
{
|
||||
struct dmmem *dmm;
|
||||
while (mem_list->next != mem_list) {
|
||||
dmm = list_entry(mem_list->next, struct dmmem, list);
|
||||
list_del(&dmm->list);
|
||||
FREE(dmm);
|
||||
}
|
||||
}
|
||||
|
||||
void dmfree(void *m)
|
||||
{
|
||||
if (m == NULL) return;
|
||||
struct dmmem *rm;
|
||||
rm = container_of(m, struct dmmem, mem);
|
||||
list_del(&rm->list);
|
||||
FREE(rm);
|
||||
}
|
||||
|
||||
void *__dmmalloc(struct list_head *mem_list, size_t size)
|
||||
{
|
||||
CHECK_MEM_LIST(mem_list);
|
||||
|
||||
struct dmmem *m = malloc(sizeof(struct dmmem) + size);
|
||||
if (m == NULL) return NULL;
|
||||
list_add(&m->list, mem_list);
|
||||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
inline void *__dmcalloc(struct list_head *mem_list, int n, size_t size)
|
||||
void *__dmcalloc(struct list_head *mem_list, int n, size_t size)
|
||||
{
|
||||
CHECK_MEM_LIST(mem_list);
|
||||
|
||||
struct dmmem *m = calloc(n, sizeof(struct dmmem) + size);
|
||||
if (m == NULL) return NULL;
|
||||
list_add(&m->list, mem_list);
|
||||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
inline void *__dmrealloc(struct list_head *mem_list, void *n, size_t size)
|
||||
void *__dmrealloc(struct list_head *mem_list, void *n, size_t size)
|
||||
{
|
||||
CHECK_MEM_LIST(mem_list);
|
||||
|
||||
struct dmmem *m = NULL;
|
||||
if (n != NULL) {
|
||||
m = container_of(n, struct dmmem, mem);
|
||||
|
|
@ -49,25 +91,6 @@ inline void *__dmrealloc(struct list_head *mem_list, void *n, size_t size)
|
|||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
inline void dmfree(void *m)
|
||||
{
|
||||
if (m == NULL) return;
|
||||
struct dmmem *rm;
|
||||
rm = container_of(m, struct dmmem, mem);
|
||||
list_del(&rm->list);
|
||||
free(rm);
|
||||
}
|
||||
|
||||
inline void __dmcleanmem(struct list_head *mem_list)
|
||||
{
|
||||
struct dmmem *dmm;
|
||||
while (mem_list->next != mem_list) {
|
||||
dmm = list_entry(mem_list->next, struct dmmem, list);
|
||||
list_del(&dmm->list);
|
||||
free(dmm);
|
||||
}
|
||||
}
|
||||
|
||||
char *__dmstrdup(struct list_head *mem_list, const char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
|
|
@ -97,7 +120,7 @@ int __dmasprintf(struct list_head *mem_list, char **s, const char *format, ...)
|
|||
|
||||
*s = __dmstrdup(mem_list, str);
|
||||
|
||||
free(str);
|
||||
FREE(str);
|
||||
if (*s == NULL)
|
||||
return -1;
|
||||
|
||||
|
|
@ -118,3 +141,166 @@ int __dmastrcat(struct list_head *mem_list, char **s, char *obj, char *lastname)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* New BBFDM Memory Management APIs
|
||||
*
|
||||
*/
|
||||
static struct list_head *dm_memhead_ptr = NULL;
|
||||
|
||||
static struct list_head *get_ctx_memhead_list(struct dmctx *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
if (!dm_memhead_ptr) {
|
||||
TRACE("'ctx->mem_head' and 'dm_memhead_ptr' are not initialized! You should initialize 'ctx->mem_head' before using bbfdm memory APIs");
|
||||
return NULL;
|
||||
}
|
||||
return dm_memhead_ptr;
|
||||
}
|
||||
|
||||
if (!ctx->memhead) {
|
||||
TRACE("'ctx->mem_head' is not initialized! You should initialize 'ctx->mem_head' before using bbfdm memory APIs");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx->memhead;
|
||||
}
|
||||
|
||||
void bbfdm_init_mem(struct dmctx *ctx)
|
||||
{
|
||||
struct list_head *memory_list_head = calloc(1, sizeof(struct list_head));
|
||||
|
||||
// Check if memory allocation was successful
|
||||
if (memory_list_head == NULL) {
|
||||
TRACE("Failed to allocate memory for the list head!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the list head
|
||||
INIT_LIST_HEAD(memory_list_head);
|
||||
|
||||
ctx->memhead = dm_memhead_ptr = memory_list_head;
|
||||
}
|
||||
|
||||
void bbfdm_clean_mem(struct dmctx *ctx)
|
||||
{
|
||||
struct dmmem *dmm = NULL;
|
||||
|
||||
if (ctx->memhead == NULL) {
|
||||
TRACE("Memory list is NULL!");
|
||||
return;
|
||||
}
|
||||
|
||||
while (ctx->memhead->next != ctx->memhead) {
|
||||
dmm = list_entry(ctx->memhead->next, struct dmmem, list);
|
||||
list_del(&dmm->list);
|
||||
FREE(dmm);
|
||||
}
|
||||
|
||||
FREE(ctx->memhead);
|
||||
dm_memhead_ptr = NULL;
|
||||
}
|
||||
|
||||
void *bbfdm_malloc(struct dmctx *ctx, size_t size)
|
||||
{
|
||||
struct list_head *ctx_memhead = get_ctx_memhead_list(ctx);
|
||||
if (ctx_memhead == NULL)
|
||||
return NULL;
|
||||
|
||||
struct dmmem *m = malloc(sizeof(struct dmmem) + size);
|
||||
if (m == NULL) return NULL;
|
||||
list_add(&m->list, ctx_memhead);
|
||||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
void *bbfdm_calloc(struct dmctx *ctx, int n, size_t size)
|
||||
{
|
||||
struct list_head *ctx_memhead = get_ctx_memhead_list(ctx);
|
||||
if (ctx_memhead == NULL)
|
||||
return NULL;
|
||||
|
||||
struct dmmem *m = calloc(n, sizeof(struct dmmem) + size);
|
||||
if (m == NULL) return NULL;
|
||||
list_add(&m->list, ctx_memhead);
|
||||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
void *bbfdm_realloc(struct dmctx *ctx, void *n, size_t size)
|
||||
{
|
||||
struct list_head *ctx_memhead = get_ctx_memhead_list(ctx);
|
||||
if (ctx_memhead == NULL)
|
||||
return NULL;
|
||||
|
||||
struct dmmem *m = NULL;
|
||||
if (n != NULL) {
|
||||
m = container_of(n, struct dmmem, mem);
|
||||
list_del(&m->list);
|
||||
}
|
||||
|
||||
struct dmmem *new_m = realloc(m, sizeof(struct dmmem) + size);
|
||||
if (new_m == NULL) {
|
||||
dmfree(m);
|
||||
return NULL;
|
||||
} else {
|
||||
m = new_m;
|
||||
}
|
||||
|
||||
list_add(&m->list, ctx_memhead);
|
||||
return (void *)m->mem;
|
||||
}
|
||||
|
||||
char *bbfdm_strdup(struct dmctx *ctx, const char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
size_t len = strlen(s) + 1;
|
||||
void *new = bbfdm_malloc(ctx, len);
|
||||
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
return (char *) memcpy(new, s, len);
|
||||
}
|
||||
|
||||
int bbfdm_asprintf(struct dmctx *ctx, char **s, const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
char *str = NULL;
|
||||
int size = 0;
|
||||
|
||||
va_start(arg, format);
|
||||
size = vasprintf(&str, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (size < 0 || str == NULL)
|
||||
return -1;
|
||||
|
||||
*s = bbfdm_strdup(ctx, str);
|
||||
|
||||
FREE(str);
|
||||
if (*s == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bbfdm_astrcat(struct dmctx *ctx, char **s, char *obj, char *lastname)
|
||||
{
|
||||
char buf[2048] = {0};
|
||||
|
||||
if (obj == NULL || lastname == NULL)
|
||||
return -1;
|
||||
|
||||
int olen = strlen(obj);
|
||||
memcpy(buf, obj, olen);
|
||||
int llen = strlen(lastname) + 1;
|
||||
memcpy(buf + olen, lastname, llen);
|
||||
|
||||
*s = bbfdm_strdup(ctx, buf);
|
||||
if (*s == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,36 +18,99 @@
|
|||
#include <string.h>
|
||||
#include <libubox/list.h>
|
||||
|
||||
extern struct list_head memhead;
|
||||
#include "dmapi.h"
|
||||
|
||||
void dmfree(void *m);
|
||||
|
||||
struct dmmem {
|
||||
struct list_head list;
|
||||
char mem[0];
|
||||
};
|
||||
|
||||
void __dminitmem(struct list_head *mem_list);
|
||||
void __dmcleanmem(struct list_head *mem_list);
|
||||
void *__dmmalloc(struct list_head *mem_list, size_t size);
|
||||
void *__dmcalloc(struct list_head *mem_list, int n, size_t size);
|
||||
void *__dmrealloc(struct list_head *mem_list, void *n, size_t size);
|
||||
char *__dmstrdup(struct list_head *mem_list, const char *s);
|
||||
int __dmasprintf(struct list_head *mem_list, char **s, const char *format, ...);
|
||||
int __dmastrcat(struct list_head *mem_list, char **s, char *obj, char *lastname);
|
||||
void __dmcleanmem(struct list_head *mem_list);
|
||||
|
||||
#define dmmalloc(x) __dmmalloc(&memhead, x)
|
||||
#define dmcalloc(n, x) __dmcalloc(&memhead, n, x)
|
||||
#define dmrealloc(x, n) __dmrealloc(&memhead, x, n)
|
||||
#define dmstrdup(x) __dmstrdup(&memhead, x)
|
||||
#define dmasprintf(s, format, ...) __dmasprintf(&memhead, s, format, ## __VA_ARGS__)
|
||||
#define dmastrcat(s, b, m) __dmastrcat(&memhead, s, b, m)
|
||||
#define dmcleanmem() __dmcleanmem(&memhead)
|
||||
/*
|
||||
* Initialize memory management.
|
||||
* @param ctx - Pointer to bbf context
|
||||
*/
|
||||
void bbfdm_init_mem(struct dmctx *ctx);
|
||||
|
||||
/*
|
||||
* Clean up memory management.
|
||||
* @param ctx - Pointer to bbf context
|
||||
*/
|
||||
void bbfdm_clean_mem(struct dmctx *ctx);
|
||||
|
||||
/*
|
||||
* Allocate memory block of the specified size.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param size - Size of memory block to allocate
|
||||
* @return Pointer to the allocated memory block
|
||||
*/
|
||||
void *bbfdm_malloc(struct dmctx *ctx, size_t size);
|
||||
|
||||
/*
|
||||
* Allocate memory for an array of n elements, each of size bytes, initialized to zero.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param n - Number of elements
|
||||
* @param size - Size of each element
|
||||
* @return Pointer to the allocated memory block
|
||||
*/
|
||||
void *bbfdm_calloc(struct dmctx *ctx, int n, size_t size);
|
||||
|
||||
/*
|
||||
* Resize the memory block pointed to by n to the new size size.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param n - Pointer to the memory block to resize
|
||||
* @param size - New size of the memory block
|
||||
* @return Pointer to the resized memory block
|
||||
*/
|
||||
void *bbfdm_realloc(struct dmctx *ctx, void *n, size_t size);
|
||||
|
||||
/*
|
||||
* Duplicate the string s.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param s - Pointer to the string to duplicate
|
||||
* @return Pointer to the duplicated string
|
||||
*/
|
||||
char *bbfdm_strdup(struct dmctx *ctx, const char *s);
|
||||
|
||||
/*
|
||||
* Allocate a string with a format similar to printf.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param s - Pointer to store the resulting string
|
||||
* @param format - Format string
|
||||
* @param ... - Additional arguments for the format string
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bbfdm_asprintf(struct dmctx *ctx, char **s, const char *format, ...);
|
||||
|
||||
/*
|
||||
* Concatenate the string lastname to the string obj.
|
||||
* @param ctx - Pointer to bbf context
|
||||
* @param s - Pointer to store the resulting string
|
||||
* @param obj - Pointer to the first string
|
||||
* @param lastname - Pointer to the second string to concatenate
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bbfdm_astrcat(struct dmctx *ctx, char **s, char *obj, char *lastname);
|
||||
|
||||
|
||||
#define dmmalloc(x) bbfdm_malloc(0, x)
|
||||
#define dmcalloc(n, x) bbfdm_calloc(0, n, x)
|
||||
#define dmrealloc(x, n) bbfdm_realloc(0, x, n)
|
||||
#define dmstrdup(x) bbfdm_strdup(0, x)
|
||||
#define dmasprintf(s, format, ...) bbfdm_asprintf(0, s, format, ## __VA_ARGS__)
|
||||
#define dmastrcat(s, b, m) bbfdm_astrcat(0, s, b, m)
|
||||
|
||||
#define dm_dynamic_malloc(m, x) __dmmalloc(m, x)
|
||||
#define dm_dynamic_calloc(m, n, x) __dmcalloc(m, n, x)
|
||||
#define dm_dynamic_realloc(m, x, n) __dmrealloc(m, x, n)
|
||||
#define dm_dynamic_strdup(m, x) __dmstrdup(m, x)
|
||||
#define dm_dynamic_asprintf(m, s, format, ...) __dmasprintf(m, s, format, ## __VA_ARGS__)
|
||||
#define dm_dynamic_initmem(m) __dminitmem(m)
|
||||
#define dm_dynamic_cleanmem(m) __dmcleanmem(m)
|
||||
|
||||
#endif /* __DMMEM_H */
|
||||
|
|
|
|||
|
|
@ -246,8 +246,8 @@ static int plugin_obj_match(char *in_param, struct dmnode *node)
|
|||
return FAULT_9005;
|
||||
}
|
||||
|
||||
static void dm_check_dynamic_obj(DMNODE *parent_node, DMOBJ *entryobj, char *full_obj, DMOBJ **root_entry);
|
||||
static void dm_check_dynamic_obj_entry(DMNODE *parent_node, DMOBJ *entryobj, char *parent_obj, char *full_obj, DMOBJ **root_entry)
|
||||
static void dm_check_dynamic_obj(struct list_head *mem_list, DMNODE *parent_node, DMOBJ *entryobj, char *full_obj, DMOBJ **root_entry);
|
||||
static void dm_check_dynamic_obj_entry(struct list_head *mem_list, DMNODE *parent_node, DMOBJ *entryobj, char *parent_obj, char *full_obj, DMOBJ **root_entry)
|
||||
{
|
||||
DMNODE node = {0};
|
||||
node.obj = entryobj;
|
||||
|
|
@ -255,7 +255,7 @@ static void dm_check_dynamic_obj_entry(DMNODE *parent_node, DMOBJ *entryobj, cha
|
|||
node.instance_level = parent_node->instance_level;
|
||||
node.matched = parent_node->matched;
|
||||
|
||||
dmasprintf(&(node.current_object), "%s%s.", parent_obj, entryobj->obj);
|
||||
dm_dynamic_asprintf(mem_list, &(node.current_object), "%s%s.", parent_obj, entryobj->obj);
|
||||
if (DM_STRCMP(node.current_object, full_obj) == 0) {
|
||||
*root_entry = entryobj;
|
||||
return;
|
||||
|
|
@ -266,15 +266,15 @@ static void dm_check_dynamic_obj_entry(DMNODE *parent_node, DMOBJ *entryobj, cha
|
|||
return;
|
||||
|
||||
if (entryobj->nextobj || entryobj->nextdynamicobj)
|
||||
dm_check_dynamic_obj(&node, entryobj->nextobj, full_obj, root_entry);
|
||||
dm_check_dynamic_obj(mem_list, &node, entryobj->nextobj, full_obj, root_entry);
|
||||
}
|
||||
|
||||
static void dm_check_dynamic_obj(DMNODE *parent_node, DMOBJ *entryobj, char *full_obj, DMOBJ **root_entry)
|
||||
static void dm_check_dynamic_obj(struct list_head *mem_list, DMNODE *parent_node, DMOBJ *entryobj, char *full_obj, DMOBJ **root_entry)
|
||||
{
|
||||
char *parent_obj = parent_node->current_object;
|
||||
|
||||
for (; (entryobj && entryobj->obj); entryobj++) {
|
||||
dm_check_dynamic_obj_entry(parent_node, entryobj, parent_obj, full_obj, root_entry);
|
||||
dm_check_dynamic_obj_entry(mem_list, parent_node, entryobj, parent_obj, full_obj, root_entry);
|
||||
if (*root_entry != NULL)
|
||||
return;
|
||||
}
|
||||
|
|
@ -287,7 +287,7 @@ static void dm_check_dynamic_obj(DMNODE *parent_node, DMOBJ *entryobj, char *ful
|
|||
for (int j = 0; next_dyn_array->nextobj[j]; j++) {
|
||||
DMOBJ *jentryobj = next_dyn_array->nextobj[j];
|
||||
for (; (jentryobj && jentryobj->obj); jentryobj++) {
|
||||
dm_check_dynamic_obj_entry(parent_node, jentryobj, parent_obj, full_obj, root_entry);
|
||||
dm_check_dynamic_obj_entry(mem_list, parent_node, jentryobj, parent_obj, full_obj, root_entry);
|
||||
if (*root_entry != NULL)
|
||||
return;
|
||||
}
|
||||
|
|
@ -305,11 +305,14 @@ DMOBJ *find_entry_obj(DMOBJ *entryobj, char *obj_path)
|
|||
|
||||
DMNODE node = {.current_object = ""};
|
||||
DMOBJ *obj = NULL;
|
||||
LIST_HEAD(local_mem);
|
||||
|
||||
char *in_obj = replace_str(obj_path, ".{i}.", ".");
|
||||
dm_check_dynamic_obj(&node, entryobj, in_obj, &obj);
|
||||
dm_check_dynamic_obj(&local_mem, &node, entryobj, in_obj, &obj);
|
||||
FREE(in_obj);
|
||||
|
||||
dm_dynamic_cleanmem(&local_mem);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -385,24 +388,40 @@ int get_leaf_idx(DMLEAF **entryleaf)
|
|||
return idx;
|
||||
}
|
||||
|
||||
int load_plugins(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, const char *plugin_path)
|
||||
void load_plugins(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, const char *plugin_path)
|
||||
{
|
||||
int max_num_files = 256;
|
||||
|
||||
#ifdef BBF_VENDOR_EXTENSION
|
||||
// Load objects and parameters exposed via vendor extension plugin
|
||||
load_vendor_dynamic_arrays(dm_entryobj, dm_VendorExtension, dm_VendorExtensionExclude);
|
||||
#endif /* BBF_VENDOR_EXTENSION */
|
||||
|
||||
if (DM_STRLEN(plugin_path) == 0) // If empty, return without further action
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (!folder_exists(plugin_path)) {
|
||||
TRACE("(%s) doesn't exist", plugin_path);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
sysfs_foreach_file_sorted(plugin_path, max_num_files) {
|
||||
struct dirent *ent = NULL;
|
||||
int num_files = 0;
|
||||
char *files[256];
|
||||
|
||||
DIR *dir = opendir(plugin_path);
|
||||
if (dir == NULL) {
|
||||
TRACE("Cannot open (%s) directory", plugin_path);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir)) != NULL && num_files < 256) {
|
||||
files[num_files++] = strdup(ent->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
qsort(files, num_files, sizeof(char *), compare_strings);
|
||||
|
||||
for (int i = 0; i < num_files; i++) {
|
||||
char buf[512] = {0};
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/%s", plugin_path, files[i]);
|
||||
|
|
@ -413,10 +432,8 @@ int load_plugins(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP
|
|||
load_dotso_plugins(dm_entryobj, buf);
|
||||
}
|
||||
|
||||
dmfree(files[i]);
|
||||
free(files[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_plugins(DMOBJ *dm_entryobj)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ int get_entry_idx(DMOBJ *entryobj);
|
|||
int get_obj_idx(DMOBJ **entryobj);
|
||||
int get_leaf_idx(DMLEAF **entryleaf);
|
||||
|
||||
int load_plugins(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, const char *plugin_path);
|
||||
void load_plugins(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, const char *plugin_path);
|
||||
void free_plugins(DMOBJ *dm_entryobj);
|
||||
|
||||
#endif //__DMPLUGIN_H__
|
||||
|
|
|
|||
|
|
@ -72,17 +72,16 @@ static void overwrite_obj(DMOBJ *entryobj, DMOBJ *dmobj)
|
|||
|
||||
static void load_vendor_extension_arrays(DMOBJ *entryobj, DM_MAP_VENDOR *vendor_map_obj)
|
||||
{
|
||||
char *pch = NULL, *pchr = NULL;
|
||||
char vendor_list[512] = {0};
|
||||
size_t length = 0;
|
||||
|
||||
DM_STRNCPY(vendor_list, BBF_VENDOR_LIST, sizeof(vendor_list));
|
||||
char **tokens = strsplit(vendor_list, ",", &length);
|
||||
|
||||
for (int idx = length - 1; idx >= 0; idx--) {
|
||||
for (pch = strtok_r(vendor_list, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
|
||||
|
||||
for (int j = 0; vendor_map_obj && vendor_map_obj[j].vendor; j++) {
|
||||
|
||||
if (DM_STRCMP(vendor_map_obj[j].vendor, tokens[idx]) != 0)
|
||||
if (DM_STRCMP(vendor_map_obj[j].vendor, pch) != 0)
|
||||
continue;
|
||||
|
||||
DM_MAP_OBJ *vendor_obj = vendor_map_obj[j].vendor_obj;
|
||||
|
|
@ -142,17 +141,16 @@ static void load_vendor_extension_arrays(DMOBJ *entryobj, DM_MAP_VENDOR *vendor_
|
|||
|
||||
static void load_vendor_extension_overwrite_arrays(DMOBJ *entryobj, DM_MAP_VENDOR *vendor_map_obj)
|
||||
{
|
||||
char *pch = NULL, *pchr = NULL;
|
||||
char vendor_list[512] = {0};
|
||||
size_t length = 0;
|
||||
|
||||
DM_STRNCPY(vendor_list, BBF_VENDOR_LIST, sizeof(vendor_list));
|
||||
char **tokens = strsplit(vendor_list, ",", &length);
|
||||
|
||||
for (int idx = length - 1; idx >= 0; idx--) {
|
||||
for (pch = strtok_r(vendor_list, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
|
||||
|
||||
for (int j = 0; vendor_map_obj && vendor_map_obj[j].vendor; j++) {
|
||||
|
||||
if (DM_STRCMP(vendor_map_obj[j].vendor, tokens[idx]) != 0)
|
||||
if (DM_STRCMP(vendor_map_obj[j].vendor, pch) != 0)
|
||||
continue;
|
||||
|
||||
DM_MAP_OBJ *dynamic_overwrite_obj = vendor_map_obj[j].vendor_obj;
|
||||
|
|
@ -228,17 +226,16 @@ static void exclude_param(DMOBJ *dm_entryobj, char *in_param)
|
|||
|
||||
static void load_vendor_extension_exclude_arrays(DMOBJ *entryobj, DM_MAP_VENDOR_EXCLUDE *vendor_map_exclude_obj)
|
||||
{
|
||||
char *pch = NULL, *pchr = NULL;
|
||||
char vendor_list[512] = {0};
|
||||
size_t length = 0;
|
||||
|
||||
DM_STRNCPY(vendor_list, BBF_VENDOR_LIST, sizeof(vendor_list));
|
||||
char **tokens = strsplit(vendor_list, ",", &length);
|
||||
|
||||
for (int idx = length - 1; idx >= 0; idx--) {
|
||||
for (pch = strtok_r(vendor_list, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
|
||||
|
||||
for (int j = 0; vendor_map_exclude_obj && vendor_map_exclude_obj[j].vendor; j++) {
|
||||
|
||||
if (DM_STRCMP(vendor_map_exclude_obj[j].vendor, tokens[idx]) != 0)
|
||||
if (DM_STRCMP(vendor_map_exclude_obj[j].vendor, pch) != 0)
|
||||
continue;
|
||||
|
||||
char **dynamic_exclude_obj = vendor_map_exclude_obj[j].vendor_obj;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@
|
|||
#include <libbbfdm-api/dmcommon.h>
|
||||
#include <libbbfdm-api/dmmem.h>
|
||||
|
||||
static struct dmctx bbf_ctx = {0};
|
||||
|
||||
static int setup_teardown(void **state)
|
||||
{
|
||||
bbfdm_init_mem(&bbf_ctx);
|
||||
dm_uci_init();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16,7 +19,7 @@ static int group_teardown(void **state)
|
|||
{
|
||||
dm_uci_exit();
|
||||
dmubus_free();
|
||||
dmcleanmem();
|
||||
bbfdm_clean_mem(&bbf_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ static void test_api_bbfdm_json_get_value(void **state)
|
|||
assert_true(&first_entry->list != &ctx->list_parameter);
|
||||
|
||||
bbf_ctx_clean_sub(ctx);
|
||||
bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
bbf_ctx_init_sub(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
|
||||
/*
|
||||
* Test of JSON Parameter Path
|
||||
|
|
@ -603,9 +603,6 @@ static void test_api_bbfdm_json_get_value(void **state)
|
|||
|
||||
first_entry = list_first_entry(&ctx->list_parameter, struct dm_parameter, list);
|
||||
assert_true(&first_entry->list != &ctx->list_parameter);
|
||||
|
||||
bbf_ctx_clean_sub(ctx);
|
||||
bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
}
|
||||
|
||||
static void test_api_bbfdm_json_add_object(void **state)
|
||||
|
|
@ -653,7 +650,7 @@ static void test_api_bbfdm_library_get_value(void **state)
|
|||
assert_true(&first_entry->list != &ctx->list_parameter);
|
||||
|
||||
bbf_ctx_clean_sub(ctx);
|
||||
bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
bbf_ctx_init_sub(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
|
||||
ctx->in_param = "Device.WiFi.SSID.1.Enable";
|
||||
|
||||
|
|
@ -662,8 +659,6 @@ static void test_api_bbfdm_library_get_value(void **state)
|
|||
|
||||
first_entry = list_first_entry(&ctx->list_parameter, struct dm_parameter, list);
|
||||
assert_true(&first_entry->list != &ctx->list_parameter);
|
||||
|
||||
bbf_ctx_clean_sub(ctx);
|
||||
}
|
||||
|
||||
static void test_api_bbfdm_library_add_object(void **state)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue