You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/05/26 10:57:34 UTC

svn commit: r1681721 [1/3] - in /subversion/branches/move-tracking-2: ./ subversion/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_x/ subversion/libsvn_subr/ subversion/libsvn_wc...

Author: julianfoad
Date: Tue May 26 08:57:33 2015
New Revision: 1681721

URL: http://svn.apache.org/r1681721
Log:
On the 'move-tracking-2' branch: catch up to trunk@1681720.

Removed:
    subversion/branches/move-tracking-2/subversion/include/private/svn_pseudo_md5.h
    subversion/branches/move-tracking-2/subversion/libsvn_subr/pseudo_md5.c
Modified:
    subversion/branches/move-tracking-2/   (props changed)
    subversion/branches/move-tracking-2/subversion/   (props changed)
    subversion/branches/move-tracking-2/subversion/include/private/svn_cmdline_private.h
    subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
    subversion/branches/move-tracking-2/subversion/include/svn_error.h
    subversion/branches/move-tracking-2/subversion/include/svn_fs.h
    subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.h
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/recovery.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache-db.sql
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.h
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rev_file.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_x/   (props changed)
    subversion/branches/move-tracking-2/subversion/libsvn_fs_x/fs.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache-db.sql
    subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.h
    subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/checksum.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/cmdline.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/config_file.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/fnv1a.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/fnv1a.h
    subversion/branches/move-tracking-2/subversion/libsvn_wc/externals.c
    subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c
    subversion/branches/move-tracking-2/subversion/svn/svn.c
    subversion/branches/move-tracking-2/subversion/svnbench/svnbench.c
    subversion/branches/move-tracking-2/subversion/svnmucc/svnmucc.c
    subversion/branches/move-tracking-2/subversion/svnrdump/svnrdump.c
    subversion/branches/move-tracking-2/subversion/svnsync/svnsync.c
    subversion/branches/move-tracking-2/subversion/tests/cmdline/basic_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--help_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version--quiet_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version--quiet_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help--version_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help--version_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_bogus-cmd_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_bogus-cmd_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout   (contents, props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_stderr   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/getopt_tests_data/svn_stdout   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/cmdline/lock_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmucc_tests.py
    subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/   (props changed)
    subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-sequential-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/cache-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/checksum-test.c
    subversion/branches/move-tracking-2/subversion/tests/svn_test_fs.c
    subversion/branches/move-tracking-2/subversion/tests/svn_test_main.c
    subversion/branches/move-tracking-2/tools/   (props changed)
    subversion/branches/move-tracking-2/tools/client-side/bash_completion

Propchange: subversion/branches/move-tracking-2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue May 26 08:57:33 2015
@@ -1,5 +1,7 @@
+/subversion/branches/1.10-cache-improvements:1675666-1677522,1679679,1679681,1679859
 /subversion/branches/1.5.x-r30215:870312
 /subversion/branches/1.7.x-fs-verify:1146708,1161180
+/subversion/branches/1.9-cache-improvements:1678948-1679863
 /subversion/branches/10Gb:1388102,1388163-1388190,1388195,1388202,1388205,1388211,1388276,1388362,1388375,1388394,1388636,1388639-1388640,1388643-1388644,1388654,1388720,1388789,1388795,1388801,1388805,1388807,1388810,1388816,1389044,1389276,1389289,1389662,1389867,1390017,1390209,1390216,1390407,1390409,1390414,1390419,1390955
 /subversion/branches/atomic-revprop:965046-1000689
 /subversion/branches/authzperf:1615360
@@ -88,4 +90,4 @@
 /subversion/branches/verify-at-commit:1462039-1462408
 /subversion/branches/verify-keep-going:1439280-1546110
 /subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1606692-1678693
+/subversion/trunk:1606692-1681720

Propchange: subversion/branches/move-tracking-2/subversion/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue May 26 08:57:33 2015
@@ -82,4 +82,4 @@
 /subversion/branches/verify-at-commit/subversion:1462039-1462408
 /subversion/branches/verify-keep-going/subversion:1439280-1546110
 /subversion/branches/wc-collate-path/subversion:1402685-1480384
-/subversion/trunk/subversion:1606692-1678693
+/subversion/trunk/subversion:1606692-1681720

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_cmdline_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_cmdline_private.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_cmdline_private.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_cmdline_private.h Tue May 26 08:57:33 2015
@@ -88,7 +88,7 @@ typedef struct svn_cmdline__config_argum
  * containing svn_cmdline__config_argument_t* elements, allocating the option
  * data in @a pool
  *
- * [Since 1.9/1.10:] If the file, section, or option value is not recognized,
+ * [Since 1.9:] If the file, section, or option value is not recognized,
  * warn to @c stderr, using @a prefix as in svn_handle_warning2().
  *
  * @since New in 1.7.
@@ -224,6 +224,20 @@ svn_boolean_t
 svn_cmdline__be_interactive(svn_boolean_t non_interactive,
                             svn_boolean_t force_interactive);
 
+/* Parses the argument value of '--trust-server-cert-failures' OPT_ARG into
+ * the expected booleans for passing to svn_cmdline_create_auth_baton2()
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_cmdline__parse_trust_options(
+                        svn_boolean_t *trust_server_cert_unknown_ca,
+                        svn_boolean_t *trust_server_cert_cn_mismatch,
+                        svn_boolean_t *trust_server_cert_expired,
+                        svn_boolean_t *trust_server_cert_not_yet_valid,
+                        svn_boolean_t *trust_server_cert_other_failure,
+                        const char *opt_arg,
+                        apr_pool_t *scratch_pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h Tue May 26 08:57:33 2015
@@ -83,6 +83,8 @@ svn_wc__get_file_external_editor(const s
                                  const char *recorded_url,
                                  const svn_opt_revision_t *recorded_peg_rev,
                                  const svn_opt_revision_t *recorded_rev,
+                                 svn_wc_conflict_resolver_func2_t conflict_func,
+                                 void *conflict_baton,
                                  svn_cancel_func_t cancel_func,
                                  void *cancel_baton,
                                  svn_wc_notify_func2_t notify_func,

Modified: subversion/branches/move-tracking-2/subversion/include/svn_error.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_error.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_error.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_error.h Tue May 26 08:57:33 2015
@@ -165,18 +165,16 @@ svn_error_wrap_apr(apr_status_t status,
                    ...)
        __attribute__((format(printf, 2, 3)));
 
-/** A quick n' easy way to create a wrapped exception with your own
- * message, before throwing it up the stack.  (It uses all of the
- * @a child's fields.)
+/** If @child is SVN_NO_ERROR, return SVN_NO_ERROR.
+ * Else, prepend a new error to the error chain of @a child. The new error
+ * uses @a new_msg as error message but all other error attributes (such
+ * as the error code) are copied from @a child.
  */
 svn_error_t *
 svn_error_quick_wrap(svn_error_t *child,
                      const char *new_msg);
 
-/** A quick n' easy way to create a wrapped exception with your own
- * printf-style error message produced by passing @a fmt, using
- * apr_psprintf(), before throwing it up the stack.  (It uses all of the
- * @a child's fields.)
+/** Like svn_error_quick_wrap(), but with format string support.
  *
  * @since New in 1.9.
  */

Modified: subversion/branches/move-tracking-2/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_fs.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_fs.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_fs.h Tue May 26 08:57:33 2015
@@ -1422,7 +1422,7 @@ svn_fs_revision_root_revision(svn_fs_roo
  * Unicode canonical decomposition and ordering.  No directory entry
  * may be named '.', '..', or the empty string.  Given a directory
  * entry name which fails to meet these requirements, a filesystem
- * function returns an SVN_ERR_FS_PATH_SYNTAX error.
+ * function returns an #SVN_ERR_FS_PATH_SYNTAX error.
  *
  * A directory path is a sequence of zero or more directory entry
  * names, separated by slash characters (U+002f), and possibly ending
@@ -1430,7 +1430,7 @@ svn_fs_revision_root_revision(svn_fs_roo
  * characters are treated as if they were a single slash.  If a path
  * ends with a slash, it refers to the same node it would without the
  * slash, but that node must be a directory, or else the function
- * returns an SVN_ERR_FS_NOT_DIRECTORY error.
+ * may return an #SVN_ERR_FS_NOT_DIRECTORY error.
  *
  * A path consisting of the empty string, or a string containing only
  * slashes, refers to the root directory.

Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c Tue May 26 08:57:33 2015
@@ -538,6 +538,8 @@ switch_file_external(const char *local_a
                                              record_url,
                                              record_peg_revision,
                                              record_revision,
+                                             ctx->conflict_func2,
+                                             ctx->conflict_baton2,
                                              ctx->cancel_func,
                                              ctx->cancel_baton,
                                              ctx->notify_func2,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c Tue May 26 08:57:33 2015
@@ -2524,11 +2524,43 @@ read_dir_entries(apr_array_header_t *ent
   return SVN_NO_ERROR;
 }
 
-/* Fetch the contents of a directory into ENTRIES.  Values are stored
+/* For directory NODEREV in FS, return the *FILENAME and *FILESIZE of its
+ * in-txn representation.  If the directory representation is comitted data,
+ * set *FILENAME to NULL and *FILESIZE to SVN_INVALID_FILESIZE.  Allocate
+ * *FILENAME in RESULT_POOL and use SCRATCH_POOL for temporaries. */
+static svn_error_t *
+get_txn_dir_info(const char **filename,
+                 svn_filesize_t *filesize,
+                 svn_fs_t *fs,
+                 node_revision_t *noderev,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  const svn_io_dirent2_t *dirent;
+
+  if (noderev->data_rep && svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id))
+    {
+      *filename = svn_fs_fs__path_txn_node_children(fs, noderev->id,
+                                                    result_pool);
+
+      SVN_ERR(svn_io_stat_dirent2(&dirent, *filename, FALSE, FALSE,
+                                  scratch_pool, scratch_pool));
+      *filesize = dirent->filesize;
+    }
+  else
+    {
+      *filename = NULL;
+      *filesize = SVN_INVALID_FILESIZE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Fetch the contents of a directory into DIR.  Values are stored
    as filename to string mappings; further conversion is necessary to
    convert them into svn_fs_dirent_t values. */
 static svn_error_t *
-get_dir_contents(apr_array_header_t **entries,
+get_dir_contents(svn_fs_fs__dir_data_t *dir,
                  svn_fs_t *fs,
                  node_revision_t *noderev,
                  apr_pool_t *result_pool,
@@ -2536,18 +2568,24 @@ get_dir_contents(apr_array_header_t **en
 {
   svn_stream_t *contents;
 
-  *entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *));
+  /* Initialize the result. */
+  dir->entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *));
+  dir->txn_filesize = SVN_INVALID_FILESIZE;
+
+  /* Read dir contents - unless there is none in which case we are done. */
   if (noderev->data_rep && svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id))
     {
-      const char *filename
-        = svn_fs_fs__path_txn_node_children(fs, noderev->id, scratch_pool);
+      /* Get location & current size of the directory representation. */
+      const char *filename;
+      SVN_ERR(get_txn_dir_info(&filename, &dir->txn_filesize, fs, noderev,
+                               scratch_pool, scratch_pool));
 
       /* The representation is mutable.  Read the old directory
          contents from the mutable children file, followed by the
          changes we've made in this transaction. */
       SVN_ERR(svn_stream_open_readonly(&contents, filename, scratch_pool,
                                        scratch_pool));
-      SVN_ERR(read_dir_entries(*entries, contents, TRUE, noderev->id,
+      SVN_ERR(read_dir_entries(dir->entries, contents, TRUE, noderev->id,
                                result_pool, scratch_pool));
       SVN_ERR(svn_stream_close(contents));
     }
@@ -2567,7 +2605,7 @@ get_dir_contents(apr_array_header_t **en
 
       /* de-serialize hash */
       contents = svn_stream_from_stringbuf(text, scratch_pool);
-      SVN_ERR(read_dir_entries(*entries, contents, FALSE,  noderev->id,
+      SVN_ERR(read_dir_entries(dir->entries, contents, FALSE, noderev->id,
                                result_pool, scratch_pool));
     }
 
@@ -2623,6 +2661,7 @@ svn_fs_fs__rep_contents_dir(apr_array_he
 {
   pair_cache_key_t pair_key = { 0 };
   const void *key;
+  svn_fs_fs__dir_data_t *dir;
 
   /* find the cache we may use */
   svn_cache__t *cache = locate_dir_cache(fs, &key, &pair_key, noderev,
@@ -2631,19 +2670,34 @@ svn_fs_fs__rep_contents_dir(apr_array_he
     {
       svn_boolean_t found;
 
-      SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, key,
+      SVN_ERR(svn_cache__get((void **)&dir, &found, cache, key,
                              result_pool));
       if (found)
-        return SVN_NO_ERROR;
+        {
+          /* Verify that the cached dir info is not stale
+           * (no-op for committed data). */
+          const char *filename;
+          svn_filesize_t filesize;
+          SVN_ERR(get_txn_dir_info(&filename, &filesize, fs, noderev,
+                                   scratch_pool, scratch_pool));
+
+          if (filesize == dir->txn_filesize)
+            {
+              /* Still valid. Done. */
+              *entries_p = dir->entries;
+              return SVN_NO_ERROR;
+            }
+        }
     }
 
   /* Read in the directory contents. */
-  SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool,
-                           scratch_pool));
+  dir = apr_pcalloc(scratch_pool, sizeof(*dir));
+  SVN_ERR(get_dir_contents(dir, fs, noderev, result_pool, scratch_pool));
+  *entries_p = dir->entries;
 
   /* Update the cache, if we are to use one. */
   if (cache)
-    SVN_ERR(svn_cache__set(cache, key, *entries_p, scratch_pool));
+    SVN_ERR(svn_cache__set(cache, key, dir, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2675,13 +2729,22 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs
                                          scratch_pool);
   if (cache)
     {
+      extract_dir_entry_baton_t baton;
+
+      const char *filename;
+      svn_filesize_t filesize;
+      SVN_ERR(get_txn_dir_info(&filename, &filesize, fs, noderev,
+                               scratch_pool, scratch_pool));
+
       /* Cache lookup. */
+      baton.txn_filesize = filesize;
+      baton.name = name;
       SVN_ERR(svn_cache__get_partial((void **)dirent,
                                      &found,
                                      cache,
                                      key,
                                      svn_fs_fs__extract_dir_entry,
-                                     (void*)name,
+                                     &baton,
                                      result_pool));
     }
 
@@ -2735,8 +2798,8 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
         {
           svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool);
 
-          svn_error_clear(svn_stream_close(stream));
-          return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
+          err = svn_error_compose_create(err, svn_stream_close(stream));
+          return svn_error_quick_wrapf(err,
                    _("malformed property list for node-revision '%s' in '%s'"),
                    id_str->data, filename);
         }
@@ -2767,9 +2830,9 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
       if (err)
         {
           svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool);
-          
-          svn_error_clear(svn_stream_close(stream));
-          return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
+
+          err = svn_error_compose_create(err, svn_stream_close(stream));
+          return svn_error_quick_wrapf(err,
                    _("malformed property list for node-revision '%s'"),
                    id_str->data);
         }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c Tue May 26 08:57:33 2015
@@ -162,9 +162,11 @@ fs_freeze_body(void *baton,
 
   SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, b->fs, pool));
   if (exists)
-    SVN_ERR(svn_fs_fs__lock_rep_cache(b->fs, pool));
-
-  SVN_ERR(b->freeze_func(b->freeze_baton, pool));
+    SVN_ERR(svn_fs_fs__with_rep_cache_lock(b->fs,
+                                           b->freeze_func, b->freeze_baton,
+                                           pool));
+  else
+    SVN_ERR(b->freeze_func(b->freeze_baton, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h Tue May 26 08:57:33 2015
@@ -623,6 +623,18 @@ typedef struct change_t
   svn_fs_path_change2_t info;
 } change_t;
 
+
+/*** Directory (only used at the cache interface) ***/
+typedef struct svn_fs_fs__dir_data_t
+{
+  /* Contents, i.e. all directory entries, sorted by name. */
+  apr_array_header_t *entries;
+
+  /* SVN_INVALID_FILESIZE for committed data, otherwise the length of the
+   * in-txn on-disk representation of that directory. */
+  svn_filesize_t txn_filesize;
+} svn_fs_fs__dir_data_t;
+
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c Tue May 26 08:57:33 2015
@@ -1917,9 +1917,8 @@ get_node_origins_from_file(svn_fs_t *fs,
   *node_origins = apr_hash_make(pool);
   err = svn_hash_read2(*node_origins, stream, SVN_HASH_TERMINATOR, pool);
   if (err)
-    return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
-                             _("malformed node origin data in '%s'"),
-                             node_origins_file);
+    return svn_error_quick_wrapf(err, _("malformed node origin data in '%s'"),
+                                 node_origins_file);
   return svn_stream_close(stream);
 }
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c Tue May 26 08:57:33 2015
@@ -222,7 +222,7 @@ write_digest_file(apr_hash_t *children,
                                  svn_io_file_del_none, pool, pool));
   if ((err = svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, pool)))
     {
-      svn_error_clear(svn_stream_close(stream));
+      err = svn_error_compose_create(err, svn_stream_close(stream));
       return svn_error_createf(err->apr_err,
                                err,
                                _("Cannot write lock/entries hashfile '%s'"),
@@ -273,7 +273,7 @@ read_digest_file(apr_hash_t **children_p
   hash = apr_hash_make(pool);
   if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool)))
     {
-      svn_error_clear(svn_stream_close(stream));
+      err = svn_error_compose_create(err, svn_stream_close(stream));
       return svn_error_createf(err->apr_err,
                                err,
                                _("Can't parse lock/entries hashfile '%s'"),

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.c Tue May 26 08:57:33 2015
@@ -189,6 +189,19 @@ svn_fs_fs__unparse_revision_trailer(apr_
                                changes_offset);
 }
 
+/* If ERR is not NULL, wrap it MESSAGE.  The latter must have an %ld
+ * format parameter that will be filled with REV. */
+static svn_error_t *
+wrap_footer_error(svn_error_t *err,
+                  const char *message,
+                  svn_revnum_t rev)
+{
+  if (err)
+    return svn_error_quick_wrapf(err, message, rev);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
                         svn_checksum_t **l2p_checksum,
@@ -196,6 +209,7 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_o
                         svn_checksum_t **p2l_checksum,
                         svn_stringbuf_t *footer,
                         svn_revnum_t rev,
+                        apr_off_t footer_offset,
                         apr_pool_t *result_pool)
 {
   apr_int64_t val;
@@ -204,17 +218,20 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_o
   /* Get the L2P offset. */
   const char *str = svn_cstring_tokenize(" ", &last_str);
   if (str == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Invalid revision footer"));
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "Invalid r%ld footer", rev);
 
-  SVN_ERR(svn_cstring_atoi64(&val, str));
+  SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0,
+                                                 footer_offset - 1, 10),
+                            "Invalid L2P offset in r%ld footer",
+                            rev));
   *l2p_offset = (apr_off_t)val;
 
   /* Get the L2P checksum. */
   str = svn_cstring_tokenize(" ", &last_str);
   if (str == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Invalid revision footer"));
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "Invalid r%ld footer", rev);
 
   SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str,
                                  result_pool));
@@ -222,17 +239,33 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_o
   /* Get the P2L offset. */
   str = svn_cstring_tokenize(" ", &last_str);
   if (str == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Invalid revision footer"));
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "Invalid r%ld footer", rev);
 
-  SVN_ERR(svn_cstring_atoi64(&val, str));
+  SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0,
+                                                 footer_offset - 1, 10),
+                            "Invalid P2L offset in r%ld footer",
+                            rev));
   *p2l_offset = (apr_off_t)val;
 
