You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2014/01/28 12:37:01 UTC

svn commit: r1562043 - in /subversion/trunk/subversion: include/svn_error_codes.h include/svn_io.h libsvn_subr/stream.c

Author: rhuijben
Date: Tue Jan 28 11:37:00 2014
New Revision: 1562043

URL: http://svn.apache.org/r1562043
Log:
Following up on r1561688, extend the stream api with a data available
callback. This allows converting the ra-svn api which currently doesn't
follow the svn_stream_t contract and to switch to using it correctly.

* subversion/include/svn_error_codes.h
  (SVN_ERR_STREAM_DATA_AVAILABLE_NOT_SUPPORTED): New value.

* subversion/include/svn_io.h
  (svn_stream_seek_fn_t): Fix indentation.
  (svn_stream_data_available_fn_t): New typedef.
  (svn_stream_set_data_available): New function.
  (svn_stream_data_available): New function.

* subversion/libsvn_subr/stream.c
  (includes): Add apr_poll.h.
  (svn_stream_t): Add value.
  (svn_stream_create): Update caller.
  (svn_stream_set_data_available): New function.
  (svn_stream_data_available): New function.

  (data_available_disown): New function.
  (svn_stream_disown): Install callback.

  (data_available_handler_apr): New function, based on ra_svn code.
  (svn_stream_from_aprfile2): Install callback.

  (data_available_handler_checksum): New function.
  (svn_stream_checksummed2): Install callback.

  (data_available_handler_stringbuf): New function.
  (svn_stream_from_stringbuf): Install callback.

  (data_available_handler_string): New function.
  (svn_stream_from_string): Install callback.

  (data_available_handler_lazyopen): New function.
  (svn_stream_lazyopen_create): Install callback.

Modified:
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/include/svn_io.h
    subversion/trunk/subversion/libsvn_subr/stream.c

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1562043&r1=1562042&r2=1562043&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Jan 28 11:37:00 2014
@@ -322,6 +322,11 @@ SVN_ERROR_START
              SVN_ERR_STREAM_CATEGORY_START + 3,
              "Stream doesn't support seeking")
 
