You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ko...@apache.org on 2017/08/11 15:31:42 UTC

svn commit: r1804807 - in /subversion/trunk/subversion: include/svn_checksum.h include/svn_io.h libsvn_subr/checksum.c libsvn_subr/fnv1a.c libsvn_subr/fnv1a.h libsvn_subr/stream.c tests/libsvn_subr/checksum-test.c

Author: kotkov
Date: Fri Aug 11 15:31:42 2017
New Revision: 1804807

URL: http://svn.apache.org/viewvc?rev=1804807&view=rev
Log:
Return resettable streams from svn_stream_checksummed2().

This lays the groundwork required to stream commits over HTTP without
creating temporary files.  To switch to the new apply_textdelta_stream()
delta editor callback, we need to make the callback that opens a txdelta
stream restartable, and this is where a resettable checksummed stream
would be handy to have.

Please note that currently the ability to reset a stream, and the new
associated svn_stream_supports_reset() API is tied to the existence of
a non-default seek_fn implementation.  The implementation is free to
_only_ support seek_fn(NULL) requests.  It would probably be slightly
better to have a separate reset_fn callback.  However, we already had it
at some point, and then reverted it in r966156, so let's keep everything
without a separate callback and keep using seek_fn(NULL) for now.

* subversion/include/svn_io.h
  (svn_stream_checksummed2): Note that now this API returns a
   resettable stream.
  (svn_stream_supports_reset): Declare this new function.

* subversion/include/svn_checksum.h
  (svn_checksum_ctx_reset): Declare this new function.

* subversion/libsvn_subr/checksum.c
  (svn_checksum_ctx_reset): Implement this new function.  Forward FNV1-a
   implementations to ...

* subversion/libsvn_subr/fnv1a.h
  (svn_fnv1a_32__context_reset, svn_fnv1a_32x4__context_reset): ...

* subversion/libsvn_subr/fnv1a.c
  (svn_fnv1a_32__context_reset, svn_fnv1a_32x4__context_reset): ...these
   new helper functions.

* subversion/libsvn_subr/stream.c
  (svn_stream_supports_reset): Implement this new function.
  (seek_handler_checksum): Implement the seek handler for checksummed
   streams, only support reset requests for now.
  (svn_stream_checksummed2): Optionally install the new seek handler.

* subversion/tests/libsvn_subr/checksum-test.c
  (test_checksummed_stream_read,
   test_checksummed_stream_reset): New tests.
  (test_funcs): Add new tests.

Modified:
    subversion/trunk/subversion/include/svn_checksum.h
    subversion/trunk/subversion/include/svn_io.h
    subversion/trunk/subversion/libsvn_subr/checksum.c
    subversion/trunk/subversion/libsvn_subr/fnv1a.c
    subversion/trunk/subversion/libsvn_subr/fnv1a.h
    subversion/trunk/subversion/libsvn_subr/stream.c
    subversion/trunk/subversion/tests/libsvn_subr/checksum-test.c

