You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/09/20 21:02:59 UTC

svn commit: r1388163 - in /subversion/branches/10Gb/subversion: include/svn_delta.h libsvn_delta/svndiff.c

Author: stefan2
Date: Thu Sep 20 19:02:58 2012
New Revision: 1388163

URL: http://svn.apache.org/viewvc?rev=1388163&view=rev
Log:
On the 10Gb branch: Provide a variant of svn_txdelta_send_txstream
that takes a data buffer, diffs it against an empty stream and sends
the result to some output stream.

The key is that we don't create a copy of the input buffer but hand
it directly over to the output stream - plus some svndiff and window
header data. Compression is supported as well but is of curse much
slower.

* subversion/include/svn_delta.h
  (svn_txdelta_send_content): declare new API
* subversion/libsvn_delta/svndiff.c
  (svn_txdelta_send_content): implement new API

Modified:
    subversion/branches/10Gb/subversion/include/svn_delta.h
    subversion/branches/10Gb/subversion/libsvn_delta/svndiff.c

Modified: subversion/branches/10Gb/subversion/include/svn_delta.h
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/include/svn_delta.h?rev=1388163&r1=1388162&r2=1388163&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/include/svn_delta.h (original)
+++ subversion/branches/10Gb/subversion/include/svn_delta.h Thu Sep 20 19:02:58 2012
@@ -452,6 +452,20 @@ svn_txdelta_send_txstream(svn_txdelta_st
                           apr_pool_t *pool);
 
 
+/** Send the @a contents of length @a len as a txdelta against an empty
+ * source directly to the stream inside @a baton.  That baton is the one
+ * returned by svn_txdelta_to_svndiff3.
+ *
+ * All temporary allocation is performed in @a pool.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_txdelta_send_contents(const unsigned char *contents,
+                          apr_size_t len,
+                          void *diff_baton,
+                          apr_pool_t *pool);
+
 /** Prepare to apply a text delta.  @a source is a readable generic stream
  * yielding the source data, @a target is a writable generic stream to
  * write target data to, and allocation takes place in a sub-pool of
@@ -483,6 +497,7 @@ svn_txdelta_apply(svn_stream_t *source,
 
 
 
+
 /*** Producing and consuming svndiff-format text deltas.  ***/
 
 /** Prepare to produce an svndiff-format diff from text delta windows.

Modified: subversion/branches/10Gb/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_delta/svndiff.c?rev=1388163&r1=1388162&r2=1388163&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/10Gb/subversion/libsvn_delta/svndiff.c Thu Sep 20 19:02:58 2012
@@ -293,6 +293,89 @@ window_handler(svn_txdelta_window_t *win
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_txdelta_send_contents(const unsigned char *contents,
+                          apr_size_t len,
+                          void *diff_baton,
+                          apr_pool_t *pool)
+{
+  struct encoder_baton *eb = diff_baton;
+
+  /* frequently reused buffers */
+  svn_stringbuf_t *header = svn_stringbuf_create_empty(eb->pool);
+  svn_stringbuf_t *compressed_temp = svn_stringbuf_create_empty(eb->pool);
+  unsigned char ibuf[MAX_INSTRUCTION_LEN];
+
+  /* Write the stream header.  */
+  char svnver[4] = {'S','V','N','\0'};
+  apr_size_t ver_len = 4;
+  svnver[3] = eb->version;
+  SVN_ERR(svn_stream_write(eb->output, svnver, &ver_len));
+
+  /* send CONTENT as a series of max-sized windows */
+  while (len > 0)
+    {
+      const char *processed_chunk;
+      apr_size_t processed_size;
+
+      apr_size_t ip_len;
+      apr_size_t chunk_size = len < SVN_DELTA_WINDOW_SIZE
+                            ? len
+                            : SVN_DELTA_WINDOW_SIZE;
+
+      /* Encode the action code (svn_txdelta_new) and length.  */
+      if (chunk_size < (1 << 6))
+        {
+          ibuf[0] = chunk_size + (0x2 << 6);
+          ip_len = 1;
+        }
+      else
+        {
+          ibuf[0] = (0x2 << 6);
+          ip_len = encode_int(ibuf + 1, chunk_size) - ibuf;
+        }
+
+      /* Encode the delta window header (empty source view).  */
+      header->len = 0;
+      svn_stringbuf_appendbyte(header, '\0');   /* source view offset */
+      svn_stringbuf_appendbyte(header, '\0');   /* source view length */
+      append_encoded_int(header, chunk_size);   /* target view length */
+      svn_stringbuf_appendbyte(header, (char)ip_len);
+
+      /* compress the window content if required */
+      if (eb->version == 1)
+        {
+          compressed_temp->len = 0;
+          SVN_ERR(zlib_encode((const char*)contents, chunk_size,
+                              compressed_temp, eb->compression_level));
+          processed_chunk = compressed_temp->data;
+          processed_size = compressed_temp->len;
+        }
+      else
+        {
+          processed_chunk = (const char*)contents;
+          processed_size = chunk_size;
+        }
+      append_encoded_int(header, processed_size);
+
+      /* Write out the window.  */
+      SVN_ERR(svn_stream_write(eb->output, header->data, &header->len));
+      if (ip_len)
+        SVN_ERR(svn_stream_write(eb->output, (const char *)ibuf, &ip_len));
+      if (processed_size)
+        SVN_ERR(svn_stream_write(eb->output, processed_chunk, &processed_size));
+
+      /* next chunk */
+      contents += chunk_size;
+      len -= chunk_size;
+    }
+
+  /* We're done; clean up.
+   */
+  svn_pool_destroy(eb->pool);
+  return svn_stream_close(eb->output);
+}
+
 void
 svn_txdelta_to_svndiff3(svn_txdelta_window_handler_t *handler,
                         void **handler_baton,