libamxd  6.4.1
Data Model Manager
amxd_transaction.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 #include <stdlib.h>
56 #include <string.h>
57 
58 #include "amxd_priv.h"
59 
60 #include <amxd/amxd_dm.h>
61 #include <amxd/amxd_object.h>
62 #include <amxd/amxd_object_event.h>
63 #include <amxd/amxd_transaction.h>
64 #include <amxd/amxd_path.h>
65 
66 #include "amxd_assert.h"
67 
68 typedef struct _validate {
69  char* path;
71  amxc_var_t* event_data;
72  amxc_llist_it_t it;
74 
76  amxc_var_clean(&(*trans)->data);
77  free(*trans);
78  *trans = NULL;
79 }
80 
81 static void amxd_trans_free_action_it(amxc_llist_it_t* it) {
82  amxd_trans_action_t* trans = amxc_llist_it_get_data(it, amxd_trans_action_t, it);
84 }
85 
86 static void amxd_trans_free_validate_it(amxc_llist_it_t* it) {
87  validate_t* val = amxc_llist_it_get_data(it, validate_t, it);
88  free(val->path);
89  free(val);
90 }
91 
93  amxc_var_t* args) {
94  amxd_object_t* instance = NULL;
95  amxc_var_t* var_index = amxc_var_get_key(args, "index", AMXC_VAR_FLAG_DEFAULT);
96  amxc_var_t* var_name = amxc_var_get_key(args, "name", AMXC_VAR_FLAG_DEFAULT);
97 
98  uint32_t index = amxc_var_dyncast(uint32_t, var_index);
99  char* name = amxc_var_dyncast(cstring_t, var_name);
100  instance = amxd_object_get_instance(templ, name, index);
101  free(name);
102 
103  return instance;
104 }
105 
107  amxd_action_t reason) {
108  amxd_trans_action_t* action = (amxd_trans_action_t*) calloc(1, sizeof(amxd_trans_action_t));
109  when_null(action, exit);
110 
111  action->action = reason;
112  amxc_var_init(&action->data);
113  amxc_var_set_type(&action->data, AMXC_VAR_ID_HTABLE);
114  amxc_llist_append(&trans->actions, &action->it);
115 
116 exit:
117  return action;
118 }
119 
121  amxd_trans_action_t* action = NULL;
122  amxc_llist_for_each_reverse(it, (&trans->actions)) {
123  action = amxc_llist_it_get_data(it, amxd_trans_action_t, it);
124  if((action->action == action_object_write) ||
125  ( action->action == action_object_add_inst)) {
126  break;
127  }
128  if(action->action == action_any) {
129  action = NULL;
130  break;
131  }
132  }
133 
134  return action;
135 }
136 
138  amxd_object_t* object,
139  amxc_var_t* data) {
140  amxd_object_t* result = NULL;
141  amxc_var_t* var_path = amxc_var_get_key(data, "path", AMXC_VAR_FLAG_DEFAULT);
142  const char* path = amxc_var_constcast(cstring_t, var_path);
143 
144  if((path == NULL) || (*path == 0)) {
145  goto exit;
146  }
147 
148  if(path[0] == '.') {
149  result = amxd_object_findf(object, "%s", path + 1);
150  } else {
151  result = amxd_dm_findf(dm, "%s", path);
152  }
153 
154 exit:
155  return result;
156 }
157 
159  amxd_trans_t* rollback,
160  amxc_var_t* data) {
161  amxc_var_t* temp = NULL;
162  uint32_t index = 0;
163  const char* name = NULL;
164 
165  temp = amxc_var_get_key(data, "index", AMXC_VAR_FLAG_DEFAULT);
166  index = amxc_var_dyncast(uint32_t, temp);
167  temp = amxc_var_get_key(data, "name", AMXC_VAR_FLAG_DEFAULT);
168  name = amxc_var_constcast(cstring_t, temp);
169 
170  if(rollback != NULL) {
171  amxd_trans_del_inst(rollback, index, name);
172  amxd_trans_select_object(rollback, object);
173  }
174  return amxd_object_get_instance(object, name, index);
175 }
176 
178  const char* param,
179  amxc_var_t* revert_params) {
180  amxc_var_t temp;
181  amxd_path_t param_path;
182  amxc_string_t p;
183  const char* path = "";
184 
185  amxc_string_init(&p, 0);
186  amxd_path_init(&param_path, param);
187  amxc_var_init(&temp);
188 
189  path = amxd_path_get(&param_path, AMXD_OBJECT_TERMINATE);
190 
191  if(path != NULL) {
192  if((strlen(path) <= 1) && (path[0] == '.')) {
193  path = "";
194  }
195  } else {
196  path = "";
197  }
198  object = amxd_object_findf(object, "%s", amxd_path_get(&param_path, AMXD_OBJECT_TERMINATE));
199  amxc_var_set_type(&temp, AMXC_VAR_ID_HTABLE);
201  &temp,
202  "attributes.volatile==false",
204  amxc_var_for_each(t, &temp) {
205  amxc_string_setf(&p,
206  "%s%s",
207  path,
208  amxc_var_key(t));
209  if(GET_ARG(revert_params, amxc_string_get(&p, 0)) != NULL) {
210  continue;
211  }
212  amxc_var_set_key(revert_params,
213  amxc_string_get(&p, 0),
214  t,
215  AMXC_VAR_FLAG_DEFAULT | AMXC_VAR_FLAG_UPDATE);
216  }
217  amxc_string_clean(&p);
218  amxd_path_clean(&param_path);
219  amxc_var_clean(&temp);
220 }
221 
223  amxd_trans_t* rollback,
224  amxc_var_t* data) {
225  const char* param_fields[] = { "parameters", "oparameters", NULL };
227  amxc_var_t* revert_params = NULL;
228  amxc_var_t* params = NULL;
229  int index = 0;
230  amxc_var_add_key(bool, &action->data, "set_read_only", true);
231  amxc_var_add_key(uint32_t, &action->data, "access", amxd_dm_access_private);
232  revert_params = amxc_var_add_key(amxc_htable_t, &action->data, "parameters", NULL);
233  while(param_fields[index] != NULL) {
234  params = GET_ARG(data, param_fields[index]);
235  amxc_var_for_each(param, params) {
236  amxd_param_t* param_def = NULL;
237  if(GET_ARG(revert_params, amxc_var_key(param)) != NULL) {
238  continue;
239  }
240  param_def = amxd_object_get_param_def(object, amxc_var_key(param));
241  if(param_def == NULL) {
242  amxd_trans_store_all_params(object, amxc_var_key(param), revert_params);
243  continue;
244  }
246  amxc_var_set_key(revert_params, amxc_var_key(param), &param_def->value, AMXC_VAR_FLAG_COPY);
247  }
248  }
249  index++;
250  }
251 }
252 
254  amxc_var_t* data) {
255  amxd_object_t* object = amxd_get_instance_from_args(trans->current, data);
256  amxc_string_t* path = (amxc_string_t*) calloc(1, sizeof(amxc_string_t));
257  char* object_path = amxd_object_get_path(object,
260  amxc_string_init(path, 0);
261  amxc_string_push_buffer(path, object_path, strlen(object_path) + 1);
262  amxc_llist_append(&trans->garbage, &path->it);
263 }
264 
266  amxd_object_t* object,
267  amxd_action_t reason,
268  amxc_var_t* data) {
269  validate_t* val_info = NULL;
270  char* object_path = amxd_object_get_path(object,
273  size_t path_len = strlen(object_path);
274 
275  amxc_llist_for_each(it, (&trans->validate)) {
276  size_t length = 0;
277  val_info = amxc_llist_it_get_data(it, validate_t, it);
278  length = strlen(val_info->path);
279  if(length <= path_len) {
280  if((length == path_len) &&
281  ( strcmp(object_path, val_info->path) == 0) &&
282  ( val_info->reason == action_object_write)) {
283  break;
284  }
285  }
286  val_info = NULL;
287  }
288 
289  if(val_info != NULL) {
290  amxc_var_t* event_params = GET_ARG(val_info->event_data, "parameters");
291  amxc_var_for_each(var, GET_ARG(data, "parameters")) {
292  amxc_var_set_key(event_params, amxc_var_key(var), var, AMXC_VAR_FLAG_DEFAULT);
293  }
294  free(object_path);
295  } else {
296  val_info = (validate_t*) calloc(1, sizeof(validate_t));
297  when_null(val_info, exit);
298  val_info->path = object_path;
299  val_info->reason = reason;
300  val_info->event_data = data;
301  amxc_llist_append(&trans->validate, &val_info->it);
302  }
303 
304 exit:
305  return;
306 }
307 
309  amxd_trans_action_t* action,
310  amxd_trans_t* rollback) {
311  if(action->action == action_object_write) {
312  if(rollback != NULL) {
313  amxc_llist_it_t* it = NULL;
314  amxd_trans_action_t* raction = NULL;
315  amxd_trans_revert_write(trans->current, rollback, &action->data);
316  it = amxc_llist_get_last(&rollback->actions);
317  raction = amxc_llist_it_get_data(it, amxd_trans_action_t, it);
318  amxd_trans_add_validate(trans, trans->current, action->action, &raction->data);
319  }
320  }
321 }
322 
324  amxd_trans_action_t* action,
325  amxd_trans_t* rollback,
326  amxc_var_t* retval) {
328  if(action->action == action_object_add_inst) {
330  rollback,
331  retval);
332  when_null_status(trans->current,
333  exit,
335  if(rollback != NULL) {
336  amxd_trans_add_validate(trans, trans->current, action->action, NULL);
337  }
338  } else if(action->action == action_object_del_inst) {
340  NULL,
341  &action->data);
342  amxd_trans_add_garbage(trans, &action->data);
343  amxd_trans_add_validate(trans, inst, action->action, NULL);
344  }
345 
346 exit:
347  return status;
348 }
349 
351  amxd_dm_t* dm,
352  amxd_trans_action_t* action,
353  amxd_trans_t* rollback) {
355  amxc_var_t* retval = amxc_var_add_new(&trans->retvals);
356 
357  if(action->action == action_any) {
358  if((trans->current != NULL) && (rollback != NULL)) {
359  amxd_trans_select_object(rollback, trans->current);
360  }
361  trans->current = amxd_trans_select(dm, trans->current, &action->data);
362  when_null_status(trans->current,
363  exit,
366  } else if(action->action == action_object_add_mib) {
367  when_null_status(trans->current, exit, status = amxd_status_object_not_found);
368  if(!amxd_object_has_mib(trans->current, GET_CHAR(&action->data, "mib"))) {
369  status = amxd_object_add_mib(trans->current, GET_CHAR(&action->data, "mib"));
370  } else {
372  }
373  } else {
374  when_null_status(trans->current, exit, status = amxd_status_object_not_found);
375  amxd_trans_action_start(trans, action, rollback);
377  NULL,
378  action->action,
379  &action->data,
380  retval);
381  when_failed(status, exit);
382  status = amxd_trans_action_end(trans, action, rollback, retval);
383  }
384 
385 exit:
386  return status;
387 }
388 
390  amxd_dm_t* dm) {
391  amxc_llist_for_each_reverse(it, (&trans->garbage)) {
392  amxc_string_t* path = amxc_string_from_llist_it(it);
393  amxd_object_t* object = amxd_dm_findf(dm, "%s", amxc_string_get(path, 0));
394  if(object != NULL) {
395  amxd_dm_invoke_action(object, NULL, action_object_destroy, NULL, NULL);
396  }
397  }
398  amxc_llist_clean(&trans->garbage, amxc_string_list_it_free);
399 }
400 
402  amxc_llist_for_each_reverse(it, (&trans->actions)) {
403  amxd_trans_action_t* action =
404  amxc_llist_it_get_data(it, amxd_trans_action_t, it);
405  amxd_trans_invoke_action(trans, dm, action, NULL);
406  }
407 
409 }
410 
411 static void amxd_trans_emit_changed(UNUSED amxd_object_t* object, amxc_var_t* params) {
412  amxd_path_t path;
413  amxc_var_t objects;
414 
415  amxc_var_init(&objects);
416  amxc_var_set_type(&objects, AMXC_VAR_ID_HTABLE);
417 
418  amxd_path_init(&path, NULL);
419 
420  amxc_var_for_each(param, params) {
421  amxc_var_t* obj_params = NULL;
422  const char* rel_obj_path = NULL;
423 
424  amxd_path_setf(&path, false, "%s", amxc_var_key(param));
425  rel_obj_path = amxd_path_get(&path, AMXD_OBJECT_TERMINATE);
426  obj_params = GET_ARG(&objects, rel_obj_path);
427 
428  if(obj_params == NULL) {
429  obj_params = amxc_var_add_key(amxc_htable_t, &objects, rel_obj_path, NULL);
430  }
431 
432  amxc_var_set_key(obj_params, amxd_path_get_param(&path), param, AMXC_VAR_FLAG_DEFAULT);
433  }
434 
435  amxc_var_for_each(object_params, &objects) {
436  amxd_object_t* rel_obj = amxd_object_findf(object, "%s", amxc_var_key(object_params));
437  amxd_object_emit_changed(rel_obj, object_params);
438  }
439 
440  amxd_path_clean(&path);
441  amxc_var_clean(&objects);
442 }
443 
445  amxd_dm_t* dm) {
447 
448  amxc_llist_for_each(it, (&trans->validate)) {
449  validate_t* val = amxc_llist_it_get_data(it, validate_t, it);
450  amxd_object_t* object = amxd_dm_findf(dm, "%s", val->path);
451  if(val->reason != action_object_del_inst) {
452  status = amxd_object_validate(object,
453  val->reason != action_object_write ?
454  INT32_MAX : 0);
455  if(status != amxd_status_ok) {
456  goto exit;
457  }
458  }
459  }
460 
461  amxc_llist_for_each(it, (&trans->validate)) {
462  validate_t* val = amxc_llist_it_get_data(it, validate_t, it);
463  amxd_object_t* object = amxd_dm_findf(dm, "%s", val->path);
464  if(val->reason == action_object_add_inst) {
466  } else if(val->reason == action_object_del_inst) {
468  } else if(val->reason == action_object_write) {
469  amxc_var_t* params = GET_ARG(val->event_data, "parameters");
470  if(params != NULL) {
471  amxd_trans_emit_changed(object, params);
472  }
473  }
474 
475  }
476 
478 
479 exit:
480  return status;
481 }
482 
483 static void amxd_trans_dump_action(amxd_trans_action_t* action, int fd) {
484  switch(action->action) {
485  case action_any:
486  when_true(write(fd, "SELECT - \n", 10) == -1, exit);
487  break;
488  case action_object_write:
489  when_true(write(fd, "SET - \n", 7) == -1, exit);
490  break;
492  when_true(write(fd, "ADD - \n", 7) == -1, exit);
493  break;
495  when_true(write(fd, "DEL - \n", 7) == -1, exit);
496  break;
497  default:
498  break;
499  }
500  amxc_var_dump(&action->data, fd);
501  when_true(write(fd, "\n", 1) == -1, exit);
502 
503 exit:
504  return;
505 }
506 
509  when_null(trans, exit);
510 
511  amxc_llist_init(&trans->actions);
512  amxc_llist_init(&trans->garbage);
513  amxc_llist_init(&trans->validate);
514  amxc_var_init(&trans->retvals);
515  amxc_var_set_type(&trans->retvals, AMXC_VAR_ID_LIST);
516 
517  trans->current = NULL;
518  trans->status = amxd_status_ok;
519  trans->fail_index = -1;
520  trans->attr.read_only = 0;
522 
524 
525 exit:
526  return status;
527 }
528 
529 void amxd_trans_clean(amxd_trans_t* const trans) {
530  when_null(trans, exit);
531 
532  amxc_llist_clean(&trans->actions, amxd_trans_free_action_it);
533  amxc_llist_clean(&trans->garbage, amxc_string_list_it_free);
534  amxc_llist_clean(&trans->validate, amxd_trans_free_validate_it);
535  amxc_var_clean(&trans->retvals);
536 
537  trans->status = amxd_status_ok;
538  trans->fail_index = -1;
539 
540 exit:
541  return;
542 }
543 
546  when_null(trans, exit);
547 
548  *trans = (amxd_trans_t*) calloc(1, sizeof(amxd_trans_t));
549  when_null((*trans), exit);
550 
551  status = amxd_trans_init(*trans);
552 
553 exit:
554  return status;
555 }
556 
558  when_null(trans, exit);
559  when_null((*trans), exit);
560 
561  amxd_trans_clean(*trans);
562 
563  free(*trans);
564  *trans = NULL;
565 
566 exit:
567  return;
568 }
569 
571  amxd_tattr_id_t attr,
572  bool enable) {
574  when_null(trans, exit);
575 
576  switch(attr) {
578  trans->attr.read_only = enable;
579  break;
581  trans->access = amxd_dm_access_public;
582  break;
585  break;
588  break;
589  }
590 
591  retval = amxd_status_ok;
592 
593 exit:
594  return retval;
595 }
596 
598  const amxd_action_t reason,
599  const amxc_var_t* data) {
601  amxd_trans_action_t* action = NULL;
602 
603  when_null(trans, exit);
604  when_true_status(reason != action_any &&
605  reason != action_object_write &&
606  reason != action_object_add_inst &&
607  reason != action_object_del_inst,
608  exit,
610 
611  action = amxd_trans_new_action(trans, reason);
612  when_null(action, exit);
613  amxc_var_copy(&action->data, data);
615 
616 exit:
617  if(trans != NULL) {
618  trans->status = status;
619  }
620  return status;
621 }
622 
624  const char* path,
625  ...) {
627  amxc_string_t full_path;
628  amxd_trans_action_t* action = NULL;
629  int length = 0;
630  va_list args;
631 
632  amxc_string_init(&full_path, 64);
633 
634  when_null(trans, exit);
635  when_null(path, exit);
636 
637  va_start(args, path);
638  amxc_string_vsetf(&full_path, path, args);
639  va_end(args);
640 
641  amxc_string_trim(&full_path, NULL);
642  when_str_empty(amxc_string_get(&full_path, 0), exit);
643  length = amxc_string_text_length(&full_path);
644  if(amxc_string_get(&full_path, 0)[length - 1] != '.') {
645  amxc_string_append(&full_path, ".", 1);
646  }
647 
648  action = amxd_trans_new_action(trans, action_any);
649  when_null(action, exit);
650  when_null(amxc_var_add_key(cstring_t,
651  &action->data,
652  "path",
653  amxc_string_get(&full_path, 0)),
654  exit);
655 
657 
658 exit:
659  if(trans != NULL) {
660  trans->status = status;
661  }
662  amxc_string_clean(&full_path);
663  return status;
664 }
665 
667  const amxd_object_t* const object) {
669  char* full_path = NULL;
670  amxd_trans_action_t* action = NULL;
671 
672  when_null(trans, exit);
673 
675  action = amxd_trans_new_action(trans, action_any);
676  when_null(action, exit);
677  when_null(amxc_var_add_key(cstring_t,
678  &action->data,
679  "path",
680  full_path),
681  exit);
682 
683  when_null(object, exit);
684 
686 
687 exit:
688  if(trans != NULL) {
689  trans->status = status;
690  }
691  free(full_path);
692  return status;
693 }
694 
696  const char* param_name,
697  amxc_var_t* const value) {
699  amxd_trans_action_t* action = NULL;
700  amxc_var_t* params = NULL;
701 
702  when_null(trans, exit);
703  when_str_empty(param_name, exit);
704  when_null(value, exit);
705 
706  action = amxd_trans_find_write_action(trans);
707  if(action == NULL) {
709  when_null(action, exit);
710  when_null(amxc_var_add_key(bool, &action->data, "set_read_only",
711  trans->attr.read_only == 1),
712  exit);
713  when_null(amxc_var_add_key(uint32_t, &action->data, "access", trans->access),
714  exit);
715  }
716 
717  params = amxc_var_get_key(&action->data, "parameters",
718  AMXC_VAR_FLAG_DEFAULT);
719  if(params == NULL) {
720  params = amxc_var_add_key(amxc_htable_t, (&action->data), "parameters",
721  NULL);
722  when_null(params, exit);
723  }
724 
725  when_failed(amxc_var_set_key(params, param_name, value,
726  AMXC_VAR_FLAG_UPDATE | AMXC_VAR_FLAG_COPY),
727  exit);
728 
730 
731 exit:
732  if(trans != NULL) {
733  trans->status = status;
734  }
735  return status;
736 }
737 
739  const uint32_t index,
740  const char* name) {
742  amxd_trans_action_t* action = NULL;
743 
744  when_null(trans, exit);
745 
747  when_null(action, exit);
748 
749  when_null(amxc_var_add_key(bool,
750  &action->data,
751  "set_read_only",
752  trans->attr.read_only == 1),
753  exit);
754  when_null(amxc_var_add_key(uint32_t,
755  &action->data,
756  "access",
757  trans->access),
758  exit);
759  when_null(amxc_var_add_key(uint32_t, &action->data, "index", index),
760  exit);
761  when_null(amxc_var_add_key(cstring_t,
762  &action->data,
763  "name",
764  name == NULL ? "" : name),
765  exit);
766 
768 
769 exit:
770  if(trans != NULL) {
771  trans->status = status;
772  }
773  return status;
774 }
775 
777  const uint32_t index,
778  const char* name) {
780  amxd_trans_action_t* action = NULL;
781 
782  when_null(trans, exit);
783 
785  when_null(action, exit);
786  when_true((index == 0 && (name == NULL || *name == 0)), exit);
787 
788  when_null(amxc_var_add_key(bool,
789  &action->data,
790  "set_read_only",
791  trans->attr.read_only == 1),
792  exit);
793  when_null(amxc_var_add_key(uint32_t,
794  &action->data,
795  "access",
796  trans->access),
797  exit);
798  when_null(amxc_var_add_key(uint32_t, &action->data, "index", index),
799  exit);
800  when_null(amxc_var_add_key(cstring_t,
801  &action->data,
802  "name",
803  name == NULL ? "" : name),
804  exit);
805 
807 
808 exit:
809  if(trans != NULL) {
810  trans->status = status;
811  }
812  return status;
813 }
814 
816  const char* mib_name) {
818  amxd_trans_action_t* action = NULL;
819 
820  when_null(trans, exit);
821 
823  when_null(action, exit);
824  when_str_empty(mib_name, exit);
825 
826  when_null(amxc_var_add_key(cstring_t,
827  &action->data,
828  "mib",
829  mib_name),
830  exit);
831 
833 
834 exit:
835  if(trans != NULL) {
836  trans->status = status;
837  }
838  return status;
839 }
840 
842  amxd_dm_t* const dm) {
843  static bool trans_buzy = false;
845  amxd_trans_t rollback;
846 
847  amxd_trans_init(&rollback);
848  when_true(trans_buzy, exit);
849  when_null(trans, exit);
850  when_null(dm, exit);
851  when_failed_status(trans->status, exit, status = trans->status);
852  trans_buzy = true;
853  trans->fail_index = 0;
854  amxc_var_clean(&trans->retvals);
855  amxc_var_set_type(&trans->retvals, AMXC_VAR_ID_LIST);
856  amxc_llist_for_each(it, (&trans->actions)) {
857  amxd_trans_action_t* action =
858  amxc_llist_it_get_data(it, amxd_trans_action_t, it);
859  status = amxd_trans_invoke_action(trans, dm, action, &rollback);
860  when_failed(status, exit);
861  trans->fail_index++;
862  }
864 
865 exit:
866  if(trans != NULL) {
867  trans->status = status;
868  if(status != amxd_status_ok) {
869  amxd_trans_select_object(&rollback, trans->current);
870  amxd_trans_revert(&rollback, dm);
871  amxc_llist_clean(&trans->garbage, amxc_string_list_it_free);
872  trans->current = NULL;
873  } else {
874  amxc_llist_clean(&trans->actions, amxd_trans_free_action_it);
875  }
876  amxd_trans_clean(&rollback);
877  }
878  trans_buzy = false;
879  return status;
880 }
881 
882 void amxd_trans_dump(const amxd_trans_t* const trans,
883  const int fd,
884  const bool reverse) {
885  if(reverse) {
886  amxc_llist_for_each_reverse(it, (&trans->actions)) {
887  amxd_trans_action_t* action =
888  amxc_llist_it_get_data(it, amxd_trans_action_t, it);
889  amxd_trans_dump_action(action, fd);
890  }
891  } else {
892  amxc_llist_for_each(it, (&trans->actions)) {
893  amxd_trans_action_t* action =
894  amxc_llist_it_get_data(it, amxd_trans_action_t, it);
895  amxd_trans_dump_action(action, fd);
896  }
897  }
898 }
#define when_failed_status(x, l, c)
Definition: amxd_assert.h:65
Ambiorix Data Model API header file.
amxd_object_t * amxd_dm_findf(amxd_dm_t *const dm, const char *abs_path,...) __attribute__((format(printf
amxd_status_t amxd_dm_invoke_action(amxd_object_t *object, amxd_param_t *param, amxd_action_t reason, const amxc_var_t *const args, amxc_var_t *const retval)
Definition: amxd_dm.c:591
Ambiorix Data Model API header file.
amxd_status_t amxd_object_validate(amxd_object_t *const object, int32_t depth)
Ambiorix Data Model API header file.
amxd_status_t amxd_object_get_params_filtered(amxd_object_t *const object, amxc_var_t *const params, const char *filter, amxd_dm_access_t access)
bool amxd_param_is_attr_set(const amxd_param_t *const param, const amxd_pattr_id_t attr)
Ambiorix path API header file.
static void amxd_trans_add_validate(amxd_trans_t *trans, amxd_object_t *object, amxd_action_t reason, amxc_var_t *data)
static void amxd_trans_action_start(amxd_trans_t *trans, amxd_trans_action_t *action, amxd_trans_t *rollback)
static void amxd_trans_free_action_it(amxc_llist_it_t *it)
amxd_status_t amxd_trans_select_pathf(amxd_trans_t *const trans, const char *path,...)
static void amxd_trans_emit_changed(UNUSED amxd_object_t *object, amxc_var_t *params)
static void amxd_trans_collect_garbage(amxd_trans_t *trans, amxd_dm_t *dm)
static amxd_status_t amxd_trans_validate_objects(amxd_trans_t *trans, amxd_dm_t *dm)
static void amxd_trans_delete_action(amxd_trans_action_t **trans)
amxd_status_t amxd_trans_add_mib(amxd_trans_t *const trans, const char *mib_name)
static void amxd_trans_revert(amxd_trans_t *trans, amxd_dm_t *dm)
static amxd_object_t * amxd_trans_select_instance(amxd_object_t *object, amxd_trans_t *rollback, amxc_var_t *data)
struct _validate validate_t
static void amxd_trans_add_garbage(amxd_trans_t *trans, amxc_var_t *data)
static amxd_trans_action_t * amxd_trans_new_action(amxd_trans_t *trans, amxd_action_t reason)
static void amxd_trans_revert_write(amxd_object_t *object, amxd_trans_t *rollback, amxc_var_t *data)
static amxd_trans_action_t * amxd_trans_find_write_action(amxd_trans_t *trans)
static amxd_status_t amxd_trans_invoke_action(amxd_trans_t *trans, amxd_dm_t *dm, amxd_trans_action_t *action, amxd_trans_t *rollback)
static amxd_object_t * amxd_trans_select(amxd_dm_t *dm, amxd_object_t *object, amxc_var_t *data)
static void amxd_trans_store_all_params(amxd_object_t *object, const char *param, amxc_var_t *revert_params)
static amxd_status_t amxd_trans_action_end(amxd_trans_t *trans, amxd_trans_action_t *action, amxd_trans_t *rollback, amxc_var_t *retval)
static void amxd_trans_free_validate_it(amxc_llist_it_t *it)
static amxd_object_t * amxd_get_instance_from_args(amxd_object_t *templ, amxc_var_t *args)
static void amxd_trans_dump_action(amxd_trans_action_t *action, int fd)
Ambiorix Data Model API header file.
@ amxd_pattr_variable
Definition: amxd_types.h:360
@ action_object_write
Definition: amxd_types.h:118
@ action_object_add_inst
Definition: amxd_types.h:123
@ action_object_del_inst
Definition: amxd_types.h:124
@ action_any
Definition: amxd_types.h:111
@ action_object_destroy
Definition: amxd_types.h:125
@ action_object_add_mib
Definition: amxd_types.h:126
enum _amxd_action amxd_action_t
enum _amxd_status amxd_status_t
@ amxd_status_object_not_found
Definition: amxd_types.h:80
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_unknown_error
Definition: amxd_types.h:79
@ amxd_status_invalid_action
Definition: amxd_types.h:89
#define AMXD_OBJECT_INDEXED
Name and path format flag - use index for instance objects.
Definition: amxd_object.h:176
#define AMXD_OBJECT_TERMINATE
Path format flag - when set the object path is terminated with a dot.
Definition: amxd_object.h:214
@ amxd_dm_access_private
Definition: amxd_types.h:141
@ amxd_dm_access_protected
Definition: amxd_types.h:139
@ amxd_dm_access_public
Definition: amxd_types.h:136
AMXD_INLINE void amxd_object_emit_add_inst(amxd_object_t *instance)
Emit an add instance object event.
AMXD_INLINE void amxd_object_emit_changed(amxd_object_t *object, amxc_var_t *params)
Emit an object changed event.
AMXD_INLINE void amxd_object_emit_del_inst(amxd_object_t *instance)
Emit a delete instance object event.
amxd_object_t amxd_status_t amxd_status_t char * amxd_object_get_path(const amxd_object_t *object, const uint32_t flags)
Get the full path of the object.
amxd_object_t * amxd_object_findf(amxd_object_t *object, const char *rel_path,...) __attribute__((format(printf
Find an object in the data model tree, starting from an object.
amxd_object_t * amxd_object_get_instance(const amxd_object_t *object, const char *name, uint32_t index)
Get an instance of the template object.
bool amxd_object_has_mib(amxd_object_t *object, const char *mib_name)
Checks if a mib has been added to a data model object.
amxd_status_t amxd_object_add_mib(amxd_object_t *const object, const char *mib_name)
Adds a mib to an object.
amxd_param_t * amxd_object_get_param_def(const amxd_object_t *const object, const char *name)
Gets a parameter definition from an object.
amxd_status_t amxd_path_init(amxd_path_t *path, const char *object_path)
Initializes an amxd_path_t structure.
Definition: amxd_path.c:328
const char * amxd_path_get_param(amxd_path_t *path)
Gets the parameter name.
Definition: amxd_path.c:497
const char * amxd_path_get(amxd_path_t *path, int flags)
Returns the path stored in the amxd_path_t structure.
Definition: amxd_path.c:470
void amxd_path_clean(amxd_path_t *path)
Cleans an amxd_path_t structure.
Definition: amxd_path.c:351
amxd_status_t amxd_path_setf(amxd_path_t *path, bool add_dot, const char *obj_path,...) __attribute__((format(printf
Sets or replaces the path contained in the amxd_path_t structure.
amxd_status_t amxd_trans_new(amxd_trans_t **trans)
Allocates a transaction object on the heap and initializes it.
amxd_status_t amxd_trans_add_action(amxd_trans_t *const trans, const amxd_action_t reason, const amxc_var_t *data)
Adds an action to a transaction.
void amxd_trans_dump(const amxd_trans_t *const trans, const int fd, const bool reverse)
Dumps the transaction to a file descriptor.
amxd_status_t amxd_trans_set_attr(amxd_trans_t *trans, amxd_tattr_id_t attr, bool enable)
Set the transaction attributes.
void amxd_trans_clean(amxd_trans_t *const trans)
Cleans the transaction object.
amxd_status_t amxd_trans_apply(amxd_trans_t *const trans, amxd_dm_t *const dm)
Applies all previously added actions.
amxd_status_t amxd_trans_add_inst(amxd_trans_t *const trans, const uint32_t index, const char *name)
Adds an instance add action to a transaction.
void amxd_trans_delete(amxd_trans_t **trans)
Frees the memory previously allocated for a transaction object.
amxd_status_t amxd_trans_del_inst(amxd_trans_t *const trans, const uint32_t index, const char *name)
Adds an instance delete action to a transaction.
amxd_status_t amxd_trans_select_object(amxd_trans_t *const trans, const amxd_object_t *const object)
Selects an object using an object pointer.
amxd_status_t amxd_trans_set_param(amxd_trans_t *trans, const char *param_name, amxc_var_t *const value)
Adds a set value action to a transaction.
enum _amxd_tattr_id amxd_tattr_id_t
Transaction attributes.
amxd_status_t amxd_trans_init(amxd_trans_t *const trans)
Initializes a transaction object.
@ amxd_tattr_change_prot
@ amxd_tattr_change_ro
@ amxd_tattr_change_priv
@ amxd_tattr_change_pub
amxc_var_t value
Definition: amxd_types.h:390
amxc_llist_it_t it
amxd_action_t action
amxd_object_t * current
amxc_llist_t validate
amxd_dm_access_t access
amxc_llist_t actions
amxc_llist_t garbage
amxd_status_t status
amxd_trans_attr_t attr
amxd_action_t reason
amxc_llist_it_t it
amxc_var_t * event_data
static amxd_dm_t dm
static amxd_status_t status