+  /* The P2L indes follows the L2P index */
+  if (*p2l_offset <= *l2p_offset)
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "P2L offset %s must be larger than L2P offset %s"
+                             " in r%ld footer",
+                             apr_psprintf(result_pool,
+                                          "%" APR_UINT64_T_HEX_FMT,
+                                          (apr_uint64_t)*p2l_offset),
+                             apr_psprintf(result_pool,
+                                          "%" APR_UINT64_T_HEX_FMT,
+                                          (apr_uint64_t)*l2p_offset),
+                             rev);
+
   /* Get the P2L checksum. */
   str = svn_cstring_tokenize(" ", &last_str);
   if (str == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Invalid revision footer"));
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "Invalid r%ld footer", rev);
 
   SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str,
                                  result_pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/low_level.h Tue May 26 08:57:33 2015
@@ -67,6 +67,8 @@ svn_fs_fs__unparse_revision_trailer(apr_
  * *P2L_OFFSET, respectively.  Also, return the expected checksums in
  * in *L2P_CHECKSUM and *P2L_CHECKSUM.
  *
+ * FOOTER_OFFSET is used for validation.
+ *
  * Note that REV is only used to construct nicer error objects that
  * mention this revision.  Allocate the checksums in RESULT_POOL.
  */
@@ -77,6 +79,7 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_o
                         svn_checksum_t **p2l_checksum,
                         svn_stringbuf_t *footer,
                         svn_revnum_t rev,
+                        apr_off_t footer_offset,
                         apr_pool_t *result_pool);
 
 /* Given the offset of the L2P index data in L2P_OFFSET, the content

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/recovery.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/recovery.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/recovery.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/recovery.c Tue May 26 08:57:33 2015
@@ -209,8 +209,8 @@ recover_find_max_ids(svn_fs_t *fs,
     {
       svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool);
 
-      svn_error_clear(svn_stream_close(stream));
-      return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
+      err = svn_error_compose_create(err, svn_stream_close(stream));
+      return svn_error_quick_wrapf(err,
                 _("malformed representation for node-revision '%s'"),
                 id_str->data);
     }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache-db.sql Tue May 26 08:57:33 2015
@@ -63,3 +63,6 @@ WHERE revision > ?1
 -- STMT_LOCK_REP
 BEGIN TRANSACTION;
 INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0)
+
+-- STMT_UNLOCK_REP
+ROLLBACK TRANSACTION;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.c Tue May 26 08:57:33 2015
@@ -374,9 +374,13 @@ svn_fs_fs__del_rep_reference(svn_fs_t *f
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
-                          apr_pool_t *pool)
+/* Start a transaction to take an SQLite reserved lock that prevents
+   other writes.
+
+   See unlock_rep_cache(). */
+static svn_error_t *
+lock_rep_cache(svn_fs_t *fs,
+               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
@@ -387,3 +391,31 @@ svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
 
   return SVN_NO_ERROR;
 }
