aacdec: Fix a brown paper bag bug.
[paraslash.git] / buffer_tree.c
index 4aeb790a6e3c6e8efe9a841e4b12fbe331f360f9..d92d9863e10e2b4081fba91a35b06233933a15cc 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright (C) 2009-2010 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file buffer_tree.c Buffer tree and buffer pool implementations. */
 #include <regex.h>
 #include <stdbool.h>
 
@@ -159,6 +166,35 @@ size_t btr_pool_get_buffer(struct btr_pool *btrp, char **result)
        return btr_pool_available(btrp);
 }
 
+/**
+ * Get references to buffers pointing to free space of the buffer pool area.
+ *
+ * \param btrp The buffer pool.
+ * \param iov The scatter array.
+ *
+ * \return Zero if the buffer pool is full, one if the free space of the buffer
+ * pool area is available as a single contiguous buffer, two if the free space
+ * consists of two buffers. If this function returns the value n, then n
+ * elements of \a iov are initialized.
+ */
+int btr_pool_get_buffers(struct btr_pool *btrp, struct iovec iov[2])
+{
+       size_t sz, unused;
+       char *buf;
+
+       sz = btr_pool_get_buffer(btrp, &buf);
+       if (sz == 0)
+               return 0;
+       iov[0].iov_len = sz;
+       iov[0].iov_base = buf;
+       unused = btr_pool_unused(btrp);
+       if (sz == unused)
+               return 1;
+       iov[1].iov_len = unused - sz;
+       iov[1].iov_base = btrp->area_start;
+       return 2;
+}
+
 /**
  * Mark a part of the buffer pool area as allocated.
  *
@@ -598,7 +634,7 @@ void btr_consume(struct btr_node *btrn, size_t numbytes)
                        numbytes -= br->btrb->size - br->consumed;
                        btr_drop_buffer_reference(br);
                }
-               assert(true);
+               assert(false);
        }
        /*
         * We have a wrap buffer, consume from it. If in total, i.e. including
@@ -727,12 +763,15 @@ void btr_splice_out_node(struct btr_node *btrn)
        assert(list_empty(&btrn->children));
 }
 
-/*
- * Return the size of the largest input queue.
+/**
+ * Return number of queued output bytes of a buffer tree node.
+ *
+ * \param btrn The node whose output queue size should be computed.
  *
- * Iterates over all children of the given node.
+ * This function iterates over all children of the given node and returns the
+ * size of the largest input queue.
  */
-static size_t btr_bytes_pending(struct btr_node *btrn)
+size_t btr_get_output_queue_size(struct btr_node *btrn)
 {
        size_t max_size = 0;
        struct btr_node *ch;
@@ -744,15 +783,6 @@ static size_t btr_bytes_pending(struct btr_node *btrn)
        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(btrn, command, value_result);
-}
-
 /**
  * Execute a inter-node command on a parent node.
  *
@@ -822,7 +852,7 @@ static void merge_input_pool(struct btr_node *btrn, size_t dest_size)
        struct btr_buffer_reference *br, *wbr = NULL;
        int num_refs; /* including wrap buffer */
        char *buf, *buf1 = NULL, *buf2 = NULL;
-       size_t sz, sz1 = 0, sz2 = 0, wsz;
+       size_t sz, sz1 = 0, sz2 = 0, wb_consumed = 0;
 
        br = get_first_input_br(btrn);
        if (!br || br_available_bytes(br) >= dest_size)
@@ -839,6 +869,7 @@ static void merge_input_pool(struct btr_node *btrn, size_t dest_size)
                        wbr = br;
                        if (sz >= dest_size)
                                return;
+                       wb_consumed = br->consumed;
                        continue;
                }
                if (!buf1) {
@@ -858,7 +889,7 @@ static void merge_input_pool(struct btr_node *btrn, size_t dest_size)
                assert(buf2 + sz2 == buf);
                sz2 += sz;
 next:
-               if (sz1 + sz2 >= dest_size)
+               if (sz1 + sz2 >= dest_size + wb_consumed)
                        break;
        }
        if (!buf2) /* nothing to do */
@@ -890,7 +921,6 @@ next:
         * We already have a wrap buffer, but it is too small. It might be
         * partially used.
         */
-       wsz = br_available_bytes(wbr);
        if (wbr->wrap_count == sz1 && wbr->btrb->size >= sz1 + sz2) /* nothing we can do about it */
                return;
        sz = sz1 + sz2 - wbr->btrb->size; /* amount of new data */
@@ -1037,7 +1067,7 @@ struct btr_node *btr_search_node(const char *name, struct btr_node *root)
 }
 
 /** 640K ought to be enough for everybody ;) */
-#define BTRN_MAX_PENDING (640 * 1024)
+#define BTRN_MAX_PENDING (96 * 1024)
 
 /**
  * Return the current state of a buffer tree node.
@@ -1074,7 +1104,7 @@ int btr_node_status(struct btr_node *btrn, size_t min_iqs,
        if (type != BTR_NT_LEAF) {
                if (btr_no_children(btrn))
                        return -E_BTR_NO_CHILD;
-               if (btr_bytes_pending(btrn) > BTRN_MAX_PENDING)
+               if (btr_get_output_queue_size(btrn) > BTRN_MAX_PENDING)
                        return 0;
        }
        if (type != BTR_NT_ROOT) {