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; }