+
+/* End the transaction started by lock_rep_cache(). */
+static svn_error_t *
+unlock_rep_cache(svn_fs_t *fs,
+                 apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  SVN_ERR_ASSERT(ffd->rep_cache_db); /* was opened by lock_rep_cache() */
+
+  SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_UNLOCK_REP));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__with_rep_cache_lock(svn_fs_t *fs,
+                               svn_error_t *(*body)(void *,
+                                                    apr_pool_t *),
+                               void *baton,
+                               apr_pool_t *pool)
+{
+  svn_error_t *err;
+
+  SVN_ERR(lock_rep_cache(fs, pool));
+  err = body(baton, pool);
+  return svn_error_compose_create(err, unlock_rep_cache(fs, pool));
+}

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rep-cache.h Tue May 26 08:57:33 2015
@@ -87,10 +87,14 @@ svn_fs_fs__del_rep_reference(svn_fs_t *f
                              apr_pool_t *pool);
 
 /* Start a transaction to take an SQLite reserved lock that prevents
-   other writes. */
+   other writes, call BODY, end the transaction, and return what BODY returned.
+ */
 svn_error_t *
-svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
-                          apr_pool_t *pool);
+svn_fs_fs__with_rep_cache_lock(svn_fs_t *fs,
+                               svn_error_t *(*body)(void *baton,
+                                                    apr_pool_t *pool),
+                               void *baton,
+                               apr_pool_t *pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rev_file.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rev_file.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/rev_file.c Tue May 26 08:57:33 2015
@@ -259,6 +259,7 @@ svn_fs_fs__auto_read_footer(svn_fs_fs__r
       SVN_ERR(svn_fs_fs__parse_footer(&file->l2p_offset, &file->l2p_checksum,
                                       &file->p2l_offset, &file->p2l_checksum,
                                       footer, file->start_revision,
+                                      filesize - footer_length - 1,
                                       file->pool));
       file->footer_offset = filesize - footer_length - 1;
     }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c Tue May 26 08:57:33 2015
@@ -36,11 +36,6 @@
 
 #include "svn_private_config.h"
 
-/* Give writing processes 10 seconds to replace an existing revprop
-   file with a new one. After that time, we assume that the writing
-   process got aborted and that we have re-read revprops. */
-#define REVPROP_CHANGE_TIMEOUT (10 * 1000000)
-
 svn_error_t *
 svn_fs_fs__upgrade_pack_revprops(svn_fs_t *fs,
                                  svn_fs_upgrade_notify_t notify_func,
@@ -657,17 +652,23 @@ write_non_packed_revprop(const char **fi
                          apr_hash_t *proplist,
                          apr_pool_t *pool)
 {
+  apr_file_t *file;
   svn_stream_t *stream;
   *final_path = svn_fs_fs__path_revprops(fs, rev, pool);
 
   /* ### do we have a directory sitting around already? we really shouldn't
      ### have to get the dirname here. */
-  SVN_ERR(svn_stream_open_unique(&stream, tmp_path,
-                                 svn_dirent_dirname(*final_path, pool),
-                                 svn_io_file_del_none, pool, pool));
+  SVN_ERR(svn_io_open_unique_file3(&file, tmp_path,
+                                   svn_dirent_dirname(*final_path, pool),
+                                   svn_io_file_del_none, pool, pool));
+  stream = svn_stream_from_aprfile2(file, TRUE, pool);
   SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, pool));
   SVN_ERR(svn_stream_close(stream));
 
+  /* Flush temporary file to disk and close it. */
+  SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -750,7 +751,7 @@ serialize_revprops_header(svn_stream_t *
   return SVN_NO_ERROR;
 }
 
-/* Writes the a pack file to FILE_STREAM.  It copies the serialized data
+/* Writes the a pack file to FILE.  It copies the serialized data
  * from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX.
  *
  * The data for the latter is taken from NEW_SERIALIZED.  Note, that
@@ -768,7 +769,7 @@ repack_revprops(svn_fs_t *fs,
                 int changed_index,
                 svn_stringbuf_t *new_serialized,
                 apr_off_t new_total_size,
-                svn_stream_t *file_stream,
+                apr_file_t *file,
                 apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -816,9 +817,11 @@ repack_revprops(svn_fs_t *fs,
                           ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT
                           : SVN_DELTA_COMPRESSION_LEVEL_NONE));
 
-  /* finally, write the content to the target stream and close it */
-  SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len));
-  SVN_ERR(svn_stream_close(file_stream));
+  /* finally, write the content to the target file, flush and close it */
+  SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len,
+                                 NULL, pool));
+  SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
 
   return SVN_NO_ERROR;
 }
