#include "list.h"
#include "string.h"
#include "buffer_tree.h"
+#include "error.h"
struct btr_buffer {
* used by this btr node.
*/
struct list_head input_queue;
+ btr_command_handler execute;
};
#define FOR_EACH_CHILD(_tn, _btrn) list_for_each_entry((_tn), \
#define FOR_EACH_BUFFER_REF_SAFE(_br, _tmp, _btrn) \
list_for_each_entry_safe((_br), (_tmp), &(_btrn)->input_queue, node)
-struct btr_node *btr_new_node(char *name, struct btr_node *parent)
+struct btr_node *btr_new_node(char *name, struct btr_node *parent,
+ btr_command_handler handler)
{
struct btr_node *btrn = para_malloc(sizeof(*btrn));
btrn->name = para_strdup(name);
btrn->parent = parent;
+ btrn->execute = handler;
if (parent)
list_add_tail(&btrn->node, &parent->children);
INIT_LIST_HEAD(&btrn->children);
{
struct btr_buffer *btrb = br->btrb;
+ //PARA_CRIT_LOG("dropping buffer reference %p\n", br);
list_del(&br->node);
free(br);
btrb->refcount--;
}
/* Return true if this node has no children. */
-bool btr_is_leaf_node(struct btr_node *btrn)
+bool btr_no_children(struct btr_node *btrn)
{
return list_empty(&btrn->children);
}
return list_is_singular(&btrn->parent->children);
}
-struct btr_buffer_reference *btr_next_br(struct btr_node *btrn)
-{
- if (list_empty(&btrn->input_queue))
- return NULL;
- return list_first_entry(&btrn->input_queue, struct btr_buffer_reference, node);
-}
-
-
static inline size_t br_available_bytes(struct btr_buffer_reference *br)
{
return br->btrb->size - br->consumed;
return br_available_bytes(br);
}
-void btr_increase_used_bytes(struct btr_buffer_reference *br, size_t consumed)
+size_t btr_next_buffer(struct btr_node *btrn, char **bufp)
{
- br->consumed += consumed;
+ struct btr_buffer_reference *br;
+
+ if (list_empty(&btrn->input_queue)) {
+ *bufp = NULL;
+ return 0;
+ }
+ br = list_first_entry(&btrn->input_queue, struct btr_buffer_reference, node);
+ return btr_get_buffer_by_reference(br, bufp);
+}
+
+void btr_consume(struct btr_node *btrn, size_t numbytes)
+{
+ struct btr_buffer_reference *br;
+
+ assert(!list_empty(&btrn->input_queue));
+ br = list_first_entry(&btrn->input_queue, struct btr_buffer_reference, node);
+ assert(br->consumed + numbytes <= br->btrb->size);
+ br->consumed += numbytes;
if (br->consumed == br->btrb->size)
btr_drop_buffer_reference(br);
}
{
struct btr_node *ch;
+ if (!btrn)
+ return;
+ PARA_NOTICE_LOG("deleting %s\n", btrn->name);
FOR_EACH_CHILD(ch, btrn)
ch->parent = NULL;
flush_input_queue(btrn);
struct btr_buffer_reference *br;
size_t size = 0;
- FOR_EACH_BUFFER_REF(br, btrn)
+ FOR_EACH_BUFFER_REF(br, btrn) {
+ //PARA_CRIT_LOG("size: %zu\n", size);
size += br_available_bytes(br);
+ }
return size;
}
+
+/**
+ * Return the size of the largest input queue.
+ *
+ * Iterates over all children of the given node.
+ */
+size_t btr_bytes_pending(struct btr_node *btrn)
+{
+ size_t max_size = 0;
+ struct btr_node *ch;
+
+ FOR_EACH_CHILD(ch, btrn) {
+ size_t size = btr_get_input_queue_size(ch);
+ max_size = PARA_MAX(max_size, size);
+ }
+ return max_size;
+}
+
+int btr_exec(struct btr_node *btrn, const char *command, char **value_result)
+{
+ if (!btrn)
+ return -ERRNO_TO_PARA_ERROR(EINVAL);
+ if (!btrn->execute)
+ return -ERRNO_TO_PARA_ERROR(ENOTSUP);
+ return btrn->execute(command, value_result);
+}
+
+int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result)
+{
+ int ret;
+
+ for (; btrn; btrn = btrn->parent) {
+ struct btr_node *parent = btrn->parent;
+ PARA_CRIT_LOG("parent: %p\n", parent);
+ if (!parent)
+ return -ERRNO_TO_PARA_ERROR(ENOTSUP);
+ if (!parent->execute)
+ continue;
+ ret = parent->execute(command, value_result);
+ if (ret == -ERRNO_TO_PARA_ERROR(ENOTSUP))
+ continue;
+ if (ret < 0)
+ return ret;
+ }
+ return -ERRNO_TO_PARA_ERROR(ENOTSUP);
+}