libamxs  0.6.0
Data Model Synchronization C API
amxs_sync_ctx.c File Reference
#include <stdlib.h>
#include <string.h>
#include <amxc/amxc.h>
#include <amxp/amxp_signal.h>
#include <amxp/amxp_slot.h>
#include <amxp/amxp_expression.h>
#include <amxd/amxd_types.h>
#include <amxd/amxd_object.h>
#include <amxd/amxd_path.h>
#include <amxd/amxd_dm.h>
#include <amxb/amxb.h>
#include <amxs/amxs_sync_ctx.h>
#include <amxs/amxs_util.h>
#include <amxs/amxs_sync_object.h>
#include <amxs/amxs_sync_param.h>
#include "amxs_priv.h"
#include "amxs_sync_entry.h"

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 

Functions

static void amxs_callback (amxs_sync_direction_t direction, const amxc_var_t *const data, void *const priv, bool batch)
 
static void amxs_callback_a (UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
 
static void amxs_callback_b (UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
 
static void amxs_batch_callback_a (UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
 
static void amxs_batch_callback_b (UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
 
static amxs_status_t amxs_subscribe_child_entries (amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
 
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 int amxs_var_find_keys_regex (const amxc_var_t *var, amxc_llist_t *paths, const char *expr_str)
 
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_param_data (const char *object, const char *name, amxc_var_t *init_data, const amxc_var_t *data)
 
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 void amxs_var_fill_initial_batch_param_data (const char *object, amxc_var_t *init_data, const amxc_var_t *data)
 
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_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 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 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)
 
static amxd_object_type_t amxb_get_object_type (amxb_bus_ctx_t *ctx, const char *path)
 
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_do_initial_sync (amxs_sync_ctx_t *ctx)
 
static amxs_status_t amxs_sync_ctx_validate_path (amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
 
static amxs_status_t amxs_sync_ctx_verify_local_dm (amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
 
static bool amxs_sync_ctx_paths_match (const char *new_path, const char *old_path)
 
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. More...
 
void amxs_sync_ctx_delete (amxs_sync_ctx_t **ctx)
 Synchronization context destructor function. More...
 
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. More...
 
void amxs_sync_ctx_clean (amxs_sync_ctx_t *ctx)
 Synchronization context cleanup function. More...
 
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. More...
 
amxs_status_t amxs_sync_ctx_start_sync (amxs_sync_ctx_t *ctx)
 Starts the object synchronization. More...
 
void amxs_sync_ctx_stop_sync (amxs_sync_ctx_t *ctx)
 Stops the object synchronization. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 56 of file amxs_sync_ctx.c.

Function Documentation

◆ amxb_get_object_type()

static amxd_object_type_t amxb_get_object_type ( amxb_bus_ctx_t *  ctx,
const char *  path 
)
static

Definition at line 504 of file amxs_sync_ctx.c.

504  {
505  amxd_object_type_t rv = amxd_object_singleton;
506  amxc_var_t ret;
507 
508  amxc_var_init(&ret);
509  if(amxb_describe(ctx, path, 0, &ret, 5) == 0) {
510  rv = (amxd_object_type_t) GETP_UINT32(&ret, "0.type_id");
511  }
512  amxc_var_clean(&ret);
513 
514  return rv;
515 }

◆ amxs_batch_callback_a()

static void amxs_batch_callback_a ( UNUSED const char *const  sig_name,
const amxc_var_t *const  data,
void *const  priv 
)
static

Definition at line 123 of file amxs_sync_ctx.c.

125  {
126  amxs_callback(amxs_sync_a_to_b, data, priv, true);
127 }
static void amxs_callback(amxs_sync_direction_t direction, const amxc_var_t *const data, void *const priv, bool batch)
Definition: amxs_sync_ctx.c:83
@ amxs_sync_a_to_b
Definition: amxs_types.h:80

◆ amxs_batch_callback_b()

static void amxs_batch_callback_b ( UNUSED const char *const  sig_name,
const amxc_var_t *const  data,
void *const  priv 
)
static

Definition at line 129 of file amxs_sync_ctx.c.

131  {
132  amxs_callback(amxs_sync_b_to_a, data, priv, true);
133 }
@ amxs_sync_b_to_a
Definition: amxs_types.h:81

◆ amxs_callback()

static void amxs_callback ( amxs_sync_direction_t  direction,
const amxc_var_t *const  data,
void *const  priv,
bool  batch 
)
static

Definition at line 83 of file amxs_sync_ctx.c.

86  {
88  amxs_sync_entry_t* entry = (amxs_sync_entry_t*) priv;
89  amxc_var_t trans_data;
91  amxs_action_cb_t action_cb = batch ? amxs_sync_param_copy_action_cb : entry->action_cb;
92 
93  amxc_var_init(&trans_data);
94 
95  if(trans_cb != NULL) {
96  status = trans_cb(entry, direction, data, &trans_data, entry->priv);
97  when_failed(status, exit);
98  } else {
99  amxc_var_copy(&trans_data, data);
100  }
101 
102  if(action_cb != NULL) {
103  status = action_cb(entry, direction, &trans_data, entry->priv);
104  when_failed(status, exit);
105  }
106 
107 exit:
108  amxc_var_clean(&trans_data);
109 }
@ amxs_status_unknown_error
Definition: amxs_types.h:90
enum _amxs_status amxs_status_t
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.
Definition: amxs_types.h:156
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.
Definition: amxs_types.h:131
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_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.
Definition: amxs_types.h:161
void * priv
Definition: amxs_types.h:168
amxs_translation_cb_t translation_cb
Definition: amxs_types.h:167
amxs_action_cb_t action_cb
Definition: amxs_types.h:166

◆ amxs_callback_a()

static void amxs_callback_a ( UNUSED const char *const  sig_name,
const amxc_var_t *const  data,
void *const  priv 
)
static

Definition at line 111 of file amxs_sync_ctx.c.

113  {
114  amxs_callback(amxs_sync_a_to_b, data, priv, false);
115 }

◆ amxs_callback_b()

static void amxs_callback_b ( UNUSED const char *const  sig_name,
const amxc_var_t *const  data,
void *const  priv 
)
static

Definition at line 117 of file amxs_sync_ctx.c.

119  {
120  amxs_callback(amxs_sync_b_to_a, data, priv, false);
121 }

◆ amxs_do_initial_sync()

static amxs_status_t amxs_do_initial_sync ( amxs_sync_ctx_t ctx)
static

Definition at line 575 of file amxs_sync_ctx.c.

575  {
577  int ret = -1;
578  amxc_var_t data_a;
579  amxc_var_t data_b;
580  uint32_t orig_access = AMXB_PROTECTED;
581  uint32_t depth = 0;
582  amxc_string_t path;
584  bool bidirectional = amxs_sync_entry_is_bidirectional(ctx);
585 
586  amxc_var_init(&data_a);
587  amxc_var_init(&data_b);
588  amxc_string_init(&path, 64);
589 
590  if((direction == amxs_sync_a_to_b) || bidirectional) {
591  if((ctx->bus_ctx_a != NULL) && (ctx->bus_ctx_a->access != AMXB_PROTECTED)) {
592  orig_access = ctx->bus_ctx_a->access;
593  amxb_set_access(ctx->bus_ctx_a, AMXB_PROTECTED);
594  }
595  depth = amxs_sync_depth(ctx, NULL, amxs_sync_a_to_b, &path, 0);
596  ret = amxb_get(ctx->bus_ctx_a, ctx->a, depth, &data_a, 5);
597  amxb_set_access(ctx->bus_ctx_a, orig_access);
598  if((ctx->attributes & AMXS_SYNC_ONLY_B_TO_A) == 0) {
599  when_failed(ret, exit);
600  }
601  }
602 
603  if((direction == amxs_sync_b_to_a) || bidirectional) {
604  if((ctx->bus_ctx_b != NULL) && (ctx->bus_ctx_b->access != AMXB_PROTECTED)) {
605  orig_access = ctx->bus_ctx_b->access;
606  amxb_set_access(ctx->bus_ctx_b, AMXB_PROTECTED);
607  }
608  depth = amxs_sync_depth(ctx, NULL, amxs_sync_b_to_a, &path, 0);
609  ret = amxb_get(ctx->bus_ctx_b, ctx->b, depth, &data_b, 5);
610  amxb_set_access(ctx->bus_ctx_b, orig_access);
611  if((ctx->attributes & AMXS_SYNC_ONLY_A_TO_B) == 0) {
612  when_failed(ret, exit);
613  }
614  }
615 
616  status = amxs_initial_sync_entry(ctx, NULL, amxs_sync_invalid, GETI_ARG(&data_a, 0), GETI_ARG(&data_b, 0));
617 
618 exit:
619  amxc_string_clean(&path);
620  amxc_var_clean(&data_a);
621  amxc_var_clean(&data_b);
622  return status;
623 }
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_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)
amxs_sync_direction_t amxs_sync_entry_get_initial_direction(const amxs_sync_entry_t *entry)
enum _amxs_sync_direction amxs_sync_direction_t
@ amxs_sync_invalid
Definition: amxs_types.h:82
bool amxs_sync_entry_is_bidirectional(const amxs_sync_entry_t *entry)
Definition: amxs_util.c:219
#define AMXS_SYNC_ONLY_B_TO_A
Only synchronize from object B to object A.
Definition: amxs_types.h:195
#define AMXS_SYNC_ONLY_A_TO_B
Only synchronize from object A to object B.
Definition: amxs_types.h:200
char * a
Definition: amxs_types.h:163
amxb_bus_ctx_t * bus_ctx_a
Definition: amxs_types.h:171
int attributes
Definition: amxs_types.h:165
char * b
Definition: amxs_types.h:164
amxb_bus_ctx_t * bus_ctx_b
Definition: amxs_types.h:172

◆ amxs_initial_sync_batch_params()

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

Definition at line 341 of file amxs_sync_ctx.c.

344  {
346  amxc_var_t init_data;
347  amxc_var_t* var = GET_ARG(data, object);
348 
349  amxc_var_init(&init_data);
350 
351  when_null_status(var, exit, status = amxs_status_object_not_found);
352 
353  amxs_var_fill_initial_batch_param_data(object, &init_data, var);
354  amxs_callback(direction, &init_data, entry, true);
355 
356  status = amxs_status_ok;
357 
358 exit:
359  amxc_var_clean(&init_data);
360  return status;
361 }
static void amxs_var_fill_initial_batch_param_data(const char *object, amxc_var_t *init_data, const amxc_var_t *data)
@ amxs_status_ok
Definition: amxs_types.h:86
@ amxs_status_object_not_found
Definition: amxs_types.h:93

◆ amxs_initial_sync_child_entries()

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

Definition at line 485 of file amxs_sync_ctx.c.

489  {
491 
492  amxc_llist_for_each(it, &entry->entries) {
493  amxs_sync_entry_t* child = amxc_container_of(it, amxs_sync_entry_t, it);
494  status = amxs_initial_sync_entry(child, parent_path, parent_direction, data_a, data_b);
495  when_failed(status, exit);
496  }
497 
498  status = amxs_status_ok;
499 
500 exit:
501  return status;
502 }
amxc_llist_t entries
Definition: amxs_types.h:169

◆ amxs_initial_sync_entry()

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 
)
static

Definition at line 440 of file amxs_sync_ctx.c.

444  {
447  const amxc_var_t* data = direction == amxs_sync_a_to_b ? data_a : data_b;
448  const char* name = NULL;
449  amxc_string_t object;
450 
451  when_null(data, exit);
452 
453  amxc_string_init(&object, 0);
454 
455  name = amxs_sync_entry_get_name(entry, direction);
456  if(direction != parent_direction) {
457  char* opposite_parent_path = amxs_sync_entry_get_opposite_parent_path(entry, parent_direction, parent_path);
458  amxc_string_set(&object, opposite_parent_path);
459  free(opposite_parent_path);
460  } else {
461  amxc_string_set(&object, parent_path);
462  }
463 
464  switch(entry->type) {
465  case amxs_sync_type_ctx:
466  status = amxs_initial_sync_object(entry, name, direction, data_a, data_b);
467  when_failed(status, exit);
468  break;
470  amxc_string_appendf(&object, "%s", name);
471  status = amxs_initial_sync_object(entry, amxc_string_get(&object, 0), direction, data_a, data_b);
472  break;
474  status = amxs_initial_sync_param(entry, amxc_string_get(&object, 0), name, direction, data);
475  break;
476  default:
477  break;
478  }
479 
480 exit:
481  amxc_string_clean(&object);
482  return status;
483 }
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 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)
@ amxs_sync_type_param
Definition: amxs_types.h:102
@ amxs_sync_type_object
Definition: amxs_types.h:101
@ amxs_sync_type_ctx
Definition: amxs_types.h:100
char * amxs_sync_entry_get_opposite_parent_path(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction, const char *old_path)
Definition: amxs_util.c:456
const char * amxs_sync_entry_get_name(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
Definition: amxs_util.c:264
amxs_sync_entry_type_t type
Definition: amxs_types.h:170

◆ amxs_initial_sync_object()

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

Definition at line 363 of file amxs_sync_ctx.c.

367  {
369  const amxc_var_t* data = direction == amxs_sync_a_to_b ? data_a : data_b;
370  amxc_string_t str;
371  amxc_llist_t list;
372  amxc_var_t init_data;
373 
374  amxc_string_init(&str, 0);
375  amxc_llist_init(&list);
376  amxc_var_init(&init_data);
377 
378  amxc_string_setf(&str, "%s[0-9]+\\.$", object);
379  when_failed(amxs_var_find_keys_regex(data, &list, amxc_string_get(&str, 0)), exit);
380 
381  // This only lists instance objects
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);
384 
385  amxs_var_fill_initial_instance_data(object, instance, &init_data, data);
386  amxs_callback(direction, &init_data, entry, false);
387 
388  status = amxs_initial_sync_child_entries(entry, instance, direction, data_a, data_b);
389  when_failed(status, exit);
390  }
391 
392  // find variant with the exact object name
393  // this will match in case the object is an instance or a non template object
394  if(amxc_var_get_pathf(data, AMXC_VAR_FLAG_DEFAULT, "'%s'", object) != NULL) {
395  status = amxs_initial_sync_batch_params(entry, object, direction, data);
396  when_failed(status, exit);
397  }
398 
399  if(GET_ARG(data, object) != NULL) {
400  status = amxs_initial_sync_child_entries(entry, object, direction, data_a, data_b);
401  when_failed(status, exit);
402  }
403 
404  status = amxs_status_ok;
405 
406 exit:
407  amxc_string_clean(&str);
408  amxc_llist_clean(&list, amxc_string_list_it_free);
409  amxc_var_clean(&init_data);
410  return status;
411 }
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 int amxs_var_find_keys_regex(const amxc_var_t *var, amxc_llist_t *paths, const char *expr_str)
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 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)

◆ amxs_initial_sync_param()

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

Definition at line 413 of file amxs_sync_ctx.c.

417  {
419  amxc_var_t init_data;
420  amxc_var_t* var = GET_ARG(data, object);
421 
422  amxc_var_init(&init_data);
423 
424  when_true_status(amxs_sync_entry_is_batch_param(entry), exit, status = amxs_status_ok);
425  when_null_status(var, exit, status = amxs_status_object_not_found);
426 
427  var = GET_ARG(var, param);
428  when_null_status(var, exit, status = amxs_status_ok);
429 
430  amxs_var_fill_initial_param_data(object, param, &init_data, var);
431  amxs_callback(direction, &init_data, entry, false);
432 
433  status = amxs_status_ok;
434 
435 exit:
436  amxc_var_clean(&init_data);
437  return status;
438 }
static void amxs_var_fill_initial_param_data(const char *object, const char *name, amxc_var_t *init_data, const amxc_var_t *data)
bool amxs_sync_entry_is_batch_param(const amxs_sync_entry_t *const entry)
Definition: amxs_util.c:251

◆ amxs_subscribe()

static amxs_status_t amxs_subscribe ( amxs_sync_ctx_t ctx,
amxs_sync_entry_t entry,
amxs_sync_direction_t  direction 
)
static

Definition at line 181 of file amxs_sync_ctx.c.

183  {
185  amxb_subscription_t* sub = NULL;
186  amxc_string_t str;
187  char* path = NULL;
188  int ret = -1;
189  amxb_bus_ctx_t* bus_ctx = amxs_sync_ctx_get_bus_ctx(ctx, direction);
190  const char* object = amxs_sync_entry_get_name(ctx, direction);
191  const char* name = amxs_sync_entry_get_name(entry, direction);
192  amxp_slot_fn_t fn = direction == amxs_sync_a_to_b ? amxs_callback_a : amxs_callback_b;
193  amxd_path_t p;
194 
195  amxd_path_init(&p, name);
196  amxc_string_init(&str, 0);
197 
198  switch(entry->type) {
200  if(amxs_sync_entry_is_batch_param(entry)) {
201  break;
202  }
203  amxc_string_setf(&str, "notification matches 'dm:object-(changed|added|removed)' && contains('parameters.%s')", name);
204  path = amxs_sync_entry_get_regex_parent_path(entry, direction);
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);
208  amxp_slot_connect(amxs_sync_entry_get_signal_manager(entry), "sync:instance-added", amxc_string_get(&str, 0), fn, entry);
209  when_failed(ret, exit);
210  amxc_llist_append(&ctx->subscriptions, &sub->it);
211  break;
213  if(amxd_path_is_instance_path(&p)) {
214  amxs_subscribe_batch_params(ctx, entry, direction);
215  amxs_subscribe_child_entries(ctx, entry, direction);
216  break;
217  }
218  path = amxs_sync_entry_get_regex_path(entry, direction);
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);
223  amxc_llist_append(&ctx->subscriptions, &sub->it);
224  amxs_subscribe_batch_params(ctx, entry, direction);
225  amxs_subscribe_child_entries(ctx, entry, direction);
226  break;
227  case amxs_sync_type_ctx:
228  amxs_subscribe_batch_params(ctx, entry, direction);
229  amxs_subscribe_child_entries(ctx, entry, direction);
230  break;
231  default:
232  break;
233  }
234 
235  status = amxs_status_ok;
236 
237 exit:
238  amxd_path_clean(&p);
239  free(path);
240  amxc_string_clean(&str);
241  return status;
242 }
static amxs_status_t amxs_subscribe_batch_params(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)
static amxs_status_t amxs_subscribe_child_entries(amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
static void amxs_callback_b(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
char * amxs_sync_entry_get_regex_parent_path(const amxs_sync_entry_t *const entry, amxs_sync_direction_t direction)
Definition: amxs_util.c:502
char * amxs_sync_entry_get_regex_path(const amxs_sync_entry_t *const entry, amxs_sync_direction_t direction)
Definition: amxs_util.c:469
amxp_signal_mngr_t * amxs_sync_entry_get_signal_manager(const amxs_sync_entry_t *const entry)
Definition: amxs_util.c:317
amxb_bus_ctx_t * amxs_sync_ctx_get_bus_ctx(const amxs_sync_ctx_t *ctx, amxs_sync_direction_t direction)
Definition: amxs_util.c:343
amxc_llist_t subscriptions
Definition: amxs_types.h:173
static amxb_bus_ctx_t * bus_ctx

◆ amxs_subscribe_batch_params()

static amxs_status_t amxs_subscribe_batch_params ( amxs_sync_ctx_t ctx,
amxs_sync_entry_t entry,
amxs_sync_direction_t  direction 
)
static

Definition at line 139 of file amxs_sync_ctx.c.

141  {
143  const char* object = amxs_sync_entry_get_name(ctx, direction);
144  amxb_bus_ctx_t* bus_ctx = amxs_sync_ctx_get_bus_ctx(ctx, direction);
145  amxp_slot_fn_t fn = direction == amxs_sync_a_to_b ? amxs_batch_callback_a : amxs_batch_callback_b;
146  amxc_var_t params;
147  amxb_subscription_t* sub = NULL;
148  char* path = NULL;
149  amxc_string_t str;
150  int ret = -1;
151 
152  amxc_var_init(&params);
153  amxc_var_set_type(&params, AMXC_VAR_ID_LIST);
154  amxc_string_init(&str, 0);
155 
156  status = amxs_sync_entry_get_batch_params(entry, &params, direction);
157  when_failed(status, exit);
158  when_null_status(amxc_var_get_first(&params), exit, status = amxs_status_ok);
159 
160  path = amxs_sync_entry_get_regex_path(entry, direction);
161  when_str_empty(path, exit);
162 
163  amxc_string_setf(&str, "notification matches 'dm:object-(changed|added|removed)' && path matches '%s' && (", path);
164  amxc_var_for_each(var, &params) {
165  amxc_string_appendf(&str, " contains('parameters.%s') ||", GET_CHAR(var, NULL));
166  }
167  amxc_string_remove_at(&str, amxc_string_text_length(&str) - 3, 3);
168  amxc_string_append(&str, ")", 1);
169 
170  ret = amxb_subscription_new(&sub, bus_ctx, object, amxc_string_get(&str, 0), fn, entry);
171  when_failed(ret, exit);
172  amxc_llist_append(&ctx->subscriptions, &sub->it);
173 
174 exit:
175  amxc_var_clean(&params);
176  free(path);
177  amxc_string_clean(&str);
178  return status;
179 }
static void amxs_batch_callback_b(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
static void amxs_batch_callback_a(UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
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)
Definition: amxs_util.c:514

◆ amxs_subscribe_child_entries()

static amxs_status_t amxs_subscribe_child_entries ( amxs_sync_ctx_t ctx,
amxs_sync_entry_t entry,
amxs_sync_direction_t  direction 
)
static

Definition at line 244 of file amxs_sync_ctx.c.

246  {
248 
249  amxc_llist_for_each(it, &entry->entries) {
250  amxs_sync_entry_t* child = amxc_container_of(it, amxs_sync_entry_t, it);
251  if(amxs_sync_entry_direction_allowed(child, direction)) {
252  status = amxs_subscribe(ctx, child, direction);
253  when_failed(status, exit);
254  }
255  }
256 
257  status = amxs_status_ok;
258 
259 exit:
260  return status;
261 }
static amxs_status_t amxs_subscribe(amxs_sync_ctx_t *ctx, amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
bool amxs_sync_entry_direction_allowed(const amxs_sync_entry_t *entry, amxs_sync_direction_t direction)
Definition: amxs_util.c:231

◆ amxs_sync_ctx_add_new_copy_object()

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.

Allocates memory for a new synchronization object and initializes this object. Then adds it to the synchronization context.

Adding the synchronization object fails when:

  • The object was already added to the context
  • The object attributes are conflicting with those of the context. E.g. The context has the AMXS_SYNC_ONLY_B_TO_A attribute set, and the object has AMXS_SYNC_ONLY_A_TO_B set.

If the context attributes are more strict than those of the object, the object attributes will be updated to match those of the context.

Uses default translation amxs_sync_object_copy_trans_cb and action amxs_sync_object_copy_action_cb callbacks.

Parameters
ctxPointer to a synchronization context.
object_aName of the object in object A
object_bName of the object in object B
attributesBitwise OR of zero or more of the following attributes:
Returns
  • amxs_status_ok: the new synchronization object is added to the synchronization context
  • amxs_status_duplicate: another synchronization object with the same direction and object names already exists for this synchronization context
  • amxs_status_invalid_attr: the attributes of the synchronization object are conflicting with those of the synchronization context
  • amxs_status_unknown_error: any other error

Definition at line 951 of file amxs_sync_ctx.c.

954  {
955  return amxs_sync_ctx_add_new_object(ctx,
956  object_a,
957  object_b,
958  attributes,
961  NULL);
962 }
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_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_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_sync_ctx_paths_match()

static bool amxs_sync_ctx_paths_match ( const char *  new_path,
const char *  old_path 
)
static

Definition at line 687 of file amxs_sync_ctx.c.

687  {
688  bool retval = false;
689  amxd_path_t old_p;
690  amxd_path_t new_p;
691  char* supported_old = NULL;
692  char* supported_new = NULL;
693 
694  amxd_path_init(&old_p, NULL);
695  amxd_path_init(&new_p, NULL);
696 
697  amxd_path_setf(&old_p, false, "%s", new_path);
698  amxd_path_setf(&new_p, false, "%s", old_path);
699 
700  supported_old = amxd_path_get_supported_path(&old_p);
701  supported_new = amxd_path_get_supported_path(&new_p);
702 
703  retval = strcmp(supported_old, supported_new) == 0;
704 
705  free(supported_old);
706  free(supported_new);
707  amxd_path_clean(&old_p);
708  amxd_path_clean(&new_p);
709 
710  return retval;
711 }

◆ amxs_sync_ctx_set_local_dm()

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.

If one or both root objects for the synchronization are located in the same process as the synchronization code, it is possible to add read-only parameters to the sync.

Having access to the datamodel enables the writing of read-only parameters.

The datamodel pointer should only be set if the synchronization needs to write the object.

Parameters
ctxPointer to a synchronization context.
dm_aPointer to the local datamodel which contains object A, may be NULL
dm_bPointer to the local datamodel which contains object B, may be NULL
Returns
  • amxs_status_ok: the datamodel pointers have been set successfully
  • amxs_status_unknown_error: any other error

Definition at line 964 of file amxs_sync_ctx.c.

966  {
968  when_null(ctx, exit);
969  when_false_status(ctx->type == amxs_sync_type_ctx, exit, status = amxs_status_invalid_type);
970 
971  if(((ctx->attributes & AMXS_SYNC_ONLY_B_TO_A) != 0) && (dm_b != NULL)) {
972  status = amxs_status_invalid_arg;
973  goto exit;
974  }
975 
976  if(((ctx->attributes & AMXS_SYNC_ONLY_A_TO_B) != 0) && (dm_a != NULL)) {
977  status = amxs_status_invalid_arg;
978  goto exit;
979  }
980 
981  ctx->local_dm_a = dm_a;
982  ctx->local_dm_b = dm_b;
983 
984  status = amxs_status_ok;
985 
986 exit:
987  return status;
988 }
@ amxs_status_invalid_type
Definition: amxs_types.h:92
@ amxs_status_invalid_arg
Definition: amxs_types.h:89
amxd_dm_t * local_dm_b
Definition: amxs_types.h:178
amxd_dm_t * local_dm_a
Definition: amxs_types.h:177

◆ amxs_sync_ctx_validate_path()

static amxs_status_t amxs_sync_ctx_validate_path ( amxs_sync_ctx_t ctx,
amxs_sync_direction_t  direction 
)
static

Definition at line 625 of file amxs_sync_ctx.c.

625  {
626  amxc_var_t data;
627  amxb_bus_ctx_t* bus_ctx = NULL;
628  char** path = NULL;
629  const char* new_path = NULL;
631  int ret = -1;
632  amxc_llist_it_t* it = NULL;
633  amxd_path_t p;
634 
635  amxc_var_init(&data);
636  amxd_path_init(&p, NULL);
637  when_null(ctx, exit);
638 
639  bus_ctx = direction == amxs_sync_a_to_b ? ctx->bus_ctx_a : ctx->bus_ctx_b;
640  path = direction == amxs_sync_a_to_b ? &ctx->a : &ctx->b;
641 
642  when_null(bus_ctx, exit);
643  when_str_empty(*path, exit);
644 
645  amxd_path_setf(&p, true, "%s", *path);
646  ret = amxb_resolve(bus_ctx, &p, &data);
647  when_failed(ret, exit);
648 
649  it = amxc_llist_get_first(amxc_var_constcast(amxc_llist_t, &data));
650  if((it == NULL) || (amxc_llist_it_get_next(it) != NULL)) {
651  goto exit;
652  }
653 
654  new_path = GET_CHAR(amxc_llist_it_get_data(it, amxc_var_t, lit), NULL);
655  when_str_empty(new_path, exit);
656  free(*path);
657  *path = strdup(new_path);
658 
659  stat = amxs_status_ok;
660 
661 exit:
662  amxd_path_clean(&p);
663  amxc_var_clean(&data);
664  return stat;
665 }

◆ amxs_sync_ctx_verify_local_dm()

static amxs_status_t amxs_sync_ctx_verify_local_dm ( amxs_sync_ctx_t ctx,
amxs_sync_direction_t  direction 
)
static

Definition at line 667 of file amxs_sync_ctx.c.

668  {
670  amxd_dm_t* dm = NULL;
671  const char* path = NULL;
672 
673  when_null(ctx, exit);
674 
675  dm = direction == amxs_sync_a_to_b ? ctx->local_dm_b : ctx->local_dm_a;
676  path = direction == amxs_sync_a_to_b ? ctx->b : ctx->a;
677  when_null_status(dm, exit, status = amxs_status_ok);
678 
679  when_null_status(amxd_dm_findf(dm, "%s", path), exit, status = amxs_status_object_not_found);
680 
681  status = amxs_status_ok;
682 
683 exit:
684  return status;
685 }

◆ amxs_sync_depth()

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

Definition at line 517 of file amxs_sync_ctx.c.

521  {
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;
527  char* part = NULL;
528  char* endptr = NULL;
529  amxd_object_type_t type = amxd_object_singleton;
530 
531  sync_entry = sync_entry == NULL? sync_ctx:sync_entry;
532  ctx = (direction == amxs_sync_a_to_b)? sync_ctx->bus_ctx_a:sync_ctx->bus_ctx_b;
533  sync_path = (direction == amxs_sync_a_to_b)? sync_entry->a: sync_entry->b;
534 
535  when_null(sync_path, exit);
536 
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);
540 
541  part = amxd_path_get_first(&rel_path, true);
542  if(strtoull(part, &endptr, 10) != 0) {
543  // if the relative path starts with a number then it is an instance
544  // decrease by 1 as the parent sync entry already added 1 for a template
545  start -= 1;
546  }
547  free(part);
548  amxd_path_clean(&rel_path);
549 
550  depth = start;
551  amxc_llist_iterate(it, &sync_entry->entries) {
552  uint32_t tree_depth = 0;
553  amxs_sync_entry_t* entry = amxc_container_of(it, amxs_sync_entry_t, it);
554  if(entry->type == amxs_sync_type_object) {
555  tree_depth = amxs_sync_depth(sync_ctx, entry, direction, path, start);
556  if(tree_depth > depth) {
557  depth = tree_depth;
558  }
559  }
560  }
561 
562  // If the current entry in the sync hierarchy is a template object the instances must be
563  // monitored as well, so add 1 in the depth
564  type = amxb_get_object_type(ctx, amxc_string_get(path, 0));
565  if(type == amxd_object_template) {
566  depth++;
567  }
568 
569  amxc_string_remove_at(path, path_pos, strlen(sync_path));
570 
571 exit:
572  return depth;
573 }
static amxd_object_type_t amxb_get_object_type(amxb_bus_ctx_t *ctx, const char *path)

◆ amxs_var_fill_initial_batch_param_data()

static void amxs_var_fill_initial_batch_param_data ( const char *  object,
amxc_var_t *  init_data,
const amxc_var_t *  data 
)
static

Definition at line 328 of file amxs_sync_ctx.c.

330  {
331  amxc_var_t* params = NULL;
332 
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);
339 }

◆ amxs_var_fill_initial_instance_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

Definition at line 291 of file amxs_sync_ctx.c.

294  {
295  unsigned int index = strtoul(instance + strlen(object), NULL, 0);
296  amxc_var_t* tmp = NULL;
297 
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));
304 }

◆ amxs_var_fill_initial_param_data()

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

Definition at line 306 of file amxs_sync_ctx.c.

309  {
310  amxc_var_t* params = NULL;
311  amxc_var_t* param = NULL;
312 
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);
320 }

◆ amxs_var_find_keys_regex()

static int amxs_var_find_keys_regex ( const amxc_var_t *  var,
amxc_llist_t *  paths,
const char *  expr_str 
)
static

Definition at line 263 of file amxs_sync_ctx.c.

265  {
266  amxc_string_t str;
267  int ret = -1;
268 
269  amxc_string_init(&str, 0);
270 
271  amxc_var_for_each(variant, var) {
272  amxp_expr_t expr;
273  amxp_expr_status_t status;
274 
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));
280  }
281  amxp_expr_clean(&expr);
282  }
283 
284  ret = 0;
285 
286 exit:
287  amxc_string_clean(&str);
288  return ret;
289 }