@@ -826,23 +829,22 @@ repack_revprops(svn_fs_t *fs,
 /* Allocate a new pack file name for revisions
  *     [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1]
  * of REVPROPS->MANIFEST.  Add the name of old file to FILES_TO_DELETE,
- * auto-create that array if necessary.  Return an open file stream to
- * the new file in *STREAM allocated in POOL.
+ * auto-create that array if necessary.  Return an open file *FILE that is
+ * allocated in POOL.
  */
 static svn_error_t *
-repack_stream_open(svn_stream_t **stream,
-                   svn_fs_t *fs,
-                   packed_revprops_t *revprops,
-                   int start,
-                   int end,
-                   apr_array_header_t **files_to_delete,
-                   apr_pool_t *pool)
+repack_file_open(apr_file_t **file,
+                 svn_fs_t *fs,
+                 packed_revprops_t *revprops,
+                 int start,
+                 int end,
+                 apr_array_header_t **files_to_delete,
+                 apr_pool_t *pool)
 {
   apr_int64_t tag;
   const char *tag_string;
   svn_string_t *new_filename;
   int i;
-  apr_file_t *file;
   int manifest_offset
     = (int)(revprops->start_revision - revprops->manifest_start);
 
@@ -874,12 +876,11 @@ repack_stream_open(svn_stream_t **stream
     APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*)
       = new_filename->data;
 
-  /* create a file stream for the new file */
-  SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder,
-                                                  new_filename->data,
-                                                  pool),
+  /* open the file */
+  SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder,
+                                                 new_filename->data,
+                                                 pool),
                            APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool));
