Author: rhuijben
Date: Mon Jan 20 16:00:33 2014
New Revision: 1559758
URL: http://svn.apache.org/r1559758
Log:
For issue #4450 "Windows checkouts much slower then Unix" create a private api
around installing a file, to prepare for an optimized Windows implementation
that reduces a lot of disk IO delays during update and checkout.
* subversion/include/private/svn_io_private.h
(svn_stream__create_for_install): New function.
(svn_stream__install_stream): New function.
* subversion/libsvn_subr/stream.c
(install_baton_t): New struct.
(svn_stream__create_for_install): New function.
(svn_stream__install_stream): New function.
* subversion/libsvn_wc/workqueue.c
(includes): Add private/svn_io_private.h.
(run_file_install): Update caller.
Modified:
subversion/trunk/subversion/include/private/svn_io_private.h
subversion/trunk/subversion/libsvn_subr/stream.c
subversion/trunk/subversion/libsvn_wc/workqueue.c
Modified: subversion/trunk/subversion/include/private/svn_io_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_io_private.h?rev=1559758&r1=1559757&r2=1559758&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_io_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_io_private.h Mon Jan 20
16:00:33 2014
@@ -105,6 +105,29 @@ svn_stream__is_buffered(svn_stream_t *st
apr_file_t *
svn_stream__aprfile(svn_stream_t *stream);
+/* Creates as *INSTALL_STREAM a stream that once completed can be installed
+ using Windows checkouts much slower then Unix.
+
+ While writing the stream is temporarily stored in TMP_ABSPATH.
+ */
+svn_error_t *
+svn_stream__create_for_install(svn_stream_t **install_stream,
+ const char *tmp_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Installs a stream created with svn_stream__create_for_install in its final
+ location FINAL_ABSPATH, potentially using platform specific optimizations.
+
+ If MAKE_PARENTS is TRUE, this function will create missing parent
+ directories if needed.
+ */
+svn_error_t *
+svn_stream__install_stream(svn_stream_t *install_stream,
+ const char *final_abspath,
+ svn_boolean_t make_parents,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/trunk/subversion/libsvn_subr/stream.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1559758&r1=1559757&r2=1559758&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/stream.c (original)
+++ subversion/trunk/subversion/libsvn_subr/stream.c Mon Jan 20 16:00:33 2014
@@ -1860,3 +1860,78 @@ svn_stream_lazyopen_create(svn_stream_la
return stream;
}
+
+/* Baton for install streams */
+struct install_baton_t
+{
+ struct baton_apr baton_apr;
+ const char *tmp_path;
+};
+
+svn_error_t *
+svn_stream__create_for_install(svn_stream_t **install_stream,
+ const char *tmp_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_file_t *file;
+ struct install_baton_t *ib;
+ const char *tmp_path;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(tmp_abspath));
+
+ SVN_ERR(svn_io_open_unique_file3(&file, &tmp_path, tmp_abspath,
+ svn_io_file_del_none,
+ result_pool, scratch_pool));
+ *install_stream = svn_stream_from_aprfile2(file, FALSE, result_pool);
+
+ ib = apr_pcalloc(result_pool, sizeof(*ib));
+ ib->baton_apr = *(struct baton_apr*)(*install_stream)->baton;
+
+ assert((void*)&ib->baton_apr == (void*)ib);
+
+ (*install_stream)->baton = ib;
+
+ ib->tmp_path = tmp_path;
+
+ /* ### Install pool cleanup handler for tempfile? */
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_stream__install_stream(svn_stream_t *install_stream,
+ const char *final_abspath,
+ svn_boolean_t make_parents,
+ apr_pool_t *scratch_pool)
+{
+ struct install_baton_t *ib = install_stream->baton;
+ svn_error_t *err;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(final_abspath));
+
+ err = svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool);
+
+ /* A missing directory is too common to not cover here. */
+ if (make_parents && err && APR_STATUS_IS_ENOENT(err->apr_err))
+ {
+ svn_error_t *err2;
+
+ err2 = svn_io_make_dir_recursively(svn_dirent_dirname(final_abspath,
+ scratch_pool),
+ scratch_pool);
+
+ if (err2)
+ /* Creating directory didn't work: Return all errors */
+ return svn_error_trace(svn_error_compose_create(err, err2));
+ else
+ /* We could create a directory: retry install */
+ svn_error_clear(err);
+
+ SVN_ERR(svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool));
+ }
+ else
+ SVN_ERR(err);
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=1559758&r1=1559757&r2=1559758&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Mon Jan 20 16:00:33 2014
@@ -38,6 +38,7 @@
#include "conflicts.h"
#include "translate.h"
+#include "private/svn_io_private.h"
#include "private/svn_skel.h"
@@ -469,7 +470,6 @@ run_file_install(work_item_baton_t *wqb,
apr_hash_t *keywords;
const char *temp_dir_abspath;
svn_stream_t *dst_stream;
- const char *dst_abspath;
apr_int64_t val;
const char *wcroot_abspath;
const char *source_abspath;
@@ -572,10 +572,8 @@ run_file_install(work_item_baton_t *wqb,
/* Translate to a temporary file. We don't want the user seeing a partial
file, nor let them muck with it while we translate. We may also need to
get its TRANSLATED_SIZE before the user can monkey it. */
- SVN_ERR(svn_stream_open_unique(&dst_stream, &dst_abspath,
- temp_dir_abspath,
- svn_io_file_del_none,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream__create_for_install(&dst_stream, temp_dir_abspath,
+ scratch_pool, scratch_pool));
/* Copy from the source to the dest, translating as we go. This will also
close both streams. */
@@ -584,35 +582,11 @@ run_file_install(work_item_baton_t *wqb,
scratch_pool));
/* All done. Move the file into place. */
-
- {
- svn_error_t *err;
-
- err = svn_io_file_rename(dst_abspath, local_abspath, scratch_pool);
-
- /* With a single db we might want to install files in a missing directory.
- Simply trying this scenario on error won't do any harm and at least
- one user reported this problem on IRC. */
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- svn_error_t *err2;
-
- err2 = svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
- scratch_pool),
- scratch_pool);
-
- if (err2)
- /* Creating directory didn't work: Return all errors */
- return svn_error_trace(svn_error_compose_create(err, err2));
- else
- /* We could create a directory: retry install */
- svn_error_clear(err);
-
- SVN_ERR(svn_io_file_rename(dst_abspath, local_abspath, scratch_pool));
- }
- else
- SVN_ERR(err);
- }
+ /* With a single db we might want to install files in a missing directory.
+ Simply trying this scenario on error won't do any harm and at least
+ one user reported this problem on IRC. */
+ SVN_ERR(svn_stream__install_stream(dst_stream, local_abspath,
+ TRUE /* make_parents*/, scratch_pool));
/* Tweak the on-disk file according to its properties. */
#ifndef WIN32