libamxb  4.8.2
Bus Agnostic C API
amxb_subscription.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 <stdlib.h>
59 #include <string.h>
60 
61 #include <amxc/amxc_macros.h>
62 #include <amxc/amxc.h>
63 #include <amxp/amxp.h>
64 
65 #include <amxd/amxd_types.h>
66 #include <amxd/amxd_path.h>
67 
68 #include <amxb/amxb_error.h>
69 #include <amxb/amxb_types.h>
70 #include <amxb/amxb_subscription.h>
71 #include <amxb/amxb_subscribe.h>
72 
73 #include "amxb_priv.h"
74 
75 static amxb_sub_t* amxb_sub_alloc(const char* object,
76  amxp_slot_fn_t slot_cb,
77  void* priv) {
78  amxb_sub_t* sub = NULL;
79  amxd_path_t path;
80 
81  amxd_path_init(&path, NULL);
82 
83  when_str_empty(object, exit);
84  when_null(slot_cb, exit);
85 
86  amxd_path_setf(&path, true, "%s", object);
87 
88  sub = (amxb_sub_t*) calloc(1, sizeof(amxb_sub_t));
89  when_null((sub), exit);
90  sub->data.slot_cb = slot_cb;
91  sub->data.priv = priv;
92 
93  sub->data.object = amxd_path_get_fixed_part(&path, false);
94  if(sub->data.object == NULL) {
95  free(sub);
96  sub = NULL;
97  goto exit;
98  }
99 
100  if(*sub->data.object != 0) {
101  sub->data.object[strlen(sub->data.object) - 1] = 0;
102  }
103 
104 exit:
105  amxd_path_clean(&path);
106  return sub;
107 }
108 
109 static bool amxb_subscription_matches(const char* p1,
110  const char* p2,
111  int len1,
112  int len2) {
113  bool match = false;
114  if(len1 < len2) {
115  if(strncmp(p1, p2, len1) == 0) {
116  match = true;
117  }
118  }
119  return match;
120 }
121 
123  const char* object,
124  bool parent) {
125  amxb_subscription_t* subscription = NULL;
126  amxd_path_t search_path;
127  amxd_path_t sub_path;
128  char* fsp = NULL;
129  int search_len = 0;
130 
131  amxd_path_init(&search_path, NULL);
132  amxd_path_init(&sub_path, NULL);
133 
134  when_str_empty(object, exit);
135 
136  amxd_path_setf(&search_path, true, "%s", object);
137  fsp = amxd_path_get_fixed_part(&search_path, false);
138  search_len = strlen(fsp);
139 
140  amxc_llist_iterate(it, (&bus_ctx->client_subs)) {
141  amxb_sub_t* sub = amxc_container_of(it, amxb_sub_t, it);
142  char* fp = NULL;
143  int sub_len = 0;
144  amxd_path_setf(&sub_path, true, "%s", sub->data.object);
145 
146  fp = amxd_path_get_fixed_part(&sub_path, false);
147  sub_len = strlen(fp);
148  subscription = &sub->data;
149 
150  if(parent) {
151  if(amxb_subscription_matches(fp, fsp, sub_len, search_len)) {
152  free(fp);
153  break;
154  }
155  } else {
156  if(amxb_subscription_matches(fsp, fp, search_len, sub_len)) {
157  free(fp);
158  break;
159  }
160  }
161  free(fp);
162  subscription = NULL;
163  }
164 
165 exit:
166  amxd_path_clean(&search_path);
167  amxd_path_clean(&sub_path);
168  free(fsp);
169  return subscription;
170 }
171 
173  int rv = AMXB_STATUS_OK;
174  amxb_sub_t* sub = amxc_container_of(subscription, amxb_sub_t, data);
175 
176  if(sub->it.llist != NULL) {
177  amxb_bus_ctx_t* bus_ctx = NULL;
178  bus_ctx = amxc_container_of(sub->it.llist, amxb_bus_ctx_t, client_subs);
179  amxc_llist_it_take(&sub->it);
180  rv = amxb_unsubscribe(bus_ctx, subscription->object, subscription->slot_cb,
181  subscription->priv);
182  }
183 
184  return rv;
185 }
186 
189  const char* object,
190  const char* expression,
191  amxp_slot_fn_t slot_cb,
192  void* priv) {
193  int retval = AMXB_ERROR_UNKNOWN;
194  amxb_sub_t* sub = amxb_sub_alloc(object, slot_cb, priv);
195 
196  when_null(sub, exit);
197  *subscription = &sub->data;
198 
199  retval = amxb_subscribe(bus_ctx,
200  object,
201  expression,
202  (*subscription)->slot_cb,
203  (*subscription)->priv);
204  when_failed(retval, exit);
205  amxc_llist_append(&bus_ctx->client_subs, &sub->it);
206 
207 exit:
208  if((retval != AMXB_STATUS_OK) && (sub != NULL)) {
209  free((*subscription)->object);
210  free(sub);
211  *subscription = NULL;
212  }
213  return retval;
214 }
215 
217  const char* object,
218  amxp_slot_fn_t slot_cb,
219  void* priv) {
220  amxb_subscription_t* subscription = NULL;
221 
222  when_str_empty(object, exit);
223  when_null(slot_cb, exit);
224 
225  amxc_llist_iterate(it, (&bus_ctx->client_subs)) {
226  amxb_sub_t* sub = amxc_container_of(it, amxb_sub_t, it);
227  subscription = &sub->data;
228  if((strcmp(subscription->object, object) == 0) &&
229  ( subscription->slot_cb == slot_cb) &&
230  ( subscription->priv == priv)) {
231  break;
232  }
233  subscription = NULL;
234  }
235 
236 exit:
237  return subscription;
238 }
239 
241  const char* object) {
242  return amxb_subscription_find_relation(bus_ctx, object, true);
243 }
244 
246  const char* object) {
247  return amxb_subscription_find_relation(bus_ctx, object, false);
248 }
249 
251  int rv = AMXB_STATUS_OK;
252  amxb_sub_t* sub = NULL;
253 
254  when_null(subscription, exit);
255  when_null(*subscription, exit);
256 
257  sub = amxc_container_of((*subscription), amxb_sub_t, data);
258  rv = amxb_subscription_remove((*subscription));
259 
260  amxc_llist_it_take(&(*subscription)->it);
261  free((*subscription)->object);
262  free(sub);
263 
264  *subscription = NULL;
265 
266 exit:
267  return rv;
268 }
269 
270 void amxb_subscription_remove_it(amxc_llist_it_t* it) {
271  amxb_subscription_t* subscription = amxc_container_of(it, amxb_subscription_t, it);
272  amxb_subscription_delete(&subscription);
273 }
Error code defines.
Ambiorix Bus Agnostic Data Model eventing API.
static amxb_subscription_t * amxb_subscription_find_relation(amxb_bus_ctx_t *bus_ctx, const char *object, bool parent)
int amxb_subscription_remove(amxb_subscription_t *subscription)
static amxb_sub_t * amxb_sub_alloc(const char *object, amxp_slot_fn_t slot_cb, void *priv)
void amxb_subscription_remove_it(amxc_llist_it_t *it)
static bool amxb_subscription_matches(const char *p1, const char *p2, int len1, int len2)
#define AMXB_ERROR_UNKNOWN
Unknown error.
Definition: amxb_error.h:80
#define AMXB_STATUS_OK
All ok.
Definition: amxb_error.h:86
int amxb_unsubscribe(amxb_bus_ctx_t *const ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
Removes an event subscription.
amxb_subscription_t * amxb_subscription_find_child(amxb_bus_ctx_t *bus_ctx, const char *object)
Find a child subscription.
int amxb_subscription_delete(amxb_subscription_t **subscription)
Deletes a subscription object and unsubscribe for events of a object tree.
amxb_subscription_t * amxb_subscription_find_parent(amxb_bus_ctx_t *bus_ctx, const char *object)
Find a parent subscription.
int amxb_subscribe(amxb_bus_ctx_t *const ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
Subscribes for events of a object tree.
amxb_subscription_t * amxb_subscription_find(amxb_bus_ctx_t *bus_ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
Find an exact subscription.
int amxb_subscription_new(amxb_subscription_t **subscription, amxb_bus_ctx_t *bus_ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
Creates a subscription object and subscribes for events of a object tree.
amxc_llist_t client_subs
Definition: amxb_types.h:127
amxp_slot_fn_t slot_cb
Definition: amxb_types.h:159
Definition: amxb_priv.h:64
amxc_llist_it_t it
Definition: amxb_priv.h:65
amxb_subscription_t data
Definition: amxb_priv.h:66
static amxb_bus_ctx_t * bus_ctx
Definition: test_amxb_e2e.c:84