gstein 00/12/08 03:02:49
Modified: include ap_buckets.h
src/buckets Makefile.in ap_buckets.c ap_buckets_eos.c
ap_buckets_file.c ap_buckets_flush.c
ap_buckets_heap.c ap_buckets_mmap.c
ap_buckets_pipe.c ap_buckets_pool.c
ap_buckets_refcount.c ap_buckets_simple.c
ap_buckets_socket.c
Log:
Add a copy() function to the buckets. Also adds two utility functions:
ap_bucket_split_any() and ap_bucket_copy_any().
Submitted by: Cliff Woolley <[EMAIL PROTECTED]>
Revision Changes Path
1.57 +90 -8 apr-util/include/ap_buckets.h
Index: ap_buckets.h
===================================================================
RCS file: /home/cvs/apr-util/include/ap_buckets.h,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -u -r1.56 -r1.57
--- ap_buckets.h 2000/12/08 01:26:34 1.56
+++ ap_buckets.h 2000/12/08 11:02:30 1.57
@@ -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 ***** */
1.4 +1 -1 apr-util/src/buckets/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/Makefile.in,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -u -r1.3 -r1.4
--- Makefile.in 2000/12/05 19:11:14 1.3
+++ Makefile.in 2000/12/08 11:02:32 1.4
@@ -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
1.35 +4 -1 apr-util/src/buckets/ap_buckets.c
Index: ap_buckets.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -u -r1.34 -r1.35
--- ap_buckets.c 2000/12/05 04:46:23 1.34
+++ ap_buckets.c 2000/12/08 11:02:33 1.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;
1.16 +9 -2 apr-util/src/buckets/ap_buckets_eos.c
Index: ap_buckets_eos.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_eos.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -u -r1.15 -r1.16
--- ap_buckets_eos.c 2000/12/06 04:42:34 1.15
+++ ap_buckets_eos.c 2000/12/08 11:02:33 1.16
@@ -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
};
1.14 +3 -2 apr-util/src/buckets/ap_buckets_file.c
Index: ap_buckets_file.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_file.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -u -r1.13 -r1.14
--- ap_buckets_file.c 2000/12/07 05:01:14 1.13
+++ ap_buckets_file.c 2000/12/08 11:02:34 1.14
@@ -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
};
1.8 +9 -2 apr-util/src/buckets/ap_buckets_flush.c
Index: ap_buckets_flush.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_flush.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -u -r1.7 -r1.8
--- ap_buckets_flush.c 2000/12/06 04:42:35 1.7
+++ ap_buckets_flush.c 2000/12/08 11:02:34 1.8
@@ -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
};
1.19 +3 -2 apr-util/src/buckets/ap_buckets_heap.c
Index: ap_buckets_heap.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_heap.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -u -r1.18 -r1.19
--- ap_buckets_heap.c 2000/12/06 04:42:35 1.18
+++ ap_buckets_heap.c 2000/12/08 11:02:35 1.19
@@ -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
};
1.23 +3 -2 apr-util/src/buckets/ap_buckets_mmap.c
Index: ap_buckets_mmap.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_mmap.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -u -r1.22 -r1.23
--- ap_buckets_mmap.c 2000/12/06 04:42:35 1.22
+++ ap_buckets_mmap.c 2000/12/08 11:02:36 1.23
@@ -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
};
1.23 +3 -2 apr-util/src/buckets/ap_buckets_pipe.c
Index: ap_buckets_pipe.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_pipe.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -u -r1.22 -r1.23
--- ap_buckets_pipe.c 2000/12/06 04:42:35 1.22
+++ ap_buckets_pipe.c 2000/12/08 11:02:37 1.23
@@ -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
};
1.7 +3 -2 apr-util/src/buckets/ap_buckets_pool.c
Index: ap_buckets_pool.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_pool.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -u -r1.6 -r1.7
--- ap_buckets_pool.c 2000/12/06 04:42:35 1.6
+++ ap_buckets_pool.c 2000/12/08 11:02:38 1.7
@@ -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
};
1.9 +30 -11 apr-util/src/buckets/ap_buckets_refcount.c
Index: ap_buckets_refcount.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_refcount.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -u -r1.8 -r1.9
--- ap_buckets_refcount.c 2000/12/05 01:02:50 1.8
+++ ap_buckets_refcount.c 2000/12/08 11:02:38 1.9
@@ -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;
}
1.16 +30 -9 apr-util/src/buckets/ap_buckets_simple.c
Index: ap_buckets_simple.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_simple.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -u -r1.15 -r1.16
--- ap_buckets_simple.c 2000/12/06 04:42:35 1.15
+++ ap_buckets_simple.c 2000/12/08 11:02:39 1.16
@@ -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
};
1.12 +3 -2 apr-util/src/buckets/ap_buckets_socket.c
Index: ap_buckets_socket.c
===================================================================
RCS file: /home/cvs/apr-util/src/buckets/ap_buckets_socket.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -u -r1.11 -r1.12
--- ap_buckets_socket.c 2000/12/06 04:42:35 1.11
+++ ap_buckets_socket.c 2000/12/08 11:02:39 1.12
@@ -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
};