apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@covalent.net
Subject [PATCH] brigade buffering... again
Date Fri, 26 Jan 2001 20:33:33 GMT

This is a second attempt at a simple brigade buffer.  For the most part,
this is exactly what was posted yesterday, except it has Greg Marr's fixes
in it.

I know that there are going to be some arguments against this patch.  I
will try to deal with some of those right now.

1)  This patch allows a brigade to chew memory.  Yep, it does.  That is
part of the generalness of the patch.  APR's bucket brigades are a data
store, and that is it.  Apache happens to use them for filters, but they
are generally useful outside of a filter scheme.  Rather than impose
Apache's memory requirements on other programs, this API allows other
programs to determine what is going on in the brigade, and react
accordingly.  This patch will be duplicated to new-httpd as a part of a
much larger patch to use this in apache 2.0.

2)  This allows data to be inserted out of order.  Yep, it does.  This
happens when going from using the buffered to the unbuffered API.  The
functions below are buffering data, the direct bucket calls are
unbuffered.  I have never seen a buffering API that doesn't expect a
function to be called when switching from buffered to unbuffered.  This
one is no different, we expect the user to call apr_brigade_flush.

I know that there are bugs in this code, I am not worried about
them.  They can all be worked out, given enough time and the desire to do
it.

Ryan


Index: buckets/apr_brigade.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_brigade.c,v
retrieving revision 1.3
diff -u -d -b -w -u -r1.3 apr_brigade.c
--- buckets/apr_brigade.c	2001/01/19 07:01:59	1.3
+++ buckets/apr_brigade.c	2001/01/26 20:09:34
@@ -99,6 +99,9 @@
 
     b = apr_palloc(p, sizeof(*b));
     b->p = p;
+
+    b->start = b->end = NULL;
+
     APR_RING_INIT(&b->list, apr_bucket, link);
 
     apr_register_cleanup(b->p, b, apr_brigade_cleanup, apr_brigade_cleanup);
@@ -185,12 +188,43 @@
     return vec - orig;
 }
 