Modified: subversion/trunk/subversion/include/svn_checksum.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_checksum.h?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_checksum.h (original)
+++ subversion/trunk/subversion/include/svn_checksum.h Fri Aug 11 15:31:42 2017
@@ -223,6 +223,15 @@ svn_checksum_ctx_create(svn_checksum_kin
                         apr_pool_t *pool);
 
 /**
+ * Reset an existing checksum @a ctx to initial state.
+ * @see svn_checksum_ctx_create()
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx);
+
+/**
  * Update the checksum represented by @a ctx, with @a len bytes starting at
  * @a data.
  *

Modified: subversion/trunk/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_io.h (original)
+++ subversion/trunk/subversion/include/svn_io.h Fri Aug 11 15:31:42 2017
@@ -1248,7 +1248,8 @@ svn_stream_compressed(svn_stream_t *stre
  * The @a stream passed into this function is closed when the created
  * stream is closed.
  *
- * @since New in 1.6.
+ * @since New in 1.6.  Since 1.10, the resulting stream supports reset
+ * via stream_stream_reset().
  */
 svn_stream_t *
 svn_stream_checksummed2(svn_stream_t *stream,
@@ -1384,6 +1385,14 @@ svn_stream_reset(svn_stream_t *stream);
 svn_boolean_t
 svn_stream_supports_mark(svn_stream_t *stream);
 
+/** Returns @c TRUE if the generic @a stream supports svn_stream_reset().
+ *
+ * @see svn_stream_reset()
+ * @since New in 1.10.
+ */
+svn_boolean_t
+svn_stream_supports_reset(svn_stream_t *stream);
+
 /** Set a @a mark at the current position of a generic @a stream,
  * which can later be sought back to using svn_stream_seek().
  * The @a mark is allocated in @a pool.

Modified: subversion/trunk/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/checksum.c?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/checksum.c (original)
+++ subversion/trunk/subversion/libsvn_subr/checksum.c Fri Aug 11 15:31:42 2017
@@ -570,6 +570,36 @@ svn_checksum_ctx_create(svn_checksum_kin
 }
 
 svn_error_t *
+svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx)
+{
+  switch (ctx->kind)
+    {
+      case svn_checksum_md5:
+        memset(ctx->apr_ctx, 0, sizeof(apr_md5_ctx_t));
+        apr_md5_init(ctx->apr_ctx);
+        break;
+
+      case svn_checksum_sha1:
+        memset(ctx->apr_ctx, 0, sizeof(apr_sha1_ctx_t));
+        apr_sha1_init(ctx->apr_ctx);
+        break;
+
+      case svn_checksum_fnv1a_32:
+        svn_fnv1a_32__context_reset(ctx->apr_ctx);
+        break;
+
+      case svn_checksum_fnv1a_32x4:
+        svn_fnv1a_32x4__context_reset(ctx->apr_ctx);
+        break;
+
+      default:
+        SVN_ERR_MALFUNCTION();
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_checksum_update(svn_checksum_ctx_t *ctx,
                     const void *data,
                     apr_size_t len)

Modified: subversion/trunk/subversion/libsvn_subr/fnv1a.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/fnv1a.c?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/fnv1a.c (original)
+++ subversion/trunk/subversion/libsvn_subr/fnv1a.c Fri Aug 11 15:31:42 2017
@@ -166,6 +166,12 @@ svn_fnv1a_32__context_create(apr_pool_t
 }
 
 void
+svn_fnv1a_32__context_reset(svn_fnv1a_32__context_t *context)
+{
+  context->hash = FNV1_BASE_32;
+}
+
+void
 svn_fnv1a_32__update(svn_fnv1a_32__context_t *context,
                      const void *data,
                      apr_size_t len)
@@ -203,6 +209,17 @@ svn_fnv1a_32x4__context_create(apr_pool_
 }
 
 void
+svn_fnv1a_32x4__context_reset(svn_fnv1a_32x4__context_t *context)
+{
+  context->hashes[0] = FNV1_BASE_32;
+  context->hashes[1] = FNV1_BASE_32;
+  context->hashes[2] = FNV1_BASE_32;
+  context->hashes[3] = FNV1_BASE_32;
+
+  context->buffered = 0;
+}
+
+void
 svn_fnv1a_32x4__update(svn_fnv1a_32x4__context_t *context,
                        const void *data,
                        apr_size_t len)

Modified: subversion/trunk/subversion/libsvn_subr/fnv1a.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/fnv1a.h?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/fnv1a.h (original)
+++ subversion/trunk/subversion/libsvn_subr/fnv1a.h Fri Aug 11 15:31:42 2017
@@ -41,6 +41,11 @@ typedef struct svn_fnv1a_32__context_t s
 svn_fnv1a_32__context_t *
 svn_fnv1a_32__context_create(apr_pool_t *pool);
 
+/* Reset the FNV-1a checksum CONTEXT to initial state.
+ */
+void
+svn_fnv1a_32__context_reset(svn_fnv1a_32__context_t *context);
+
 /* Feed LEN bytes from DATA into the FNV-1a checksum creation CONTEXT.
  */
 void
@@ -63,6 +68,11 @@ typedef struct svn_fnv1a_32x4__context_t
 svn_fnv1a_32x4__context_t *
 svn_fnv1a_32x4__context_create(apr_pool_t *pool);
 
+/* Reset the modified FNV-1a checksum CONTEXT to initial state.
+ */
+void
+svn_fnv1a_32x4__context_reset(svn_fnv1a_32x4__context_t *context);
+
 /* Feed LEN bytes from DATA into the modified FNV-1a checksum creation
  * CONTEXT.
  */

Modified: subversion/trunk/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/stream.c (original)
+++ subversion/trunk/subversion/libsvn_subr/stream.c Fri Aug 11 15:31:42 2017
@@ -235,6 +235,12 @@ svn_stream_supports_mark(svn_stream_t *s
   return stream->mark_fn != NULL;
 }
 
+svn_boolean_t
+svn_stream_supports_reset(svn_stream_t *stream)
+{
+  return stream->seek_fn != NULL;
+}
+
 svn_error_t *
 svn_stream_mark(svn_stream_t *stream, svn_stream_mark_t **mark,
                 apr_pool_t *pool)
@@ -1427,6 +1433,31 @@ close_handler_checksum(void *baton)
   return svn_error_trace(svn_stream_close(btn->proxy));
 }
 
