Hi devs,
FSFS calculates and checks MD5 in rep_read_contents.
So, there is no reason so calculate it a second time in the
delta stream svn_fs_fs__get_file_delta_stream returns.
However, it gets calculated there "accidentally" and not
used later.
This patch adds a variant of svn_txdelta() that will not
calculate the checksum. It uses that new function in FSFS.
-- Stefan^2.
[[[
Eliminate superfluous checksum calculation when
reading deltas from FSFS.
* subversion/include/svn_delta.h
(svn_txdelta_unchecked): declare new function
* subversion/libsvn_delta/text_delta.c
add include for the _() nls macro
(txdelta_baton): extend commentary
(txdelta_no_digest, svn_txdelta_unchecked):
new functions
(svn_txdelta_send_stream): make sure to detect
cases where svn_txdelta_unchecked was used
but not appropriate
* subversion/libsvn_fs_fs/fs_fs.c
(svn_fs_fs__get_file_delta_stream): return
a non-checksumming stream.
patch by stefanfuhrmann < at > alice-dsl.de
]]]
Index: subversion/include/svn_delta.h
===================================================================
--- subversion/include/svn_delta.h (revision 930220)
+++ subversion/include/svn_delta.h (working copy)
@@ -353,7 +353,22 @@
svn_stream_t *target,
apr_pool_t *pool);
+/** Just like @ref svn_txdelta except that no checksum is being created.
+ * When calling @ref svn_txdelta_md5_digest with @a *stream, it will
+ * return @c NULL.
+ *
+ * Use this function only if the @a source stream comes from a trustworthy
+ * source as e.g. an in-process FS driver.
+ *
+ * @since New in 1.7.
+ */
+void
+svn_txdelta_unchecked(svn_txdelta_stream_t **stream,
+ svn_stream_t *source,
+ svn_stream_t *target,
+ apr_pool_t *pool);
+
/**
* Return a writable stream which, when fed target data, will send
* delta windows to @a handler/@a handler_baton which transform the
Index: subversion/libsvn_delta/text_delta.c
===================================================================
--- subversion/libsvn_delta/text_delta.c (revision 930220)
+++ subversion/libsvn_delta/text_delta.c (working copy)
@@ -32,6 +32,7 @@
#include "svn_io.h"
#include "svn_pools.h"
#include "svn_checksum.h"
+#include "svn_private_config.h"
#include "delta.h"
@@ -57,7 +58,7 @@
svn_filesize_t pos; /* Offset of next read in source file. */
char *buf; /* Buffer for input data. */
- svn_checksum_ctx_t *context; /* Context for computing the checksum. */
+ svn_checksum_ctx_t *context; /* Context for computing the checksum. May be NULL. */
svn_checksum_t *checksum; /* If non-NULL, the checksum of TARGET. */
apr_pool_t *result_pool; /* For results (e.g. checksum) */
@@ -368,6 +369,13 @@
}
+static const unsigned char *
+txdelta_no_digest(void *baton)
+{
+ return NULL;
+}
+
+
svn_error_t *
svn_txdelta_run(svn_stream_t *source,
svn_stream_t *target,
@@ -440,7 +448,26 @@
txdelta_md5_digest, pool);
}
+void
+svn_txdelta_unchecked(svn_txdelta_stream_t **stream,
+ svn_stream_t *source,
+ svn_stream_t *target,
+ apr_pool_t *pool)
+{
+ struct txdelta_baton *b = apr_pcalloc(pool, sizeof(*b));
+ b->source = source;
+ b->target = target;
+ b->more_source = TRUE;
+ b->more = TRUE;
+ b->buf = apr_palloc(pool, 2 * SVN_DELTA_WINDOW_SIZE);
+ b->result_pool = pool;
+
+ *stream = svn_txdelta_stream_create(b, txdelta_next_window,
+ txdelta_no_digest, pool);
+}
+
+
/* Functions for implementing a "target push" delta. */
@@ -814,7 +859,14 @@
{
const unsigned char *result_md5;
result_md5 = svn_txdelta_md5_digest(txstream);
- /* Since err is null, result_md5 "cannot" be null. */
+
+ /* Don't call this function for streams created with
+ svn_txdelta_unchecked. Or txdelta_md5_digest was
+ called prematurely. */
+ if (result_md5 == NULL)
+ return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("Unchecked or incomplete stream"));
+
memcpy(digest, result_md5, APR_MD5_DIGESTSIZE);
}
return err;
Index: subversion/libsvn_fs_fs/fs_fs.c
===================================================================
--- subversion/libsvn_fs_fs/fs_fs.c (revision 930220)
+++ subversion/libsvn_fs_fs/fs_fs.c (working copy)
@@ -3481,13 +3481,14 @@
SVN_ERR(svn_io_file_close(rep_state->file, pool));
}
- /* Read both fulltexts and construct a delta. */
+ /* Read both fulltexts and construct a delta. The checksum for stream_p
+ will not be used by the callers. Thus, don't calculate it. */
if (source)
SVN_ERR(read_representation(&source_stream, fs, source->data_rep, pool));
else
source_stream = svn_stream_empty(pool);
SVN_ERR(read_representation(&target_stream, fs, target->data_rep, pool));
- svn_txdelta(stream_p, source_stream, target_stream, pool);
+ svn_txdelta_unchecked(stream_p, source_stream, target_stream, pool);
return SVN_NO_ERROR;
}
Received on 2010-04-06 20:24:42 CEST