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 2014/03/03 23:58:29 UTC
svn commit: r1573794 -
/subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
Author: kotkov
Date: Mon Mar 3 22:58:28 2014
New Revision: 1573794
URL: http://svn.apache.org/r1573794
Log:
Tweak the get_root_changes_offset() routine in order to fix the problems I
identified in http://svn.haxx.se/dev/archive-2014-02/0189.shtml
This changeset fixes the following issues in its implementation:
- It avoids seeking to a negative offset for the scenarios when the revision
file is smaller than buffer.
- It avoids touching internal svn_stringbuf_t fields (such as DATA and LEN)
and achieves the wanted behavior using the stringbuf API only.
- We no longer rely on the allocator-specific BLOCKSIZE when determining the
buffer size for the trailer. In a theoretical case where the allocator
allocates huge 2KiB blocks for every stringbuf, we would fail to parse the
trailer for smaller (< 2KiB) revision files.
- It uses svn_io_file_read_full2() instead of svn_io_file_read() when reading
the file block with the revision trailer. svn_io_file_read(), as opposed
to svn_io_file_read_full2(), can read any number of bytes <= NBYTES before
exiting. This essentially means we would fail to parse the revision
trailer in all scenarios where this function returns without filling
the buffer.
* subversion/libsvn_fs_fs/cached_data.c
(get_root_changes_offset): Create the stringbuf around a stack-allocated
BUFFER. Do that only when the buffer is filled (thus avoiding the
necessity to touch the internal stringbuf fields, i.e. DATA, LEN and
BLOCKSIZE). Handle the possibility of revision files being smaller than
the expected trailer block size (64 bytes). Do not attempt seeking to
negative file offsets in that case. Finally, use svn_io_file_read_full2()
instead of svn_io_file_read() when reading the file contents.
Modified:
subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
Modified: subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/cached_data.c?rev=1573794&r1=1573793&r2=1573794&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/cached_data.c Mon Mar 3 22:58:28 2014
@@ -462,10 +462,13 @@ get_root_changes_offset(apr_off_t *root_
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- apr_off_t offset;
apr_off_t rev_offset;
apr_seek_where_t seek_relative;
- svn_stringbuf_t *trailer = svn_stringbuf_create_ensure(64, pool);
+ svn_stringbuf_t *trailer;
+ char buffer[64];
+ apr_off_t start;
+ apr_off_t end;
+ apr_size_t len;
/* Determine where to seek to in the file.
@@ -479,13 +482,13 @@ get_root_changes_offset(apr_off_t *root_
if (svn_fs_fs__is_packed_rev(fs, rev)
&& ((rev + 1) % ffd->max_files_per_dir != 0))
{
- SVN_ERR(svn_fs_fs__get_packed_offset(&offset, fs, rev + 1, pool));
+ SVN_ERR(svn_fs_fs__get_packed_offset(&end, fs, rev + 1, pool));
seek_relative = APR_SET;
}
else
{
seek_relative = APR_END;
- offset = 0;
+ end = 0;
}
/* Offset of the revision from the start of the pack file, if applicable. */
@@ -496,16 +499,25 @@ get_root_changes_offset(apr_off_t *root_
/* We will assume that the last line containing the two offsets
will never be longer than 64 characters. */
- SVN_ERR(svn_io_file_seek(rev_file, seek_relative, &offset, pool));
+ SVN_ERR(svn_io_file_seek(rev_file, seek_relative, &end, pool));
- trailer->len = trailer->blocksize-1;
- SVN_ERR(aligned_seek(fs, rev_file, NULL, offset - trailer->len, pool));
+ if (end < sizeof(buffer))
+ {
+ len = (apr_size_t)end;
+ start = 0;
+ }
+ else
+ {
+ len = sizeof(buffer);
+ start = end - sizeof(buffer);
+ }
/* Read in this last block, from which we will identify the last line. */
- SVN_ERR(svn_io_file_read(rev_file, trailer->data, &trailer->len, pool));
- trailer->data[trailer->len] = 0;
+ SVN_ERR(aligned_seek(fs, rev_file, NULL, start, pool));
+ SVN_ERR(svn_io_file_read_full2(rev_file, buffer, len, NULL, NULL, pool));
/* Parse the last line. */
+ trailer = svn_stringbuf_ncreate(buffer, len, pool);
SVN_ERR(svn_fs_fs__parse_revision_trailer(root_offset,
changes_offset,
trailer,