-  *stream = svn_stream_from_aprfile2(file, FALSE, pool);
 
   return SVN_NO_ERROR;
 }
@@ -903,6 +904,7 @@ write_packed_revprop(const char **final_
   packed_revprops_t *revprops;
   apr_int64_t generation = 0;
   svn_stream_t *stream;
+  apr_file_t *file;
   svn_stringbuf_t *serialized;
   apr_off_t new_total_size;
   int changed_index;
@@ -933,11 +935,11 @@ write_packed_revprop(const char **final_
 
       *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(svn_io_open_unique_file3(&file, 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));
+                              file, pool));
     }
   else
     {
@@ -983,50 +985,53 @@ write_packed_revprop(const char **final_
       /* 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_file_open(&file, 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));
+                                  file, 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_file_open(&file, 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));
+                                  file, 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_file_open(&file, 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,
+                                  serialized, new_total_size, file,
                                   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));
+      SVN_ERR(svn_io_open_unique_file3(&file, 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_io_file_write_full(file, filename, strlen(filename),
+                                         NULL, pool));
+          SVN_ERR(svn_io_file_putc('\n', file, pool));
         }
 
-      SVN_ERR(svn_stream_close(stream));
+      SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+      SVN_ERR(svn_io_file_close(file, pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure Tue May 26 08:57:33 2015
@@ -525,6 +525,7 @@ A revision file contains a concatenation
   * Text and property representations
   * Node-revisions
   * The changed-path data
+  * Two offsets at the very end (physical addressing only)
   * Index data (logical addressing only)
   * Revision / pack file footer (logical addressing only)
 
@@ -757,6 +758,9 @@ Format 7 introduces logical addressing t
 to be translated / mapped to physical rev / pack file offsets.
 These indexes are appended to the respective rev / pack file.
 
+The indexes map (revision number, item-index) pairs to absolute file offsets
+and absolute file offsets to (revision number, item-index, item metadata).
+
 Details of the binary format used by these index files can be
 found in structure-indexes.
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c Tue May 26 08:57:33 2015
@@ -153,6 +153,10 @@ typedef struct dir_data_t
    * (it's int because the directory is an APR array) */
   int count;
 
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */
+  svn_filesize_t txn_filesize;
+
   /* number of unused dir entry buckets in the index */
   apr_size_t over_provision;
 
@@ -198,15 +202,16 @@ serialize_dir_entry(svn_temp_serializer_
   svn_temp_serializer__pop(context);
 }
 
-/* Utility function to serialize the ENTRIES into a new serialization
+/* Utility function to serialize the DIR into a new serialization
  * context to be returned. Allocation will be made form POOL.
  */
 static svn_temp_serializer__context_t *
-serialize_dir(apr_array_header_t *entries, apr_pool_t *pool)
+serialize_dir(svn_fs_fs__dir_data_t *dir, apr_pool_t *pool)
 {
   dir_data_t dir_data;
   int i = 0;
   svn_temp_serializer__context_t *context;
+  apr_array_header_t *entries = dir->entries;
 
   /* calculate sizes */
   int count = entries->nelts;
@@ -216,6 +221,7 @@ serialize_dir(apr_array_header_t *entrie
 
   /* copy the hash entries to an auxiliary struct of known layout */
   dir_data.count = count;
+  dir_data.txn_filesize = dir->txn_filesize;
   dir_data.over_provision = over_provision;
   dir_data.operations = 0;
   dir_data.entries = apr_palloc(pool, entries_len);
@@ -252,24 +258,29 @@ serialize_dir(apr_array_header_t *entrie
   return context;
 }
 
-/* Utility function to reconstruct a dir entries array from serialized data
+/* Utility function to reconstruct a dir entries struct from serialized data
  * in BUFFER and DIR_DATA. Allocation will be made form POOL.
  */
-static apr_array_header_t *
+static svn_fs_fs__dir_data_t *
 deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool)
 {
-  apr_array_header_t *result
-    = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *));
+  svn_fs_fs__dir_data_t *result;
   apr_size_t i;
   apr_size_t count;
   svn_fs_dirent_t *entry;
   svn_fs_dirent_t **entries;
 
+  /* Construct empty directory object. */
+  result = apr_pcalloc(pool, sizeof(*result));
+  result->entries
+    = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *));
+  result->txn_filesize = dir_data->txn_filesize;
+
   /* resolve the reference to the entries array */
   svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries);
   entries = dir_data->entries;
 
