summaryrefslogtreecommitdiff
path: root/src/lib/rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/rib.c')
-rw-r--r--src/lib/rib.c1431
1 files changed, 0 insertions, 1431 deletions
diff --git a/src/lib/rib.c b/src/lib/rib.c
deleted file mode 100644
index 9e45a302..00000000
--- a/src/lib/rib.c
+++ /dev/null
@@ -1,1431 +0,0 @@
-/*
- * Ouroboros - Copyright (C) 2016 - 2017
- *
- * Resource Information Base
- *
- * Dimitri Staessens <dimitri.staessens@ugent.be>
- * Sander Vrijders <sander.vrijders@ugent.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., http://www.fsf.org/about/contact/.
- */
-
-#define _POSIX_C_SOURCE 200809L
-
-#include "config.h"
-
-#include <ouroboros/errno.h>
-#include <ouroboros/list.h>
-#include <ouroboros/rib.h>
-#include <ouroboros/rqueue.h>
-#include <ouroboros/bitmap.h>
-#include <ouroboros/crc32.h>
-#include <ouroboros/time_utils.h>
-#include <ouroboros/sha3.h>
-#include <ouroboros/btree.h>
-
-#include "ro.pb-c.h"
-typedef RoMsg ro_msg_t;
-
-#include <pthread.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define RIB_PATH_DLR "/"
-#define RIB_BTREE_ORDER 64
-#define GEN_NAME_SIZE 8
-
-struct revent {
- struct list_head next;
-
- char * path;
- int32_t flags;
-};
-
-struct rqueue {
- struct list_head events;
-};
-
-struct ro_set {
- uint32_t sid;
-};
-
-struct rn_ptr {
- struct list_head next;
-
- struct rnode * node;
-};
-
-struct rib_sub {
- struct list_head next;
-
- uint32_t sid;
-
- struct list_head rnodes;
-
- struct list_head events;
-
- pthread_cond_t cond;
- pthread_mutex_t lock;
-};
-
-struct rn_sub {
- struct list_head next;
-
- struct rib_sub * sub;
- int32_t flags;
-};
-
-struct rnode {
- char * path;
- char * name;
-
- uint8_t * data;
- size_t len;
-
- uint8_t sha3[SHA3_256_HASH_LEN];
-
- struct rnode * parent;
-
- size_t chlen;
- struct list_head children;
-
- struct list_head subs;
-};
-
-struct child {
- struct list_head next;
-
- struct rnode * node;
-};
-
-struct rib {
- struct rnode * root;
-
- struct btree * idx;
-
- pthread_rwlock_t lock;
-
- struct bmp * sids;
-
- struct list_head subs;
-
- pthread_rwlock_t s_lock;
-} rib;
-
-static void rnode_hash(struct rnode * node)
-{
- struct sha3_ctx ctx;
- struct list_head * p;
-
- assert(node);
- assert(node->path);
- assert(node->name);
-
- rhash_sha3_256_init(&ctx);
-
- rhash_sha3_update(&ctx, (uint8_t *) node->path, strlen(node->path));
-
- if (node->data != NULL)
- rhash_sha3_update(&ctx, node->data, node->len);
-
- list_for_each(p, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- rhash_sha3_update(&ctx, c->node->sha3, SHA3_256_HASH_LEN);
- }
-
- rhash_sha3_final(&ctx, node->sha3);
-}
-
-static void branch_hash(struct rnode * node)
-{
- assert(node);
-
- do {
- rnode_hash(node);
- node = node->parent;
- } while (node != NULL);
-}
-
-static struct revent * revent_dup(struct revent * ev)
-{
- struct revent * re;
-
- assert(ev);
- assert(ev->path);
-
- re = malloc(sizeof(*re));
- if (re == NULL)
- return NULL;
-
- re->path = strdup(ev->path);
- if (re->path == NULL) {
- free(re);
- return NULL;
- }
-
- re->flags = ev->flags;
-
- list_head_init(&re->next);
-
- return re;
-}
-
-/* defined below but needed here */
-static void rib_sub_del_rnode(struct rib_sub * sub,
- struct rnode * node);
-
-static void rnode_notify_subs(struct rnode * node,
- struct rnode * ch,
- struct revent * ev)
-{
- struct list_head * p;
-
- assert(node);
-
- list_for_each(p, &node->subs) {
- struct rn_sub * s = list_entry(p, struct rn_sub, next);
- if (s->flags & ev->flags) {
- struct revent * e = revent_dup(ev);
- if (e == NULL)
- continue;
-
- pthread_mutex_lock(&s->sub->lock);
- list_add_tail(&e->next, &s->sub->events);
- pthread_cond_signal(&s->sub->cond);
- pthread_mutex_unlock(&s->sub->lock);
- }
-
- if (ev->flags & RO_DELETE)
- rib_sub_del_rnode(s->sub, ch);
- }
-}
-
-static int rnode_throw_event(struct rnode * node,
- int32_t flags)
-{
- struct revent * ev = malloc(sizeof(*ev));
- struct rnode * rn = node;
-
- assert(node);
- assert(node->path);
-
- if (ev == NULL)
- return -ENOMEM;
-
- list_head_init(&ev->next);
-
- ev->path = strdup(node->path);
- if (ev->path == NULL) {
- free(ev);
- return -ENOMEM;
- }
-
- ev->flags = flags;
-
- do {
- rnode_notify_subs(rn, node, ev);
- rn = rn->parent;
- } while (rn != NULL);
-
- free(ev->path);
- free(ev);
-
- return 0;
-}
-
-static int rnode_add_child(struct rnode * node,
- struct rnode * child)
-{
- struct child * c;
- struct list_head * p;
- struct child * n;
-
- assert(node);
- assert(child);
-
- c = malloc(sizeof(*c));
- if (c == NULL)
- return -ENOMEM;
-
- c->node = child;
-
- list_for_each(p, &node->children) {
- n = list_entry(p, struct child, next);
- if (strcmp(n->node->name, child->name) > 0)
- break;
- }
-
- list_add_tail(&c->next, p);
-
- ++node->chlen;
-
- return 0;
-}
-
-static void rnode_remove_child(struct rnode * node,
- struct rnode * child)
-{
- struct list_head * p;
- struct list_head * h;
-
- assert(node);
- assert(child);
-
- list_for_each_safe(p, h, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- if (c->node == child) {
- list_del(&c->next);
- free(c);
- --node->chlen;
- return;
- }
- }
-}
-
-static struct rnode * rnode_create(struct rnode * parent,
- const char * name)
-{
- struct rnode * node;
- char * parent_path;
-
- uint32_t crc = 0;
-
- assert(name);
-
- node = malloc(sizeof(*node));
- if (node == NULL)
- return NULL;
-
- list_head_init(&node->children);
- list_head_init(&node->subs);
-
- if (parent == NULL)
- parent_path = "";
- else
- parent_path = parent->path;
-
- node->path = malloc(strlen(parent_path)
- + strlen(RIB_PATH_DLR)
- + strlen(name)
- + 1);
- if (node->path == NULL) {
- free(node);
- return NULL;
- }
-
- strcpy(node->path, parent_path);
- node->name = node->path + strlen(parent_path);
- if (parent != NULL) {
- strcpy(node->name, RIB_PATH_DLR);
- node->name += strlen(RIB_PATH_DLR);
- }
-
- strcpy(node->name, name);
-
- if (parent != NULL) {
- if (rnode_add_child(parent, node)) {
- free(node->path);
- free(node);
- return NULL;
- }
- }
-
- node->data = NULL;
- node->len = 0;
-
- node->parent = parent;
-
- node->chlen = 0;
-
- crc32(&crc, node->path, strlen(node->path));
- btree_insert(rib.idx, crc, node);
-
- branch_hash(node);
- rnode_throw_event(node, RO_CREATE);
-
- return node;
-}
-
-static void destroy_rnode(struct rnode * node)
-{
- struct list_head * p;
- struct list_head * h;
-
- uint32_t crc = 0;
-
- assert(node);
-
- if (node != rib.root) {
- rnode_remove_child(node->parent, node);
- branch_hash(node->parent);
- }
-
- if (node->parent != NULL)
- rnode_throw_event(node->parent, RO_DELETE);
-
- list_for_each_safe(p, h, &node->subs) {
- struct rn_sub * s = list_entry(p, struct rn_sub, next);
- list_del(&s->next);
- free(s);
- }
-
- crc32(&crc, node->path, strlen(node->path));
- btree_remove(rib.idx, crc);
-
- free(node->path);
- if (node->data != NULL)
- free(node->data);
-
- free(node);
-}
-
-static void destroy_rtree(struct rnode * node)
-{
- struct list_head * p;
- struct list_head * h;
-
- assert(node);
-
- list_for_each_safe(p, h, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- destroy_rtree(c->node);
- }
-
- destroy_rnode(node);
-}
-
-static void rnode_update(struct rnode * node,
- uint8_t * data,
- size_t len)
-{
- assert(node);
- assert(!(data == NULL && len != 0));
- assert(!(data != NULL && len == 0));
-
- if (node->data != NULL)
- free(node->data);
-
- node->data = data;
- node->len = len;
-
- rnode_throw_event(node, RO_MODIFY);
-
- branch_hash(node);
-}
-
-static struct rn_sub * rnode_get_sub(struct rnode * node,
- struct rib_sub * sub)
-{
- struct list_head * p;
-
- list_for_each(p, &node->subs) {
- struct rn_sub * r = list_entry(p, struct rn_sub, next);
- if (r->sub == sub)
- return r;
- }
-
- return NULL;
-}
-
-static int rnode_add_sub(struct rnode * node,
- struct rib_sub * sub,
- int32_t flags)
-{
- struct rn_sub * rs;
-
- assert(node);
- assert(sub);
-
- rs = rnode_get_sub(node, sub);
- if (rs != NULL)
- return -EPERM;
-
- rs = malloc(sizeof(*rs));
- if (rs == NULL)
- return -ENOMEM;
-
- rs->sub = sub;
- rs->flags = flags;
-
- list_add(&rs->next, &node->subs);
-
- return 0;
-}
-
-static int rnode_del_sub(struct rnode * node,
- struct rib_sub * sub)
-{
- struct rn_sub * rs;
-
- assert(node);
- assert(sub);
-
- rs = rnode_get_sub(node, sub);
- if (rs == NULL)
- return 0;
-
- list_del(&rs->next);
- free(rs);
-
- return 0;
-}
-
-static struct rnode * find_rnode_by_path(const char * path)
-{
- uint32_t crc = 0;
-
- if (strcmp(path, RIB_ROOT) == 0)
- return rib.root;
-
- crc32(&crc, path, strlen(path));
-
- return (struct rnode *) btree_search(rib.idx, crc);
-}
-
-int rib_init(void)
-{
- if (rib.root != NULL)
- return -EPERM;
-
- rib.idx = btree_create(RIB_BTREE_ORDER);
- if (rib.idx == NULL) {
- destroy_rtree(rib.root);
- rib.root = NULL;
- return -1;
- }
-
- rib.root = rnode_create(NULL, "");
- if (rib.root == NULL)
- return -ENOMEM;
-
- rib.sids = bmp_create(32, 1);
- if (rib.sids == NULL) {
- btree_destroy(rib.idx);
- destroy_rtree(rib.root);
- rib.root = NULL;
- return -1;
- }
-
- if (pthread_rwlock_init(&rib.lock, NULL)) {
- bmp_destroy(rib.sids);
- btree_destroy(rib.idx);
- destroy_rtree(rib.root);
- rib.root = NULL;
- return -1;
- }
-
- if (pthread_rwlock_init(&rib.s_lock, NULL)) {
- pthread_rwlock_destroy(&rib.lock);
- bmp_destroy(rib.sids);
- btree_destroy(rib.idx);
- destroy_rtree(rib.root);
- rib.root = NULL;
- return -1;
- }
-
- list_head_init(&rib.subs);
-
- assert(rib.root);
-
- return 0;
-}
-
-void rib_fini(void)
-{
- if (rib.root == NULL)
- return;
-
- bmp_destroy(rib.sids);
-
- destroy_rtree(rib.root);
- rib.root = NULL;
-
- btree_destroy(rib.idx);
-
- pthread_rwlock_destroy(&rib.lock);
-}
-
-int rib_add(const char * path,
- const char * name)
-{
- struct rnode * parent;
- struct rnode * node;
-
- if (name == NULL)
- return -EINVAL;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- parent = find_rnode_by_path(path);
- if (parent == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- node = rnode_create(parent, name);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -ENOMEM;
- }
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-int rib_del(char * path)
-{
- struct rnode * node;
-
- if (path == NULL)
- return -EINVAL;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EINVAL;
- }
-
- destroy_rtree(node);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-ssize_t rib_read(const char * path,
- void * data,
- size_t len)
-{
- struct rnode * node;
- ssize_t rlen;
-
- if (path == NULL || data == NULL)
- return -EINVAL;
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- if (len < node->len) {
- pthread_rwlock_unlock(&rib.lock);
- return -EFBIG;
- }
-
- if (node->data == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return 0;
- }
-
- assert(node->len > 0);
-
- memcpy(data, node->data, node->len);
- rlen = node->len;
-
- rnode_throw_event(node, RO_READ);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return rlen;
-}
-
-int rib_write(const char * path,
- const void * data,
- size_t len)
-{
- struct rnode * node;
-
- uint8_t * cdata;
-
- if (path == NULL || data == NULL || len == 0)
- return -EINVAL;
-
- cdata = malloc(len);
- if (cdata == NULL)
- return -ENOMEM;
-
- memcpy(cdata, data, len);
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- free(cdata);
- return -1;
- }
-
- rnode_update(node, cdata, len);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-int rib_put(const char * path,
- void * data,
- size_t len)
-{
- struct rnode * node;
-
- if (path == NULL)
- return -EINVAL;
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node != NULL)
- rnode_update(node, (uint8_t *) data, len);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-bool rib_has(const char * path)
-{
- struct rnode * node;
-
- if (path == NULL)
- return -EINVAL;
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return node != NULL;
-}
-
-ssize_t rib_children(const char * path,
- char *** children)
-{
- struct list_head * p;
-
- struct rnode * node;
-
- ssize_t i = 0;
-
- if (path == NULL)
- return -EINVAL;
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- if (children == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- assert((ssize_t) node->chlen >= 0);
- return (ssize_t) node->chlen;
- }
-
- if (node->chlen == 0) {
- pthread_rwlock_unlock(&rib.lock);
- *children = NULL;
- return 0;
- }
-
- *children = malloc(sizeof(**children) * node->chlen);
- if (*children == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -ENOMEM;
- }
-
- list_for_each(p, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- (*children)[i] = strdup(c->node->name);
- if ((*children)[i] == NULL) {
- ssize_t j;
- pthread_rwlock_unlock(&rib.lock);
- for (j = 0; j < i; ++j)
- free((*children)[j]);
- free(*children);
- return -ENOMEM;
- }
- ++i;
- }
-
- assert(i > 0);
- assert((size_t) i == node->chlen);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return i;
-}
-
-static struct rib_sub * rib_get_sub(uint32_t sid)
-{
- struct list_head * p;
- struct list_head * h;
-
- list_for_each_safe(p, h, &rib.subs) {
- struct rib_sub * r = list_entry(p, struct rib_sub, next);
- if (r->sid == sid)
- return r;
- }
-
- return NULL;
-}
-
-static struct rib_sub * rib_sub_create(uint32_t sid)
-{
- pthread_condattr_t cattr;
- struct rib_sub * sub = malloc(sizeof(*sub));
- if (sub == NULL)
- return NULL;
-
- if (pthread_condattr_init(&cattr)) {
- free(sub);
- return NULL;
- }
-#ifndef __APPLE__
- pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
-#endif
- if (pthread_cond_init(&sub->cond, &cattr)) {
- free(sub);
- return NULL;
- }
-
- if (pthread_mutex_init(&sub->lock, NULL)) {
- pthread_cond_destroy(&sub->cond);
- free(sub);
- return NULL;
- }
-
- list_head_init(&sub->rnodes);
- list_head_init(&sub->events);
-
- sub->sid = sid;
-
- return sub;
-}
-
-static void rib_sub_zero(struct rib_sub * sub)
-{
- struct list_head * p;
- struct list_head * h;
-
- assert(sub);
-
- list_for_each_safe(p, h, &sub->rnodes) {
- struct rn_ptr * r = list_entry(p, struct rn_ptr, next);
- assert(r->node);
- rnode_del_sub(r->node, sub);
- list_del(&r->next);
- free(r);
- }
-
- list_for_each_safe(p, h, &sub->events) {
- struct revent * r = list_entry(p, struct revent, next);
- list_del(&r->next);
- assert(r->path);
- free(r->path);
- free(r);
- }
-}
-
-static struct rn_ptr * rib_sub_get_rn_ptr(struct rib_sub * sub,
- struct rnode * node)
-{
- struct list_head * p;
-
- list_for_each(p, &sub->rnodes) {
- struct rn_ptr * r = list_entry(p, struct rn_ptr, next);
- assert(r->node);
- if (r->node == node)
- return r;
- }
-
- return NULL;
-}
-
-static int rib_sub_add_rnode(struct rib_sub * sub,
- struct rnode * node)
-{
- struct rn_ptr * rn;
-
- assert(sub);
- assert(node);
-
- if (rib_sub_get_rn_ptr(sub, node) != NULL)
- return 0;
-
- rn = malloc(sizeof(*rn));
- if (rn == NULL)
- return -ENOMEM;
-
- rn->node = node;
-
- list_add(&rn->next, &sub->rnodes);
-
- return 0;
-}
-
-static void rib_sub_del_rnode(struct rib_sub * sub,
- struct rnode * node)
-{
- struct rn_ptr * rn;
-
- assert(sub);
- assert(node);
-
- rn = rib_sub_get_rn_ptr(sub, node);
- if (rn == NULL)
- return;
-
- list_del(&rn->next);
-
- free(rn);
-}
-
-static void rib_sub_destroy(struct rib_sub * sub)
-{
- assert(sub);
-
- rib_sub_zero(sub);
-
- free(sub);
-}
-
-/* Event calls from rqueue.h. */
-ro_set_t * ro_set_create(void)
-{
- ro_set_t * set;
- struct rib_sub * sub;
-
- set = malloc(sizeof(*set));
- if (set == NULL)
- return NULL;
-
- pthread_rwlock_wrlock(&rib.s_lock);
-
- set->sid = bmp_allocate(rib.sids);
- if (!bmp_is_id_valid(rib.sids, set->sid)) {
- pthread_rwlock_unlock(&rib.s_lock);
- free(set);
- return NULL;
- }
-
- pthread_rwlock_unlock(&rib.s_lock);
-
- pthread_rwlock_wrlock(&rib.lock);
-
- sub = rib_sub_create(set->sid);
- if (sub == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- free(set);
- return NULL;
- }
-
- list_add(&sub->next, &rib.subs);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return set;
-}
-
-void ro_set_destroy(ro_set_t * set)
-{
- struct rib_sub * sub = NULL;
-
- struct list_head * p;
- struct list_head * h;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- list_for_each_safe(p, h, &rib.subs) {
- struct rib_sub * r = list_entry(p, struct rib_sub, next);
- if (r->sid == set->sid) {
- sub = r;
- break;
- }
- }
-
- if (sub != NULL)
- rib_sub_destroy(sub);
-
- pthread_rwlock_unlock(&rib.lock);
-
- pthread_rwlock_wrlock(&rib.s_lock);
-
- bmp_release(rib.sids, set->sid);
-
- pthread_rwlock_unlock(&rib.s_lock);
-
- free(set);
-}
-
-rqueue_t * rqueue_create(void)
-{
- rqueue_t * rq = malloc(sizeof(*rq));
- if (rq == NULL)
- return NULL;
-
- list_head_init(&rq->events);
-
- return rq;
-}
-
-int rqueue_destroy(struct rqueue * rq)
-{
- struct list_head * p;
- struct list_head * h;
-
- list_for_each_safe(p, h, &rq->events) {
- struct revent * e = list_entry(p, struct revent, next);
- list_del(&e->next);
- free(e->path);
- free(e);
- }
-
- free(rq);
-
- return 0;
-}
-
-int ro_set_zero(ro_set_t * set)
-{
- struct rib_sub * sub;
-
- if (set == NULL)
- return -EINVAL;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- sub = rib_get_sub(set->sid);
-
- assert(sub);
-
- rib_sub_zero(sub);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-int ro_set_add(ro_set_t * set,
- const char * path,
- int32_t flags)
-{
- struct rib_sub * sub;
- struct rnode * node;
-
- if (set == NULL)
- return -EINVAL;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- sub = rib_get_sub(set->sid);
-
- assert(sub);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -1;
- }
-
- if (rnode_add_sub(node, sub, flags)) {
- pthread_rwlock_unlock(&rib.lock);
- return -ENOMEM;
- }
-
- if (rib_sub_add_rnode(sub, node)) {
- pthread_rwlock_unlock(&rib.lock);
- return -ENOMEM;
- }
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-int ro_set_del(ro_set_t * set,
- const char * path)
-{
- struct rib_sub * sub;
- struct rnode * node;
-
- if (set == NULL)
- return -EINVAL;
-
- pthread_rwlock_wrlock(&rib.lock);
-
- sub = rib_get_sub(set->sid);
-
- assert(sub);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -1;
- }
-
- rnode_del_sub(node, sub);
-
- rib_sub_del_rnode(sub, node);
-
- pthread_rwlock_unlock(&rib.lock);
-
- return 0;
-}
-
-int32_t rqueue_next(rqueue_t * rq,
- char * path)
-{
- struct revent * ev;
- int32_t ret;
-
- if (list_is_empty(&rq->events))
- return -1;
-
- ev = list_first_entry(&rq->events, struct revent, next);
- list_del(&ev->next);
-
- strcpy(path, ev->path);
- ret = ev->flags;
-
- free(ev->path);
- free(ev);
-
- return ret;
-}
-
-int rib_event_wait(ro_set_t * set,
- rqueue_t * rq,
- const struct timespec * timeout)
-{
- struct rib_sub * sub;
- struct timespec abstime;
- struct revent * ev;
-
- ssize_t ret = 0;
-
- if (set == NULL || rq == NULL)
- return -EINVAL;
-
- if (!list_is_empty(&rq->events))
- return 0;
-
- if (timeout != NULL) {
- clock_gettime(PTHREAD_COND_CLOCK, &abstime);
- ts_add(&abstime, timeout, &abstime);
- }
-
- pthread_rwlock_rdlock(&rib.lock);
-
- sub = rib_get_sub(set->sid);
-
- assert(sub);
-
- pthread_rwlock_unlock(&rib.lock);
-
- pthread_mutex_lock(&sub->lock);
-
- pthread_cleanup_push((void(*)(void *)) pthread_mutex_unlock,
- (void *) &sub->lock);
-
- while (list_is_empty(&sub->events) && ret != -ETIMEDOUT) {
- if (timeout != NULL)
- ret = -pthread_cond_timedwait(&sub->cond,
- &sub->lock,
- &abstime);
- else
- ret = -pthread_cond_wait(&sub->cond, &sub->lock);
- }
-
- pthread_cleanup_pop(true);
-
- pthread_rwlock_wrlock(&rib.lock);
-
- if (ret != -ETIMEDOUT) {
- ev = list_first_entry(&sub->events, struct revent, next);
- list_move(&ev->next, &rq->events);
- }
-
- pthread_rwlock_unlock(&rib.lock);
-
- return ret;
-}
-
-/* Path name management. */
-char * rib_path_append(char * path,
- const char * name)
-{
- char * pos;
-
- if (path == NULL || name == NULL || strstr(name, RIB_PATH_DLR))
- return NULL;
-
- pos = path + strlen(path);
- memcpy(pos++, RIB_PATH_DLR, 1);
- strcpy(pos, name);
-
- return path;
-}
-
-char * rib_name_gen(void * data,
- size_t len)
-{
- uint32_t crc = 0;
- char * name;
-
- if (data == NULL || len == 0)
- return NULL;
-
- name= malloc(GEN_NAME_SIZE + 1);
- if (name == NULL)
- return NULL;
-
- crc32(&crc, data, len);
-
- sprintf(name, "%08x", crc);
-
- return name;
-}
-
-static ro_msg_t * rnode_pack(struct rnode * node,
- uint32_t flags,
- bool root)
-{
- ro_msg_t * msg;
-
- assert(node);
-
- if (node->parent == NULL)
- return NULL;
-
- msg = malloc(sizeof(*msg));
- if (msg == NULL)
- return NULL;
-
- ro_msg__init(msg);
-
- msg->name = node->name;
- if (root) {
- assert(node->parent->path);
- msg->parent = node->parent->path;
- }
-
- if ((root && (flags & PACK_HASH_ROOT)) ||
- (flags & PACK_HASH_ALL)) {
- msg->has_hash = true;
- msg->hash.data = node->sha3;
- msg->hash.len = SHA3_256_HASH_LEN;
- }
-
- if (node->data != NULL) {
- msg->has_data = true;
- msg->data.data = node->data;
- msg->data.len = node->len;
- }
-
- if (node->chlen > 0) {
- int n = 0;
- struct list_head * p;
- ro_msg_t ** msgs = malloc(sizeof(*msgs) * node->chlen);
- if (msgs == NULL) {
- free(msg);
- return NULL;
- }
-
- msg->n_children = node->chlen;
-
- list_for_each(p, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- msgs[n] = rnode_pack(c->node, flags, false);
- if (msgs[n] == NULL) {
- int i;
- for (i = 0; i < n; ++i)
- free(msgs[i]);
- free(msgs);
- free(msg);
- return NULL;
- }
- ++n;
- }
- msg->children = msgs;
- }
-
- return msg;
-}
-
-static void free_ro_msg(ro_msg_t * msg)
-{
- size_t n = 0;
- while (n < msg->n_children)
- free_ro_msg(msg->children[n++]);
-
- free(msg->children);
- free(msg);
-}
-
-ssize_t rib_pack(const char * path,
- uint8_t ** buf,
- uint32_t flags)
-{
- struct rnode * node;
- ro_msg_t * msg;
- ssize_t len;
-
- if (path == NULL)
- return -EINVAL;
-
- pthread_rwlock_rdlock(&rib.lock);
-
- node = find_rnode_by_path(path);
- if (node == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- msg = rnode_pack(node, flags, true);
- if (msg == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- len = ro_msg__get_packed_size(msg);
- if (len == 0) {
- pthread_rwlock_unlock(&rib.lock);
- free_ro_msg(msg);
- return 0;
- }
-
- *buf = malloc(len);
- if (*buf == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- free_ro_msg(msg);
- return -ENOMEM;
- }
-
- ro_msg__pack(msg, *buf);
-
- pthread_rwlock_unlock(&rib.lock);
-
- free_ro_msg(msg);
-
- return len;
-}
-
-static struct rnode * rnode_get_child(struct rnode * node,
- const char * name)
-{
- struct list_head * p;
-
- list_for_each(p, &node->children) {
- struct child * c = list_entry(p, struct child, next);
- if (strcmp(c->node->name, name) == 0)
- return c->node;
- }
-
- return NULL;
-}
-
-static int rnode_unpack(ro_msg_t * msg,
- struct rnode * parent,
- uint32_t flags)
-{
- struct rnode * node;
-
- size_t i;
-
- assert(msg);
- assert(parent);
-
- node = rnode_get_child(parent, msg->name);
- if (node == NULL) {
- if (flags & UNPACK_CREATE)
- node = rnode_create(parent, msg->name);
- else
- return -EPERM;
- }
-
- if (node == NULL)
- return -ENOMEM;
-
- /* Unpack in reverse order for faster insertion */
- i = msg->n_children;
- while (i > 0)
- rnode_unpack(msg->children[--i], node, flags);
-
- if (msg->has_data) {
- uint8_t * data = malloc(msg->data.len);
- if (data == NULL)
- return -ENOMEM;
-
- memcpy(data, msg->data.data, msg->data.len);
- rnode_update(node, data, msg->data.len);
- }
-
- return 0;
-}
-
-int rib_unpack(uint8_t * packed,
- size_t len,
- uint32_t flags)
-{
- ro_msg_t * msg;
- struct rnode * root;
- int ret;
-
- if (packed == NULL)
- return -EINVAL;
-
- msg = ro_msg__unpack(NULL, len, packed);
- if (msg == NULL)
- return -EPERM;
-
- assert(msg->parent);
-
- pthread_rwlock_wrlock(&rib.lock);
-
- root = find_rnode_by_path(msg->parent);
- if (root == NULL) {
- pthread_rwlock_unlock(&rib.lock);
- return -EPERM;
- }
-
- ret = rnode_unpack(msg, root, flags);
-
- if (ret == 0 && msg->has_hash) {
- root = rnode_get_child(root, msg->name);
- if (memcmp(msg->hash.data, root->sha3, SHA3_256_HASH_LEN)) {
- ro_msg__free_unpacked(msg, NULL);
- pthread_rwlock_unlock(&rib.lock);
- return -EFAULT;
- }
- }
-
- pthread_rwlock_unlock(&rib.lock);
-
- ro_msg__free_unpacked(msg, NULL);
-
- free(packed);
-
- return ret;
-}