libamxo  4.3.4
Object Definition Language (ODL) parsing
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
amxo_parser_dm_sync_utils.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 #ifndef _GNU_SOURCE
55 #define _GNU_SOURCE
56 #endif
57 
58 #include "amxo_parser_priv.h"
59 #include "amxo_parser.tab.h"
60 #include "amxo_parser_hooks_priv.h"
61 
62 #define MSG_CREATION_FAILED \
63  "Creation failed for %s and %s (direction = %d, status = %d)"
64 #define MSG_SET_DM_FAILED \
65  "Set datamodel for %s and %s failed (direction = %d, status = %d)"
66 #define MSG_MUST_CONTAIN_SYNC_ENTRIES \
67  "Object synchronisation must contain sub-entries"
68 #define MSG_BATCH_PARAM_WITH_CB \
69  "Batch parameter synchronisation with callbacks have no effect"
70 
71 typedef struct _amxo_sync_data {
72  amxs_sync_entry_t* entry;
73  amxc_llist_it_t it;
74  amxc_htable_it_t hit;
76 
77 typedef amxs_status_t (* amxo_sync_add_item_fn_t) (amxs_sync_object_t* parent,
78  amxs_sync_object_t* child);
79 
80 static amxc_htable_t sync_templates;
81 
83  amxc_llist_it_t* it = amxc_llist_get_last(pctx->sync_contexts);
84  amxo_sync_data_t* data = amxc_container_of(it, amxo_sync_data_t, it);
85 
86  return data;
87 }
88 
89 static amxs_status_t amxo_parser_sync_add_item(amxo_parser_t* pctx,
90  amxo_sync_data_t* data,
92  amxo_sync_add_item_fn_t object_add) {
93  amxs_status_t status = amxs_status_unknown_error;
94  amxo_sync_data_t* parent = NULL;
95 
96  parent = amxo_parser_get_sync_data(pctx);
97  when_null(parent, exit);
98  when_null(parent->entry, exit);
99 
100  switch(parent->entry->type) {
101  case amxs_sync_type_ctx:
102  status = ctx_add(parent->entry, data->entry);
103  break;
104  case amxs_sync_type_object:
105  status = object_add(parent->entry, data->entry);
106  break;
107  default:
108  break;
109  }
110 
111  if(status == amxs_status_ok) {
112  amxc_llist_append(pctx->sync_contexts, &data->it);
113  }
114 
115 exit:
116  return status;
117 }
118 
119 static amxd_dm_t* amxo_parser_get_sync_dm(amxo_parser_t* pctx,
120  const char* path) {
121  amxd_dm_t* dm = amxd_object_get_dm(pctx->object);
122  dm = amxd_dm_findf(dm, "%s", path) == NULL? NULL:dm;
123  return dm;
124 }
125 
126 static void amxo_parser_sync_set_status(amxo_parser_t* pctx, amxs_status_t status) {
127  switch(status) {
128  case amxs_status_ok:
129  pctx->status = amxd_status_ok;
130  break;
131  case amxs_status_duplicate:
132  pctx->status = amxd_status_duplicate;
133  break;
134  case amxs_status_invalid_attr:
135  pctx->status = amxd_status_invalid_attr;
136  break;
137  case amxs_status_invalid_arg:
138  pctx->status = amxd_status_invalid_arg;
139  break;
140  case amxs_status_empty_context:
141  pctx->status = amxd_status_invalid_value;
142  break;
143  case amxs_status_invalid_type:
144  pctx->status = amxd_status_invalid_type;
145  break;
146  case amxs_status_object_not_found:
147  pctx->status = amxd_status_object_not_found;
148  break;
149  case amxs_status_subscription_failed:
150  pctx->status = amxd_status_function_not_found;
151  break;
152  default:
153  pctx->status = amxd_status_unknown_error;
154  break;
155  }
156 }
157 
158 amxs_sync_entry_type_t amxo_parser_get_sync_type(amxo_parser_t* pctx) {
159  amxs_sync_entry_type_t type = amxs_sync_type_invalid;
160  amxo_sync_data_t* sync_data = amxo_parser_get_sync_data(pctx);
161  when_null(sync_data, exit);
162  when_null(sync_data->entry, exit);
163 
164  type = sync_data->entry->type;
165 
166 exit:
167  return type;
168 }
169 
171  amxs_sync_entry_type_t type = amxo_parser_get_sync_type(pctx);
172  return (type == amxs_sync_type_object || type == amxs_sync_type_param);
173 }
174 
175 int amxo_parser_sync_update_flags(int direction) {
176  if((direction & AMXS_SYNC_ONLY_B_TO_A) == AMXS_SYNC_ONLY_B_TO_A) {
177  direction |= AMXS_SYNC_INIT_B;
178  }
179 
180  return direction;
181 }
182 
183 void amxo_parser_del_sync_data(amxc_llist_it_t* it) {
184  amxo_sync_data_t* data = amxc_container_of(it, amxo_sync_data_t, it);
185  when_null(data, exit);
186 
187  amxc_llist_it_take(it);
188  amxc_htable_it_clean(&data->hit, NULL);
189 
190  when_null(data->entry, exit);
191 
192  switch(data->entry->type) {
193  case amxs_sync_type_ctx:
194  amxs_sync_ctx_delete(&data->entry);
195  break;
196  case amxs_sync_type_object:
197  amxs_sync_object_delete(&data->entry);
198  break;
199  case amxs_sync_type_param:
200  amxs_sync_param_delete(&data->entry);
201  break;
202  default:
203  break;
204  }
205 
206 exit:
207  free(data);
208 }
209 
211  amxo_sync_data_t* data = NULL;
212  when_null(pctx->sync_contexts, exit);
213 
214  data = amxo_parser_get_sync_data(pctx);
215  amxc_llist_it_take(&data->it);
216  free(data);
217 
218 exit:
219  return;
220 }
221 
223  const char* path_a,
224  const char* path_b,
225  int direction) {
226  amxs_status_t status = amxs_status_unknown_error;
227  amxc_string_t res_path_a;
228  amxc_string_t res_path_b;
229  amxd_dm_t* dm_a = NULL;
230  amxd_dm_t* dm_b = NULL;
231  amxo_sync_data_t* data =
232  (amxo_sync_data_t*) calloc(1, sizeof(amxo_sync_data_t));
233 
234  amxc_string_init(&res_path_a, 0);
235  amxc_string_init(&res_path_b, 0);
236  when_null(data, exit);
237 
238  if(amxc_string_set_resolved(&res_path_a, path_a, &pctx->config) > 0) {
239  path_a = amxc_string_get(&res_path_a, 0);
240  }
241  if(amxc_string_set_resolved(&res_path_b, path_b, &pctx->config) > 0) {
242  path_b = amxc_string_get(&res_path_b, 0);
243  }
244 
245  status = amxs_sync_ctx_new(&data->entry, path_a, path_b, direction);
246  if(status != 0) {
248  path_a, path_b, direction, status);
249  amxo_parser_sync_set_status(pctx, status);
250  data->entry = NULL;
251  goto exit;
252  }
253 
254  if((direction & AMXS_SYNC_ONLY_A_TO_B) == 0) {
255  dm_a = amxo_parser_get_sync_dm(pctx, path_a);
256  }
257  if((direction & AMXS_SYNC_ONLY_B_TO_A) == 0) {
258  dm_b = amxo_parser_get_sync_dm(pctx, path_b);
259  }
260 
261  status = amxs_sync_ctx_set_local_dm(data->entry, dm_a, dm_b);
262  if(status != 0) {
264  path_a, path_b, direction, status);
265  amxo_parser_sync_set_status(pctx, status);
266  goto exit;
267  }
268 
269  if(pctx->sync_contexts == NULL) {
270  amxc_llist_new(&pctx->sync_contexts);
271  }
272  amxc_llist_append(pctx->sync_contexts, &data->it);
273 
274 exit:
275  if(status != 0) {
276  if(data != NULL) {
278  }
279  }
280  amxc_string_clean(&res_path_a);
281  amxc_string_clean(&res_path_b);
282  return status;
283 }
284 
286  const char* path_a,
287  const char* path_b,
288  int direction,
289  const char* name) {
290  int status = amxs_status_unknown_error;
291  amxd_path_t path;
292  amxo_sync_data_t* data = NULL;
293  amxd_path_init(&path, NULL);
294 
295  status = amxo_parser_push_sync_ctx(pctx, path_a, path_b, direction);
296  when_failed(status, exit);
297 
298  data = amxo_parser_get_sync_data(pctx);
299  status = amxs_status_invalid_type;
300  amxd_path_setf(&path, false, "%s", data->entry->a);
301  when_true(amxd_path_is_instance_path(&path), exit);
302  when_false(amxd_path_is_supported_path(&path) || amxd_path_is_object_path(&path), exit);
303  amxd_path_setf(&path, false, "%s", data->entry->b);
304  when_true(amxd_path_is_instance_path(&path), exit);
305  when_false(amxd_path_is_supported_path(&path) || amxd_path_is_object_path(&path), exit);
306  status = amxs_status_ok;
307 
308  amxc_htable_insert(&sync_templates, name, &data->hit);
309 
310 exit:
311  if(status != 0) {
312  if(data != NULL) {
314  }
315  }
316  amxd_path_clean(&path);
317  return status;
318 }
319 
321  const char* path_a,
322  const char* path_b,
323  int direction) {
324  amxs_status_t status = amxs_status_unknown_error;
325  amxc_string_t res_a;
326  amxc_string_t res_b;
327  amxo_sync_data_t* data = NULL;
328 
329  amxc_string_init(&res_a, 0);
330  amxc_string_init(&res_b, 0);
331 
332  data = (amxo_sync_data_t*) calloc(1, sizeof(amxo_sync_data_t));
333  when_null(data, exit);
334 
335  if(amxc_string_set_resolved(&res_a, path_a, &pctx->config) > 0) {
336  path_a = amxc_string_get(&res_a, 0);
337  }
338  if(amxc_string_set_resolved(&res_b, path_b, &pctx->config) > 0) {
339  path_b = amxc_string_get(&res_b, 0);
340  }
341 
342  status = amxs_sync_object_new_copy(&data->entry, path_a, path_b, direction);
343  when_failed_status(status, exit, data->entry = NULL);
344 
345  status = amxo_parser_sync_add_item(pctx, data,
346  amxs_sync_ctx_add_object,
347  amxs_sync_object_add_object);
348 
349 exit:
350  if(status != 0) {
352  path_a, path_b, direction, status);
353  amxo_parser_sync_set_status(pctx, status);
354  if(data != NULL) {
355  amxs_sync_object_delete(&data->entry);
356  }
357  free(data);
358  }
359  amxc_string_clean(&res_a);
360  amxc_string_clean(&res_b);
361  return status;
362 }
363 
365  const char* param_a,
366  const char* param_b,
367  int direction) {
368  amxs_status_t status = amxs_status_unknown_error;
369  amxc_string_t res_a;
370  amxc_string_t res_b;
371  amxo_sync_data_t* data = NULL;
372 
373  amxc_string_init(&res_a, 0);
374  amxc_string_init(&res_b, 0);
375 
376  data = (amxo_sync_data_t*) calloc(1, sizeof(amxo_sync_data_t));
377  when_null(data, exit);
378 
379  if(amxc_string_set_resolved(&res_a, param_a, &pctx->config) > 0) {
380  param_a = amxc_string_get(&res_a, 0);
381  }
382  if(amxc_string_set_resolved(&res_b, param_b, &pctx->config) > 0) {
383  param_b = amxc_string_get(&res_b, 0);
384  }
385 
386  status = amxs_sync_param_new_copy(&data->entry, param_a, param_b, direction);
387  when_failed_status(status, exit, data->entry = NULL);
388 
389  status = amxo_parser_sync_add_item(pctx,
390  data,
391  amxs_sync_ctx_add_param,
392  amxs_sync_object_add_param);
393 
394 exit:
395  if(status != 0) {
397  param_a, param_b, direction, status);
398  amxo_parser_sync_set_status(pctx, status);
399  if(data != NULL) {
400  amxs_sync_param_delete(&data->entry);
401  }
402  free(data);
403  }
404  amxc_string_clean(&res_a);
405  amxc_string_clean(&res_b);
406  return status;
407 }
408 
410  amxs_translation_cb_t cb) {
411  amxd_status_t status = amxd_status_unknown_error;
412  amxo_sync_data_t* sync_data = amxo_parser_get_sync_data(pctx);
413  when_null(sync_data, exit);
414  when_null(sync_data->entry, exit);
415 
416  if(amxs_sync_entry_is_batch_param(sync_data->entry)) {
418  pctx->status = amxd_status_invalid_action;
419  } else {
420  sync_data->entry->translation_cb = cb;
421  status = amxd_status_ok;
422  }
423 
424 exit:
425  return status;
426 }
427 
429  amxs_action_cb_t cb) {
430  amxd_status_t status = amxd_status_unknown_error;
431  amxo_sync_data_t* sync_data = amxo_parser_get_sync_data(pctx);
432  when_null(sync_data, exit);
433  when_null(sync_data->entry, exit);
434 
435  if(amxs_sync_entry_is_batch_param(sync_data->entry)) {
437  pctx->status = amxd_status_invalid_action;
438  } else {
439  sync_data->entry->action_cb = cb;
440  status = amxd_status_ok;
441  }
442 
443 exit:
444  return status;
445 }
446 
448  bool retval = false;
449  amxo_sync_data_t* sync_data = amxo_parser_get_sync_data(pctx);
450  when_null(sync_data, exit);
451  when_null(sync_data->entry, exit);
452 
453  retval = true;
454  if(amxc_llist_is_empty(&sync_data->entry->entries)) {
456  pctx->status = amxd_status_invalid_action;
457  retval = false;
458  }
459 
460 exit:
461  return retval;
462 }
463 
464 int amxo_parser_start_sync(amxc_llist_it_t* it) {
465  int status = -1;
466  amxo_sync_data_t* data = amxc_container_of(it, amxo_sync_data_t, it);
467  when_null(data, exit);
468  when_null(data->entry, exit);
469  when_false(data->entry->type == amxs_sync_type_ctx, exit);
470 
471  if(amxc_htable_it_get_key(&data->hit) == NULL) {
472  if(!amxs_sync_ctx_is_started(data->entry)) {
473  status = amxs_sync_ctx_start_sync(data->entry);
474  }
475  } else {
476  status = 0;
477  }
478 
479 exit:
480  return status;
481 }
482 
483 void amxo_parser_stop_sync(amxc_llist_it_t* it) {
484  amxo_sync_data_t* data = amxc_container_of(it, amxo_sync_data_t, it);
485  when_null(data, exit);
486  when_null(data->entry, exit);
487  when_false(data->entry->type == amxs_sync_type_ctx, exit);
488 
489  if(amxc_htable_it_get_key(&data->hit) == NULL) {
490  amxs_sync_ctx_stop_sync(data->entry);
491  }
492 
493 exit:
494  return;
495 }
496 
498  when_null(pctx, exit);
499  when_null(pctx->sync_contexts, exit);
500 
501  amxc_llist_for_each_reverse(it, pctx->sync_contexts) {
502  amxo_sync_data_t* data = amxc_container_of(it, amxo_sync_data_t, it);
503  switch(data->entry->type) {
504  case amxs_sync_type_param:
505  case amxs_sync_type_object:
507  break;
508  case amxs_sync_type_ctx:
509  if(amxc_llist_is_empty(&data->entry->entries)) {
511  }
512  break;
513  default:
514  break;
515  }
516  }
517 
518  if(amxc_llist_is_empty(pctx->sync_contexts)) {
519  amxc_llist_delete(&pctx->sync_contexts, NULL);
520  }
521 
522 exit:
523  return;
524 }
525 
526 amxs_sync_ctx_t* amxo_parser_sync_get(const char* sync_template) {
527  amxs_sync_ctx_t* ctx = NULL;
528  amxo_sync_data_t* sync_data = NULL;
529  amxc_htable_it_t* hit = amxc_htable_get(&sync_templates, sync_template);
530 
531  when_null(hit, exit);
532  sync_data = amxc_container_of(hit, amxo_sync_data_t, hit);
533 
534  ctx = sync_data->entry;
535 
536 exit:
537  return ctx;
538 }
539 
540 CONSTRUCTOR_LVL(110) static void amxo_parser_sync_templates_init(void) {
541  amxc_htable_init(&sync_templates, 10);
542 }
543 
544 DESTRUCTOR_LVL(110) static void amxo_parser_sync_templates_cleanup(void) {
545  amxc_htable_clean(&sync_templates, NULL);
546 }
amxs_sync_entry_type_t amxo_parser_get_sync_type(amxo_parser_t *pctx)
#define MSG_MUST_CONTAIN_SYNC_ENTRIES
static amxc_htable_t sync_templates
static amxd_dm_t * amxo_parser_get_sync_dm(amxo_parser_t *pctx, const char *path)
struct _amxo_sync_data amxo_sync_data_t
amxd_status_t amxo_parser_sync_set_translator(amxo_parser_t *pctx, amxs_translation_cb_t cb)
int amxo_parser_push_sync_ctx(amxo_parser_t *pctx, const char *path_a, const char *path_b, int direction)
int amxo_parser_start_sync(amxc_llist_it_t *it)
static amxs_status_t amxo_parser_sync_add_item(amxo_parser_t *pctx, amxo_sync_data_t *data, amxo_sync_add_item_fn_t ctx_add, amxo_sync_add_item_fn_t object_add)
amxd_status_t amxo_parser_sync_set_action(amxo_parser_t *pctx, amxs_action_cb_t cb)
amxs_sync_ctx_t * amxo_parser_sync_get(const char *sync_template)
int amxo_parser_push_sync_object(amxo_parser_t *pctx, const char *path_a, const char *path_b, int direction)
bool amxo_parser_is_sync_item(amxo_parser_t *pctx)
static void amxo_parser_sync_set_status(amxo_parser_t *pctx, amxs_status_t status)
void amxo_parser_sync_remove_invalid(amxo_parser_t *pctx)
#define MSG_SET_DM_FAILED
int amxo_parser_push_sync_parameter(amxo_parser_t *pctx, const char *param_a, const char *param_b, int direction)
#define MSG_CREATION_FAILED
void amxo_parser_pop_sync_item(amxo_parser_t *pctx)
#define MSG_BATCH_PARAM_WITH_CB
amxs_status_t(* amxo_sync_add_item_fn_t)(amxs_sync_object_t *parent, amxs_sync_object_t *child)
int amxo_parser_push_sync_template(amxo_parser_t *pctx, const char *path_a, const char *path_b, int direction, const char *name)
void amxo_parser_del_sync_data(amxc_llist_it_t *it)
int amxo_parser_sync_update_flags(int direction)
CONSTRUCTOR_LVL(110)
static amxo_sync_data_t * amxo_parser_get_sync_data(amxo_parser_t *pctx)
DESTRUCTOR_LVL(110)
void amxo_parser_stop_sync(amxc_llist_it_t *it)
bool amxo_parser_sync_item_contains_entries(amxo_parser_t *pctx)
PRIVATE void amxo_parser_msg(amxo_parser_t *parser, const char *format,...) __attribute__((format(printf
The ODL parser structure.
Definition: amxo_types.h:245
amxc_var_t config
Definition: amxo_types.h:250
amxd_status_t status
Definition: amxo_types.h:258
amxd_object_t * object
Definition: amxo_types.h:262
amxc_llist_t * sync_contexts
Definition: amxo_types.h:290
amxs_sync_entry_t * entry