diff options
author | dimitri staessens <[email protected]> | 2016-08-20 10:42:36 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-08-21 18:32:12 +0200 |
commit | 0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66 (patch) | |
tree | 9c0adf0b6ef3b9350c13939f6d40c79eca7546fd /src/irmd/api_table.c | |
parent | ba27593e3e8406e109393ae383f17c7416675c1e (diff) | |
download | ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.tar.gz ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.zip |
irmd, lib: Rebuild the IRMd data model
The complete data model inside the IRMd has been restructured. The
bind operation was revised to allow binding of AP and AP instances and
register those names with different DIFs (see "irm bind" for details).
Server applications require to call ap_init with a server name
argument, client application that do not the be reachable over any DIF
can call ap_init(NULL). Calling ap_init for a client with a specified
name will not have adverse consequences for the application, but will
consume unnecessary resources in the IRMd.
Application servers can now be started at any point after the IRMd has
been started. Starting servers, binding AP names and registering names in
DIFs can be performed in any order that does not defy temporal logic.
Supports naming instances by their pid. In case of IPCP Instances
created with the IRM tool, the name assigned during "irm ipcp create"
can be used.
All the changes required updates in the tools.
Diffstat (limited to 'src/irmd/api_table.c')
-rw-r--r-- | src/irmd/api_table.c | 190 |
1 files changed, 153 insertions, 37 deletions
diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c index b62b2b55..2747ed1a 100644 --- a/src/irmd/api_table.c +++ b/src/irmd/api_table.c @@ -23,92 +23,208 @@ #include <ouroboros/config.h> #include <ouroboros/list.h> #include <ouroboros/errno.h> +#include <ouroboros/time_utils.h> #include "api_table.h" +#include "registry.h" #include <stdlib.h> +#include <unistd.h> +#include <limits.h> -struct api_entry * api_entry_create(pid_t api, - char * apn, - char * ap_subset) +struct api_entry * api_entry_create(pid_t api, char * apn) { - struct api_entry * e = malloc(sizeof(*e)); + struct api_entry * e; + + if (apn == NULL) + return NULL; + + e = malloc(sizeof(*e)); if (e == NULL) return NULL; INIT_LIST_HEAD(&e->next); + INIT_LIST_HEAD(&e->names); + + e->api = api; + e->apn = apn; + e->daf_name = NULL; - e->api = api; - e->apn = apn; - e->ap_subset = ap_subset; + e->re = NULL; + + e->state = API_INIT; + + pthread_mutex_init(&e->state_lock, NULL); + pthread_cond_init(&e->state_cond, NULL); return e; } void api_entry_destroy(struct api_entry * e) { + struct list_head * p; + struct list_head * h; + + if (e == NULL) + return; + + pthread_mutex_lock(&e->state_lock); + + if (e->state == API_SLEEP) + e->state = API_DESTROY; + + pthread_cond_signal(&e->state_cond); + + while (e->state != API_INIT) + pthread_cond_wait(&e->state_cond, &e->state_lock); + + pthread_mutex_unlock(&e->state_lock); + + pthread_cond_destroy(&e->state_cond); + pthread_mutex_destroy(&e->state_lock); + if (e->apn != NULL) free(e->apn); - if (e->ap_subset != NULL) - free(e->ap_subset); + + list_for_each_safe(p, h, &e->names) { + struct str_el * n = list_entry(p, struct str_el, next); + list_del(&n->next); + if (n->str != NULL) + free(n->str); + free(n); + } + free(e); } -int api_table_add_api(struct list_head * api_table, - pid_t api, char * apn, char * ap_subset) +int api_entry_add_name(struct api_entry * e, char * name) { - if (apn == NULL) + struct str_el * s; + if (e == NULL || name == NULL) return -EINVAL; - struct api_entry * e = api_entry_create(api, apn, ap_subset); - if (e == NULL) + s = malloc(sizeof(*s)); + if (s == NULL) return -ENOMEM; - list_add(&e->next, api_table); + s->str = name; + list_add(&s->next, &e->names); return 0; } -void api_table_del_api(struct list_head * api_table, pid_t api) +void api_entry_del_name(struct api_entry * e, char * name) { - struct list_head * p; - struct list_head * h; + struct list_head * p = NULL; + struct list_head * h = NULL; + + list_for_each_safe(p, h, &e->names) { + struct str_el * s = list_entry(p, struct str_el, next); + if (!wildcard_match(name, s->str)) { + list_del(&s->next); + if (s->str != NULL) + free(s->str); + free(s); + } + } +} - list_for_each_safe(p, h, api_table) { - struct api_entry * e = - list_entry(p, struct api_entry, next); +int api_entry_sleep(struct api_entry * e) +{ + struct timespec timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), + (IRMD_ACCEPT_TIMEOUT % 1000) * MILLION}; + struct timespec now; + struct timespec dl; - if (api == e->api) { - list_del(&e->next); - api_entry_destroy(e); + int ret = 0; + + if (e == NULL) + return -EINVAL; + + e->re = NULL; + + clock_gettime(CLOCK_REALTIME, &now); + + ts_add(&now, &timeout, &dl); + + pthread_mutex_lock(&e->state_lock); + if (e->state != API_INIT) { + pthread_mutex_unlock(&e->state_lock); + return -EINVAL; + } + + e->state = API_SLEEP; + + while (e->state == API_SLEEP) { + if ((ret = -pthread_cond_timedwait(&e->state_cond, + &e->state_lock, + &dl)) == -ETIMEDOUT) { + break; } } + + e->state = API_INIT; + pthread_cond_broadcast(&e->state_cond); + pthread_mutex_unlock(&e->state_lock); + + return ret; } -char * api_table_get_apn(struct list_head * api_table, pid_t api) +void api_entry_wake(struct api_entry * e, struct reg_entry * re) { - struct list_head * h; + if (e == NULL) + return; - list_for_each(h, api_table) { - struct api_entry * e = - list_entry(h, struct api_entry, next); + pthread_mutex_lock(&e->state_lock); - if (api == e->api) - return e->apn; + if (e->state == API_NULL) { + pthread_mutex_unlock(&e->state_lock); + return; } - return NULL; + e->state = API_WAKE; + e->re = re; + + pthread_cond_broadcast(&e->state_cond); + + while (e->state == API_WAKE) + pthread_cond_wait(&e->state_cond, &e->state_lock); + + pthread_mutex_unlock(&e->state_lock); +} + +int api_table_add(struct list_head * api_table, struct api_entry * e) +{ + if (api_table == NULL || e == NULL) + return -EINVAL; + + list_add(&e->next, api_table); + + return 0; } -char * api_table_get_ap_subset(struct list_head * api_table, pid_t api) + +void api_table_del(struct list_head * api_table, pid_t api) { + struct list_head * p; struct list_head * h; - list_for_each(h, api_table) { - struct api_entry * e = - list_entry(h, struct api_entry, next); + list_for_each_safe(p, h, api_table) { + struct api_entry * e = list_entry(p, struct api_entry, next); + if (api == e->api) { + list_del(&e->next); + api_entry_destroy(e); + } + } +} +struct api_entry * api_table_get(struct list_head * api_table, pid_t api) +{ + struct list_head * h; + + list_for_each(h, api_table) { + struct api_entry * e = list_entry(h, struct api_entry, next); if (api == e->api) - return e->ap_subset; + return e; } return NULL; |