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