The attached patch adds a capabilities flag field to the
apr_bucket_type_t. Flags currently included indicate whether the
"optional" functions (setaside,copy,split) are implemented or not without
having to actually call them to find out, whether the bucket is a
"metadata" bucket, and whether the bucket has a file descriptor in it for
the use by apr_sendfile().
The main reason I need this right now is that I've implemented and am
about to commit a patch to Apache's mod_file_cache that uses a custom
bucket type ("ap_bucket_cachedfile") to denote a file descriptor that's
shared among multiple threads. Such a file descriptor can be sendfile'd,
but cannot be read by other means without causing thread-safety problems.
Apache's core_output_filter currently is hardcoded to assume that a bucket
can be sendfile'd ONLY if it matches APR_BUCKET_IS_FILE(), though the
above is clearly a case where an APR_BUCKET_SUPPORTS_SENDFILE() test would
be much more useful and extensible. The flags field gives us that
ability.
I can easily see future situations arising where similar strategies would
be useful, so adding a flags field now would allow us to easily handle
those situations.
If nobody objects, I'll commit this tomorrow, followed closely by the
patch to mod_file_cache and the core_output_filter in Apache.
--Cliff
PS: I tried to find names for these flags that were both descriptive and
reasonably short, but if anybody has any better ideas, I'm all ears...
--------------------------------------------------------------
Cliff Woolley
[EMAIL PROTECTED]
Charlottesville, VA
Index: buckets/apr_buckets_eos.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_eos.c,v
retrieving revision 1.25
diff -u -d -r1.25 apr_buckets_eos.c
--- buckets/apr_buckets_eos.c 2001/06/13 19:16:07 1.25
+++ buckets/apr_buckets_eos.c 2001/06/19 01:05:33
@@ -89,6 +89,7 @@
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_eos = {
"EOS", 5,
+ APR_BUCKET_FLAGSETASIDE | APR_BUCKET_FLAGCOPY | APR_BUCKET_FLAGMETADATA,
apr_bucket_destroy_noop,
eos_read,
apr_bucket_setaside_noop,
Index: buckets/apr_buckets_file.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_file.c,v
retrieving revision 1.45
diff -u -d -r1.45 apr_buckets_file.c
--- buckets/apr_buckets_file.c 2001/06/18 21:57:10 1.45
+++ buckets/apr_buckets_file.c 2001/06/19 01:05:33
@@ -236,7 +236,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_file = {
- "FILE", 5,
+ "FILE", 5, APR_BUCKET_FLAGALLFNS | APR_BUCKET_FLAGSENDFILE,
file_destroy,
file_read,
file_setaside,
Index: buckets/apr_buckets_flush.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_flush.c,v
retrieving revision 1.17
diff -u -d -r1.17 apr_buckets_flush.c
--- buckets/apr_buckets_flush.c 2001/06/13 19:16:11 1.17
+++ buckets/apr_buckets_flush.c 2001/06/19 01:05:33
@@ -89,6 +89,7 @@
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_flush = {
"FLUSH", 5,
+ APR_BUCKET_FLAGSETASIDE | APR_BUCKET_FLAGCOPY | APR_BUCKET_FLAGMETADATA,
apr_bucket_destroy_noop,
flush_read,
apr_bucket_setaside_noop,
Index: buckets/apr_buckets_heap.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_heap.c,v
retrieving revision 1.33
diff -u -d -r1.33 apr_buckets_heap.c
--- buckets/apr_buckets_heap.c 2001/06/07 10:13:36 1.33
+++ buckets/apr_buckets_heap.c 2001/06/19 01:05:33
@@ -124,7 +124,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_heap = {
- "HEAP", 5,
+ "HEAP", 5, APR_BUCKET_FLAGALLFNS,
heap_destroy,
heap_read,
apr_bucket_setaside_noop,
Index: buckets/apr_buckets_mmap.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_mmap.c,v
retrieving revision 1.36
diff -u -d -r1.36 apr_buckets_mmap.c
--- buckets/apr_buckets_mmap.c 2001/06/14 22:56:13 1.36
+++ buckets/apr_buckets_mmap.c 2001/06/19 01:05:33
@@ -140,7 +140,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_mmap = {
- "MMAP", 5,
+ "MMAP", 5, APR_BUCKET_FLAGALLFNS,
mmap_destroy,
mmap_read,
mmap_setaside,
Index: buckets/apr_buckets_pipe.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_pipe.c,v
retrieving revision 1.35
diff -u -d -r1.35 apr_buckets_pipe.c
--- buckets/apr_buckets_pipe.c 2001/06/13 19:16:13 1.35
+++ buckets/apr_buckets_pipe.c 2001/06/19 01:05:34
@@ -151,7 +151,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pipe = {
- "PIPE", 5,
+ "PIPE", 5, APR_BUCKET_FLAGNONE,
apr_bucket_destroy_noop,
pipe_read,
apr_bucket_setaside_notimpl,
Index: buckets/apr_buckets_pool.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_pool.c,v
retrieving revision 1.19
diff -u -d -r1.19 apr_buckets_pool.c
--- buckets/apr_buckets_pool.c 2001/06/18 21:39:27 1.19
+++ buckets/apr_buckets_pool.c 2001/06/19 01:05:34
@@ -169,7 +169,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = {
- "POOL", 5,
+ "POOL", 5, APR_BUCKET_FLAGALLFNS,
pool_destroy,
pool_read,
apr_bucket_setaside_noop,
Index: buckets/apr_buckets_simple.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_simple.c,v
retrieving revision 1.28
diff -u -d -r1.28 apr_buckets_simple.c
--- buckets/apr_buckets_simple.c 2001/06/13 19:16:15 1.28
+++ buckets/apr_buckets_simple.c 2001/06/19 01:05:34
@@ -155,8 +155,8 @@
return apr_bucket_transient_make(b, buf, length);
}
-const apr_bucket_type_t apr_bucket_type_immortal = {
- "IMMORTAL", 5,
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_immortal = {
+ "IMMORTAL", 5, APR_BUCKET_FLAGALLFNS,
apr_bucket_destroy_noop,
simple_read,
apr_bucket_setaside_noop,
@@ -165,7 +165,7 @@
};
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_transient = {
- "TRANSIENT", 5,
+ "TRANSIENT", 5, APR_BUCKET_FLAGALLFNS,
apr_bucket_destroy_noop,
simple_read,
transient_setaside,
Index: buckets/apr_buckets_socket.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_socket.c,v
retrieving revision 1.24
diff -u -d -r1.24 apr_buckets_socket.c
--- buckets/apr_buckets_socket.c 2001/06/13 19:16:17 1.24
+++ buckets/apr_buckets_socket.c 2001/06/19 01:05:34
@@ -146,7 +146,7 @@
}
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_socket = {
- "SOCKET", 5,
+ "SOCKET", 5, APR_BUCKET_FLAGNONE,
apr_bucket_destroy_noop,
socket_read,
apr_bucket_setaside_notimpl,
Index: include/apr_buckets.h
===================================================================
RCS file: /home/cvs/apr-util/include/apr_buckets.h,v
retrieving revision 1.99
diff -u -d -r1.99 apr_buckets.h
--- include/apr_buckets.h 2001/06/13 19:16:35 1.99
+++ include/apr_buckets.h 2001/06/19 01:05:42
@@ -157,6 +157,10 @@
*/
int num_func;
/**
+ * Capability flags for this bucket type
+ */
+ apr_uint32_t flags;
+ /**
* Free the private data and any resources used by the bucket
* (if they aren't shared with another bucket).
* @param data The private data pointer from the bucket to be destroyed
@@ -414,6 +418,62 @@
*/
#define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link);
+
+/**
+ * apr_bucket_type_t flags
+ */
+#define APR_BUCKET_FLAGNONE 0x00000000
+#define APR_BUCKET_FLAGSETASIDE 0x00000001
+#define APR_BUCKET_FLAGSPLIT 0x00000002
+#define APR_BUCKET_FLAGCOPY 0x00000004
+#define APR_BUCKET_FLAGSENDFILE 0x00000010
+#define APR_BUCKET_FLAGMETADATA 0x00000100
+#define APR_BUCKET_FLAGALLFNS \
+ (APR_BUCKET_FLAGSETASIDE | APR_BUCKET_FLAGSPLIT | APR_BUCKET_FLAGCOPY)
+
+/**
+ * Determine whether a bucket implements setaside
+ * @param e The bucket to inspect
+ * @return true or false
+ * @deffunc int APR_BUCKET_SUPPORTS_SETASIDE(apr_bucket *e)
+ */
+#define APR_BUCKET_SUPPORTS_SETASIDE(e)
\
+ (e->type->flags & APR_BUCKET_FLAGSETASIDE)
+/**
+ * Determine whether a bucket implements split
+ * @param e The bucket to inspect
+ * @return true or false
+ * @deffunc int APR_BUCKET_SUPPORTS_SPLIT(apr_bucket *e)
+ */
+#define APR_BUCKET_SUPPORTS_SPLIT(e) (e->type->flags & APR_BUCKET_FLAGSPLIT)
+/**
+ * Determine whether a bucket implements copy
+ * @param e The bucket to inspect
+ * @return true or false
+ * @deffunc int APR_BUCKET_SUPPORTS_COPY(apr_bucket *e)
+ */
+#define APR_BUCKET_SUPPORTS_COPY(e) (e->type->flags & APR_BUCKET_FLAGCOPY)
+/**
+ * Determine whether a bucket supports sendfile
+ * @param e The bucket to inspect
+ * @return true or false
+ * @tip Using sendfile on a bucket is done by assuming that there is
+ * an apr_file_t at a given location in the bucket's private
+ * data structure. The offset that's expected is the same as the
+ * one in the FILE bucket's canonical apr_bucket_file struct.
+ * Any bucket with this property will support this:
+ * apr_sendfile(sock, ((apr_bucket_file *)e->data)->fd);
+ * @deffunc int APR_BUCKET_SUPPORTS_SENDFILE(apr_bucket *e)
+ */
+#define APR_BUCKET_SUPPORTS_SENDFILE(e)
\
+ (e->type->flags & APR_BUCKET_FLAGSENDFILE)
+/**
+ * Determine if a bucket is metadata (eg EOS or FLUSH)
+ * @param e The bucket to inspect
+ * @return true or false
+ * @deffunc int APR_BUCKET_IS_METADATA(apr_bucket *e)
+ */
+#define APR_BUCKET_IS_METADATA(e) (e->type->flags & APR_BUCKET_FLAGMETADATA)
/**
* Determine if a bucket is a FLUSH bucket
* @param e The bucket to inspect