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:45:23 UTC

svn commit: r1804811 - /subversion/trunk/subversion/libsvn_client/import.c

Author: kotkov
Date: Fri Aug 11 15:45:23 2017
New Revision: 1804811

URL: http://svn.apache.org/viewvc?rev=1804811&view=rev
Log:
Stream svndiff deltas without creating temporary files during 'svn import'
over HTTP.

Creating the temporary files has a certain overhead (time to write them
and disk space), but what is more important, it prevents the client and
server from simultaneously processing the data, i.e., checksumming and
compressing it.

This is an alternative solution that involves using resettable streams.
The original and more complex solution was implemented in r1803144, see
its log message for more details on why do we start streaming deltas.

* subversion/libsvn_client/import.c
  (open_txdelta_stream_baton_t): New.
  (open_txdelta_stream): New, implements svn_txdelta_stream_open_func_t.
   Note that this function must be restartable, as it can be called
   more than once, for example, if the HTTP server decides to do a
   renegotiation, and we would be forced to resend the whole request
   body.  If this is the case, we reset the stream and continue.
  (send_file_contents): Use the new apply_textdelta_stream() delta
   editor callback.  Calculate the MD5 checksum with the help of
   svn_stream_checksummed2() stream instead of using svn_txdelta2()
   for this purpose.  Pass the disowned stream to the open txdelta
   callback, and explicitly close the stream in this function (to
   finalize the checksum).
  (import_file): Update, according to the changes in send_file_contents().

Modified:
    subversion/trunk/subversion/libsvn_client/import.c

Modified: subversion/trunk/subversion/libsvn_client/import.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/import.c?rev=1804811&r1=1804810&r2=1804811&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/import.c (original)
+++ subversion/trunk/subversion/libsvn_client/import.c Fri Aug 11 15:45:23 2017
@@ -73,32 +73,59 @@ typedef struct import_ctx_t
   apr_hash_t *autoprops;
 } import_ctx_t;
 
+typedef struct open_txdelta_stream_baton_t
+{
+  svn_boolean_t need_reset;
+  svn_stream_t *stream;
+} open_txdelta_stream_baton_t;
+
+/* Implements svn_txdelta_stream_open_func_t */
+static svn_error_t *
+open_txdelta_stream(svn_txdelta_stream_t **txdelta_stream_p,
+                    void *baton,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  open_txdelta_stream_baton_t *b = baton;
+
+  if (b->need_reset)
+    {
+      /* Under rare circumstances, we can be restarted and would need to
+       * supply the delta stream again.  In this case, reset the base
+       * stream. */
+      SVN_ERR(svn_stream_reset(b->stream));
+    }
+
+  /* Get the delta stream (delta against the empty string). */
+  svn_txdelta2(txdelta_stream_p, svn_stream_empty(result_pool),
+               b->stream, FALSE, result_pool);
+  b->need_reset = TRUE;
+  return SVN_NO_ERROR;
+}
 
 /* Apply LOCAL_ABSPATH's contents (as a delta against the empty string) to
    FILE_BATON in EDITOR.  Use POOL for any temporary allocation.
    PROPERTIES is the set of node properties set on this file.
 
-   Fill DIGEST with the md5 checksum of the sent file; DIGEST must be
-   at least APR_MD5_DIGESTSIZE bytes long. */
+   Return the resulting checksum in *RESULT_MD5_CHECKSUM_P. */
 
 /* ### how does this compare against svn_wc_transmit_text_deltas2() ??? */
 
 static svn_error_t *
-send_file_contents(const char *local_abspath,
+send_file_contents(svn_checksum_t **result_md5_checksum_p,
+                   const char *local_abspath,
                    void *file_baton,
                    const svn_delta_editor_t *editor,
                    apr_hash_t *properties,
-                   unsigned char *digest,
                    apr_pool_t *pool)
 {
   svn_stream_t *contents;
-  svn_txdelta_window_handler_t handler;
-  void *handler_baton;
   const svn_string_t *eol_style_val = NULL, *keywords_val = NULL;
   svn_boolean_t special = FALSE;
   svn_subst_eol_style_t eol_style;
   const char *eol;
   apr_hash_t *keywords;
+  open_txdelta_stream_baton_t baton = { 0 };
 
   /* If there are properties, look for EOL-style and keywords ones. */
   if (properties)
@@ -111,10 +138,6 @@ send_file_contents(const char *local_abs
         special = TRUE;
     }
 
-  /* Get an editor func that wants to consume the delta stream. */
-  SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool,
-                                  &handler, &handler_baton));
-
   if (eol_style_val)
     svn_subst_eol_style_from_value(&eol_style, &eol, eol_style_val->data);
   else
@@ -168,10 +191,17 @@ send_file_contents(const char *local_abs
         }
     }
 
-  /* Send the file's contents to the delta-window handler. */
-  return svn_error_trace(svn_txdelta_send_stream(contents, handler,
-                                                 handler_baton, digest,
-                                                 pool));
+  /* Arrange the stream to calculate the resulting MD5. */
+  contents = svn_stream_checksummed2(contents, result_md5_checksum_p, NULL,
+                                     svn_checksum_md5, TRUE, pool);
+  /* Send the contents. */
+  baton.need_reset = FALSE;
+  baton.stream = svn_stream_disown(contents, pool);
+  SVN_ERR(editor->apply_textdelta_stream(editor, file_baton, NULL,
+                                         open_txdelta_stream, &baton, pool));
+  SVN_ERR(svn_stream_close(contents));
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -198,7 +228,7 @@ import_file(const svn_delta_editor_t *ed
 {
   void *file_baton;
   const char *mimetype = NULL;
-  unsigned char digest[APR_MD5_DIGESTSIZE];
+  svn_checksum_t *result_md5_checksum;
   const char *text_checksum;
   apr_hash_t* properties;
   apr_hash_index_t *hi;
@@ -262,13 +292,11 @@ import_file(const svn_delta_editor_t *ed
     }
 
   /* Now, transmit the file contents. */
-  SVN_ERR(send_file_contents(local_abspath, file_baton, editor,
-                             properties, digest, pool));
+  SVN_ERR(send_file_contents(&result_md5_checksum, local_abspath,
+                             file_baton, editor, properties, pool));
 
   /* Finally, close the file. */
-  text_checksum =
-    svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
-
+  text_checksum = svn_checksum_to_cstring(result_md5_checksum, pool);
   return svn_error_trace(editor->close_file(file_baton, text_checksum, pool));
 }