Fix stream grabbing.
[paraslash.git] / buffer_tree.c
index dbdcb58..8aa66b6 100644 (file)
@@ -9,6 +9,7 @@
 #include "sched.h"
 
 struct btr_pool {
+       char *name;
        char *area_start;
        char *area_end;
        char *rhead;
@@ -55,14 +56,17 @@ struct btr_node {
        void *context;
 };
 
-struct btr_pool *btr_pool_new(size_t area_size)
+struct btr_pool *btr_pool_new(const char *name, size_t area_size)
 {
-       struct btr_pool *btrp = para_malloc(sizeof(*btrp));
+       struct btr_pool *btrp;
 
+       PARA_INFO_LOG("%s, %zu bytes\n", name, area_size);
+       btrp = para_malloc(sizeof(*btrp));
        btrp->area_start = para_malloc(area_size);
        btrp->area_end = btrp->area_start + area_size;
        btrp->rhead = btrp->area_start;
        btrp->whead = btrp->area_start;
+       btrp->name = para_strdup(name);
        return btrp;
 }
 
@@ -73,6 +77,7 @@ void btr_pool_free(struct btr_pool *btrp)
        if (!btrp)
                return;
        free(btrp->area_start);
+       free(btrp->name);
        free(btrp);
 }
 
@@ -123,7 +128,7 @@ void btr_pool_allocate(struct btr_pool *btrp, size_t size)
        assert(end <= btrp->area_end);
 
        if (end == btrp->area_end) {
-               PARA_DEBUG_LOG("end of pool area reached: %p\n", end);
+               PARA_DEBUG_LOG("%s: end of pool area reached\n", btrp->name);
                end = btrp->area_start;
        }
        if (end == btrp->rhead) {
@@ -188,7 +193,8 @@ struct btr_node *btr_new_node(const char *name, struct btr_node *parent,
 /*
  * Allocate a new btr buffer.
  *
- * The freshly allocated buffer will have a zero refcount.
+ * The freshly allocated buffer will have a zero refcount and will
+ * not be associated with a btr pool.
  */
 static struct btr_buffer *new_btrb(char *buf, size_t size)
 {
@@ -263,21 +269,45 @@ void btr_add_output(char *buf, size_t size, struct btr_node *btrn)
        add_btrb_to_children(btrb, btrn, 0);
 }
 
-void btr_add_output_pool(struct btr_pool *btrp, char *buf, size_t size,
-       struct btr_node *btrn)
+void btr_add_output_pool(struct btr_pool *btrp, size_t size,
+               struct btr_node *btrn)
 {
        struct btr_buffer *btrb;
+       char *buf;
+       size_t avail;
 
        assert(size != 0);
-       if (list_empty(&btrn->children)) {
-               btr_pool_deallocate(btrp, size);
+       if (list_empty(&btrn->children))
                return;
-       }
+       avail = btr_pool_get_buffer(btrp, &buf);
+       assert(avail >= size);
+       btr_pool_allocate(btrp, size);
        btrb = new_btrb(buf, size);
        btrb->pool = btrp;
        add_btrb_to_children(btrb, btrn, 0);
 }
 
+void btr_copy(const void *src, size_t n, struct btr_pool *btrp,
+       struct btr_node *btrn)
+{
+       char *buf;
+       size_t sz, copy;
+
+       if (n == 0)
+               return;
+       assert(n <= btr_pool_unused(btrp));
+       sz = btr_pool_get_buffer(btrp, &buf);
+       copy = PARA_MIN(sz, n);
+       memcpy(buf, src, copy);
+       btr_add_output_pool(btrp, copy, btrn);
+       if (copy == n)
+               return;
+       sz = btr_pool_get_buffer(btrp, &buf);
+       assert(sz >= n - copy);
+       memcpy(buf, src + copy, n - copy);
+       btr_add_output_pool(btrp, n - copy, btrn);
+}
+
 static void btr_pushdown_br(struct btr_buffer_reference *br, struct btr_node *btrn)
 {
        add_btrb_to_children(br->btrb, btrn, br->consumed);
@@ -659,8 +689,8 @@ static int merge_input(struct btr_node *btrn)
        /* make a new btrb that combines the two buffers and a br to it. */
        sz = szs[0] + szs[1];
        buf = para_malloc(sz);
-       PARA_DEBUG_LOG("memory merging input buffers: (%zu, %zu) -> %zu\n",
-               szs[0], szs[1], sz);
+       PARA_DEBUG_LOG("%s: memory merging input buffers: (%zu, %zu) -> %zu\n",
+               btrn->name, szs[0], szs[1], sz);
        memcpy(buf, bufs[0], szs[0]);
        memcpy(buf + szs[0], bufs[1], szs[1]);
 
@@ -715,6 +745,25 @@ void btr_log_tree(struct btr_node *btrn, int loglevel)
        return log_tree_recursively(btrn, loglevel, 0);
 }
 
+/*
+ * \return \a root if \a name is \p NULL.
+ */
+struct btr_node *btr_search_node(const char *name, struct btr_node *root)
+{
+       struct btr_node *ch;
+
+       if (!name)
+               return root;
+       if (!strcmp(root->name, name))
+               return root;
+       FOR_EACH_CHILD(ch, root) {
+               struct btr_node *result = btr_search_node(name, ch);
+               if (result)
+                       return result;
+       }
+       return NULL;
+}
+
 /** 640K ought to be enough for everybody ;) */
 #define BTRN_MAX_PENDING (640 * 1024)
 
@@ -723,6 +772,8 @@ int btr_node_status(struct btr_node *btrn, size_t min_iqs,
 {
        size_t iqs;
 
+       if (!btrn)
+               return 0;
        if (type != BTR_NT_LEAF) {
                if (btr_no_children(btrn))
                        return -E_BTR_NO_CHILD;