You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Cliff Woolley <cl...@yahoo.com> on 2000/12/08 10:05:24 UTC
(oops) [PATCH] Buckets: add copy function, ap_bucket_split_any(), etc
--- Cliff Woolley <cl...@yahoo.com> wrote:
> Here's a patch (sorry it took me so long) that adds a copy function to the
> bucket API.
It'd have been nice if I'd actually pasted in the patch BEFORE I hit send. =-)
4am, time for sleep...
Here it is, for real this time.
Index: include/ap_buckets.h
===================================================================
RCS file: /home/cvspublic/apr-util/include/ap_buckets.h,v
retrieving revision 1.56
diff -u -r1.56 ap_buckets.h
--- include/ap_buckets.h 2000/12/08 01:26:34 1.56
+++ include/ap_buckets.h 2000/12/08 08:41:32
@@ -88,7 +88,7 @@
* Buckets are data stores of varous types. They can refer to data in
* memory, or part of a file or mmap area, or the output of a process,
* etc. Buckets also have some type-dependent accessor functions:
- * read, split, setaside, and destroy.
+ * read, split, copy, setaside, and destroy.
*
* read returns the address and size of the data in the bucket. If the
* data isn't in memory then it is read in and the bucket changes type
@@ -109,9 +109,17 @@
* expectation turns out not to be valid, the setaside function is
* called to move the data somewhere safer.
*
+ * copy makes a duplicate of the bucket structure as long as it's
+ * possible to have multiple references to a single copy of the
+ * data itself. Not all bucket types can be copied.
+ *
* destroy maintains the reference counts on the resources used by a
* bucket and frees them if necessary.
*
+ * Note: all of the above functions have wrapper macros (ap_bucket_read(),
+ * ap_bucket_destroy(), etc), and those macros should be used rather
+ * than using the function pointers directly.
+ *
* To write a bucket brigade, they are first made into an iovec, so that we
* don't write too little data at one time. Currently we ignore compacting the
* buckets into as few buckets as possible, but if we really want good
@@ -135,17 +143,19 @@
const char *name;
/**
* The number of functions this bucket understands. Can not be less than
- * four.
+ * five.
*/
int num_func;
/**
* Free the private data and any resources used by the bucket
- * (if they aren't shared with another bucket).
+ * (if they aren't shared with another bucket).
* @param data The private data pointer from the bucket to be destroyed
*/
void (*destroy)(void *data);
- /** Read the data from the bucket.
+ /**
+ * Read the data from the bucket. This is guaranteed to be implemented
+ * for all bucket types.
* @param b The bucket to read from
* @param str A place to store the data read. Allocation should only be
* done if absolutely necessary.
@@ -156,20 +166,39 @@
*/
apr_status_t (*read)(ap_bucket *b, const char **str, apr_size_t *len,
ap_read_type block);
- /** Make it possible to set aside the data. For most bucket types this is
- * a no-op; buckets containing data that dies when the stack is un-wound
- * must convert the bucket into a heap bucket.
+ /**
+ * Make it possible to set aside the data. Buckets containing data that
+ * dies when the stack is un-wound must convert the bucket into a heap
+ * bucket. For most bucket types, though, this is a no-op and this
+ * function will return APR_ENOTIMPL.
* @param e The bucket to convert
* @deffunc apr_status_t setaside(ap_bucket *e)
*/
apr_status_t (*setaside)(ap_bucket *e);
- /** Split one bucket in two at the specified position
+ /**
+ * Split one bucket in two at the specified position by duplicating
+ * the bucket structure (not the data) and modifying any necessary
+ * start/end/offset information. If it's not possible to do this
+ * for the bucket type (perhaps the length of the data is indeterminate,
+ * as with pipe and socket buckets), then APR_ENOTIMPL is returned.
+ * See also ap_bucket_split_any().
* @param e The bucket to split
* @param point The offset of the first byte in the new bucket
* @deffunc apr_status_t split(ap_bucket *e, apr_off_t point)
*/
apr_status_t (*split)(ap_bucket *e, apr_off_t point);
+
+ /**
+ * Copy the bucket structure (not the data), assuming that this is
+ * possible for the bucket type. If it's not, APR_ENOTIMPL is returned.
+ * See also ap_bucket_copy_any().
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @deffunc apr_status_t copy
+ */
+ apr_status_t (*copy)(ap_bucket *e, ap_bucket **c);
+
};
/**
@@ -669,6 +698,37 @@
*/
#define ap_bucket_split(e,point) e->type->split(e, point)
+/**
+ * Copy a bucket.
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @deffunc apr_status_t ap_bucket_copy(ap_bucket *e, ap_bucket **c)
+ */
+#define ap_bucket_copy(e,c) e->type->copy(e, c)
+
+/**
+ * Split a bucket into two, using ap_bucket_split() if that's possible
+ * for the given bucket type. If split() is not implemented for the
+ * bucket's type, then we perform a blocking read on the bucket. That
+ * morphs the bucket into a splittable bucket (eg, pipe becomes heap),
+ * and we then split the result.
+ * @param e The bucket to split
+ * @param point The offset to split the bucket at
+ * @deffunc apr_status_t ap_bucket_split_any(ap_bucket *e, apr_off_t point)
+ */
+APR_DECLARE(apr_status_t) ap_bucket_split_any(ap_bucket *e, apr_off_t point);
+
+/**
+ * Copy a bucket, using ap_bucket_copy() if that's possible for the given
+ * bucket type. If copy() is not implemented for the bucket's type, then
+ * we copy the data as well by performing a blocking read on the bucket.
+ * That morphs the bucket into a copyable one, which we then copy.
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @deffunc apr_status_t ap_bucket_copy_any(ap_bucket *e, ap_bucket **c)
+ */
+APR_DECLARE(apr_status_t) ap_bucket_copy_any(ap_bucket *e, ap_bucket **c);
+
/* Bucket type handling */
@@ -691,6 +751,16 @@
APR_DECLARE_NONSTD(apr_status_t) ap_bucket_split_notimpl(ap_bucket *data,
apr_off_t point);
/**
+ * A place holder function that signifies that the copy function was not
+ * implemented for this bucket
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @return APR_ENOTIMPL
+ * @deffunc apr_status_t ap_bucket_copy_notimpl(ap_bucket *e, ap_bucket **c)
+ */
+APR_DECLARE_NONSTD(apr_status_t) ap_bucket_copy_notimpl(ap_bucket *e,
+ ap_bucket **c);
+/**
* A place holder function that signifies that the destroy function was not
* implemented for this bucket
* @param data The bucket to destroy
@@ -807,6 +877,18 @@
* @deffunc apr_status_t ap_bucket_split_shared(ap_bucket *b, apr_off_t point)
*/
APR_DECLARE_NONSTD(apr_status_t) ap_bucket_split_shared(ap_bucket *b, apr_off_t
point);
+
+/**
+ * Copy a refcounted bucket, incrementing the reference count. Most
+ * reference-counting bucket types will be able to use this function
+ * as their copy function without any additional type-specific handling.
+ * @param a The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @return APR_ENOMEM if allocation failed;
+ or APR_SUCCESS
+ * @deffunc apr_status_t ap_bucket_copy_shared(ap_bucket *a, ap_bucket **c)
+ */
+APR_DECLARE(apr_status_t) ap_bucket_copy_shared(ap_bucket *a, ap_bucket **c);
/* ***** Functions to Create Buckets of varying type ***** */
Index: src/buckets/Makefile.in
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- src/buckets/Makefile.in 2000/12/05 19:11:14 1.3
+++ src/buckets/Makefile.in 2000/12/08 08:41:35
@@ -2,7 +2,7 @@
TARGETS = ap_buckets_file.lo ap_buckets_pool.lo ap_buckets_flush.lo \
ap_buckets_refcount.lo ap_buckets_heap.lo ap_buckets_simple.lo ap_buckets.lo \
ap_buckets_mmap.lo ap_buckets_socket.lo ap_buckets_eos.lo ap_buckets_pipe.lo \
-ap_buckets.lo
+ap_buckets_util.lo ap_buckets.lo
top_builddir = @top_builddir@
include $(top_builddir)/build/rules.mk
Index: src/buckets/ap_buckets.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets.c,v
retrieving revision 1.34
diff -u -r1.34 ap_buckets.c
--- src/buckets/ap_buckets.c 2000/12/05 04:46:23 1.34
+++ src/buckets/ap_buckets.c 2000/12/08 08:41:35
@@ -241,7 +241,10 @@
{
return APR_ENOTIMPL;
}
-
+APR_DECLARE_NONSTD(apr_status_t) ap_bucket_copy_notimpl(ap_bucket *e, ap_bucket
**c)
+{
+ return APR_ENOTIMPL;
+}
APR_DECLARE_NONSTD(void) ap_bucket_destroy_notimpl(void *data)
{
return;
Index: src/buckets/ap_buckets_eos.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_eos.c,v
retrieving revision 1.15
diff -u -r1.15 ap_buckets_eos.c
--- src/buckets/ap_buckets_eos.c 2000/12/06 04:42:34 1.15
+++ src/buckets/ap_buckets_eos.c 2000/12/08 08:41:36
@@ -63,6 +63,12 @@
return APR_SUCCESS;
}
+static apr_status_t eos_copy(ap_bucket *e, ap_bucket **c)
+{
+ *c = ap_bucket_create_eos();
+ return APR_SUCCESS;
+}
+
APR_DECLARE(ap_bucket *) ap_bucket_make_eos(ap_bucket *b)
{
b->length = 0;
@@ -79,9 +85,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_eos_type = {
- "EOS", 4,
+ "EOS", 5,
ap_bucket_destroy_notimpl,
eos_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_notimpl
+ ap_bucket_split_notimpl,
+ eos_copy
};
Index: src/buckets/ap_buckets_file.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_file.c,v
retrieving revision 1.13
diff -u -r1.13 ap_buckets_file.c
--- src/buckets/ap_buckets_file.c 2000/12/07 05:01:14 1.13
+++ src/buckets/ap_buckets_file.c 2000/12/08 08:41:37
@@ -187,9 +187,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_file_type = {
- "FILE", 4,
+ "FILE", 5,
ap_bucket_destroy_notimpl,
file_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_notimpl
+ ap_bucket_split_notimpl,
+ ap_bucket_copy_notimpl
};
Index: src/buckets/ap_buckets_flush.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_flush.c,v
retrieving revision 1.7
diff -u -r1.7 ap_buckets_flush.c
--- src/buckets/ap_buckets_flush.c 2000/12/06 04:42:35 1.7
+++ src/buckets/ap_buckets_flush.c 2000/12/08 08:41:39
@@ -63,6 +63,12 @@
return APR_SUCCESS;
}
+static apr_status_t flush_copy(ap_bucket *e, ap_bucket **c)
+{
+ *c = ap_bucket_create_flush();
+ return APR_SUCCESS;
+}
+
APR_DECLARE(ap_bucket *) ap_bucket_make_flush(ap_bucket *b)
{
b->length = 0;
@@ -79,9 +85,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_flush_type = {
- "FLUSH", 4,
+ "FLUSH", 5,
ap_bucket_destroy_notimpl,
flush_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_notimpl
+ ap_bucket_split_notimpl,
+ flush_copy
};
Index: src/buckets/ap_buckets_heap.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_heap.c,v
retrieving revision 1.18
diff -u -r1.18 ap_buckets_heap.c
--- src/buckets/ap_buckets_heap.c 2000/12/06 04:42:35 1.18
+++ src/buckets/ap_buckets_heap.c 2000/12/08 08:41:40
@@ -141,9 +141,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_heap_type = {
- "HEAP", 4,
+ "HEAP", 5,
heap_destroy,
heap_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_shared
+ ap_bucket_split_shared,
+ ap_bucket_copy_shared
};
Index: src/buckets/ap_buckets_mmap.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_mmap.c,v
retrieving revision 1.22
diff -u -r1.22 ap_buckets_mmap.c
--- src/buckets/ap_buckets_mmap.c 2000/12/06 04:42:35 1.22
+++ src/buckets/ap_buckets_mmap.c 2000/12/08 08:41:42
@@ -116,9 +116,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_mmap_type = {
- "MMAP", 4,
+ "MMAP", 5,
mmap_destroy,
mmap_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_shared
+ ap_bucket_split_shared,
+ ap_bucket_copy_shared
};
Index: src/buckets/ap_buckets_pipe.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_pipe.c,v
retrieving revision 1.22
diff -u -r1.22 ap_buckets_pipe.c
--- src/buckets/ap_buckets_pipe.c 2000/12/06 04:42:35 1.22
+++ src/buckets/ap_buckets_pipe.c 2000/12/08 08:41:44
@@ -140,9 +140,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_pipe_type = {
- "PIPE", 4,
+ "PIPE", 5,
ap_bucket_destroy_notimpl,
pipe_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_notimpl
+ ap_bucket_split_notimpl,
+ ap_bucket_copy_notimpl
};
Index: src/buckets/ap_buckets_pool.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_pool.c,v
retrieving revision 1.6
diff -u -r1.6 ap_buckets_pool.c
--- src/buckets/ap_buckets_pool.c 2000/12/06 04:42:35 1.6
+++ src/buckets/ap_buckets_pool.c 2000/12/08 08:41:53
@@ -133,9 +133,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_pool_type = {
- "POOL", 4,
+ "POOL", 5,
pool_destroy,
pool_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_shared
+ ap_bucket_split_shared,
+ ap_bucket_copy_shared
};
Index: src/buckets/ap_buckets_refcount.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_refcount.c,v
retrieving revision 1.8
diff -u -r1.8 ap_buckets_refcount.c
--- src/buckets/ap_buckets_refcount.c 2000/12/05 01:02:50 1.8
+++ src/buckets/ap_buckets_refcount.c 2000/12/08 08:41:55
@@ -62,20 +62,44 @@
{
ap_bucket *b;
ap_bucket_shared *ad, *bd;
- ap_bucket_refcount *r;
+ apr_status_t rv;
if (point < 0 || point > a->length) {
return APR_EINVAL;
}
+
+ rv = ap_bucket_copy_shared(a, &b);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
- b = malloc(sizeof(*b));
+ ad = a->data;
+ bd = b->data;
+
+ a->length = point;
+ ad->end = ad->start + point;
+ b->length -= point;
+ bd->start += point;
+
+ AP_BUCKET_INSERT_AFTER(a, b);
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) ap_bucket_copy_shared(ap_bucket *a, ap_bucket **c)
+{
+ ap_bucket *b;
+ ap_bucket_shared *ad, *bd;
+ ap_bucket_refcount *r;
+
+ b = malloc(sizeof(*b));
if (b == NULL) {
- return APR_ENOMEM;
+ return APR_ENOMEM;
}
bd = malloc(sizeof(*bd));
if (bd == NULL) {
- free(b);
- return APR_ENOMEM;
+ free(b);
+ return APR_ENOMEM;
}
*b = *a;
ad = a->data;
@@ -84,13 +108,8 @@
r = ad->data;
r->refcount += 1;
-
- a->length = point;
- ad->end = ad->start + point;
- b->length -= point;
- bd->start += point;
- AP_BUCKET_INSERT_AFTER(a, b);
+ *c = b;
return APR_SUCCESS;
}
Index: src/buckets/ap_buckets_simple.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_simple.c,v
retrieving revision 1.15
diff -u -r1.15 ap_buckets_simple.c
--- src/buckets/ap_buckets_simple.c 2000/12/06 04:42:35 1.15
+++ src/buckets/ap_buckets_simple.c 2000/12/08 08:41:57
@@ -59,15 +59,11 @@
* We can't simplify this function by using an ap_bucket_make function
* because we aren't sure of the exact type of this bucket.
*/
-static apr_status_t simple_split(ap_bucket *a, apr_off_t point)
+static apr_status_t simple_copy(ap_bucket *a, ap_bucket **c)
{
ap_bucket *b;
ap_bucket_simple *ad, *bd;
- if (point < 0 || point > a->length) {
- return APR_EINVAL;
- }
-
b = malloc(sizeof(*b));
if (b == NULL) {
return APR_ENOMEM;
@@ -82,6 +78,29 @@
b->data = bd;
*bd = *ad;
+ *c = b;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t simple_split(ap_bucket *a, apr_off_t point)
+{
+ ap_bucket *b;
+ ap_bucket_simple *ad, *bd;
+ apr_status_t rv;
+
+ if (point < 0 || point > a->length) {
+ return APR_EINVAL;
+ }
+
+ rv = simple_copy(a, &b);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ ad = a->data;
+ bd = b->data;
+
a->length = point;
ad->end = ad->start + point;
b->length -= point;
@@ -172,17 +191,19 @@
}
const ap_bucket_type ap_immortal_type = {
- "IMMORTAL", 4,
+ "IMMORTAL", 5,
free,
simple_read,
ap_bucket_setaside_notimpl,
- simple_split
+ simple_split,
+ simple_copy
};
APR_DECLARE_DATA const ap_bucket_type ap_transient_type = {
- "TRANSIENT", 4,
+ "TRANSIENT", 5,
ap_bucket_destroy_notimpl,
simple_read,
transient_setaside,
- simple_split
+ simple_split,
+ simple_copy
};
Index: src/buckets/ap_buckets_socket.c
===================================================================
RCS file: /home/cvspublic/apr-util/src/buckets/ap_buckets_socket.c,v
retrieving revision 1.11
diff -u -r1.11 ap_buckets_socket.c
--- src/buckets/ap_buckets_socket.c 2000/12/06 04:42:35 1.11
+++ src/buckets/ap_buckets_socket.c 2000/12/08 08:41:58
@@ -135,9 +135,10 @@
}
APR_DECLARE_DATA const ap_bucket_type ap_socket_type = {
- "SOCKET", 4,
+ "SOCKET", 5,
ap_bucket_destroy_notimpl,
socket_read,
ap_bucket_setaside_notimpl,
- ap_bucket_split_notimpl
+ ap_bucket_split_notimpl,
+ ap_bucket_copy_notimpl
};
? src/buckets/ap_buckets_util.c
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr_lib.h"
#include "ap_buckets.h"
APR_DECLARE(apr_status_t) ap_bucket_split_any(ap_bucket *e, apr_off_t point)
{
apr_status_t rv;
const char *str;
apr_size_t len;
/* try to split this bucket directly */
rv = ap_bucket_split(e, point);
if (rv != APR_ENOTIMPL) {
return rv;
}
/* if the bucket cannot be split, we must read from it,
* changing its type to one that can be split */
if (point < 0) {
return APR_EINVAL;
}
rv = ap_bucket_read(e, &str, &len, AP_BLOCK_READ);
if (rv != APR_SUCCESS) {
return rv;
}
if (point > len) {
return APR_EINVAL;
}
return ap_bucket_split(e, point);
}
APR_DECLARE(apr_status_t) ap_bucket_copy_any(ap_bucket *e, ap_bucket **c)
{
apr_status_t rv;
const char *str;
apr_size_t len;
/* try to copy the bucket directly */
rv = ap_bucket_copy(e, c);
if (rv != APR_ENOTIMPL) {
return rv;
}
/* if the bucket cannot be copied, we must read from it,
* changing its type to one that can be copied */
rv = ap_bucket_read(e, &str, &len, AP_BLOCK_READ);
if (rv != APR_SUCCESS) {
return rv;
}
return ap_bucket_copy(e, c);
}
__________________________________________________
Do You Yahoo!?
Yahoo! Shopping - Thousands of Stores. Millions of Products.
http://shopping.yahoo.com/