1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nrappkit/src/registry/registrycb.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,440 @@ 1.4 +/* 1.5 + * 1.6 + * registrycb.c 1.7 + * 1.8 + * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registrycb.c,v $ 1.9 + * $Revision: 1.3 $ 1.10 + * $Date: 2007/06/26 22:37:51 $ 1.11 + * 1.12 + * Callback-related functions 1.13 + * 1.14 + * 1.15 + * Copyright (C) 2005, Network Resonance, Inc. 1.16 + * Copyright (C) 2006, Network Resonance, Inc. 1.17 + * All Rights Reserved 1.18 + * 1.19 + * Redistribution and use in source and binary forms, with or without 1.20 + * modification, are permitted provided that the following conditions 1.21 + * are met: 1.22 + * 1.23 + * 1. Redistributions of source code must retain the above copyright 1.24 + * notice, this list of conditions and the following disclaimer. 1.25 + * 2. Redistributions in binary form must reproduce the above copyright 1.26 + * notice, this list of conditions and the following disclaimer in the 1.27 + * documentation and/or other materials provided with the distribution. 1.28 + * 3. Neither the name of Network Resonance, Inc. nor the name of any 1.29 + * contributors to this software may be used to endorse or promote 1.30 + * products derived from this software without specific prior written 1.31 + * permission. 1.32 + * 1.33 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 1.34 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.35 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.36 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.37 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.38 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.39 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.40 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.41 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.42 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.43 + * POSSIBILITY OF SUCH DAMAGE. 1.44 + * 1.45 + * 1.46 + */ 1.47 + 1.48 +#include <assert.h> 1.49 +#include <string.h> 1.50 +#include "registry.h" 1.51 +#include "registry_int.h" 1.52 +#include "r_assoc.h" 1.53 +#include "r_errors.h" 1.54 +#include "nr_common.h" 1.55 +#include "r_log.h" 1.56 +#include "r_macros.h" 1.57 + 1.58 +static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD, 1.59 + NR_REG_CB_ACTION_DELETE, 1.60 + NR_REG_CB_ACTION_CHANGE, 1.61 + NR_REG_CB_ACTION_FINAL }; 1.62 + 1.63 +typedef struct nr_reg_cb_info_ { 1.64 + char action; 1.65 + void (*cb)(void *cb_arg, char action, NR_registry name); 1.66 + void *cb_arg; 1.67 + NR_registry name; 1.68 +} nr_reg_cb_info; 1.69 + 1.70 +/* callbacks that are registered, a mapping from names like "foo.bar.baz" 1.71 + * to an r_assoc which contains possibly several nr_reg_cb_info*'s */ 1.72 +static r_assoc *nr_registry_callbacks = 0; 1.73 + 1.74 +//static size_t SIZEOF_CB_ID = (sizeof(void (*)()) + 1); 1.75 +#define SIZEOF_CB_ID (sizeof(void (*)()) + 1) 1.76 + 1.77 +static int nr_reg_validate_action(char action); 1.78 +static int nr_reg_assoc_destroy(void *ptr); 1.79 +static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]); 1.80 +static int nr_reg_info_free(void *ptr); 1.81 +static int nr_reg_raise_event_recurse(char *name, char *tmp, int action); 1.82 +static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg); 1.83 +static int nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)); 1.84 + 1.85 +int 1.86 +nr_reg_cb_init() 1.87 +{ 1.88 + int r, _status; 1.89 + 1.90 + if (nr_registry_callbacks == 0) { 1.91 + if ((r=r_assoc_create(&nr_registry_callbacks, r_assoc_crc32_hash_compute, 12))) 1.92 + ABORT(r); 1.93 + } 1.94 + 1.95 + _status=0; 1.96 + abort: 1.97 + if (_status) { 1.98 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't init notifications: %s", nr_strerror(_status)); 1.99 + } 1.100 + return(_status); 1.101 +} 1.102 + 1.103 +int 1.104 +nr_reg_validate_action(char action) 1.105 +{ 1.106 + int _status; 1.107 + int i; 1.108 + 1.109 + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { 1.110 + if (action == CB_ACTIONS[i]) 1.111 + return 0; 1.112 + } 1.113 + ABORT(R_BAD_ARGS); 1.114 + 1.115 + _status=0; 1.116 + abort: 1.117 + return(_status); 1.118 +} 1.119 + 1.120 +int 1.121 +nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) 1.122 +{ 1.123 + int r, _status; 1.124 + r_assoc *assoc; 1.125 + int create_assoc = 0; 1.126 + nr_reg_cb_info *info; 1.127 + int create_info = 0; 1.128 + unsigned char cb_id[SIZEOF_CB_ID]; 1.129 + 1.130 + if (name == 0 || cb == 0) 1.131 + ABORT(R_BAD_ARGS); 1.132 + 1.133 + if (nr_registry_callbacks == 0) 1.134 + ABORT(R_FAILED); 1.135 + 1.136 + if ((r=nr_reg_is_valid(name))) 1.137 + ABORT(r); 1.138 + 1.139 + if ((r=nr_reg_validate_action(action))) 1.140 + ABORT(r); 1.141 + 1.142 + if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) { 1.143 + if (r == R_NOT_FOUND) 1.144 + create_assoc = 1; 1.145 + else 1.146 + ABORT(r); 1.147 + } 1.148 + 1.149 + if (create_assoc) { 1.150 + if ((r=r_assoc_create(&assoc, r_assoc_crc32_hash_compute, 5))) 1.151 + ABORT(r); 1.152 + 1.153 + if ((r=r_assoc_insert(nr_registry_callbacks, name, strlen(name)+1, assoc, 0, nr_reg_assoc_destroy, R_ASSOC_NEW))) 1.154 + ABORT(r); 1.155 + } 1.156 + 1.157 + if ((r=compute_cb_id(cb, action, cb_id))) 1.158 + ABORT(r); 1.159 + 1.160 + if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) { 1.161 + if (r == R_NOT_FOUND) 1.162 + create_info = 1; 1.163 + else 1.164 + ABORT(r); 1.165 + } 1.166 + 1.167 + if (create_info) { 1.168 + if (!(info=(void*)RCALLOC(sizeof(*info)))) 1.169 + ABORT(R_NO_MEMORY); 1.170 + } 1.171 + 1.172 + strncpy(info->name, name, sizeof(info->name)); 1.173 + info->action = action; 1.174 + info->cb = cb; 1.175 + info->cb_arg = cb_arg; 1.176 + 1.177 + if (create_info) { 1.178 + if ((r=r_assoc_insert(assoc, (char*)cb_id, SIZEOF_CB_ID, info, 0, nr_reg_info_free, R_ASSOC_NEW))) 1.179 + ABORT(r); 1.180 + } 1.181 + 1.182 + _status=0; 1.183 + abort: 1.184 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "register callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded")); 1.185 + 1.186 + if (_status) { 1.187 + if (create_info && info) RFREE(info); 1.188 + if (create_assoc && assoc) nr_reg_assoc_destroy(&assoc); 1.189 + } 1.190 + return(_status); 1.191 +} 1.192 + 1.193 +int 1.194 +nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)) 1.195 +{ 1.196 + int r, _status; 1.197 + r_assoc *assoc; 1.198 + int size; 1.199 + unsigned char cb_id[SIZEOF_CB_ID]; 1.200 + 1.201 + if (name == 0 || cb == 0) 1.202 + ABORT(R_BAD_ARGS); 1.203 + 1.204 + if (nr_registry_callbacks == 0) 1.205 + ABORT(R_FAILED); 1.206 + 1.207 + if ((r=nr_reg_is_valid(name))) 1.208 + ABORT(r); 1.209 + 1.210 + if ((r=nr_reg_validate_action(action))) 1.211 + ABORT(r); 1.212 + 1.213 + if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) { 1.214 + if (r != R_NOT_FOUND) 1.215 + ABORT(r); 1.216 + } 1.217 + else { 1.218 + if ((r=compute_cb_id(cb, action, cb_id))) 1.219 + ABORT(r); 1.220 + 1.221 + if ((r=r_assoc_delete(assoc, (char*)cb_id, SIZEOF_CB_ID))) { 1.222 + if (r != R_NOT_FOUND) 1.223 + ABORT(r); 1.224 + } 1.225 + 1.226 + if ((r=r_assoc_num_elements(assoc, &size))) 1.227 + ABORT(r); 1.228 + 1.229 + if (size == 0) { 1.230 + if ((r=r_assoc_delete(nr_registry_callbacks, name, strlen(name)+1))) 1.231 + ABORT(r); 1.232 + } 1.233 + } 1.234 + 1.235 + _status=0; 1.236 + abort: 1.237 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "unregister callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded")); 1.238 + 1.239 + return(_status); 1.240 +} 1.241 + 1.242 +int 1.243 +compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]) 1.244 +{ 1.245 + /* callbacks are identified by the pointer to the cb function plus 1.246 + * the action being watched */ 1.247 + assert(sizeof(cb) == sizeof(void (*)())); 1.248 + assert(sizeof(cb) == (SIZEOF_CB_ID - 1)); 1.249 + 1.250 + memcpy(cb_id, &(cb), sizeof(cb)); 1.251 + cb_id[SIZEOF_CB_ID-1] = action; 1.252 + 1.253 + return 0; 1.254 +} 1.255 + 1.256 +char * 1.257 +nr_reg_action_name(int action) 1.258 +{ 1.259 + char *name = "*Unknown*"; 1.260 + 1.261 + switch (action) { 1.262 + case NR_REG_CB_ACTION_ADD: name = "add"; break; 1.263 + case NR_REG_CB_ACTION_DELETE: name = "delete"; break; 1.264 + case NR_REG_CB_ACTION_CHANGE: name = "change"; break; 1.265 + case NR_REG_CB_ACTION_FINAL: name = "final"; break; 1.266 + } 1.267 + 1.268 + return name; 1.269 +} 1.270 + 1.271 +int 1.272 +nr_reg_assoc_destroy(void *ptr) 1.273 +{ 1.274 + return r_assoc_destroy((r_assoc**)&ptr); 1.275 +} 1.276 + 1.277 +int 1.278 +nr_reg_info_free(void *ptr) 1.279 +{ 1.280 + RFREE(ptr); 1.281 + return 0; 1.282 +} 1.283 + 1.284 +/* call with tmp=0 */ 1.285 +int 1.286 +nr_reg_raise_event_recurse(char *name, char *tmp, int action) 1.287 +{ 1.288 + int r, _status; 1.289 + r_assoc *assoc; 1.290 + nr_reg_cb_info *info; 1.291 + r_assoc_iterator iter; 1.292 + char *key; 1.293 + int keyl; 1.294 + char *c; 1.295 + int free_tmp = 0; 1.296 + int count; 1.297 + 1.298 + if (tmp == 0) { 1.299 + if (!(tmp = (char*)r_strdup(name))) 1.300 + ABORT(R_NO_MEMORY); 1.301 + free_tmp = 1; 1.302 + } 1.303 + 1.304 + if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) { 1.305 + if (r != R_NOT_FOUND) 1.306 + ABORT(r); 1.307 + 1.308 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found on '%s'", tmp); 1.309 + } 1.310 + else { 1.311 + if (!r_assoc_num_elements(assoc, &count)) { 1.312 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "%d callback%s found on '%s'", 1.313 + count, ((count == 1) ? "" : "s"), tmp); 1.314 + } 1.315 + 1.316 + if ((r=r_assoc_init_iter(assoc, &iter))) 1.317 + ABORT(r); 1.318 + 1.319 + for (;;) { 1.320 + if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) { 1.321 + if (r == R_EOD) 1.322 + break; 1.323 + else 1.324 + ABORT(r); 1.325 + } 1.326 + 1.327 + if (info->action == action) { 1.328 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, 1.329 + "Invoking callback %p for '%s'", 1.330 + info->cb, 1.331 + nr_reg_action_name(info->action)); 1.332 + 1.333 + (void)info->cb(info->cb_arg, action, name); 1.334 + } 1.335 + else { 1.336 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, 1.337 + "Skipping callback %p for '%s'", 1.338 + info->cb, 1.339 + nr_reg_action_name(info->action)); 1.340 + } 1.341 + } 1.342 + } 1.343 + 1.344 + if (strlen(tmp) > 0) { 1.345 + c = strrchr(tmp, '.'); 1.346 + if (c != 0) 1.347 + *c = '\0'; 1.348 + else 1.349 + tmp[0] = '\0'; 1.350 + 1.351 + if ((r=nr_reg_raise_event_recurse(name, tmp, action))) 1.352 + ABORT(r); 1.353 + } 1.354 + 1.355 + _status=0; 1.356 + abort: 1.357 + if (free_tmp && tmp != 0) RFREE(tmp); 1.358 + return(_status); 1.359 +} 1.360 + 1.361 + 1.362 +/* NON-STATIC METHODS */ 1.363 + 1.364 +int 1.365 +nr_reg_raise_event(char *name, int action) 1.366 +{ 1.367 + int r, _status; 1.368 + int count; 1.369 + char *event = nr_reg_action_name(action); 1.370 + 1.371 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name); 1.372 + 1.373 + if (name == 0) 1.374 + ABORT(R_BAD_ARGS); 1.375 + 1.376 + if ((r=nr_reg_validate_action(action))) 1.377 + ABORT(r); 1.378 + 1.379 + if ((r=r_assoc_num_elements(nr_registry_callbacks, &count))) 1.380 + ABORT(r); 1.381 + 1.382 + if (count > 0) { 1.383 + if ((r=nr_reg_raise_event_recurse(name, 0, action))) 1.384 + ABORT(r); 1.385 + } 1.386 + else { 1.387 + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found"); 1.388 + return 0; 1.389 + } 1.390 + 1.391 + _status=0; 1.392 + abort: 1.393 + return(_status); 1.394 +} 1.395 + 1.396 + 1.397 +/* PUBLIC METHODS */ 1.398 + 1.399 +int 1.400 +NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) 1.401 +{ 1.402 + int r, _status; 1.403 + int i; 1.404 + 1.405 + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { 1.406 + if (action & CB_ACTIONS[i]) { 1.407 + if ((r=nr_reg_register_callback(name, CB_ACTIONS[i], cb, cb_arg))) 1.408 + ABORT(r); 1.409 + 1.410 + action &= ~(CB_ACTIONS[i]); 1.411 + } 1.412 + } 1.413 + 1.414 + if (action) 1.415 + ABORT(R_BAD_ARGS); 1.416 + 1.417 + _status=0; 1.418 + abort: 1.419 + return(_status); 1.420 +} 1.421 + 1.422 +int 1.423 +NR_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)) 1.424 +{ 1.425 + int r, _status; 1.426 + int i; 1.427 + 1.428 + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { 1.429 + if (action & CB_ACTIONS[i]) { 1.430 + if ((r=nr_reg_unregister_callback(name, CB_ACTIONS[i], cb))) 1.431 + ABORT(r); 1.432 + 1.433 + action &= ~(CB_ACTIONS[i]); 1.434 + } 1.435 + } 1.436 + 1.437 + if (action) 1.438 + ABORT(R_BAD_ARGS); 1.439 + 1.440 + _status=0; 1.441 + abort: 1.442 + return(_status); 1.443 +}