-  /* fixup the references within each entry and add it to the hash */
+  /* fixup the references within each entry and add it to the RESULT */
   for (i = 0, count = dir_data->count; i < count; ++i)
     {
       svn_temp_deserializer__resolve(entries, (void **)&entries[i]);
@@ -280,7 +291,7 @@ deserialize_dir(void *buffer, dir_data_t
       svn_fs_fs__id_deserialize(entry, (svn_fs_id_t **)&entry->id);
 
       /* add the entry to the hash */
-      APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = entry;
+      APR_ARRAY_PUSH(result->entries, svn_fs_dirent_t *) = entry;
     }
 
   /* return the now complete hash */
@@ -764,7 +775,7 @@ svn_fs_fs__serialize_dir_entries(void **
                                  void *in,
                                  apr_pool_t *pool)
 {
-  apr_array_header_t *dir = in;
+  svn_fs_fs__dir_data_t *dir = in;
 
   /* serialize the dir content into a new serialization context
    * and return the serialized data */
@@ -803,6 +814,20 @@ svn_fs_fs__get_sharded_offset(void **out
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_fs__extract_dir_filesize(void **out,
+                                const void *data,
+                                apr_size_t data_len,
+                                void *baton,
+                                apr_pool_t *pool)
+{
+  const dir_data_t *dir_data = data;
+
+  *(svn_filesize_t *)out = dir_data->txn_filesize;
+
+  return SVN_NO_ERROR;
+}
+
 /* Utility function that returns the lowest index of the first entry in
  * *ENTRIES that points to a dir entry with a name equal or larger than NAME.
  * If an exact match has been found, *FOUND will be set to TRUE. COUNT is
@@ -857,7 +882,7 @@ svn_fs_fs__extract_dir_entry(void **out,
                              apr_pool_t *pool)
 {
   const dir_data_t *dir_data = data;
-  const char* name = baton;
+  const extract_dir_entry_baton_t *entry_baton = baton;
   svn_boolean_t found;
 
   /* resolve the reference to the entries array */
@@ -870,13 +895,14 @@ svn_fs_fs__extract_dir_entry(void **out,
 
   /* binary search for the desired entry by name */
   apr_size_t pos = find_entry((svn_fs_dirent_t **)entries,
-                              name,
+                              entry_baton->name,
                               dir_data->count,
                               &found);
 
-  /* de-serialize that entry or return NULL, if no match has been found */
+  /* de-serialize that entry or return NULL, if no match has been found.
+   * Be sure to check that the directory contents is still up-to-date. */
   *out = NULL;
-  if (found)
+  if (found && dir_data->txn_filesize == entry_baton->txn_filesize)
     {
       const svn_fs_dirent_t *source =
           svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]);
@@ -911,31 +937,34 @@ slowly_replace_dir_entry(void **data,
 {
   replace_baton_t *replace_baton = (replace_baton_t *)baton;
   dir_data_t *dir_data = (dir_data_t *)*data;
-  apr_array_header_t *dir;
+  svn_fs_fs__dir_data_t *dir;
   int idx = -1;
   svn_fs_dirent_t *entry;
+  apr_array_header_t *entries;
 
   SVN_ERR(svn_fs_fs__deserialize_dir_entries((void **)&dir,
                                              *data,
                                              dir_data->len,
                                              pool));
 
-  entry = svn_fs_fs__find_dir_entry(dir, replace_baton->name, &idx);
+  entries = dir->entries;
+  entry = svn_fs_fs__find_dir_entry(entries, replace_baton->name, &idx);
 
   /* Replacement or removal? */
   if (replace_baton->new_entry)
     {
       /* Replace ENTRY with / insert the NEW_ENTRY */
       if (entry)
-        APR_ARRAY_IDX(dir, idx, svn_fs_dirent_t *) = replace_baton->new_entry;
+        APR_ARRAY_IDX(entries, idx, svn_fs_dirent_t *)
+          = replace_baton->new_entry;
       else
-        svn_sort__array_insert(dir, &replace_baton->new_entry, idx);
+        svn_sort__array_insert(entries, &replace_baton->new_entry, idx);
     }
   else
     {
       /* Remove the old ENTRY. */
       if (entry)
-        svn_sort__array_delete(dir, idx, 1);
+        svn_sort__array_delete(entries, idx, 1);
     }
 
   return svn_fs_fs__serialize_dir_entries(data, data_len, dir, pool);
@@ -957,6 +986,12 @@ svn_fs_fs__replace_dir_entry(void **data
 
   svn_temp_serializer__context_t *context;
 
+  /* update the cached file length info.
+   * Because we are writing to the cache, it is fair to assume that the
+   * caller made sure that the current contents is consistent with the
+   * previous state of the directory file. */
+  dir_data->txn_filesize = replace_baton->txn_filesize;
+
   /* after quite a number of operations, let's re-pack everything.
    * This is to limit the number of wasted space as we cannot overwrite
    * existing data but must always append. */

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h Tue May 26 08:57:33 2015
@@ -192,7 +192,7 @@ svn_fs_fs__deserialize_node_revision(voi
                                      apr_pool_t *pool);
 
 /**
- * Implements #svn_cache__serialize_func_t for a directory contents array
+ * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__dir_data_t
  */
 svn_error_t *
 svn_fs_fs__serialize_dir_entries(void **data,
@@ -201,7 +201,7 @@ svn_fs_fs__serialize_dir_entries(void **
                                  apr_pool_t *pool);
 
 /**
- * Implements #svn_cache__deserialize_func_t for a directory contents array
+ * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__dir_data_t
  */
 svn_error_t *
 svn_fs_fs__deserialize_dir_entries(void **out,
@@ -221,9 +221,38 @@ svn_fs_fs__get_sharded_offset(void **out
                               apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__partial_getter_func_t.
+ * Set (svn_filesize_t) @a *out to the filesize info stored with the
+ * serialized directory in @a data of @a data_len.  @a baton is unused.
+ */
+svn_error_t *
+svn_fs_fs__extract_dir_filesize(void **out,
+                                const void *data,
+                                apr_size_t data_len,
+                                void *baton,
+                                apr_pool_t *pool);
+
+/**
+ * Describes the entry to be found in a directory: Identifies the entry
+ * by @a name and requires the directory file size to be @a filesize.
+ */
+typedef struct extract_dir_entry_baton_t
+{
+  /** name of the directory entry to return */
+  const char *name;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
+} extract_dir_entry_baton_t;
+
+
+/**
  * Implements #svn_cache__partial_getter_func_t for a single
  * #svn_fs_dirent_t within a serialized directory contents hash,
- * identified by its name (const char @a *baton).
+ * identified by its name (in (extract_dir_entry_baton_t *) @a *baton).
+ * If the filesize specified in the baton does not match the cached
+ * value for this directory, @a *out will be NULL as well.
  */
 svn_error_t *
 svn_fs_fs__extract_dir_entry(void **out,
@@ -236,7 +265,10 @@ svn_fs_fs__extract_dir_entry(void **out,
  * Describes the change to be done to a directory: Set the entry
  * identify by @a name to the value @a new_entry. If the latter is
  * @c NULL, the entry shall be removed if it exists. Otherwise it
- * will be replaced or automatically added, respectively.
+ * will be replaced or automatically added, respectively.  The
+ * @a filesize allows readers to identify stale cache data (e.g.
+ * due to concurrent access to txns); writers use it to update the
+ * cached file size info.
  */
 typedef struct replace_baton_t
 {
@@ -245,6 +277,10 @@ typedef struct replace_baton_t
 
   /** directory entry to insert instead */
   svn_fs_dirent_t *new_entry;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
 } replace_baton_t;
 
 /**

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c Tue May 26 08:57:33 2015
@@ -1145,9 +1145,9 @@ get_txn_proplist(apr_hash_t *proplist,
   err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool);
   if (err)
     {
-      svn_error_clear(svn_stream_close(stream));  
-      return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
-               _("malformed transaction property list in '%s'"),
+      err = svn_error_compose_create(err, svn_stream_close(stream));
+      return svn_error_quick_wrapf(err,
+               _("malformed property list in transaction '%s'"),
                path_txn_props(fs, txn_id, pool));
     }
 
@@ -1524,22 +1524,80 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
     }
   else
     {
+      const svn_io_dirent2_t *dirent;
+
       /* The directory rep is already mutable, so just open it for append. */
       SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND,
-                               APR_OS_DEFAULT, pool));
-      out = svn_stream_from_aprfile2(file, TRUE, pool);
+                               APR_OS_DEFAULT, subpool));
+      out = svn_stream_from_aprfile2(file, TRUE, subpool);
+
+      /* If the cache contents is stale, drop it.
+       *
+       * Note that the directory file is append-only, i.e. if the size
+       * did not change, the contents didn't either. */
+      if (ffd->txn_dir_cache)
+        {
+          const char *key
+            = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data;
+          svn_boolean_t found;
+          svn_filesize_t filesize;
+
+          /* Get the file size that corresponds to the cached contents
+           * (if any). */
+          SVN_ERR(svn_cache__get_partial((void **)&filesize, &found,
+                                         ffd->txn_dir_cache, key,
+                                         svn_fs_fs__extract_dir_filesize,
+                                         NULL, subpool));
+
+          /* File size info still matches?
+           * If not, we need to drop the cache entry. */
+          if (found)
+            {
+              SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE,
+                                          subpool, subpool));
+
+              if (filesize != dirent->filesize)
+                SVN_ERR(svn_cache__set(ffd->txn_dir_cache, key, NULL,
+                                       subpool));
+            }
+        }
+    }
+
+  /* Append an incremental hash entry for the entry change. */
+  if (id)
+    {
+      svn_fs_dirent_t entry;
+      entry.name = name;
+      entry.id = id;
+      entry.kind = kind;
+
+      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
+    }
+  else
+    {
+      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
+                                strlen(name), name));
     }
 
+  /* Flush APR buffers. */
+  SVN_ERR(svn_io_file_close(file, subpool));
+  svn_pool_clear(subpool);
+
   /* if we have a directory cache for this transaction, update it */
   if (ffd->txn_dir_cache)
     {
-      /* build parameters: (name, new entry) pair */
+      /* build parameters: name, new entry, new file size  */
       const char *key =
           svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data;
       replace_baton_t baton;
 
+      const svn_io_dirent2_t *dirent;
+      SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE,
+                                  subpool, subpool));
+
       baton.name = name;
       baton.new_entry = NULL;
+      baton.txn_filesize = dirent->filesize;
 
       if (id)
         {
@@ -1554,25 +1612,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
                                      svn_fs_fs__replace_dir_entry, &baton,
                                      subpool));
     }
