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

Reply via email to