summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@intec.ugent.be>2017-01-29 16:29:51 +0100
committerdimitri staessens <dimitri.staessens@intec.ugent.be>2017-01-29 16:29:51 +0100
commitd6321a22f8c957523e7acbf6c57f5730b55ac378 (patch)
treeeaf66f732f52d84a5daf3f6736b489c3a755a620 /src
parentbbee20a43f23f4f62cb1ab1f2ab0645581cfbaac (diff)
downloadouroboros-d6321a22f8c957523e7acbf6c57f5730b55ac378.tar.gz
ouroboros-d6321a22f8c957523e7acbf6c57f5730b55ac378.zip
lib: Add function to get children of node in RIB
Returns the names of the nodes (not the full paths). The function allocates memory to the children pointer that should be freed.
Diffstat (limited to 'src')
-rw-r--r--src/lib/rib.c67
-rw-r--r--src/lib/tests/rib_test.c24
2 files changed, 91 insertions, 0 deletions
diff --git a/src/lib/rib.c b/src/lib/rib.c
index 4d1ae884..6b27ad27 100644
--- a/src/lib/rib.c
+++ b/src/lib/rib.c
@@ -95,6 +95,7 @@ struct rnode {
struct rnode * parent;
+ size_t chlen;
struct list_head children;
struct list_head subs;
@@ -248,6 +249,8 @@ static int rnode_add_child(struct rnode * node,
c->node = child;
list_add(&c->next, &node->children);
+ ++node->chlen;
+
return 0;
}
@@ -265,6 +268,7 @@ static void rnode_remove_child(struct rnode * node,
if (c->node == child) {
list_del(&c->next);
free(c);
+ --node->chlen;
return;
}
}
@@ -321,6 +325,8 @@ static struct rnode * rnode_create(struct rnode * parent,
node->parent = parent;
+ node->chlen = 0;
+
branch_hash(node);
rnode_throw_event(node, RO_CREATE);
@@ -606,6 +612,13 @@ ssize_t rib_read(const char * path,
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;
@@ -681,6 +694,60 @@ bool rib_has(const char * path)
return node != NULL;
}
+ssize_t rib_children(const char * path,
+ char *** children)
+{
+ struct list_head * p;
+
+ struct rnode * node;
+
+ ssize_t i = 0;
+
+ assert(path);
+ assert(children);
+
+ pthread_rwlock_rdlock(&rib.lock);
+
+ node = find_rnode_by_path(path);
+ if (node == NULL) {
+ pthread_rwlock_unlock(&rib.lock);
+ return -EPERM;
+ }
+
+ 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;
diff --git a/src/lib/tests/rib_test.c b/src/lib/tests/rib_test.c
index 37503941..bad01083 100644
--- a/src/lib/tests/rib_test.c
+++ b/src/lib/tests/rib_test.c
@@ -46,6 +46,9 @@ int rib_test(int argc,
char tmp[RIB_MAX_PATH_LEN];
+ char ** kids;
+ ssize_t ch;
+
struct timespec t = {0, 100 * BILLION};
(void) argc;
@@ -73,6 +76,16 @@ int rib_test(int argc,
return -1;
}
+ ch = rib_children("/static_info", &kids);
+ if (ch != 0) {
+ printf("Wrong number of children returned.\n");
+ rib_fini();
+ while (ch > 0)
+ free(kids[--ch]);
+ free(kids);
+ return -1;
+ }
+
if (!rib_has("/static_info")) {
printf("Failed to find added element.\n");
rib_fini();
@@ -118,6 +131,17 @@ int rib_test(int argc,
return -1;
}
+ ch = rib_children("/static_info", &kids);
+ if (ch != 2) {
+ printf("Wrong number of children returned.\n");
+ rib_fini();
+ return -1;
+ }
+
+ while (ch > 0)
+ free(kids[--ch]);
+ free(kids);
+
if (addr_chk != addr_size) {
printf("Failed to verify added element contents.\n");
rib_fini();