libamxb  4.8.2
Bus Agnostic C API
amxb_backend_mngr.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 <dlfcn.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 
64 #include <amxc/amxc.h>
65 #include <amxp/amxp.h>
66 
67 #include <amxd/amxd_dm.h>
68 #include <amxd/amxd_object.h>
69 #include <amxd/amxd_path.h>
70 
71 #include <amxb/amxb_be_intf.h>
72 #include <amxb/amxb.h>
73 
74 #include "amxb_priv.h"
75 #include "amxb_version.h"
76 
77 typedef struct _amxb_who_has_cache {
78  amxc_htable_it_t hit;
79  amxc_llist_it_t lit;
82 
83 static amxc_htable_t amxb_backends;
84 static amxb_be_funcs_t* current_be = NULL;
85 static const amxc_var_t* amxb_conf = NULL;
86 
87 static uint32_t amxb_cache_size = 5;
88 static amxc_llist_t amxb_cache_list;
89 static amxc_htable_t amxb_cache_table;
90 
92  .major = AMXB_VERSION_MAJOR,
93  .minor = AMXB_VERSION_MINOR,
94  .build = AMXB_VERSION_BUILD
95 };
96 
97 static int amxb_close_backend(UNUSED amxb_be_funcs_t* fns) {
98  void* handle = fns->handle;
99  char* no_dlclose = getenv("AMXB_NO_DLCLOSE");
100  int retval = 0;
101 
102  fns->handle = NULL;
103  if(no_dlclose == NULL) {
104  retval = dlclose(handle);
105  if(retval != 0) {
106  const char* errstr = dlerror();
107  printf("dlclose failed - %s", errstr != NULL? errstr:"no error");
108  }
109  }
110 
111  return retval;
112 }
113 
114 static void amxb_be_remove_connections(amxc_llist_it_t* lit) {
115  amxb_bus_ctx_t* bus_ctx = amxc_llist_it_get_data(lit, amxb_bus_ctx_t, it);
116  amxb_free(&bus_ctx);
117 }
118 
119 static void amxb_be_remove_backend(UNUSED const char* key,
120  amxc_htable_it_t* it) {
121  amxb_be_funcs_t* fns = NULL;
122 
123  fns = amxc_htable_it_get_data(it, amxb_be_funcs_t, it);
124  amxc_llist_clean(&fns->connections, amxb_be_remove_connections);
125  if(fns->handle != NULL) {
126  amxb_close_backend(fns);
127  }
128 }
129 
130 static int amxb_be_invoke_on_all_connections(amxc_llist_t* connections,
132  const amxc_var_t* args,
133  uint32_t type,
134  void* priv) {
135  int retval = 0;
136 
137  amxc_llist_for_each(it, connections) {
138  amxb_bus_ctx_t* ctx = amxc_llist_it_get_data(it, amxb_bus_ctx_t, it);
139  if(ctx->socket_type != type) {
140  continue;
141  }
142  retval = fn(ctx, args, priv);
143  when_failed(retval, exit);
144  }
145 
146 exit:
147  return retval;
148 }
149 
150 static bool amxb_has_object(amxb_bus_ctx_t* bus_ctx, const char* object, bool full_match) {
151  bool retval = false;
152  const amxb_be_funcs_t* fns = NULL;
153 
154  fns = bus_ctx->bus_fn;
155  if(amxb_is_valid_be_func(fns, has, fns->has)) {
156  if(full_match) {
157  retval = fns->has(bus_ctx->bus_ctx, object);
158  } else {
159  amxd_path_t path;
160  char* part = NULL;
161 
162  amxd_path_init(&path, NULL);
163  amxd_path_setf(&path, true, "%s", object);
164 
165  do {
166  free(part);
167  object = amxd_path_get(&path, 0);
168  retval = fns->has(bus_ctx->bus_ctx, object);
169  part = amxd_path_get_last(&path, true);
170  } while(part != NULL && !retval);
171  free(part);
172  amxd_path_clean(&path);
173  }
174  }
175 
176  return retval;
177 }
178 
179 static void amxb_be_object_exists(UNUSED const amxb_bus_ctx_t* bus_ctx,
180  const amxc_var_t* const data,
181  void* priv) {
182  bool* found = (bool*) priv;
183 
184  if(data != NULL) {
185  *found = true;
186  }
187 }
188 
189 static amxb_bus_ctx_t* amxb_be_find_connection(amxc_llist_t* connections,
190  const char* object_path,
191  bool full_match) {
192  amxb_bus_ctx_t* ctx = NULL;
193  amxc_var_t data;
194  bool found = false;
195  amxd_path_t path;
196  char* fixed_path = NULL;
197  uint32_t caps = 0;
198 
199  amxd_path_init(&path, NULL);
200  amxc_var_init(&data);
201  amxd_path_setf(&path, true, "%s", object_path);
202  fixed_path = amxd_path_get_fixed_part(&path, false);
203 
204  // remove the trailing dot if any
205  if((fixed_path != NULL) && (*fixed_path != 0)) {
206  int len = strlen(fixed_path);
207  if(fixed_path[len - 1] == '.') {
208  fixed_path[len - 1] = 0;
209  }
210  }
211 
212  amxc_llist_for_each(it, connections) {
213  ctx = amxc_llist_it_get_data(it, amxb_bus_ctx_t, it);
214  if(ctx->socket_type == AMXB_LISTEN_SOCK) {
215  ctx = NULL;
216  continue;
217  }
218  if(amxb_is_local_object(ctx, fixed_path)) {
219  break;
220  }
222  if(((caps & AMXB_BE_DISCOVER) == AMXB_BE_DISCOVER) &&
223  amxb_has_object(ctx, fixed_path, full_match)) {
224  break;
225  }
227  ( amxb_describe(ctx, fixed_path, AMXB_FLAG_EXISTS, &data, 5) == 0)) {
228  if(amxc_var_is_null(&data)) {
229  ctx = NULL;
230  continue;
231  }
232  break;
233  }
236  amxb_be_object_exists, &found);
237  if(found) {
238  break;
239  }
240  }
241  ctx = NULL;
242  }
243 
244  free(fixed_path);
245  amxd_path_clean(&path);
246  amxc_var_clean(&data);
247  return ctx;
248 }
249 
251  amxc_var_t* const config) {
252  if(amxb_is_valid_be_func(funcs, set_config, funcs->set_config)) {
253  funcs->set_config(config);
254  }
255 }
256 
257 amxb_bus_ctx_t* amxb_be_who_has_impl(const char* object_path, bool full_match) {
258  amxb_bus_ctx_t* ctx = NULL;
259  amxc_htable_it_t* cache_hit = NULL;
260  amxb_who_has_cache_t* cache = NULL;
261 
262  when_str_empty(object_path, exit);
263  when_true(strcmp(object_path, ".") == 0, exit);
264 
265  cache_hit = amxc_htable_get(&amxb_cache_table, object_path);
266  if(cache_hit != NULL) {
267  cache = amxc_container_of(cache_hit, amxb_who_has_cache_t, hit);
268  ctx = cache->ctx;
269  amxc_llist_prepend(&amxb_cache_list, &cache->lit);
270  goto exit;
271  }
272 
273  amxc_htable_for_each(hit, &amxb_backends) {
274  amxb_be_funcs_t* funcs = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
275  ctx = amxb_be_find_connection(&funcs->connections, object_path, full_match);
276  if(ctx == NULL) {
277  continue;
278  }
279  if(amxb_cache_size == 0) {
280  break;
281  }
282  if(amxc_htable_size(&amxb_cache_table) >= amxb_cache_size) {
283  amxc_llist_it_t* it = amxc_llist_take_last(&amxb_cache_list);
284  if(it != NULL) {
285  cache = amxc_container_of(it, amxb_who_has_cache_t, lit);
286  amxc_htable_it_clean(&cache->hit, NULL);
287  free(cache);
288  }
289  }
290 
291  cache = (amxb_who_has_cache_t*) calloc(1, sizeof(amxb_who_has_cache_t));
292  when_null(cache, exit);
293  cache->ctx = ctx;
294  amxc_htable_insert(&amxb_cache_table, object_path, &cache->hit);
295  amxc_llist_prepend(&amxb_cache_list, &cache->lit);
296  break;
297  }
298 
299 exit:
300  return ctx;
301 }
302 
303 // returns 0 when lib version and be version are equal
304 // 1 when lib version is > then be version
305 // -1 when lib version is < then be version
306 //
307 // -1 can be used as a wildcard in the be version
308 // if major be version is -1 all lib version match
309 // if minor be version is -1 only checks major versions
310 // if build be version is -1 only major and minor versions are checked
313  return 1;
314  }
316  return -1;
317  }
318  if(be_version->minor == -1) {
319  return 0;
320  }
322  return 1;
323  }
325  return -1;
326  }
327  if(be_version->build == -1) {
328  return 0;
329  }
331  return 1;
332  }
334  return -1;
335  }
336  return 0;
337 }
338 
340  const amxb_version_t* max) {
341  if((min->major == -1) || (max->major == -1)) {
342  return -1;
343  }
344 
345  if(min->major > max->major) {
346  return -1;
347  }
348  if(min->major == max->major) {
349  if((min->minor > max->minor) && (max->minor != -1)) {
350  return -1;
351  }
352  if(min->minor == max->minor) {
353  if((min->build > max->build) && (max->build != -1)) {
354  return -1;
355  }
356  }
357  }
358 
359  return 0;
360 }
361 
363  static amxb_version_t libv;
364 
365  libv.major = lib_version.major;
366  libv.minor = lib_version.minor;
367  libv.build = lib_version.build;
368 
369  return &libv;
370 }
371 
373  int retval = -1;
374  amxc_htable_it_t* hit = NULL;
375 
376  when_null(funcs, exit);
377  when_null(funcs->name, exit);
378  when_true(*(funcs->name) == 0, exit);
379  when_true(funcs->size > sizeof(amxb_be_funcs_t), exit);
380 
381  if(amxc_htable_is_empty(&amxb_backends)) {
382  when_failed(amxc_htable_init(&amxb_backends, 10), exit);
383  } else {
384  hit = amxc_htable_get(&amxb_backends, funcs->name);
385  when_not_null(hit, exit);
386  }
387 
388  current_be = funcs;
389  funcs->handle = NULL;
390 
391  amxc_htable_it_init(&funcs->it);
392  amxc_llist_init(&funcs->connections);
393  when_failed(amxc_htable_insert(&amxb_backends, funcs->name, &funcs->it), exit);
394 
395  if(amxb_conf != NULL) {
396  amxc_var_t* cfg = amxc_var_get_key(amxb_conf, funcs->name, AMXC_VAR_FLAG_DEFAULT);
397  amxb_apply_be_config(funcs, cfg);
398  }
399 
400  retval = 0;
401 
402 exit:
403  return retval;
404 }
405 
407  int retval = -1;
408  amxc_htable_it_t* hit = NULL;
409 
410  when_null(funcs, exit);
411  when_null(funcs->name, exit);
412  when_true(*(funcs->name) == 0, exit);
413 
414  hit = amxc_htable_get(&amxb_backends, funcs->name);
415 
416  when_null(hit, exit);
417  when_true(hit != &funcs->it, exit);
418 
419  amxc_htable_it_clean(hit, amxb_be_remove_backend);
420 
421  funcs->handle = NULL;
422 
423  retval = 0;
424 
425 exit:
426  if(amxc_htable_is_empty(&amxb_backends)) {
427  amxc_htable_clean(&amxb_backends, NULL);
428  }
429  return retval;
430 }
431 
432 amxb_be_funcs_t* amxb_be_find(const char* name) {
433  amxb_be_funcs_t* fns = NULL;
434  amxc_htable_it_t* hit = NULL;
435 
436  when_null(name, exit);
437  when_true(*(name) == 0, exit);
438 
439  hit = amxc_htable_get(&amxb_backends, name);
440  when_null(hit, exit);
441 
442  fns = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
443 
444 exit:
445  return fns;
446 }
447 
448 const amxb_be_info_t* amxb_be_get_info(const char* name) {
449  amxb_be_funcs_t* fns = NULL;
450  amxb_be_info_fn_t be_get_info = NULL;
451  amxb_be_info_t* info = NULL;
452  amxc_htable_it_t* hit = NULL;
453 
454  when_null(name, exit);
455  when_true(*(name) == 0, exit);
456 
457  hit = amxc_htable_get(&amxb_backends, name);
458  when_null(hit, exit);
459 
460  fns = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
461 
462  be_get_info = (amxb_be_info_fn_t) dlsym(fns->handle, "amxb_be_info");
463  when_null(be_get_info, exit);
464  info = be_get_info();
465 
466 exit:
467  return info;
468 }
469 
470 int amxb_be_load(const char* path_name) {
471  int retval = -1;
472  void* handle = NULL;
473  amxb_be_info_fn_t be_get_info = NULL;
474  amxb_be_info_t* be_info = NULL;
475  when_str_empty(path_name, exit);
476 
477  // Set current backend functions to NULL.
478  // If the loaded shared object has a construct that calls amxb_be_register
479  // the current_be will be set correctly.
480  // This happends during the dlopen
481  current_be = NULL;
482  handle = dlopen(path_name, RTLD_LAZY);
483  if(handle == NULL) {
484  const char* errstr = dlerror();
485  printf("DLOPEN - %s\n", errstr != NULL? errstr:"no error");
486  goto exit;
487  }
488 
489  be_get_info = (amxb_be_info_fn_t) dlsym(handle, "amxb_be_info");
490  when_null(be_get_info, exit);
491 
492  be_info = be_get_info();
493  when_null(be_info, exit);
494  when_null(be_info->min_supported, exit);
495  when_null(be_info->max_supported, exit);
496 
498  be_info->max_supported), exit);
499 
500  when_true(amxb_check_version(be_info->min_supported) < 0, exit);
501  when_true(amxb_check_version(be_info->max_supported) > 0, exit);
502 
503  // The loaded back-end could call amxb_be_register using a constructor
504  // function. This method is not always reliable, depending on the platform
505  // the constructor is not invoked.
506  // Or the back-end did not call amxb_be_register function
507 
508  // Prefered solution is that the backend gives the function table using
509  // the back-end information structure. The following lines are here for
510  // backwards compatibility.
511  if(current_be == NULL) {
512  when_null(be_info->funcs, exit);
513  if(be_info->funcs->handle == handle) {
514  dlclose(handle);
515  } else if(be_info->funcs->handle != NULL) {
516  goto exit;
517  } else {
518  when_failed(amxb_be_register(be_info->funcs), exit);
519  }
520  } else {
522  }
523 
524  be_info->funcs->handle = handle;
525 
526  retval = 0;
527 
528 exit:
529  if((retval != 0) && (handle != NULL)) {
530  dlclose(handle);
531  }
532  current_be = NULL;
533  return retval;
534 }
535 
536 int amxb_be_load_multiple(amxc_var_t* const bes) {
537  int retval = -1;
538  const amxc_llist_t* list = NULL;
539  amxc_llist_t list_bes;
540 
541  amxc_llist_init(&list_bes);
542 
543  when_null(bes, exit);
544  when_true(amxc_var_type_of(bes) != AMXC_VAR_ID_LIST &&
545  amxc_var_type_of(bes) != AMXC_VAR_ID_CSTRING, exit);
546 
547 
548  if(amxc_var_type_of(bes) == AMXC_VAR_ID_CSTRING) {
549  amxc_string_t* str_bes = amxc_var_take(amxc_string_t, bes);
550  when_null(str_bes, exit);
551  amxc_string_split_to_llist(str_bes, &list_bes, ':');
552  amxc_var_clean(bes);
553  amxc_var_set_type(bes, AMXC_VAR_ID_LIST);
554  amxc_llist_for_each(it, (&list_bes)) {
555  amxc_string_t* str = amxc_string_from_llist_it(it);
556  amxc_var_add(cstring_t, bes, amxc_string_get(str, 0));
557  }
558  amxc_string_delete(&str_bes);
559  }
560  list = amxc_var_constcast(amxc_llist_t, bes);
561 
562  when_true(amxc_llist_is_empty(list), exit);
563  retval = 0;
564  amxc_llist_for_each(it, list) {
565  amxc_var_t* be = amxc_var_from_llist_it(it);
566  if(amxb_be_load(amxc_var_constcast(cstring_t, be)) == 0) {
567  amxc_var_delete(&be);
568  } else {
569  retval++;
570  }
571  }
572 
573 exit:
574  amxc_llist_clean(&list_bes, amxc_string_list_it_free);
575  return retval;
576 }
577 
578 int amxb_be_remove(const char* backend_name) {
579  amxb_be_funcs_t* fns = NULL;
580  amxc_htable_it_t* hit = NULL;
581  int retval = -1;
582 
583  when_str_empty(backend_name, exit);
584 
585  hit = amxc_htable_get(&amxb_backends, backend_name);
586  when_null(hit, exit);
587 
588  fns = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
589  when_null(fns->handle, exit);
590  amxc_llist_clean(&fns->connections, amxb_be_remove_connections);
591  amxc_htable_it_clean(hit, NULL);
592 
593  retval = amxb_close_backend(fns);
594 
595 exit:
596  if(amxc_htable_is_empty(&amxb_backends)) {
597  amxc_htable_clean(&amxb_backends, NULL);
598  }
599  return retval;
600 }
601 
602 void amxb_be_remove_all(void) {
603  amxc_htable_clean(&amxb_backends, amxb_be_remove_backend);
604 }
605 
606 amxc_array_t* amxb_be_list(void) {
607  return amxc_htable_get_sorted_keys(&amxb_backends);
608 }
609 
611  const amxc_var_t* args,
612  void* priv) {
613  int retval = AMXB_ERROR_UNKNOWN;
614  when_null(fn, exit);
615 
616  amxc_htable_for_each(hit, &amxb_backends) {
617  amxb_be_funcs_t* funcs = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
619  fn,
620  args,
622  priv) == AMXB_STATUS_OK) {
623  retval = AMXB_STATUS_OK;
624  }
625  }
626 
627 exit:
628  return retval;
629 }
630 
632  const amxc_var_t* args,
633  void* priv) {
634  int retval = 0;
635  when_null(fn, exit);
636 
637  amxc_htable_for_each(hit, &amxb_backends) {
638  amxb_be_funcs_t* funcs = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
640  fn,
641  args,
643  priv);
644  }
645 
646 exit:
647  return retval;
648 }
649 
650 amxb_bus_ctx_t* amxb_be_who_has(const char* object_path) {
651  return amxb_be_who_has_impl(object_path, false);
652 }
653 
655  when_null(ctx, exit);
656 
657  amxc_llist_for_each(lit, &amxb_cache_list) {
658  amxb_who_has_cache_t* cache = amxc_container_of(lit, amxb_who_has_cache_t, lit);
659  if(cache->ctx == ctx) {
660  amxc_llist_it_take(&cache->lit);
661  amxc_htable_it_clean(&cache->hit, NULL);
662  free(cache);
663  }
664  }
665 
666 exit:
667  return;
668 }
669 
670 void amxb_be_cache_remove_path(const char* object_path) {
671  amxc_htable_it_t* cache_hit = NULL;
672  amxb_who_has_cache_t* cache = NULL;
673 
674  when_str_empty(object_path, exit);
675  when_true(strcmp(object_path, ".") == 0, exit);
676 
677  cache_hit = amxc_htable_get(&amxb_cache_table, object_path);
678  when_null(cache_hit, exit);
679 
680  cache = amxc_container_of(cache_hit, amxb_who_has_cache_t, hit);
681  amxc_llist_it_take(&cache->lit);
682  amxc_htable_it_clean(&cache->hit, NULL);
683  free(cache);
684 
685 exit:
686  return;
687 }
688 
689 void amxb_be_cache_set_size(uint32_t size) {
690  uint32_t items = amxc_htable_size(&amxb_cache_table);
691  if(size < items) {
692  amxc_llist_for_each_reverse(it, &amxb_cache_list) {
693  amxb_who_has_cache_t* cache = amxc_container_of(it, amxb_who_has_cache_t, lit);
694  amxc_llist_it_take(&cache->lit);
695  amxc_htable_it_clean(&cache->hit, NULL);
696  free(cache);
697  items--;
698  if(size >= items) {
699  break;
700  }
701  }
702  }
703 
704  amxb_cache_size = size;
705 }
706 
707 int amxb_set_config(amxc_var_t* const config) {
708  amxb_conf = config;
709  if(config == NULL) {
710  amxc_htable_for_each(hit, &amxb_backends) {
711  amxb_be_funcs_t* funcs = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
712  amxb_apply_be_config(funcs, NULL);
713  }
714  } else {
715  amxc_htable_for_each(hit, &amxb_backends) {
716  amxb_be_funcs_t* funcs = amxc_htable_it_get_data(hit, amxb_be_funcs_t, it);
717  amxc_var_t* be_config = GET_ARG(config, amxc_htable_it_get_key(hit));
718  if(be_config == NULL) {
719  be_config = amxc_var_add_key(amxc_htable_t, config, amxc_htable_it_get_key(hit), NULL);
720  }
721  amxb_apply_be_config(funcs, be_config);
722  }
723  }
724 
725  return 0;
726 }
727 
728 CONSTRUCTOR static void amxb_cache_init(void) {
729  amxc_htable_init(&amxb_cache_table, amxb_cache_size * 2);
730 }
731 
732 DESTRUCTOR static void amxb_cache_clean(void) {
733  amxc_htable_clean(&amxb_cache_table, NULL);
734 }
Ambiorix bus agnostic API header file.
static const amxc_var_t * amxb_conf
static amxb_be_funcs_t * current_be
static int amxb_be_invoke_on_all_connections(amxc_llist_t *connections, amxb_be_task_fn_t fn, const amxc_var_t *args, uint32_t type, void *priv)
static amxb_version_t lib_version
amxb_bus_ctx_t * amxb_be_who_has_impl(const char *object_path, bool full_match)
static void amxb_be_remove_connections(amxc_llist_it_t *lit)
static void amxb_apply_be_config(amxb_be_funcs_t *funcs, amxc_var_t *const config)
struct _amxb_who_has_cache amxb_who_has_cache_t
static amxc_htable_t amxb_backends
static uint32_t amxb_cache_size
static int amxb_close_backend(UNUSED amxb_be_funcs_t *fns)
static amxb_bus_ctx_t * amxb_be_find_connection(amxc_llist_t *connections, const char *object_path, bool full_match)
static bool amxb_has_object(amxb_bus_ctx_t *bus_ctx, const char *object, bool full_match)
static void amxb_be_object_exists(UNUSED const amxb_bus_ctx_t *bus_ctx, const amxc_var_t *const data, void *priv)
static CONSTRUCTOR void amxb_cache_init(void)
static amxc_llist_t amxb_cache_list
static void amxb_be_remove_backend(UNUSED const char *key, amxc_htable_it_t *it)
static amxc_htable_t amxb_cache_table
static DESTRUCTOR void amxb_cache_clean(void)
Ambiorix Bus Backend Interface.
#define AMXB_BE_DISCOVER
Definition: amxb_be_intf.h:343
#define AMXB_BE_DISCOVER_DESCRIBE
Definition: amxb_be_intf.h:341
#define AMXB_BE_DISCOVER_LIST
Definition: amxb_be_intf.h:342
config
Definition: test.odl:56
#define AMXB_FLAG_EXISTS
#define AMXB_FLAG_FIRST_LVL
#define amxb_is_valid_be_func(ft, member, ptr)
Definition: amxb_priv.h:78
bool PRIVATE amxb_is_local_object(amxb_bus_ctx_t *ctx, const char *obj_path)
Definition: amxb_ba_priv.c:94
uint32_t PRIVATE amxb_be_get_capabilities(amxb_bus_ctx_t *bus_ctx)
Definition: amxb_ba_priv.c:157
#define AMXB_LISTEN_SOCK
Definition: amxb_types.h:77
int(* amxb_be_task_fn_t)(amxb_bus_ctx_t *bus_ctx, const amxc_var_t *args, void *priv)
Definition: amxb_types.h:94
#define AMXB_DATA_SOCK
Definition: amxb_types.h:76
amxb_be_info_t *(* amxb_be_info_fn_t)(void)
Definition: amxb_types.h:113
static uint32_t caps
Definition: dummy_be.c:70
int amxb_be_for_all_listeners(amxb_be_task_fn_t fn, const amxc_var_t *args, void *priv)
Calls a function on all listen sockets.
int amxb_be_for_all_connections(amxb_be_task_fn_t fn, const amxc_var_t *args, void *priv)
Calls a function on all open connections.
amxb_bus_ctx_t * amxb_be_who_has(const char *object_path)
Searches a bus context that can provide a certain object.
int amxb_be_unregister(amxb_be_funcs_t *const funcs)
Unregisters a backend interface.
void amxb_be_cache_remove_ctx(amxb_bus_ctx_t *ctx)
Removes a bus context from the lookup cache.
const amxb_version_t * amxb_get_version(void)
Gets the version of the library.
int amxb_be_register(amxb_be_funcs_t *const funcs)
Registers backend interface.
void amxb_be_cache_set_size(uint32_t size)
Changes the size of the lookup cache.
const amxb_be_info_t * amxb_be_get_info(const char *name)
Gets a backend information.
int amxb_be_load(const char *path_name)
Loads a shared object that implements a bus specific backend interface.
int amxb_be_load_multiple(amxc_var_t *const bes)
Loads multiple shared objects that each implement a bus specific backend interface.
void amxb_be_cache_remove_path(const char *object_path)
Removes an object path and its corresponding bus context from the lookup cache.
int amxb_check_be_versions(const amxb_version_t *min, const amxb_version_t *max)
Checks if the library version is in the given range.
int amxb_be_remove(const char *backend_name)
Removes and unloads a backend with a given name.
int amxb_check_version(const amxb_version_t *be_version)
Compares the given version with the library version.
amxb_be_funcs_t * amxb_be_find(const char *name)
Gets a backend function table using its name.
int amxb_set_config(amxc_var_t *const config)
Passes configuration options to the backends.
void amxb_be_remove_all(void)
Removes and unloads all backends.
amxc_array_t * amxb_be_list(void)
Get the loaded back-end names.
void amxb_free(amxb_bus_ctx_t **ctx)
Frees allocated memory.
#define AMXB_ERROR_UNKNOWN
Unknown error.
Definition: amxb_error.h:80
#define AMXB_STATUS_OK
All ok.
Definition: amxb_error.h:86
int amxb_describe(amxb_bus_ctx_t *const bus_ctx, const char *object, uint32_t flags, amxc_var_t *ret, int timeout)
Describes an object.
int amxb_list(amxb_bus_ctx_t *const bus_ctx, const char *object, uint32_t flags, amxb_be_cb_fn_t fn, void *priv)
List the service elements/nodes of an object.
The back-end interface structure.
amxb_be_has_fn_t has
const char * name
amxc_llist_t connections
amxc_htable_it_t it
amxb_be_set_config_t set_config
const amxb_version_t * min_supported
Definition: amxb_types.h:105
amxb_be_funcs_t * funcs
Definition: amxb_types.h:110
const amxb_version_t * max_supported
Definition: amxb_types.h:106
const amxb_be_funcs_t * bus_fn
Definition: amxb_types.h:121
uint32_t socket_type
Definition: amxb_types.h:126
void * bus_ctx
Definition: amxb_types.h:122
int32_t major
Definition: amxb_types.h:99
int32_t minor
Definition: amxb_types.h:100
int32_t build
Definition: amxb_types.h:101
amxb_bus_ctx_t * ctx
amxc_htable_it_t hit
amxc_llist_it_t lit
static amxb_be_info_t be_info
static amxb_version_t be_version
static amxb_bus_ctx_t * bus_ctx
Definition: test_amxb_e2e.c:84