62 #include <amxc/amxc.h>
64 #include <amxp/amxp_signal.h>
65 #include <amxp/amxp_slot.h>
66 #include <amxp/amxp_expression.h>
68 #include <amxd/amxd_types.h>
69 #include <amxd/amxd_object.h>
70 #include <amxd/amxd_path.h>
71 #include <amxd/amxd_dm.h>
73 #include <amxb/amxb.h>
84 const amxc_var_t*
const data,
89 amxc_var_t trans_data;
93 amxc_var_init(&trans_data);
95 if(trans_cb != NULL) {
96 status = trans_cb(entry, direction, data, &trans_data, entry->
priv);
97 when_failed(status, exit);
99 amxc_var_copy(&trans_data, data);
102 if(action_cb != NULL) {
103 status = action_cb(entry, direction, &trans_data, entry->
priv);
104 when_failed(status, exit);
108 amxc_var_clean(&trans_data);
112 const amxc_var_t*
const data,
118 const amxc_var_t*
const data,
124 const amxc_var_t*
const data,
130 const amxc_var_t*
const data,
147 amxb_subscription_t* sub = NULL;
152 amxc_var_init(¶ms);
153 amxc_var_set_type(¶ms, AMXC_VAR_ID_LIST);
154 amxc_string_init(&str, 0);
157 when_failed(status, exit);
158 when_null_status(amxc_var_get_first(¶ms), exit, status =
amxs_status_ok);
161 when_str_empty(path, exit);
163 amxc_string_setf(&str,
"notification matches 'dm:object-(changed|added|removed)' && path matches '%s' && (", path);
164 amxc_var_for_each(var, ¶ms) {
165 amxc_string_appendf(&str,
" contains('parameters.%s') ||", GET_CHAR(var, NULL));
167 amxc_string_remove_at(&str, amxc_string_text_length(&str) - 3, 3);
168 amxc_string_append(&str,
")", 1);
170 ret = amxb_subscription_new(&sub,
bus_ctx,
object, amxc_string_get(&str, 0), fn, entry);
171 when_failed(ret, exit);
175 amxc_var_clean(¶ms);
177 amxc_string_clean(&str);
185 amxb_subscription_t* sub = NULL;
195 amxd_path_init(&p, name);
196 amxc_string_init(&str, 0);
198 switch(entry->
type) {
203 amxc_string_setf(&str,
"notification matches 'dm:object-(changed|added|removed)' && contains('parameters.%s')", name);
205 when_str_empty(path, exit);
206 amxc_string_appendf(&str,
" && path matches '%s'", path);
207 ret = amxb_subscription_new(&sub,
bus_ctx,
object, amxc_string_get(&str, 0), fn, entry);
209 when_failed(ret, exit);
213 if(amxd_path_is_instance_path(&p)) {
219 when_str_empty(path, exit);
220 amxc_string_setf(&str,
"notification matches 'dm:instance-*' && path matches '%s'", path);
221 ret = amxb_subscription_new(&sub,
bus_ctx,
object, amxc_string_get(&str, 0), fn, entry);
222 when_failed(ret, exit);
240 amxc_string_clean(&str);
249 amxc_llist_for_each(it, &entry->
entries) {
253 when_failed(status, exit);
265 const char* expr_str) {
269 amxc_string_init(&str, 0);
271 amxc_var_for_each(variant, var) {
273 amxp_expr_status_t status;
275 amxc_string_setf(&str,
"'%s' matches '%s'", amxc_var_key(variant), expr_str);
276 status = amxp_expr_init(&expr, amxc_string_get(&str, 0));
277 when_failed(status, exit);
278 if(amxp_expr_eval(&expr, &status)) {
279 amxc_llist_add_string(paths, amxc_var_key(variant));
281 amxp_expr_clean(&expr);
287 amxc_string_clean(&str);
292 const char* instance,
293 amxc_var_t* init_data,
294 const amxc_var_t* data) {
295 unsigned int index = strtoul(instance + strlen(
object), NULL, 0);
296 amxc_var_t* tmp = NULL;
298 amxc_var_set_type(init_data, AMXC_VAR_ID_HTABLE);
299 amxc_var_add_key(cstring_t, init_data,
"path",
object);
300 amxc_var_add_key(cstring_t, init_data,
"notification",
"sync:init-object");
301 amxc_var_add_key(uint32_t, init_data,
"index", index);
302 tmp = amxc_var_add_new_key(init_data,
"parameters");
303 amxc_var_copy(tmp, GET_ARG(data, instance));
308 amxc_var_t* init_data,
309 const amxc_var_t* data) {
310 amxc_var_t* params = NULL;
311 amxc_var_t* param = NULL;
313 amxc_var_set_type(init_data, AMXC_VAR_ID_HTABLE);
314 amxc_var_add_key(cstring_t, init_data,
"path",
object);
315 amxc_var_add_key(cstring_t, init_data,
"notification",
"sync:init-param");
316 params = amxc_var_add_new_key(init_data,
"parameters");
317 amxc_var_set_type(params, AMXC_VAR_ID_HTABLE);
318 param = amxc_var_add_new_key(params, name);
319 amxc_var_copy(param, data);
323 const char*
const parent_path,
325 const amxc_var_t*
const data_a,
326 const amxc_var_t*
const data_b);
329 amxc_var_t* init_data,
330 const amxc_var_t* data) {
331 amxc_var_t* params = NULL;
333 amxc_var_set_type(init_data, AMXC_VAR_ID_HTABLE);
334 amxc_var_add_key(cstring_t, init_data,
"path",
object);
335 amxc_var_add_key(cstring_t, init_data,
"notification",
"sync:init-batch-param");
336 params = amxc_var_add_new_key(init_data,
"parameters");
337 amxc_var_set_type(params, AMXC_VAR_ID_HTABLE);
338 amxc_var_copy(params, data);
342 UNUSED
const char*
const object,
344 UNUSED
const amxc_var_t*
const data) {
346 amxc_var_t init_data;
347 amxc_var_t* var = GET_ARG(data,
object);
349 amxc_var_init(&init_data);
359 amxc_var_clean(&init_data);
364 const char*
const object,
366 const amxc_var_t*
const data_a,
367 const amxc_var_t*
const data_b) {
372 amxc_var_t init_data;
374 amxc_string_init(&str, 0);
375 amxc_llist_init(&list);
376 amxc_var_init(&init_data);
378 amxc_string_setf(&str,
"%s[0-9]+\\.$",
object);
382 amxc_llist_for_each(it, &list) {
383 const char* instance = amxc_string_get(amxc_llist_it_get_data(it, amxc_string_t, it), 0);
389 when_failed(status, exit);
394 if(amxc_var_get_pathf(data, AMXC_VAR_FLAG_DEFAULT,
"'%s'",
object) != NULL) {
396 when_failed(status, exit);
399 if(GET_ARG(data,
object) != NULL) {
401 when_failed(status, exit);
407 amxc_string_clean(&str);
408 amxc_llist_clean(&list, amxc_string_list_it_free);
409 amxc_var_clean(&init_data);
414 const char*
const object,
415 const char*
const param,
417 const amxc_var_t*
const data) {
419 amxc_var_t init_data;
420 amxc_var_t* var = GET_ARG(data,
object);
422 amxc_var_init(&init_data);
427 var = GET_ARG(var, param);
436 amxc_var_clean(&init_data);
441 const char*
const parent_path,
443 const amxc_var_t*
const data_a,
444 const amxc_var_t*
const data_b) {
448 const char* name = NULL;
449 amxc_string_t object;
451 when_null(data, exit);
453 amxc_string_init(&
object, 0);
456 if(direction != parent_direction) {
458 amxc_string_set(&
object, opposite_parent_path);
459 free(opposite_parent_path);
461 amxc_string_set(&
object, parent_path);
464 switch(entry->
type) {
467 when_failed(status, exit);
470 amxc_string_appendf(&
object,
"%s", name);
481 amxc_string_clean(&
object);
486 const char*
const parent_path,
488 const amxc_var_t*
const data_a,
489 const amxc_var_t*
const data_b) {
492 amxc_llist_for_each(it, &entry->
entries) {
495 when_failed(status, exit);
505 amxd_object_type_t rv = amxd_object_singleton;
509 if(amxb_describe(ctx, path, 0, &ret, 5) == 0) {
510 rv = (amxd_object_type_t) GETP_UINT32(&ret,
"0.type_id");
512 amxc_var_clean(&ret);
522 uint32_t depth = start;
523 uint32_t path_pos = amxc_string_text_length(path);
524 const char* sync_path = NULL;
525 amxb_bus_ctx_t* ctx = NULL;
526 amxd_path_t rel_path;
529 amxd_object_type_t type = amxd_object_singleton;
531 sync_entry = sync_entry == NULL? sync_ctx:sync_entry;
535 when_null(sync_path, exit);
537 amxd_path_init(&rel_path, sync_path);
538 amxc_string_appendf(path,
"%s", sync_path);
539 start += (sync_entry == sync_ctx)? 0:amxd_path_get_depth(&rel_path);
541 part = amxd_path_get_first(&rel_path,
true);
542 if(strtoull(part, &endptr, 10) != 0) {
548 amxd_path_clean(&rel_path);
551 amxc_llist_iterate(it, &sync_entry->
entries) {
552 uint32_t tree_depth = 0;
556 if(tree_depth > depth) {
565 if(type == amxd_object_template) {
569 amxc_string_remove_at(path, path_pos, strlen(sync_path));
580 uint32_t orig_access = AMXB_PROTECTED;
586 amxc_var_init(&data_a);
587 amxc_var_init(&data_b);
588 amxc_string_init(&path, 64);
593 amxb_set_access(ctx->
bus_ctx_a, AMXB_PROTECTED);
596 ret = amxb_get(ctx->
bus_ctx_a, ctx->
a, depth, &data_a, 5);
597 amxb_set_access(ctx->
bus_ctx_a, orig_access);
599 when_failed(ret, exit);
606 amxb_set_access(ctx->
bus_ctx_b, AMXB_PROTECTED);
609 ret = amxb_get(ctx->
bus_ctx_b, ctx->
b, depth, &data_b, 5);
610 amxb_set_access(ctx->
bus_ctx_b, orig_access);
612 when_failed(ret, exit);
619 amxc_string_clean(&path);
620 amxc_var_clean(&data_a);
621 amxc_var_clean(&data_b);
627 amxb_bus_ctx_t*
bus_ctx = NULL;
629 const char* new_path = NULL;
632 amxc_llist_it_t* it = NULL;
635 amxc_var_init(&data);
636 amxd_path_init(&p, NULL);
637 when_null(ctx, exit);
643 when_str_empty(*path, exit);
645 amxd_path_setf(&p,
true,
"%s", *path);
646 ret = amxb_resolve(
bus_ctx, &p, &data);
647 when_failed(ret, exit);
649 it = amxc_llist_get_first(amxc_var_constcast(amxc_llist_t, &data));
650 if((it == NULL) || (amxc_llist_it_get_next(it) != NULL)) {
654 new_path = GET_CHAR(amxc_llist_it_get_data(it, amxc_var_t, lit), NULL);
655 when_str_empty(new_path, exit);
657 *path = strdup(new_path);
663 amxc_var_clean(&data);
670 amxd_dm_t* dm = NULL;
671 const char* path = NULL;
673 when_null(ctx, exit);
691 char* supported_old = NULL;
692 char* supported_new = NULL;
694 amxd_path_init(&old_p, NULL);
695 amxd_path_init(&new_p, NULL);
697 amxd_path_setf(&old_p,
false,
"%s", new_path);
698 amxd_path_setf(&new_p,
false,
"%s", old_path);
700 supported_old = amxd_path_get_supported_path(&old_p);
701 supported_new = amxd_path_get_supported_path(&new_p);
703 retval = strcmp(supported_old, supported_new) == 0;
707 amxd_path_clean(&old_p);
708 amxd_path_clean(&new_p);
714 const char* object_a,
715 const char* object_b,
728 when_null(ctx, exit);
729 when_null(*ctx, exit);
739 const char* object_a,
740 const char* object_b,
753 when_null(ctx, exit);
768 when_null(ctx, exit);
798 when_failed(status, cleanup_subs);
803 when_failed(status, cleanup_subs);
807 when_failed(status, cleanup_subs);
819 when_null(ctx, exit);
829 const char* object_a,
830 const char* object_b) {
832 char* supported_a = NULL;
833 char* supported_b = NULL;
835 when_null(ctx, exit);
839 supported_a = ctx->
a;
840 supported_b = ctx->
b;
842 ctx->
a = strdup(object_a);
843 ctx->
b = strdup(object_b);
870 when_null(ctx, exit);
871 when_null(param, exit);
891 status =
amxs_sync_param_new(¶m, param_a, param_b, attributes, translation_cb, action_cb, priv);
892 when_failed(status, exit);
918 when_null(ctx, exit);
919 when_null(
object, exit);
930 const char* object_a,
931 const char* object_b,
939 status =
amxs_sync_object_new(&
object, object_a, object_b, attributes, translation_cb, action_cb, priv);
940 when_failed(status, exit);
952 const char* object_a,
953 const char* object_b,
968 when_null(ctx, exit);
void amxs_llist_it_delete_subscription(amxc_llist_it_t *it)
static amxs_status_t amxs_sync_ctx_verify_local_dm(amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
static amxs_status_t amxs_initial_sync_child_entries(amxs_sync_entry_t *entry, const char *const parent_path, amxs_sync_direction_t parent_direction, const amxc_var_t *const data_a, const amxc_var_t *const data_b)
static amxs_status_t amxs_subscribe_batch_params(amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
static amxs_status_t amxs_subscribe(amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
static void amxs_callback_a(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
amxs_status_t amxs_sync_ctx_set_local_dm(amxs_sync_ctx_t *ctx, amxd_dm_t *dm_a, amxd_dm_t *dm_b)
Set the local datamodel pointer for the sync root objects.
static int amxs_var_find_keys_regex(const amxc_var_t *var, amxc_llist_t *paths, const char *expr_str)
static void amxs_batch_callback_b(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
static void amxs_callback(amxs_sync_direction_t direction, const amxc_var_t *const data, void *const priv, bool batch)
static amxs_status_t amxs_initial_sync_param(amxs_sync_entry_t *entry, const char *const object, const char *const param, amxs_sync_direction_t direction, const amxc_var_t *const data)
static amxd_object_type_t amxb_get_object_type(amxb_bus_ctx_t *ctx, const char *path)
static amxs_status_t amxs_sync_ctx_validate_path(amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
static void amxs_var_fill_initial_param_data(const char *object, const char *name, amxc_var_t *init_data, const amxc_var_t *data)
static void amxs_var_fill_initial_instance_data(const char *object, const char *instance, amxc_var_t *init_data, const amxc_var_t *data)
static void amxs_var_fill_initial_batch_param_data(const char *object, amxc_var_t *init_data, const amxc_var_t *data)
static uint32_t amxs_sync_depth(amxs_sync_ctx_t *sync_ctx, amxs_sync_entry_t *sync_entry, amxs_sync_direction_t direction, amxc_string_t *path, uint32_t start)
static amxs_status_t amxs_initial_sync_batch_params(UNUSED amxs_sync_entry_t *entry, UNUSED const char *const object, UNUSED amxs_sync_direction_t direction, UNUSED const amxc_var_t *const data)
static amxs_status_t amxs_subscribe_child_entries(amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
amxs_status_t amxs_sync_ctx_add_new_copy_object(amxs_sync_ctx_t *ctx, const char *object_a, const char *object_b, int attributes)
Creates and adds a synchronization object to a synchronization context.
static amxs_status_t amxs_initial_sync_object(amxs_sync_entry_t *entry, const char *const object, amxs_sync_direction_t direction, const amxc_var_t *const data_a, const amxc_var_t *const data_b)
static void amxs_callback_b(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
static bool amxs_sync_ctx_paths_match(const char *new_path, const char *old_path)
static amxs_status_t amxs_do_initial_sync(amxs_sync_ctx_t *ctx)
static void amxs_batch_callback_a(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
static amxs_status_t amxs_initial_sync_entry(amxs_sync_entry_t *entry, const char *const parent_path, amxs_sync_direction_t parent_direction, const amxc_var_t *const data_a, const amxc_var_t *const data_b)
Ambiorix Object Synchronization API header file.
amxs_status_t amxs_sync_entry_add_entry(amxs_sync_entry_t *parent, amxs_sync_entry_t *child)
amxs_status_t amxs_sync_entry_new(amxs_sync_entry_t **entry, const char *a, const char *b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, amxs_sync_entry_type_t type, void *priv)
amxs_sync_direction_t amxs_sync_entry_get_initial_direction(const amxs_sync_entry_t *entry)
amxs_status_t amxs_sync_entry_init(amxs_sync_entry_t *entry, const char *a, const char *b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, amxs_sync_entry_type_t type, void *priv)
amxs_status_t amxs_sync_entry_copy(amxs_sync_entry_t **dest, amxs_sync_entry_t *src, void *priv)
void amxs_sync_entry_delete(amxs_sync_entry_t **entry)
void amxs_sync_entry_clean(amxs_sync_entry_t *entry)
Ambiorix Object Synchronization API header file.
Ambiorix Object Synchronization API header file.
@ amxs_status_object_not_found
@ amxs_status_unknown_error
@ amxs_status_invalid_type
@ amxs_status_invalid_arg
@ amxs_status_empty_context
enum _amxs_sync_direction amxs_sync_direction_t
enum _amxs_status amxs_status_t
char * amxs_sync_entry_get_regex_parent_path(const amxs_sync_entry_t *const entry, amxs_sync_direction_t direction)
amxs_status_t amxs_sync_entry_get_batch_params(const amxs_sync_entry_t *const entry, amxc_var_t *params, amxs_sync_direction_t direction)
char * amxs_sync_entry_get_opposite_parent_path(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, const char *old_path)
bool amxs_sync_entry_direction_allowed(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
char * amxs_sync_entry_get_regex_path(const amxs_sync_entry_t *const entry, amxs_sync_direction_t direction)
bool amxs_sync_entry_is_batch_param(const amxs_sync_entry_t *const entry)
const char * amxs_sync_entry_get_name(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
bool amxs_sync_entry_is_bidirectional(const amxs_sync_entry_t *entry)
amxp_signal_mngr_t * amxs_sync_entry_get_signal_manager(const amxs_sync_entry_t *const entry)
amxb_bus_ctx_t * amxs_sync_ctx_get_bus_ctx(const amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
amxs_status_t amxs_sync_object_new(amxs_sync_object_t **object, const char *object_a, const char *object_b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, void *priv)
Synchronization object constructor function.
void amxs_sync_object_delete(amxs_sync_object_t **object)
Synchronization object destructor function.
void amxs_sync_param_delete(amxs_sync_param_t **param)
Synchronization parameter destructor function.
amxs_status_t amxs_sync_param_new(amxs_sync_param_t **param, const char *param_a, const char *param_b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, void *priv)
Synchronization parameter constructor function.
#define AMXS_SYNC_ONLY_B_TO_A
Only synchronize from object B to object A.
#define AMXS_SYNC_ONLY_A_TO_B
Only synchronize from object A to object B.
#define AMXS_SYNC_PARAM_BATCH
Indicate that this parameter may be part of a batch copy operation.
amxs_status_t(* amxs_action_cb_t)(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, amxc_var_t *data, void *priv)
Definition of the action callback function.
amxs_status_t(* amxs_translation_cb_t)(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, const amxc_var_t *input, amxc_var_t *output, void *priv)
Definition of the translation callback function.
amxs_status_t amxs_sync_batch_param_copy_trans_cb(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, const amxc_var_t *input, amxc_var_t *output, void *priv)
Translates data from a dm:object-changed event to data suited for an amxb_set call for all parameters...
amxs_status_t amxs_sync_object_copy_trans_cb(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, const amxc_var_t *input, amxc_var_t *output, void *priv)
Translates data from a dm:instance-added or dm:instance-removed event to data suited for an amxb call...
amxs_status_t amxs_sync_param_copy_action_cb(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, amxc_var_t *data, void *priv)
Sets the new parameter value.
amxs_status_t amxs_sync_object_copy_action_cb(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, amxc_var_t *data, void *priv)
Adds, removes or updates an object with the given data using an amxb call.
amxs_status_t amxs_sync_ctx_new(amxs_sync_ctx_t **ctx, const char *object_a, const char *object_b, int attributes)
Synchronization context constructor function.
amxs_status_t amxs_sync_ctx_copy(amxs_sync_ctx_t **dest, amxs_sync_ctx_t *src, void *priv)
Copies an existing synchronization context to a new synchronization context.
amxs_status_t amxs_sync_ctx_add_new_param(amxs_sync_ctx_t *ctx, const char *param_a, const char *param_b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, void *priv)
Creates and adds a synchronization parameter to a synchronization context.
amxs_status_t amxs_sync_ctx_add_param(amxs_sync_ctx_t *ctx, amxs_sync_param_t *param)
Adds a synchronization parameter to a synchronization context.
amxs_status_t amxs_sync_ctx_start_sync(amxs_sync_ctx_t *ctx)
Starts the object synchronization.
amxs_status_t amxs_sync_ctx_add_new_copy_param(amxs_sync_ctx_t *ctx, const char *param_a, const char *param_b, int attributes)
Creates and adds a synchronization parameter to a synchronization context.
void amxs_sync_ctx_delete(amxs_sync_ctx_t **ctx)
Synchronization context destructor function.
amxs_status_t amxs_sync_ctx_add_new_object(amxs_sync_ctx_t *ctx, const char *object_a, const char *object_b, int attributes, amxs_translation_cb_t translation_cb, amxs_action_cb_t action_cb, void *priv)
Creates and adds a synchronization object to a synchronization context.
amxs_status_t amxs_sync_ctx_init(amxs_sync_ctx_t *ctx, const char *object_a, const char *object_b, int attributes)
Synchronization context initialization function.
amxs_status_t amxs_sync_ctx_add_object(amxs_sync_ctx_t *ctx, amxs_sync_object_t *object)
Adds a synchronization object to a synchronization context.
void amxs_sync_ctx_stop_sync(amxs_sync_ctx_t *ctx)
Stops the object synchronization.
void amxs_sync_ctx_clean(amxs_sync_ctx_t *ctx)
Synchronization context cleanup function.
amxs_status_t amxs_sync_ctx_set_paths(amxs_sync_ctx_t *const ctx, const char *object_a, const char *object_b)
Updates the object paths of the synchronization context.
amxs_sync_entry_type_t type
amxb_bus_ctx_t * bus_ctx_a
amxs_translation_cb_t translation_cb
amxc_llist_t subscriptions
amxs_action_cb_t action_cb
amxb_bus_ctx_t * bus_ctx_b
static amxb_bus_ctx_t * bus_ctx