-  svn_pool_clear(subpool);
 
-  /* Append an incremental hash entry for the entry change. */
-  if (id)
-    {
-      svn_fs_dirent_t entry;
-      entry.name = name;
-      entry.id = id;
-      entry.kind = kind;
-
-      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
-    }
-  else
-    {
-      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
-                                strlen(name), name));
-    }
-
-  SVN_ERR(svn_io_file_close(file, subpool));
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }

Propchange: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue May 26 08:57:33 2015
@@ -90,4 +90,4 @@
 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
 /subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1653608,
 1658482
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1606692-1673179
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1606692-1681720

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/fs.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/fs.c Tue May 26 08:57:33 2015
@@ -164,9 +164,11 @@ x_freeze_body(void *baton,
 
   SVN_ERR(svn_fs_x__exists_rep_cache(&exists, b->fs, scratch_pool));
   if (exists)
-    SVN_ERR(svn_fs_x__lock_rep_cache(b->fs, scratch_pool));
-
-  SVN_ERR(b->freeze_func(b->freeze_baton, scratch_pool));
+    SVN_ERR(svn_fs_x__with_rep_cache_lock(b->fs,
+                                          b->freeze_func, b->freeze_baton,
+                                          scratch_pool));
+  else
+    SVN_ERR(b->freeze_func(b->freeze_baton, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache-db.sql?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache-db.sql (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache-db.sql Tue May 26 08:57:33 2015
@@ -65,3 +65,6 @@ WHERE revision > ?1
 -- STMT_LOCK_REP
 BEGIN TRANSACTION;
 INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0)
+
+-- STMT_UNLOCK_REP
+ROLLBACK TRANSACTION;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.c?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.c Tue May 26 08:57:33 2015
@@ -369,16 +369,48 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_x__lock_rep_cache(svn_fs_t *fs,
-                         apr_pool_t *scratch_pool)
+/* Start a transaction to take an SQLite reserved lock that prevents
+   other writes.
+
+   See unlock_rep_cache(). */
+static svn_error_t *
+lock_rep_cache(svn_fs_t *fs,
+               apr_pool_t *pool)
 {
   svn_fs_x__data_t *ffd = fs->fsap_data;
 
   if (! ffd->rep_cache_db)
-    SVN_ERR(svn_fs_x__open_rep_cache(fs, scratch_pool));
+    SVN_ERR(svn_fs_x__open_rep_cache(fs, pool));
 
   SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_LOCK_REP));
 
   return SVN_NO_ERROR;
 }
+
+/* End the transaction started by lock_rep_cache(). */
+static svn_error_t *
+unlock_rep_cache(svn_fs_t *fs,
+                 apr_pool_t *pool)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+
+  SVN_ERR_ASSERT(ffd->rep_cache_db); /* was opened by lock_rep_cache() */
+
+  SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_UNLOCK_REP));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_x__with_rep_cache_lock(svn_fs_t *fs,
+                              svn_error_t *(*body)(void *,
+                                                   apr_pool_t *),
+                              void *baton,
+                              apr_pool_t *pool)
+{
+  svn_error_t *err;
+
+  SVN_ERR(lock_rep_cache(fs, pool));
+  err = body(baton, pool);
+  return svn_error_compose_create(err, unlock_rep_cache(fs, pool));
+}

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.h?rev=1681721&r1=1681720&r2=1681721&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rep-cache.h Tue May 26 08:57:33 2015
@@ -88,12 +88,16 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs
                             svn_revnum_t youngest,
                             apr_pool_t *scratch_pool);
 
+
 /* Start a transaction to take an SQLite reserved lock that prevents
-   other writes. */
+   other writes, call BODY, end the transaction, and return what BODY returned.
+ */
 svn_error_t *
-svn_fs_x__lock_rep_cache(svn_fs_t *fs,
-                         apr_pool_t *scratch_pool);
-
+svn_fs_x__with_rep_cache_lock(svn_fs_t *fs,
+                              svn_error_t *(*body)(void *baton,
+                                                   apr_pool_t *pool),
+                              void *baton,
+                              apr_pool_t *pool);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */