libamxd  6.4.1
Data Model Manager
amxd_object_instance.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 <stdio.h>
61 #include <string.h>
62 #include <ctype.h>
63 
64 #include <amxc/amxc.h>
65 #include <amxp/amxp.h>
66 
67 #include <amxd/amxd_types.h>
68 #include <amxd/amxd_object.h>
70 #include <amxd/amxd_action.h>
71 #include <amxd/amxd_dm.h>
72 
73 #include "amxd_priv.h"
74 #include "amxd_dm_priv.h"
75 #include "amxd_object_priv.h"
76 #include "amxd_assert.h"
77 
78 static bool amxd_template_has_instance(const amxd_object_t* const templ,
79  const char* name) {
80  bool retval = false;
81 
82  amxc_llist_for_each(it, (&templ->instances)) {
83  const char* n = NULL;
84  amxd_object_t* result = amxc_llist_it_get_data(it, amxd_object_t, it);
86  if(strcmp(n, name) == 0) {
87  retval = true;
88  break;
89  }
90  }
91 
92  return retval;
93 }
94 
95 static bool amxd_template_has_index(const amxd_object_t* const templ,
96  uint32_t index) {
97  bool retval = false;
98 
99  if(index != 0) {
100  amxc_llist_for_each(it, (&templ->instances)) {
101  amxd_object_t* result = amxc_llist_it_get_data(it, amxd_object_t, it);
102  if(result->index == index) {
103  retval = true;
104  break;
105  }
106  }
107  } else {
108  // index 0 is a special case, it can not be used as an index id
109  // it is considered always available.
110  retval = true;
111  }
112  return retval;
113 }
114 
116  amxc_var_t* templ_params,
117  amxc_htable_t* values,
118  uint32_t index,
119  const char** name) {
121  amxc_var_t* alias = amxc_var_get_key(templ_params, "Alias", AMXC_VAR_FLAG_DEFAULT);
122  amxc_htable_it_t* halias = amxc_htable_get(values, "Alias");
123  const char* obj_name = amxd_object_get_name(templ, AMXD_OBJECT_NAMED);
124  uint32_t new_index = index == 0 ? (templ->last_index + 1) : index;
125  amxc_var_t* alias_var = NULL;
126 
127  when_null(alias, exit);
128  when_true(!amxc_var_constcast(bool, GET_FIELD(alias, "attributes.key")), exit);
129  when_true(!amxc_var_constcast(bool, GET_FIELD(alias, "attributes.unique")), exit);
130 
131  if(halias == NULL) {
132  amxc_var_new(&alias_var);
133  if((*name != NULL) && ((*name)[0] != 0)) {
134  amxc_var_set(cstring_t, alias_var, *name);
135  } else {
136  amxc_string_t alias_name;
137  amxc_string_init(&alias_name, 0);
138  amxc_string_appendf(&alias_name, "cpe-%s-%d", obj_name, new_index);
139  amxc_var_push(amxc_string_t, alias_var, &alias_name);
140  amxc_string_clean(&alias_name);
141  }
142  amxc_htable_insert(values, "Alias", &alias_var->hit);
143  } else {
144  alias_var = amxc_var_from_htable_it(halias);
145  if((amxc_var_type_of(alias_var) != AMXC_VAR_ID_CSTRING) &&
146  ( amxc_var_type_of(alias_var) != AMXC_VAR_ID_SSV_STRING) &&
147  ( amxc_var_type_of(alias_var) != AMXC_VAR_ID_CSV_STRING)) {
149  goto exit;
150  }
151  }
152 
153  *name = amxc_var_constcast(cstring_t, alias_var);
154  if(isdigit((*name)[0]) != 0) {
156  }
157  *name = "";
158 
159 exit:
160  return status;
161 }
162 
164  const char** name,
165  uint32_t index,
166  amxc_var_t* templ_params,
167  amxc_var_t* values) {
168  amxd_status_t retval = amxd_status_ok;
169  amxp_expr_t* expr = NULL;
170  amxc_htable_t* hvalues = (amxc_htable_t*) amxc_var_constcast(amxc_htable_t, values);
171  bool has_matches = false;
172 
173  if(index != 0) {
174  when_true_status(amxd_template_has_index(templ, index),
175  exit,
176  retval = amxd_status_duplicate);
177  }
178 
179  retval = amxd_object_check_instance_alias(templ, templ_params, hvalues, index, name);
180  when_true(retval != amxd_status_ok, exit);
181 
182  retval = amxd_object_build_key_expr(templ_params, &expr, hvalues);
183  when_failed(retval, exit);
184 
185  has_matches = amxd_object_has_matching_instances(templ, expr);
186  when_true_status(has_matches, exit, retval = amxd_status_duplicate);
187 
188 
189  if((*name != NULL) && ((*name)[0] != 0)) {
190  when_true_status(!amxd_name_is_valid(*name),
191  exit,
192  retval = amxd_status_invalid_name);
193  when_true_status(amxd_template_has_instance(templ, *name),
194  exit,
195  retval = amxd_status_duplicate);
196  }
197 
198 exit:
199  amxp_expr_delete(&expr);
200  return retval;
201 }
202 
204  amxd_object_t* templ,
205  const char* name,
206  uint32_t index) {
208  uint32_t index_try = 0;
209  int size_needed = 0;
210 
211  if(index == 0) {
212  while(amxd_template_has_index(templ, templ->last_index + 1)) {
213  index_try++;
214  templ->last_index++;
215 
216  if(index_try > 10) {
217  goto exit;
218  }
219  }
220  object->index = templ->last_index + 1;
221  } else {
222  object->index = index;
223  }
224 
225  size_needed = snprintf(NULL, 0, "%" PRIu32, object->index);
226  object->index_name = (char*) calloc(size_needed + 1, sizeof(char));
227  when_null(object->index_name, exit);
228  snprintf(object->index_name, size_needed + 1, "%" PRIu32, object->index);
229  if(object->name == NULL) {
230  if((name == NULL) || (name[0] == 0)) {
231  object->name = strdup(object->index_name);
232  when_null(object->name, exit);
233  }
234  }
235  if(object->index > templ->last_index) {
236  templ->last_index = object->index;
237  }
238 
239  retval = amxd_status_ok;
240 
241 exit:
242  return retval;
243 }
244 
246  amxd_object_t* templ,
247  const char* name,
248  uint32_t index,
249  amxc_var_t* templ_params,
250  amxc_var_t* tmp_values) {
252  uint32_t attrs = 0;
253  amxd_param_t* counter = NULL;
254 
255  *object = (amxd_object_t*) calloc(1, sizeof(amxd_object_t));
256  when_null((*object), exit);
257  retval = amxd_object_init(*object, amxd_object_instance, name, templ_params, tmp_values);
258  when_true(retval != amxd_status_ok, exit);
259  retval = amxd_object_instance_set_index_name((*object), templ, name, index);
260  when_true(retval != amxd_status_ok, exit);
261  attrs = amxd_object_get_attrs(templ);
262  amxd_object_set_attrs(*object, attrs, true);
263 
264  amxc_llist_append(&templ->instances, &(*object)->it);
265  retval = amxd_object_copy_children((*object), templ);
266  when_failed(retval, exit);
267  retval = amxd_object_copy_params((*object), templ);
268  when_failed(retval, exit);
269  retval = amxd_object_copy_mib_names((*object), templ);
270 
272  when_null(counter, exit);
274 
275 exit:
276  if(*object != NULL) {
277  if(retval != amxd_status_ok) {
278  amxd_object_clean(*object);
279  free(*object);
280  *object = NULL;
281  }
282  }
283  return retval;
284 }
285 
287  UNUSED amxd_param_t* const param,
288  amxd_action_t reason,
289  UNUSED const amxc_var_t* const args,
290  UNUSED amxc_var_t* const retval,
291  void* priv) {
293  amxc_var_t* data = (amxc_var_t*) priv;
294 
295  // action private data must not be removed when the action is used
296  // on derivced objects.
297  // only remove action data when the action is owned by the object or
298  // parameter on which the action is called.
300  amxc_var_delete(&data);
302  }
303 
304  return status;
305 }
306 
308  amxc_var_t* max_var) {
309  if(max_var != NULL) {
310  amxc_var_delete(&max_var);
317  }
318 }
319 
321  uint32_t max) {
322  amxc_var_t* max_var = NULL;
324 
325  amxc_var_new(&max_var);
326  amxc_var_set(uint32_t, max_var, max);
327  retval = amxd_object_add_action_cb(object,
330  max_var);
331  when_failed_status(retval, exit, amxc_var_delete(&max_var));
332  retval = amxd_object_add_action_cb(object,
335  max_var);
336  if(retval != amxd_status_ok) {
340  amxc_var_delete(&max_var);
341  goto exit;
342  }
343 
344  retval = amxd_status_ok;
345 
346 exit:
347  return retval;
348 }
349 
351  amxd_object_t* templ,
352  const char* name,
353  uint32_t index,
354  amxc_var_t* values) {
356  amxc_var_t templ_params;
357  amxc_var_t* tmp_values = NULL;
358  amxc_var_t rv;
359 
360  amxc_var_init(&templ_params);
361  amxc_var_init(&rv);
362  when_null(object, exit);
363  when_null(templ, exit);
364  when_true_status(templ->type != amxd_object_template,
365  exit,
366  retval = amxd_status_invalid_type);
367  when_true_status(values != NULL && amxc_var_type_of(values) != AMXC_VAR_ID_HTABLE,
368  exit,
369  retval = amxd_status_invalid_value);
370  if(values == NULL) {
371  amxc_var_new(&tmp_values);
372  amxc_var_set_type(tmp_values, AMXC_VAR_ID_HTABLE);
373  } else {
374  tmp_values = values;
375  }
376  *object = NULL;
377  retval = amxd_object_describe_key_params(templ, &templ_params, amxd_dm_access_private);
378  when_failed(retval, exit);
379  retval = amxd_object_instance_validate_id(templ, &name, index, &templ_params, tmp_values);
380  when_failed(retval, exit);
381  retval = amxd_object_instantiate(object, templ, name, index, &templ_params, tmp_values);
382  when_failed(retval, exit);
383  if(values == NULL) {
384  retval = amxd_action_set_values((*object), amxd_dm_access_protected, true,
385  tmp_values, &rv, true);
386  }
387 
388 exit:
389  if(values == NULL) {
390  amxc_var_delete(&tmp_values);
391  }
392  amxc_var_clean(&rv);
393  amxc_var_clean(&templ_params);
394  return retval;
395 }
396 
398  uint32_t max) {
400  amxc_var_t* max_var = NULL;
401  uint32_t instances = 0;
402  when_null(object, exit);
403  when_true_status(object->type != amxd_object_template,
404  exit,
405  retval = amxd_status_invalid_type);
406 
407  instances = amxd_object_get_instance_count(object);
408  when_true_status(max < instances, exit, retval = amxd_status_invalid_value);
409 
410  max_var =
411  (amxc_var_t*) amxd_object_get_action_cb_data(object,
414  if(max == UINT32_MAX) {
415  amxd_object_remove_max_instance_check(object, max_var);
416  retval = amxd_status_ok;
417  goto exit;
418  }
419 
420  if(max_var != NULL) {
421  amxc_var_set(uint32_t, max_var, max);
422  } else {
423  retval = amxd_object_add_max_instance_check(object, max);
424  when_failed(retval, exit);
425  }
426 
427  retval = amxd_status_ok;
428 
429 exit:
430  return retval;
431 }
Ambiorix Data Model Default actions header file.
amxd_status_t amxd_action_object_add_inst(amxd_object_t *const object, amxd_param_t *const param, amxd_action_t reason, const amxc_var_t *const args, amxc_var_t *const retval, void *priv)
#define when_failed_status(x, l, c)
Definition: amxd_assert.h:65
bool amxd_name_is_valid(const char *name)
Definition: amxd_common.c:115
Ambiorix Data Model API header file.
Ambiorix Data Model API header file.
bool amxd_object_has_action_cb(amxd_object_t *const object, const amxd_action_t reason, amxd_action_fn_t fn)
amxd_status_t amxd_object_add_action_cb(amxd_object_t *const object, const amxd_action_t reason, amxd_action_fn_t fn, void *priv)
void amxd_object_set_action_cb_data(amxd_object_t *const object, const amxd_action_t reason, amxd_action_fn_t fn, void *data)
void * amxd_object_get_action_cb_data(amxd_object_t *const object, const amxd_action_t reason, amxd_action_fn_t fn)
amxd_status_t amxd_object_remove_action_cb(amxd_object_t *const object, const amxd_action_t reason, amxd_action_fn_t fn)
bool amxd_object_has_matching_instances(const amxd_object_t *const templ, amxp_expr_t *expr)
static uint32_t amxd_object_get_instance_count(const amxd_object_t *object)
static void amxd_object_remove_max_instance_check(amxd_object_t *object, amxc_var_t *max_var)
static bool amxd_template_has_instance(const amxd_object_t *const templ, const char *name)
static bool amxd_template_has_index(const amxd_object_t *const templ, uint32_t index)
static amxd_status_t amxd_object_instantiate(amxd_object_t **object, amxd_object_t *templ, const char *name, uint32_t index, amxc_var_t *templ_params, amxc_var_t *tmp_values)
static amxd_status_t amxd_object_instance_set_index_name(amxd_object_t *object, amxd_object_t *templ, const char *name, uint32_t index)
static amxd_status_t amxd_object_add_max_instance_check(amxd_object_t *object, uint32_t max)
static amxd_status_t amxd_object_instance_validate_id(amxd_object_t *templ, const char **name, uint32_t index, amxc_var_t *templ_params, amxc_var_t *values)
amxd_status_t amxd_object_set_max_instances(amxd_object_t *object, uint32_t max)
static amxd_status_t amxd_cleanup_max_instance(amxd_object_t *const object, UNUSED amxd_param_t *const param, amxd_action_t reason, UNUSED const amxc_var_t *const args, UNUSED amxc_var_t *const retval, void *priv)
static amxd_status_t amxd_object_check_instance_alias(amxd_object_t *const templ, amxc_var_t *templ_params, amxc_htable_t *values, uint32_t index, const char **name)
amxd_param_t * amxd_object_get_param_counter_by_counted_object(const amxd_object_t *const object)
Gets a parameter definition associated with a counted object.
amxd_status_t amxd_object_describe_key_params(amxd_object_t *const object, amxc_var_t *const value, amxd_dm_access_t access)
PRIVATE amxd_status_t amxd_object_build_key_expr(amxc_var_t *const templ_params, amxp_expr_t **expr, const amxc_htable_t *const data)
PRIVATE void amxd_object_clean(amxd_object_t *const object)
PRIVATE amxd_status_t amxd_object_copy_params(amxd_object_t *const dst, const amxd_object_t *const src)
PRIVATE amxd_status_t amxd_object_copy_children(amxd_object_t *const dst, const amxd_object_t *const src)
PRIVATE amxd_status_t amxd_object_init(amxd_object_t *const object, const amxd_object_type_t type, const char *name, amxc_var_t *templ_params, amxc_var_t *values)
PRIVATE amxd_status_t amxd_object_copy_mib_names(amxd_object_t *const dst, const amxd_object_t *const src)
amxd_status_t amxd_param_counter_update(amxd_param_t *counter)
#define GET_FIELD(var, field)
Definition: amxd_priv.h:76
amxd_status_t PRIVATE amxd_action_set_values(amxd_object_t *const object, amxd_dm_access_t access, bool ro, const amxc_var_t *values, amxc_var_t *retval, bool required)
@ action_object_add_inst
Definition: amxd_types.h:123
@ action_object_destroy
Definition: amxd_types.h:125
enum _amxd_action amxd_action_t
enum _amxd_status amxd_status_t
@ amxd_status_invalid_name
Definition: amxd_types.h:86
@ amxd_status_invalid_type
Definition: amxd_types.h:90
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_unknown_error
Definition: amxd_types.h:79
@ amxd_status_invalid_value
Definition: amxd_types.h:88
@ amxd_status_duplicate
Definition: amxd_types.h:91
#define AMXD_OBJECT_NAMED
Name and path format flag - default behavior, use name for instance objects.
Definition: amxd_object.h:164
@ amxd_dm_access_private
Definition: amxd_types.h:141
@ amxd_dm_access_protected
Definition: amxd_types.h:139
@ amxd_object_template
Definition: amxd_types.h:183
@ amxd_object_instance
Definition: amxd_types.h:186
amxd_status_t amxd_object_new_instance(amxd_object_t **object, amxd_object_t *templ, const char *name, uint32_t index, amxc_var_t *values)
Data model object constructor function.
const char * amxd_object_get_name(const amxd_object_t *const object, const uint32_t flags)
Get the name of the object (or index as a string for instance objects)
Definition: amxd_object.c:239
amxd_status_t amxd_object_set_attrs(amxd_object_t *const object, const uint32_t bitmask, bool enable)
Sets or unsets object attributes using a bitmap.
Definition: amxd_object.c:301
uint32_t amxd_object_get_attrs(const amxd_object_t *const object)
Gets the set attributes of an object.
Definition: amxd_object.c:334
amxd_object_type_t type
Definition: amxd_types.h:236
uint32_t last_index
Definition: amxd_types.h:241
uint32_t index
Definition: amxd_types.h:240
char * name
Definition: amxd_types.h:238
amxc_llist_t instances
Definition: amxd_types.h:244
char * index_name
Definition: amxd_types.h:239
static int counter
static amxd_status_t status