+  /** Since New in 1.9. */
+  SVN_ERRDEF(SVN_ERR_STREAM_DATA_AVAILABLE_NOT_SUPPORTED,
+             SVN_ERR_STREAM_CATEGORY_START + 4,
+             "Stream doesn't support data available")
+
   /* node errors */
 
   SVN_ERRDEF(SVN_ERR_NODE_UNKNOWN_KIND,

Modified: subversion/trunk/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1562043&r1=1562042&r2=1562043&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_io.h (original)
+++ subversion/trunk/subversion/include/svn_io.h Tue Jan 28 11:37:00 2014
@@ -890,7 +890,16 @@ typedef svn_error_t *(*svn_stream_mark_f
  * @since New in 1.7.
  */
 typedef svn_error_t *(*svn_stream_seek_fn_t)(void *baton,
-                                         const svn_stream_mark_t *mark);
+                                             const svn_stream_mark_t *mark);
+
+/** Poll handler for generic streams that support incomplete reads, @see
+ * svn_stream_t and svn_stream_data_available().
+ *
+ * @since New in 1.9.
+ */
+typedef svn_error_t *
+            (*svn_stream_data_available_fn_t)(void *baton,
+                                              svn_boolean_t *data_available);
 
 /** Create a generic stream.  @see svn_stream_t. */
 svn_stream_t *
@@ -957,6 +966,14 @@ void
 svn_stream_set_seek(svn_stream_t *stream,
                     svn_stream_seek_fn_t seek_fn);
 
+/** Set @a stream's data available function to @a data_available_fn
+ *
+ * @since New in 1.9.
+ */
+void
+svn_stream_set_data_available(svn_stream_t *stream,
+                              svn_stream_data_available_fn_t data_available);
+
 /** Create a stream that is empty for reading and infinite for writing. */
 svn_stream_t *
 svn_stream_empty(apr_pool_t *pool);
@@ -1298,6 +1315,20 @@ svn_stream_mark(svn_stream_t *stream,
 svn_error_t *
 svn_stream_seek(svn_stream_t *stream, const svn_stream_mark_t *mark);
 
+/** When a stream supports polling for available data, obtain a boolean
+ * indicating whether data is waiting to be read. If the stream doesn't
+ * support polling this function returns a
+ * #SVN_ERR_STREAM_DATA_AVAILABLE_NOT_SUPPORTED error.
+ *
+ * If the data_available callback is implemented and the stream is at the end
+ * the stream will set @a *data_available to FALSE.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_stream_data_available(svn_stream_t *stream,
+                          svn_boolean_t *data_available);
+
 /** Return a writable stream which, when written to, writes to both of the
  * underlying streams.  Both of these streams will be closed upon closure of
  * the returned stream; use svn_stream_disown() if this is not the desired

Modified: subversion/trunk/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1562043&r1=1562042&r2=1562043&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/stream.c (original)
+++ subversion/trunk/subversion/libsvn_subr/stream.c Tue Jan 28 11:37:00 2014
@@ -29,6 +29,7 @@
 #include <apr_strings.h>
 #include <apr_file_io.h>
 #include <apr_errno.h>
+#include <apr_poll.h>
 #include <apr_portable.h>
 
 #include <zlib.h>
@@ -58,6 +59,7 @@ struct svn_stream_t {
   svn_close_fn_t close_fn;
   svn_stream_mark_fn_t mark_fn;
   svn_stream_seek_fn_t seek_fn;
+  svn_stream_data_available_fn_t data_available_fn;
   svn_stream__is_buffered_fn_t is_buffered_fn;
   apr_file_t *file; /* Maybe NULL */
 };
@@ -84,6 +86,7 @@ svn_stream_create(void *baton, apr_pool_
   stream->close_fn = NULL;
   stream->mark_fn = NULL;
   stream->seek_fn = NULL;
+  stream->data_available_fn = NULL;
   stream->is_buffered_fn = NULL;
   stream->file = NULL;
   return stream;
@@ -137,6 +140,13 @@ svn_stream_set_seek(svn_stream_t *stream
 }
 
 void
+svn_stream_set_data_available(svn_stream_t *stream,
+                              svn_stream_data_available_fn_t data_available_fn)
+{
+  stream->data_available_fn = data_available_fn;
+}
+
+void
 svn_stream__set_is_buffered(svn_stream_t *stream,
                             svn_stream__is_buffered_fn_t is_buffered_fn)
 {
@@ -209,6 +219,18 @@ svn_stream_seek(svn_stream_t *stream, co
   return svn_error_trace(stream->seek_fn(stream->baton, mark));
 }
 
+svn_error_t *
+svn_stream_data_available(svn_stream_t *stream,
+                          svn_boolean_t *data_available)
+{
+  if (stream->data_available_fn == NULL)
+    return svn_error_create(SVN_ERR_STREAM_DATA_AVAILABLE_NOT_SUPPORTED,
+                            NULL, NULL);
+
+  return svn_error_trace(stream->data_available_fn(stream->baton,
+                                                   data_available));
+}
+
 svn_boolean_t
 svn_stream__is_buffered(svn_stream_t *stream)
 {
@@ -726,6 +748,12 @@ seek_handler_disown(void *baton, const s
   return svn_error_trace(svn_stream_seek(baton, mark));
 }
 
+static svn_error_t *
+data_available_disown(void *baton, svn_boolean_t *data_available)
+{
+  return svn_error_trace(svn_stream_data_available(baton, data_available));
+}
+
 static svn_boolean_t
 is_buffered_handler_disown(void *baton)
 {
@@ -742,6 +770,7 @@ svn_stream_disown(svn_stream_t *stream, 
   svn_stream_set_write(s, write_handler_disown);
   svn_stream_set_mark(s, mark_handler_disown);
   svn_stream_set_seek(s, seek_handler_disown);
+  svn_stream_set_data_available(s, data_available_disown);
   svn_stream__set_is_buffered(s, is_buffered_handler_disown);
 
   return s;
@@ -879,6 +908,40 @@ seek_handler_apr(void *baton, const svn_
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+data_available_handler_apr(void *baton, svn_boolean_t *data_available)
+{
+  struct baton_apr *btn = baton;
+  apr_pollfd_t pfd;
+  apr_status_t status;
+  int n;
+
+  pfd.desc_type = APR_POLL_FILE;
+  pfd.desc.f = btn->file;
+  pfd.p = btn->pool;
+  pfd.reqevents = APR_POLLIN;
+
+  status = apr_poll(&pfd, 1, &n, 0);
+  svn_pool_clear(btn->pool);
+
+  if (status == APR_SUCCESS)
+    {
+      *data_available = (n > 0);
+      return SVN_NO_ERROR;
+    }
+  else if (APR_STATUS_IS_EOF(status))
+    {
+      *data_available = FALSE;
+      return SVN_NO_ERROR;
+    }
+  else
+    {
+      return svn_error_create(SVN_ERR_STREAM_DATA_AVAILABLE_NOT_SUPPORTED,
+                              svn_error_create(status, NULL, NULL),
+                              NULL);
+    }
+}
+
 static svn_boolean_t
 is_buffered_handler_apr(void *baton)
 {
@@ -960,6 +1023,7 @@ svn_stream_from_aprfile2(apr_file_t *fil
   svn_stream_set_skip(stream, skip_handler_apr);
   svn_stream_set_mark(stream, mark_handler_apr);
   svn_stream_set_seek(stream, seek_handler_apr);
+  svn_stream_set_data_available(stream, data_available_handler_apr);
   svn_stream__set_is_buffered(stream, is_buffered_handler_apr);
   stream->file = file;
 
@@ -1276,6 +1340,14 @@ write_handler_checksum(void *baton, cons
   return svn_error_trace(svn_stream_write(btn->proxy, buffer, len));
 }
 
+static svn_error_t *
+data_available_handler_checksum(void *baton, svn_boolean_t *data_available)
+{
+  struct checksum_stream_baton *btn = baton;
+
+  return svn_error_trace(svn_stream_data_available(btn->proxy,
+                                                   data_available));
+}
 
 static svn_error_t *
 close_handler_checksum(void *baton)
@@ -1340,6 +1412,7 @@ svn_stream_checksummed2(svn_stream_t *st
   s = svn_stream_create(baton, pool);
   svn_stream_set_read2(s, read_handler_checksum, read_full_handler_checksum);
   svn_stream_set_write(s, write_handler_checksum);
+  svn_stream_set_data_available(s, data_available_handler_checksum);
   svn_stream_set_close(s, close_handler_checksum);
   return s;
 }
@@ -1450,6 +1523,15 @@ seek_handler_stringbuf(void *baton, cons
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+data_available_handler_stringbuf(void *baton, svn_boolean_t *data_available)
+{
+  struct stringbuf_stream_baton *btn = baton;
+
+  *data_available = ((btn->str->len - btn->amt_read) > 0);
+  return SVN_NO_ERROR;
+}
+
 static svn_boolean_t
 is_buffered_handler_stringbuf(void *baton)
 {
@@ -1475,6 +1557,7 @@ svn_stream_from_stringbuf(svn_stringbuf_
   svn_stream_set_write(stream, write_handler_stringbuf);
   svn_stream_set_mark(stream, mark_handler_stringbuf);
   svn_stream_set_seek(stream, seek_handler_stringbuf);
+  svn_stream_set_data_available(stream, data_available_handler_stringbuf);
   svn_stream__set_is_buffered(stream, is_buffered_handler_stringbuf);
   return stream;
 }
@@ -1545,6 +1628,15 @@ skip_handler_string(void *baton, apr_siz
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+data_available_handler_string(void *baton, svn_boolean_t *data_available)
+{
+  struct string_stream_baton *btn = baton;
+
+  *data_available = ((btn->str->len - btn->amt_read) > 0);
+  return SVN_NO_ERROR;
+}
+
 static svn_boolean_t
 is_buffered_handler_string(void *baton)
 {
@@ -1569,6 +1661,7 @@ svn_stream_from_string(const svn_string_
   svn_stream_set_mark(stream, mark_handler_string);
   svn_stream_set_seek(stream, seek_handler_string);
   svn_stream_set_skip(stream, skip_handler_string);
+  svn_stream_set_data_available(stream, data_available_handler_string);
   svn_stream__set_is_buffered(stream, is_buffered_handler_string);
   return stream;
 }
@@ -1806,6 +1899,17 @@ seek_handler_lazyopen(void *baton,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+data_available_handler_lazyopen(void *baton,
+                                svn_boolean_t *data_available)
+{
+  lazyopen_baton_t *b = baton;
+
+  SVN_ERR(lazyopen_if_unopened(b));
+  return svn_error_trace(svn_stream_data_available(b->real_stream,
+                                                   data_available));
+}
+
 /* Implements svn_stream__is_buffered_fn_t */
 static svn_boolean_t
 is_buffered_lazyopen(void *baton)
@@ -1842,6 +1946,7 @@ svn_stream_lazyopen_create(svn_stream_la
   svn_stream_set_close(stream, close_handler_lazyopen);
   svn_stream_set_mark(stream, mark_handler_lazyopen);
   svn_stream_set_seek(stream, seek_handler_lazyopen);
+  svn_stream_set_data_available(stream, data_available_handler_lazyopen);
   svn_stream__set_is_buffered(stream, is_buffered_lazyopen);
 
   return stream;