libamxs  0.6.0
Data Model Synchronization C API
amxs_sync_entry.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 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <stdlib.h>
60 #include <string.h>
61 
62 #include <amxc/amxc.h>
63 
64 #include "amxs_sync_entry.h"
65 #include "amxs_priv.h"
66 
67 static void amxs_llist_it_delete_sync_entry(amxc_llist_it_t* it) {
68  amxs_sync_entry_t* entry = amxc_container_of(it, amxs_sync_entry_t, it);
69 
70  amxs_sync_entry_delete(&entry);
71 }
72 
73 static int amxs_sync_entry_compare_name(const char* const a, const char* const b) {
74  int ret = -1;
75 
76  if((a == NULL) && (b != NULL)) {
77  goto exit;
78  }
79 
80  if((a != NULL) && (b == NULL)) {
81  goto exit;
82  }
83 
84  if(((a != NULL) && (b != NULL)) && (strcmp(a, b) != 0)) {
85  goto exit;
86  }
87 
88  ret = 0;
89 
90 exit:
91  return ret;
92 }
93 
96  when_null(entry, exit);
97 
98  direction = (entry->attributes & AMXS_SYNC_INIT_B) == 0 ? amxs_sync_a_to_b : amxs_sync_b_to_a;
99 
100 exit:
101  return direction;
102 }
103 
105  const char* a,
106  const char* b,
107  int attributes,
108  amxs_translation_cb_t translation_cb,
109  amxs_action_cb_t action_cb,
111  void* priv) {
113  when_null(entry, exit);
114 
115  *entry = (amxs_sync_entry_t*) calloc(1, sizeof(amxs_sync_entry_t));
116  when_null(*entry, exit);
117 
118  status = amxs_sync_entry_init(*entry, a, b, attributes, translation_cb, action_cb, type, priv);
119  if(status != amxs_status_ok) {
120  free(*entry);
121  *entry = NULL;
122  }
123 
124 exit:
125  return status;
126 }
127 
129  when_null(entry, exit);
130  when_null(*entry, exit);
131 
132  amxs_sync_entry_clean(*entry);
133 
134  free(*entry);
135  *entry = NULL;
136 
137 exit:
138  return;
139 }
140 
142  const char* a,
143  const char* b,
144  int attributes,
145  amxs_translation_cb_t translation_cb,
146  amxs_action_cb_t action_cb,
148  void* priv) {
150  when_null(entry, exit);
151 
152  status = amxs_validate_attributes(attributes, 0);
153  when_failed(status, exit);
154 
155  memset(entry, 0, sizeof(amxs_sync_entry_t));
156 
157  status = amxs_status_invalid_arg;
158  if((attributes & AMXS_SYNC_ONLY_B_TO_A) == 0) {
159  when_str_empty(a, exit);
160  }
161 
162  if((attributes & AMXS_SYNC_ONLY_A_TO_B) == 0) {
163  when_str_empty(b, exit);
164  }
165 
166  if(a != NULL) {
167  if((type != amxs_sync_type_param) && (a[strlen(a) - 1] != '.')) {
168  status = amxs_status_invalid_arg;
169  goto exit;
170  }
171  entry->a = strdup(a);
172  when_null(entry->a, exit);
173  }
174 
175  if(b != NULL) {
176  if((type != amxs_sync_type_param) && (b[strlen(b) - 1] != '.')) {
177  status = amxs_status_invalid_arg;
178  goto exit;
179  }
180  entry->b = strdup(b);
181  when_null(entry->b, exit);
182  }
183 
184  entry->attributes = attributes;
185  entry->action_cb = action_cb;
186  entry->translation_cb = translation_cb;
187  entry->type = type;
188  entry->priv = priv;
189  entry->bus_ctx_a = NULL;
190  entry->bus_ctx_b = NULL;
191  amxc_llist_it_init(&entry->it);
192  amxc_llist_init(&entry->entries);
193  amxc_llist_init(&entry->subscriptions);
194  amxc_var_init(&entry->a_to_b);
195  amxc_var_init(&entry->b_to_a);
196  entry->local_dm_a = NULL;
197  entry->local_dm_b = NULL;
198 
199  if(type == amxs_sync_type_ctx) {
200  amxc_var_set_type(&entry->a_to_b, AMXC_VAR_ID_HTABLE);
201  amxc_var_set_type(&entry->b_to_a, AMXC_VAR_ID_HTABLE);
202  when_failed(amxp_sigmngr_new(&entry->sig_mngr), exit);
203  amxp_sigmngr_add_signal(entry->sig_mngr, "sync:instance-added");
204  }
205 
206  status = amxs_status_ok;
207 
208 exit:
209  if((status != amxs_status_ok) && (entry != NULL)) {
210  free(entry->a);
211  entry->a = NULL;
212  free(entry->b);
213  entry->b = NULL;
214  amxc_var_clean(&entry->a_to_b);
215  amxc_var_clean(&entry->b_to_a);
216  }
217  return status;
218 }
219 
221  when_null(entry, exit);
222 
223  if(entry->type == amxs_sync_type_ctx) {
224  amxp_sigmngr_delete(&entry->sig_mngr);
225  }
226 
227  free(entry->a);
228  entry->a = NULL;
229  free(entry->b);
230  entry->b = NULL;
231  entry->attributes = 0;
232  entry->action_cb = NULL;
233  entry->translation_cb = NULL;
234  entry->type = amxs_sync_type_invalid;
235  entry->priv = NULL;
236  entry->bus_ctx_a = NULL;
237  entry->bus_ctx_b = NULL;
238  amxc_llist_it_take(&entry->it);
239  amxc_llist_clean(&entry->entries, amxs_llist_it_delete_sync_entry);
240  amxc_llist_clean(&entry->subscriptions, amxs_llist_it_delete_subscription);
241  amxc_var_clean(&entry->a_to_b);
242  amxc_var_clean(&entry->b_to_a);
243 
244 exit:
245  return;
246 }
247 
249  amxs_sync_entry_t* src,
250  void* priv) {
252  amxs_sync_entry_t* dst_child = NULL;
253  amxs_sync_entry_t* src_child = NULL;
254 
255  when_null(dest, exit);
256  when_null(src, exit);
257 
258  status = amxs_sync_entry_new(dest,
259  src->a,
260  src->b,
261  src->attributes,
262  src->translation_cb,
263  src->action_cb,
264  src->type,
265  priv);
266  when_failed(status, exit);
267 
268  (*dest)->local_dm_a = src->local_dm_a;
269  (*dest)->local_dm_b = src->local_dm_b;
270 
271  amxc_llist_for_each(it, &src->entries) {
272  src_child = amxc_container_of(it, amxs_sync_entry_t, it);
273  amxs_sync_entry_copy(&dst_child, src_child, NULL);
274  status = amxs_sync_entry_add_entry(*dest, dst_child);
275  when_failed(status, exit);
276  }
277 
278 exit:
279  if(status != 0) {
281  }
282  return status;
283 }
284 
287  when_null(parent, exit);
288  when_null(child, exit);
289  when_true(parent == child, exit);
290 
291  if((parent->type == amxs_sync_type_invalid) ||
292  ( parent->type == amxs_sync_type_param) ||
293  ( child->type == amxs_sync_type_invalid) ||
294  ( child->type == amxs_sync_type_ctx)) {
295  status = amxs_status_invalid_type;
296  goto exit;
297  }
298 
299  status = amxs_validate_attributes(parent->attributes, child->attributes);
300  when_failed(status, exit);
301  status = amxs_update_child_attributes(parent->attributes, &child->attributes);
302  when_failed(status, exit);
303 
304  amxc_llist_iterate(it, &child->entries) {
305  amxs_sync_entry_t* entry = amxc_container_of(it, amxs_sync_entry_t, it);
306 
307  status = amxs_update_child_attributes(child->attributes, &entry->attributes);
308  when_failed(status, exit);
309  }
310 
311  amxc_llist_iterate(it, &parent->entries) {
312  amxs_sync_entry_t* entry = amxc_container_of(it, amxs_sync_entry_t, it);
313  if(amxs_sync_entry_compare(entry, child) == 0) {
314  status = amxs_status_duplicate;
315  goto exit;
316  }
317  }
318  amxc_llist_append(&parent->entries, &child->it);
319 
320  status = amxs_status_ok;
321 
322 exit:
323  return status;
324 }
325 
327  int ret = -1;
328 
329  if(entry1 == entry2) {
330  ret = 0;
331  goto exit;
332  }
333 
334  if((entry1 == NULL) || (entry2 == NULL)) {
335  goto exit;
336  }
337 
338  if(entry1->type != entry2->type) {
339  goto exit;
340  }
341 
342  if(amxs_sync_entry_compare_name(entry1->a, entry2->a) != 0) {
343  goto exit;
344  }
345 
346  if(amxs_sync_entry_compare_name(entry1->b, entry2->b) != 0) {
347  goto exit;
348  }
349 
350  if(((entry1->attributes | entry2->attributes) & (AMXS_SYNC_ONLY_B_TO_A | AMXS_SYNC_ONLY_A_TO_B ))
352  goto exit;
353  }
354 
355  ret = 0;
356 
357 exit:
358  return ret;
359 }
amxs_status_t amxs_update_child_attributes(int parent_attr, int *child_attr)
Definition: amxs_common.c:124
amxs_status_t amxs_validate_attributes(int parent_attr, int child_attr)
Definition: amxs_common.c:111
void amxs_llist_it_delete_subscription(amxc_llist_it_t *it)
Definition: amxs_common.c:140
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 *const entry)
int amxs_sync_entry_compare(amxs_sync_entry_t *entry1, amxs_sync_entry_t *entry2)
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)
static void amxs_llist_it_delete_sync_entry(amxc_llist_it_t *it)
void amxs_sync_entry_delete(amxs_sync_entry_t **entry)
void amxs_sync_entry_clean(amxs_sync_entry_t *entry)
static int amxs_sync_entry_compare_name(const char *const a, const char *const b)
enum _amxs_sync_entry_type amxs_sync_entry_type_t
@ amxs_status_ok
Definition: amxs_types.h:86
@ amxs_status_unknown_error
Definition: amxs_types.h:90
@ amxs_status_invalid_type
Definition: amxs_types.h:92
@ amxs_status_duplicate
Definition: amxs_types.h:87
@ amxs_status_invalid_arg
Definition: amxs_types.h:89
enum _amxs_sync_direction amxs_sync_direction_t
@ amxs_sync_a_to_b
Definition: amxs_types.h:80
@ amxs_sync_b_to_a
Definition: amxs_types.h:81
@ amxs_sync_invalid
Definition: amxs_types.h:82
enum _amxs_status amxs_status_t
@ amxs_sync_type_param
Definition: amxs_types.h:102
@ amxs_sync_type_invalid
Definition: amxs_types.h:99
@ amxs_sync_type_ctx
Definition: amxs_types.h:100
#define AMXS_SYNC_INIT_B
Take the initial values from object B.
Definition: amxs_types.h:205
#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
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
Definition: amxs_types.h:161
amxd_dm_t * local_dm_b
Definition: amxs_types.h:178
char * a
Definition: amxs_types.h:163
amxs_sync_entry_type_t type
Definition: amxs_types.h:170
amxc_llist_it_t it
Definition: amxs_types.h:162
void * priv
Definition: amxs_types.h:168
amxb_bus_ctx_t * bus_ctx_a
Definition: amxs_types.h:171
amxd_dm_t * local_dm_a
Definition: amxs_types.h:177
amxs_translation_cb_t translation_cb
Definition: amxs_types.h:167
amxc_var_t b_to_a
Definition: amxs_types.h:176
amxc_var_t a_to_b
Definition: amxs_types.h:175
amxc_llist_t subscriptions
Definition: amxs_types.h:173
amxs_action_cb_t action_cb
Definition: amxs_types.h:166
int attributes
Definition: amxs_types.h:165
amxp_signal_mngr_t * sig_mngr
Definition: amxs_types.h:174
char * b
Definition: amxs_types.h:164
amxc_llist_t entries
Definition: amxs_types.h:169
amxb_bus_ctx_t * bus_ctx_b
Definition: amxs_types.h:172