+static int check_brigade_flush(char *start, char **end, const char **str, 
+                               apr_size_t *n, apr_bucket_brigade *b)
+{
+    if (*n > (APR_BUCKET_BUFF_SIZE - (*end - start))) {
+        if (start) {
+            int size = APR_BUCKET_BUFF_SIZE - (*end - start);
+            memcpy(*end, *str, size);
+            *n -= size;
+            *end += size;
+            *str += size;
+            apr_brigade_flush(b);
+        }
+        if (*n > APR_BUCKET_BUFF_SIZE) {
+            apr_bucket *e = apr_bucket_create_heap(*str, *n, 1, NULL);
+            APR_BRIGADE_INSERT_TAIL(b, e);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+APU_DECLARE(void) apr_brigade_flush(apr_bucket_brigade *b)
+{
+    apr_bucket *e;
+    apr_size_t i = b->end - b->start;
+
+    if (i) {
+        e = apr_bucket_create_heap(b->start, i, 0, NULL);
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        b->start = b->end = NULL;
+    }
+}
+
 APU_DECLARE(int) apr_brigade_vputstrs(apr_bucket_brigade *b, va_list va)
 {
-    apr_bucket *r;
     const char *x;
     int j, k;
-    apr_size_t i;
 
     for (k = 0;;) {
         x = va_arg(va, const char *);
@@ -198,18 +232,51 @@
             break;
         j = strlen(x);
        
-	/* XXX: copy or not? let the caller decide? */
-        r = apr_bucket_create_heap(x, j, 1, &i);
-        if (i != j) {
-            /* Do we need better error reporting?  */
-            return -1;
+        k += apr_brigade_write(b, x, j);
         }
-        k += i;
+    return k;
+}
 
-        APR_BRIGADE_INSERT_TAIL(b, r);
+APU_DECLARE(int) apr_brigade_putc(apr_bucket_brigade *b, const char c)
+{
+    apr_size_t nbyte = 1;
+    const char *str = &c;
+
+    if (check_brigade_flush(b->start, &b->end, &str, &nbyte, b)) {
+        return 1;
     }
 
-    return k;
+    if (!b->start) {
+        b->start = b->end = malloc(APR_BUCKET_BUFF_SIZE);
+    }
+
+    memcpy(b->end, &c, 1);
+    b->end++;
+
+    return 1;
+}
+
+APU_DECLARE(int) apr_brigade_write(apr_bucket_brigade *b, const char *str, apr_size_t nbyte)
+{
+    apr_size_t n = nbyte;
+
+    if (check_brigade_flush(b->start, &b->end, &str, &nbyte, b)) {
+        return n;
+    }
+
+    if (!b->start) {
+        b->start = b->end = malloc(APR_BUCKET_BUFF_SIZE);
+    }
+
+    memcpy(b->end, str, nbyte);
+    b->end += nbyte;
+
+    return n;
+}
+
+APU_DECLARE(int) apr_brigade_puts(apr_bucket_brigade *b, const char *str)
+{
+    return apr_brigade_write(b, str, strlen(str));
 }
 
 APU_DECLARE_NONSTD(int) apr_brigade_putstrs(apr_bucket_brigade *b, ...)
@@ -240,13 +307,9 @@
      * directly into a bucket.  I'm being lazy right now.  RBB
      */
     char buf[4096];
-    apr_bucket *r;
-    int res;
-
-    res = apr_vsnprintf(buf, 4096, fmt, va);
 
-    r = apr_bucket_create_heap(buf, strlen(buf), 1, NULL);
-    APR_BRIGADE_INSERT_TAIL(b, r);
+    apr_vsnprintf(buf, 4096, fmt, va);
 
-    return res;
+    return apr_brigade_puts(b, buf);
 }
+
Index: include/apr_buckets.h
===================================================================
RCS file: /home/cvs/apr-util/include/apr_buckets.h,v
retrieving revision 1.67
diff -u -d -b -w -u -r1.67 apr_buckets.h
--- include/apr_buckets.h	2001/01/23 22:24:06	1.67
+++ include/apr_buckets.h	2001/01/26 20:09:43
@@ -78,6 +78,8 @@
  * @package Bucket Brigades
  */
 
+#define APR_BUCKET_BUFF_SIZE 9000
+
 typedef enum {APR_BLOCK_READ, APR_NONBLOCK_READ} apr_read_type_e;
 
 /*
@@ -237,6 +239,8 @@
      *  the destroying function is responsible for killing the cleanup.
      */
     apr_pool_t *p;
+    char *start;
+    char *end;
     /** The buckets in the brigade are on this list. */
     /*
      * XXX: the apr_bucket_list structure doesn't actually need a name tag
@@ -628,9 +632,10 @@
 APU_DECLARE(int) apr_brigade_to_iovec(apr_bucket_brigade *b, 
 				     struct iovec *vec, int nvec);
 
+APU_DECLARE(void) apr_brigade_flush(apr_bucket_brigade *b);
+
 /**
- * This function writes a list of strings into a bucket brigade.  We just 
- * allocate a new heap bucket for each string.
+ * This function writes a list of strings into a bucket brigade. 
  * @param b The bucket brigade to add to
  * @param va A list of strings to add
  * @return The number of bytes added to the brigade
@@ -639,8 +644,34 @@
 APU_DECLARE(int) apr_brigade_vputstrs(apr_bucket_brigade *b, va_list va);
 
 /**
+ * This function writes an string into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param str The string to add
+ * @return The number of bytes added to the brigade
+ * @deffunc int apr_brigade_write(ap_bucket_brigade *b, const char *str)
+ */
+APU_DECLARE(int) apr_brigade_write(apr_bucket_brigade *b, const char *str, apr_size_t nbyte);
+
+/**
+ * This function writes an string into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param str The string to add
+ * @return The number of bytes added to the brigade
+ * @deffunc int apr_brigade_puts(ap_bucket_brigade *b, const char *str)
+ */
+APU_DECLARE(int) apr_brigade_puts(apr_bucket_brigade *b, const char *str);
+
+/**
+ * This function writes a character into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param c The character to add
+ * @return The number of bytes added to the brigade
+ * @deffunc int apr_brigade_putc(apr_bucket_brigade *b, const char c)
+ */
+APU_DECLARE(int) apr_brigade_putc(apr_bucket_brigade *b, const char c);
+
+/**
  * This function writes an unspecified number of strings into a bucket brigade.
- * We just allocate a new heap bucket for each string.
  * @param b The bucket brigade to add to
  * @param ... The strings to add
  * @return The number of bytes added to the brigade
@@ -649,7 +680,7 @@
 APU_DECLARE_NONSTD(int) apr_brigade_putstrs(apr_bucket_brigade *b, ...);
 
 /**
- * Evaluate a printf and put the resulting string into a bucket at the end 
+ * Evaluate a printf and put the resulting string at the end 
  * of the bucket brigade.
  * @param b The brigade to write to
  * @param fmt The format of the string to write
@@ -661,7 +692,7 @@
                                           const char *fmt, ...);
 
 /**
- * Evaluate a printf and put the resulting string into a bucket at the end 
+ * Evaluate a printf and put the resulting string at the end 
  * of the bucket brigade.
  * @param b The brigade to write to
  * @param fmt The format of the string to write


_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------





Mime
View raw message