+static svn_error_t *
+seek_handler_checksum(void *baton, const svn_stream_mark_t *mark)
+{
+  struct checksum_stream_baton *btn = baton;
+
+  /* Only reset support. */
+  if (mark)
+    {
+      return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED,
+                              NULL, NULL);
+    }
+  else
+    {
+      if (btn->read_ctx)
+        svn_checksum_ctx_reset(btn->read_ctx);
+
+      if (btn->write_ctx)
+        svn_checksum_ctx_reset(btn->write_ctx);
+
+      SVN_ERR(svn_stream_reset(btn->proxy));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 svn_stream_t *
 svn_stream_checksummed2(svn_stream_t *stream,
@@ -1464,6 +1495,8 @@ svn_stream_checksummed2(svn_stream_t *st
   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);
+  if (svn_stream_supports_reset(stream))
+    svn_stream_set_seek(s, seek_handler_checksum);
   return s;
 }
 

Modified: subversion/trunk/subversion/tests/libsvn_subr/checksum-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/checksum-test.c?rev=1804807&r1=1804806&r2=1804807&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/checksum-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/checksum-test.c Fri Aug 11 15:31:42 2017
@@ -296,6 +296,74 @@ test_checksum_parse_all_zero(apr_pool_t
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_checksummed_stream_read(apr_pool_t *pool)
+{
+  const svn_string_t *str = svn_string_create("abcde", pool);
+  svn_checksum_kind_t kind;
+
+  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+    {
+      svn_stream_t *stream;
+      svn_checksum_t *expected_checksum;
+      svn_checksum_t *actual_checksum;
+      char buf[64];
+      apr_size_t len;
+
+      stream = svn_stream_from_string(str, pool);
+      stream = svn_stream_checksummed2(stream, &actual_checksum, NULL,
+                                       kind, TRUE, pool);
+      len = str->len;
+      SVN_ERR(svn_stream_read_full(stream, buf, &len));
+      SVN_TEST_INT_ASSERT((int) len, str->len);
+
+      SVN_ERR(svn_stream_close(stream));
+
+      SVN_ERR(svn_checksum(&expected_checksum, kind,
+                           str->data, str->len, pool));
+      SVN_TEST_ASSERT(svn_checksum_match(expected_checksum, actual_checksum));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_checksummed_stream_reset(apr_pool_t *pool)
+{
+  const svn_string_t *str = svn_string_create("abcde", pool);
+  svn_checksum_kind_t kind;
+
+  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+    {
+      svn_stream_t *stream;
+      svn_checksum_t *expected_checksum;
+      svn_checksum_t *actual_checksum;
+      char buf[64];
+      apr_size_t len;
+
+      stream = svn_stream_from_string(str, pool);
+      stream = svn_stream_checksummed2(stream, &actual_checksum, NULL,
+                                       kind, TRUE, pool);
+      len = str->len;
+      SVN_ERR(svn_stream_read_full(stream, buf, &len));
+      SVN_TEST_INT_ASSERT((int) len, str->len);
+
+      SVN_ERR(svn_stream_reset(stream));
+
+      len = str->len;
+      SVN_ERR(svn_stream_read_full(stream, buf, &len));
+      SVN_TEST_INT_ASSERT((int) len, str->len);
+
+      SVN_ERR(svn_stream_close(stream));
+
+      SVN_ERR(svn_checksum(&expected_checksum, kind,
+                           str->data, str->len, pool));
+      SVN_TEST_ASSERT(svn_checksum_match(expected_checksum, actual_checksum));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* An array of all test functions */
 
 static int max_threads = 1;
@@ -317,6 +385,10 @@ static struct svn_test_descriptor_t test
                    "checksum (de-)serialization"),
     SVN_TEST_PASS2(test_checksum_parse_all_zero,
                    "checksum parse all zero"),
+    SVN_TEST_PASS2(test_checksummed_stream_read,
+                   "read from checksummed stream"),
+    SVN_TEST_PASS2(test_checksummed_stream_reset,
+                   "reset checksummed stream"),
     SVN_TEST_NULL
   };