Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_fs_fs/fs_fs.c view on Meta::CPAN
/* read contents of the current pack file */
SVN_ERR(read_pack_revprop(&revprops, fs, rev, generation, pool));
/* serialize the new revprops */
serialized = svn_stringbuf_create_empty(pool);
stream = svn_stream_from_stringbuf(serialized, pool);
SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, pool));
SVN_ERR(svn_stream_close(stream));
/* calculate the size of the new data */
changed_index = (int)(rev - revprops->start_revision);
new_total_size = revprops->total_size - revprops->serialized_size
+ serialized->len
+ (revprops->offsets->nelts + 2) * SVN_INT64_BUFFER_SIZE;
APR_ARRAY_IDX(revprops->sizes, changed_index, apr_off_t) = serialized->len;
/* can we put the new data into the same pack as the before? */
if ( new_total_size < ffd->revprop_pack_size
|| revprops->sizes->nelts == 1)
{
/* simply replace the old pack file with new content as we do it
* in the non-packed case */
*final_path = svn_dirent_join(revprops->folder, revprops->filename,
pool);
SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts,
changed_index, serialized, new_total_size,
stream, pool));
}
else
{
/* split the pack file into two of roughly equal size */
int right_count, left_count, i;
int left = 0;
int right = revprops->sizes->nelts - 1;
apr_off_t left_size = 2 * SVN_INT64_BUFFER_SIZE;
apr_off_t right_size = 2 * SVN_INT64_BUFFER_SIZE;
/* let left and right side grow such that their size difference
* is minimal after each step. */
while (left <= right)
if ( left_size + APR_ARRAY_IDX(revprops->sizes, left, apr_off_t)
< right_size + APR_ARRAY_IDX(revprops->sizes, right, apr_off_t))
{
left_size += APR_ARRAY_IDX(revprops->sizes, left, apr_off_t)
+ SVN_INT64_BUFFER_SIZE;
++left;
}
else
{
right_size += APR_ARRAY_IDX(revprops->sizes, right, apr_off_t)
+ SVN_INT64_BUFFER_SIZE;
--right;
}
/* since the items need much less than SVN_INT64_BUFFER_SIZE
* bytes to represent their length, the split may not be optimal */
left_count = left;
right_count = revprops->sizes->nelts - left;
/* if new_size is large, one side may exceed the pack size limit.
* In that case, split before and after the modified revprop.*/
if ( left_size > ffd->revprop_pack_size
|| right_size > ffd->revprop_pack_size)
{
left_count = changed_index;
right_count = revprops->sizes->nelts - left_count - 1;
}
/* write the new, split files */
if (left_count)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops, 0,
left_count, files_to_delete, pool));
SVN_ERR(repack_revprops(fs, revprops, 0, left_count,
changed_index, serialized, new_total_size,
stream, pool));
}
if (left_count + right_count < revprops->sizes->nelts)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index,
changed_index + 1, files_to_delete,
pool));
SVN_ERR(repack_revprops(fs, revprops, changed_index,
changed_index + 1,
changed_index, serialized, new_total_size,
stream, pool));
}
if (right_count)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops,
revprops->sizes->nelts - right_count,
revprops->sizes->nelts,
files_to_delete, pool));
SVN_ERR(repack_revprops(fs, revprops,
revprops->sizes->nelts - right_count,
revprops->sizes->nelts, changed_index,
serialized, new_total_size, stream,
pool));
}
/* write the new manifest */
*final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, pool);
SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
for (i = 0; i < revprops->manifest->nelts; ++i)
{
const char *filename = APR_ARRAY_IDX(revprops->manifest, i,
const char*);
SVN_ERR(svn_stream_printf(stream, pool, "%s\n", filename));
}
SVN_ERR(svn_stream_close(stream));
}
( run in 1.248 second using v1.01-cache-2.11-cpan-39bf76dae61 )