You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2014/11/14 14:18:03 UTC

svn commit: r1639628 [4/23] - in /subversion/branches/svn-auth-x509: ./ build/ build/generator/ notes/ notes/api-errata/1.8/ notes/api-errata/1.9/ notes/wc-ng/ subversion/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/binding...

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c Fri Nov 14 13:17:55 2014
@@ -610,7 +610,7 @@ static const svn_diff_output_fns_t mem_o
 
 
 svn_error_t *
-svn_diff_mem_string_output_unified2(svn_stream_t *output_stream,
+svn_diff_mem_string_output_unified3(svn_stream_t *output_stream,
                                     svn_diff_t *diff,
                                     svn_boolean_t with_diff_header,
                                     const char *hunk_delimiter,
@@ -619,6 +619,9 @@ svn_diff_mem_string_output_unified2(svn_
                                     const char *header_encoding,
                                     const svn_string_t *original,
                                     const svn_string_t *modified,
+                                    int context_size,
+                                    svn_cancel_func_t cancel_func,
+                                    void *cancel_baton,
                                     apr_pool_t *pool)
 {
 
@@ -636,7 +639,8 @@ svn_diff_mem_string_output_unified2(svn_
         = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
           ? APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR
           : APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_PROPERTY APR_EOL_STR;
-      baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+      baton.context_size = context_size >= 0 ? context_size
+                                             : SVN_DIFF__UNIFIED_CONTEXT_SIZE;
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_context]), " ",
@@ -658,8 +662,9 @@ svn_diff_mem_string_output_unified2(svn_
                     original_header, modified_header, pool));
         }
 
-      SVN_ERR(svn_diff_output(diff, &baton,
-                              &mem_output_unified_vtable));
+      SVN_ERR(svn_diff_output2(diff, &baton,
+                              &mem_output_unified_vtable,
+                              cancel_func, cancel_baton));
 
       SVN_ERR(output_unified_flush_hunk(&baton, hunk_delimiter));
 
@@ -669,28 +674,6 @@ svn_diff_mem_string_output_unified2(svn_
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_diff_mem_string_output_unified(svn_stream_t *output_stream,
-                                   svn_diff_t *diff,
-                                   const char *original_header,
-                                   const char *modified_header,
-                                   const char *header_encoding,
-                                   const svn_string_t *original,
-                                   const svn_string_t *modified,
-                                   apr_pool_t *pool)
-{
-  SVN_ERR(svn_diff_mem_string_output_unified2(output_stream,
-                                              diff,
-                                              TRUE,
-                                              NULL,
-                                              original_header,
-                                              modified_header,
-                                              header_encoding,
-                                              original,
-                                              modified,
-                                              pool));
-  return SVN_NO_ERROR;
-}
 
 
 
@@ -739,6 +722,10 @@ typedef struct merge_output_baton_t
   svn_diff_conflict_display_style_t conflict_style;
   int context_size;
 
+  /* cancel support */
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+
   /* The rest of the fields are for
      svn_diff_conflict_display_only_conflicts only.  Note that for
      these batons, OUTPUT_STREAM is either CONTEXT_SAVER->STREAM or
@@ -923,7 +910,8 @@ output_conflict(void *baton,
   if (style == svn_diff_conflict_display_resolved_modified_latest)
     {
       if (diff)
-        return svn_diff_output(diff, baton, &merge_output_vtable);
+        return svn_diff_output2(diff, baton, &merge_output_vtable,
+                                btn->cancel_func, btn->cancel_baton);
       else
         style = svn_diff_conflict_display_modified_latest;
     }
@@ -1066,7 +1054,7 @@ detect_eol(svn_string_t *token)
 }
 
 svn_error_t *
-svn_diff_mem_string_output_merge2(svn_stream_t *output_stream,
+svn_diff_mem_string_output_merge3(svn_stream_t *output_stream,
                                   svn_diff_t *diff,
                                   const svn_string_t *original,
                                   const svn_string_t *modified,
@@ -1076,6 +1064,8 @@ svn_diff_mem_string_output_merge2(svn_st
                                   const char *conflict_latest,
                                   const char *conflict_separator,
                                   svn_diff_conflict_display_style_t style,
+                                  svn_cancel_func_t cancel_func,
+                                  void *cancel_baton,
                                   apr_pool_t *pool)
 {
   merge_output_baton_t btn;
@@ -1113,6 +1103,8 @@ svn_diff_mem_string_output_merge2(svn_st
     eol = APR_EOL_STR;  /* use the platform default */
 
   btn.marker_eol = eol;
+  btn.cancel_func = cancel_func;
+  btn.cancel_baton = cancel_baton;
 
   SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[1],
                                     conflict_modified
@@ -1135,45 +1127,9 @@ svn_diff_mem_string_output_merge2(svn_st
                                     : ">>>>>>> (latest)",
                                     pool));
 
-  SVN_ERR(svn_diff_output(diff, &btn, vtable));
+  SVN_ERR(svn_diff_output2(diff, &btn, vtable, cancel_func, cancel_baton));
   if (conflicts_only)
     svn_pool_destroy(btn.pool);
 
   return SVN_NO_ERROR;
 }
-
-svn_error_t *
-svn_diff_mem_string_output_merge(svn_stream_t *output_stream,
-                                 svn_diff_t *diff,
-                                 const svn_string_t *original,
-                                 const svn_string_t *modified,
-                                 const svn_string_t *latest,
-                                 const char *conflict_original,
-                                 const char *conflict_modified,
-                                 const char *conflict_latest,
-                                 const char *conflict_separator,
-                                 svn_boolean_t display_original_in_conflict,
-                                 svn_boolean_t display_resolved_conflicts,
-                                 apr_pool_t *pool)
-{
-  svn_diff_conflict_display_style_t style =
-    svn_diff_conflict_display_modified_latest;
-
-  if (display_resolved_conflicts)
-    style = svn_diff_conflict_display_resolved_modified_latest;
-
-  if (display_original_in_conflict)
-    style = svn_diff_conflict_display_modified_original_latest;
-
-  return svn_diff_mem_string_output_merge2(output_stream,
-                                           diff,
-                                           original,
-                                           modified,
-                                           latest,
-                                           conflict_original,
-                                           conflict_modified,
-                                           conflict_latest,
-                                           conflict_separator,
-                                           style,
-                                           pool);
-}

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c Fri Nov 14 13:17:55 2014
@@ -516,6 +516,9 @@ svn_diff__display_prop_diffs(svn_stream_
                              const apr_array_header_t *propchanges,
                              apr_hash_t *original_props,
                              svn_boolean_t pretty_print_mergeinfo,
+                             int context_size,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
                              apr_pool_t *scratch_pool)
 {
   apr_pool_t *pool = scratch_pool;
@@ -600,9 +603,10 @@ svn_diff__display_prop_diffs(svn_stream_
          * UNIX patch could apply the property diff to, so we use "##"
          * instead of "@@" as the default hunk delimiter for property diffs.
          * We also suppress the diff header. */
-        SVN_ERR(svn_diff_mem_string_output_unified2(
+        SVN_ERR(svn_diff_mem_string_output_unified3(
                   outstream, diff, FALSE /* no header */, "##", NULL, NULL,
-                  encoding, orig, val, iterpool));
+                  encoding, orig, val, context_size,
+                  cancel_func, cancel_baton, iterpool));
       }
     }
   svn_pool_destroy(iterpool);

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c Fri Nov 14 13:17:55 2014
@@ -63,8 +63,6 @@ struct edit_baton {
 };
 
 #define FSPATH(relpath, pool) apr_pstrcat(pool, "/", relpath, SVN_VA_NULL)
-#define UNUSED(x) ((void)(x))
-
 
 static svn_error_t *
 get_root(svn_fs_root_t **root,
@@ -522,7 +520,8 @@ alter_symlink_cb(void *baton,
 {
   struct edit_baton *eb = baton;
 
-  UNUSED(eb); SVN__NOT_IMPLEMENTED();
+  SVN_UNUSED(eb);
+  SVN__NOT_IMPLEMENTED();
 }
 
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c Fri Nov 14 13:17:55 2014
@@ -393,7 +393,7 @@ synchronized_initialize(void *baton, apr
 {
   common_pool = svn_pool_create(pool);
   base_defn.next = NULL;
-  SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, TRUE, common_pool));
+  SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, common_pool));
 
   /* ### This won't work if POOL is NULL and libsvn_fs is loaded as a DSO
      ### (via libsvn_ra_local say) since the global common_pool will live
@@ -558,6 +558,13 @@ svn_fs_upgrade2(const char *path,
   return SVN_NO_ERROR;
 }
 
+/* A warning handling function that does not abort on errors,
+   but just lets them be returned normally.  */
+static void
+verify_fs_warning_func(void *baton, svn_error_t *err)
+{
+}
+
 svn_error_t *
 svn_fs_verify(const char *path,
               apr_hash_t *fs_config,
@@ -574,6 +581,7 @@ svn_fs_verify(const char *path,
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   fs = fs_new(fs_config, pool);
+  svn_fs_set_warning_func(fs, verify_fs_warning_func, NULL);
 
   SVN_ERR(vtable->verify_fs(fs, path, start, end,
                             notify_func, notify_baton,

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c Fri Nov 14 13:17:55 2014
@@ -121,12 +121,32 @@ svn_fs_bdb__changes_delete(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Return a deep FS API type copy of SOURCE in internal format and allocate
+ * the result in RESULT_POOL.
+ */
+static svn_fs_path_change2_t *
+change_to_fs_change(const change_t *change,
+                    apr_pool_t *result_pool)
+{
+  svn_fs_path_change2_t *result = svn_fs__path_change_create_internal(
+                                    svn_fs_base__id_copy(change->noderev_id,
+                                                         result_pool),
+                                    change->kind,
+                                    result_pool);
+  result->text_mod = change->text_mod;
+  result->prop_mod = change->prop_mod;
+  result->node_kind = svn_node_unknown;
+  result->copyfrom_known = FALSE;
+
+  return result;
+}
 
 /* Merge the internal-use-only CHANGE into a hash of public-FS
    svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
    single succinct change per path. */
 static svn_error_t *
 fold_change(apr_hash_t *changes,
+            apr_hash_t *deletions,
             const change_t *change)
 {
   apr_pool_t *pool = apr_hash_pool_get(changes);
@@ -185,7 +205,7 @@ fold_change(apr_hash_t *changes,
         case svn_fs_path_change_reset:
           /* A reset here will simply remove the path change from the
              hash. */
-          old_change = NULL;
+          new_change = NULL;
           break;
 
         case svn_fs_path_change_delete:
@@ -194,14 +214,21 @@ fold_change(apr_hash_t *changes,
               /* If the path was introduced in this transaction via an
                  add, and we are deleting it, just remove the path
                  altogether. */
-              old_change = NULL;
+              new_change = NULL;
+            }
+          else if (old_change->change_kind == svn_fs_path_change_replace)
+            {
+              /* A deleting a 'replace' restore the original deletion. */
+              new_change = svn_hash_gets(deletions, path);
+              SVN_ERR_ASSERT(new_change);
             }
           else
             {
               /* A deletion overrules all previous changes. */
-              old_change->change_kind = svn_fs_path_change_delete;
-              old_change->text_mod = change->text_mod;
-              old_change->prop_mod = change->prop_mod;
+              new_change = old_change;
+              new_change->change_kind = svn_fs_path_change_delete;
+              new_change->text_mod = change->text_mod;
+              new_change->prop_mod = change->prop_mod;
             }
           break;
 
@@ -209,38 +236,33 @@ fold_change(apr_hash_t *changes,
         case svn_fs_path_change_replace:
           /* An add at this point must be following a previous delete,
              so treat it just like a replace. */
-          old_change->change_kind = svn_fs_path_change_replace;
-          old_change->node_rev_id = svn_fs_base__id_copy(change->noderev_id,
-                                                         pool);
-          old_change->text_mod = change->text_mod;
-          old_change->prop_mod = change->prop_mod;
+
+          new_change = change_to_fs_change(change, pool);
+          new_change->change_kind = svn_fs_path_change_replace;
+
+          /* Remember the original deletion.
+           * Make sure to allocate the hash key in a durable pool. */
+          svn_hash_sets(deletions,
+                        apr_pstrdup(apr_hash_pool_get(deletions), path),
+                        old_change);
           break;
 
         case svn_fs_path_change_modify:
         default:
+          new_change = old_change;
           if (change->text_mod)
-            old_change->text_mod = TRUE;
+            new_change->text_mod = TRUE;
           if (change->prop_mod)
-            old_change->prop_mod = TRUE;
+            new_change->prop_mod = TRUE;
           break;
         }
-
-      /* Point our new_change to our (possibly modified) old_change. */
-      new_change = old_change;
     }
   else
     {
       /* This change is new to the hash, so make a new public change
          structure from the internal one (in the hash's pool), and dup
          the path into the hash's pool, too. */
-      new_change = svn_fs__path_change_create_internal(
-                       svn_fs_base__id_copy(change->noderev_id, pool),
-                       change->kind,
-                       pool);
-      new_change->text_mod = change->text_mod;
-      new_change->prop_mod = change->prop_mod;
-      new_change->node_kind = svn_node_unknown;
-      new_change->copyfrom_known = FALSE;
+      new_change = change_to_fs_change(change, pool);
       path = apr_pstrdup(pool, change->path);
     }
 
@@ -265,6 +287,8 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
   svn_error_t *err = SVN_NO_ERROR;
   apr_hash_t *changes = apr_hash_make(pool);
   apr_pool_t *subpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_hash_t *deletions = apr_hash_make(subpool);
 
   /* Get a cursor on the first record matching KEY, and then loop over
      the records, adding them to the return array. */
@@ -286,11 +310,11 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
       svn_skel_t *result_skel;
 
       /* Clear the per-iteration subpool. */
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
       /* RESULT now contains a change record associated with KEY.  We
          need to parse that skel into an change_t structure ...  */
-      result_skel = svn_skel__parse(result.data, result.size, subpool);
+      result_skel = svn_skel__parse(result.data, result.size, iterpool);
       if (! result_skel)
         {
           err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -298,12 +322,12 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
                                   key);
           goto cleanup;
         }
-      err = svn_fs_base__parse_change_skel(&change, result_skel, subpool);
+      err = svn_fs_base__parse_change_skel(&change, result_skel, iterpool);
       if (err)
         goto cleanup;
 
       /* ... and merge it with our return hash.  */
-      err = fold_change(changes, change);
+      err = fold_change(changes, deletions, change);
       if (err)
         goto cleanup;
 
@@ -319,7 +343,7 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
         {
           apr_hash_index_t *hi;
 
-          for (hi = apr_hash_first(subpool, changes);
+          for (hi = apr_hash_first(iterpool, changes);
                hi;
                hi = apr_hash_next(hi))
             {
@@ -347,6 +371,7 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
     }
 
   /* Destroy the per-iteration subpool. */
+  svn_pool_destroy(iterpool);
   svn_pool_destroy(subpool);
 
   /* If there are no (more) change records for this KEY, we're

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c Fri Nov 14 13:17:55 2014
@@ -380,7 +380,7 @@ bdb_init_cb(void *baton, apr_pool_t *poo
   bdb_cache_pool = svn_pool_create(pool);
   bdb_cache = apr_hash_make(bdb_cache_pool);
 
-  SVN_ERR(svn_mutex__init(&bdb_cache_lock, TRUE, TRUE, bdb_cache_pool));
+  SVN_ERR(svn_mutex__init(&bdb_cache_lock, TRUE, bdb_cache_pool));
   apr_pool_cleanup_register(bdb_cache_pool, NULL, clear_cache,
                             apr_pool_cleanup_null);
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c Fri Nov 14 13:17:55 2014
@@ -1084,7 +1084,7 @@ svn_fs_base__clean_logs(const char *live
 
   {  /* Process unused logs from live area */
     int idx;
-    apr_pool_t *sub_pool = svn_pool_create(pool);
+    apr_pool_t *subpool = svn_pool_create(pool);
 
     /* Process log files. */
     for (idx = 0; idx < logfiles->nelts; idx++)
@@ -1093,9 +1093,9 @@ svn_fs_base__clean_logs(const char *live
         const char *live_log_path;
         const char *backup_log_path;
 
-        svn_pool_clear(sub_pool);
-        live_log_path = svn_dirent_join(live_path, log_file, sub_pool);
-        backup_log_path = svn_dirent_join(backup_path, log_file, sub_pool);
+        svn_pool_clear(subpool);
+        live_log_path = svn_dirent_join(live_path, log_file, subpool);
+        backup_log_path = svn_dirent_join(backup_path, log_file, subpool);
 
         { /* Compare files. No point in using MD5 and wasting CPU cycles as we
              got full copies of both logs */
@@ -1112,17 +1112,17 @@ svn_fs_base__clean_logs(const char *live
             SVN_ERR(svn_io_files_contents_same_p(&files_match,
                                                  live_log_path,
                                                  backup_log_path,
-                                                 sub_pool));
+                                                 subpool));
 
           /* If log files do not match, go to the next log file. */
           if (!files_match)
             continue;
         }
 
-        SVN_ERR(svn_io_remove_file2(live_log_path, FALSE, sub_pool));
+        SVN_ERR(svn_io_remove_file2(live_log_path, FALSE, subpool));
       }
 
-    svn_pool_destroy(sub_pool);
+    svn_pool_destroy(subpool);
   }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c Fri Nov 14 13:17:55 2014
@@ -74,7 +74,7 @@ dbg_log_access(svn_fs_t *fs,
                svn_revnum_t revision,
                apr_uint64_t item_index,
                void *item,
-               int item_type,
+               apr_uint32_t item_type,
                apr_pool_t *scratch_pool)
 {
   /* no-op if this macro is not defined */
@@ -154,7 +154,7 @@ dbg_log_access(svn_fs_t *fs,
     }
 
   /* some info is only available in format7 repos */
-  if (svn_fs_fs__use_log_addressing(fs, revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       /* reverse index lookup: get item description in ENTRY */
       SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, revision,
@@ -284,8 +284,7 @@ use_block_read(svn_fs_t *fs,
                svn_revnum_t revision)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  return   svn_fs_fs__use_log_addressing(fs, revision)
-        && ffd->use_block_read;
+  return svn_fs_fs__use_log_addressing(fs) && ffd->use_block_read;
 }
 
 /* Get the node-revision for the node ID in FS.
@@ -552,7 +551,7 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   fs_fs_data_t *ffd = fs->fsap_data;
   SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
 
-  if (svn_fs_fs__use_log_addressing(fs, rev))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       *root_id_p = svn_fs_fs__id_create_root(rev, result_pool);
     }
@@ -922,7 +921,7 @@ svn_fs_fs__check_rep(representation_t *r
                      void **hint,
                      apr_pool_t *scratch_pool)
 {
-  if (svn_fs_fs__use_log_addressing(fs, rep->revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       apr_off_t offset;
       svn_fs_fs__p2l_entry_t *entry;
@@ -937,8 +936,9 @@ svn_fs_fs__check_rep(representation_t *r
 
       /* This may fail if there is a background pack operation (can't auto-
          retry because the item offset lookup has to be redone as well). */
-      SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, rep->revision,
-                                          offset, scratch_pool));
+      SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file,
+                                          rep->revision, offset,
+                                          scratch_pool, scratch_pool));
 
       if (   entry == NULL
           || entry->type < SVN_FS_FS__ITEM_TYPE_FILE_REP
@@ -978,7 +978,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
   svn_revnum_t shard_size = ffd->max_files_per_dir
                           ? ffd->max_files_per_dir
                           : 1;
-  apr_pool_t *sub_pool = svn_pool_create(scratch_pool);
+  apr_pool_t *subpool = svn_pool_create(scratch_pool);
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_boolean_t is_delta = FALSE;
   int count = 0;
@@ -1014,7 +1014,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
                                     &file_hint,
                                     &base_rep,
                                     fs,
-                                    sub_pool,
+                                    subpool,
                                     iterpool));
 
       base_rep.revision = header->base_revision;
@@ -1023,18 +1023,28 @@ svn_fs_fs__rep_chain_length(int *chain_l
       svn_fs_fs__id_txn_reset(&base_rep.txn_id);
       is_delta = header->type == svn_fs_fs__rep_delta;
 
+      /* Clear it the SUBPOOL once in a while.  Doing it too frequently
+       * renders the FILE_HINT ineffective.  Doing too infrequently, may
+       * leave us with too many open file handles.
+       *
+       * Note that this is mostly about efficiency, with larger values
+       * being more efficient, and any non-zero value is legal here.  When
+       * reading deltified contents, we may keep 10s of rev files open at
+       * the same time and the system has to cope with that.  Thus, the
+       * limit of 16 chosen below is in the same ballpark.
+       */
       ++count;
       if (count % 16 == 0)
         {
           file_hint = NULL;
-          svn_pool_clear(sub_pool);
+          svn_pool_clear(subpool);
         }
     }
   while (is_delta && base_rep.revision);
 
   *chain_length = count;
   *shard_count = shards;
-  svn_pool_destroy(sub_pool);
+  svn_pool_destroy(subpool);
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -2393,7 +2403,7 @@ read_dir_entries(apr_array_header_t *ent
                            _("Directory entry corrupt in '%s'"),
                            svn_fs_fs__id_unparse(id, scratch_pool)->data);
 
-      dirent->id = svn_fs_fs__id_parse(str, result_pool);
+      SVN_ERR(svn_fs_fs__id_parse(&dirent->id, str, result_pool));
 
       /* In incremental mode, update the hash; otherwise, write to the
        * final array.  Be sure to use hash keys that survive this iteration.
@@ -2710,7 +2720,7 @@ svn_fs_fs__get_changes(apr_array_header_
         {
           /* Addressing is very different for old formats
            * (needs to read the revision trailer). */
-          if (svn_fs_fs__use_log_addressing(fs, rev))
+          if (svn_fs_fs__use_log_addressing(fs))
             SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs,
                                            revision_file, rev, NULL,
                                            SVN_FS_FS__ITEM_INDEX_CHANGES,
@@ -3251,7 +3261,8 @@ block_read(void **result,
       block_start = offset - (offset % ffd->block_size);
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
                                           revision, block_start,
-                                          ffd->block_size, scratch_pool));
+                                          ffd->block_size, scratch_pool,
+                                          scratch_pool));
 
       SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
                            iterpool));
@@ -3286,7 +3297,7 @@ block_read(void **result,
                             && entry->size < ffd->block_size))
             {
               void *item = NULL;
-              SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET,
+              SVN_ERR(svn_io_file_seek(revision_file->file, APR_SET,
                                        &entry->offset, iterpool));
               switch (entry->type)
                 {

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c Fri Nov 14 13:17:55 2014
@@ -66,9 +66,8 @@ normalize_key_part(const char *original,
   return normalized->data;
 }
 
-/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS and *CACHE_REVPROPS flags will be set
-   according to FS->CONFIG.  *CACHE_NAMESPACE receives the cache prefix
-   to use.
+/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS flags will be set according to
+   FS->CONFIG.  *CACHE_NAMESPACE receives the cache prefix to use.
 
    Use FS->pool for allocating the memcache and CACHE_NAMESPACE, and POOL
    for temporary allocations. */
@@ -76,7 +75,6 @@ static svn_error_t *
 read_config(const char **cache_namespace,
             svn_boolean_t *cache_txdeltas,
             svn_boolean_t *cache_fulltexts,
-            svn_boolean_t *cache_revprops,
             svn_fs_t *fs,
             apr_pool_t *pool)
 {
@@ -119,24 +117,6 @@ read_config(const char **cache_namespace
                          SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                          TRUE);
 
-  /* don't cache revprops by default.
-   * Revprop caching significantly speeds up operations like
-   * svn ls -v. However, it requires synchronization that may
-   * not be available or efficient in the current server setup.
-   *
-   * If the caller chose option "2", enable revprop caching if
-   * the required API support is there to make it efficient.
-   */
-  if (strcmp(svn_hash__get_cstring(fs->config,
-                                   SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                                   ""), "2"))
-    *cache_revprops
-      = svn_hash__get_bool(fs->config,
-                           SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                           FALSE);
-  else
-    *cache_revprops = svn_named_atomic__is_efficient();
-
   return SVN_NO_ERROR;
 }
 
@@ -368,14 +348,12 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   svn_boolean_t no_handler = ffd->fail_stop;
   svn_boolean_t cache_txdeltas;
   svn_boolean_t cache_fulltexts;
-  svn_boolean_t cache_revprops;
   const char *cache_namespace;
 
   /* Evaluating the cache configuration. */
   SVN_ERR(read_config(&cache_namespace,
                       &cache_txdeltas,
                       &cache_fulltexts,
-                      &cache_revprops,
                       fs,
                       pool));
 
@@ -581,28 +559,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       ffd->mergeinfo_existence_cache = NULL;
     }
 
-  /* if enabled, cache revprops */
-  if (cache_revprops)
-    {
-      SVN_ERR(create_cache(&(ffd->revprop_cache),
-                           NULL,
-                           membuffer,
-                           0, 0, /* Do not use inprocess cache */
-                           svn_fs_fs__serialize_properties,
-                           svn_fs_fs__deserialize_properties,
-                           sizeof(pair_cache_key_t),
-                           apr_pstrcat(pool, prefix, "REVPROP",
-                                       SVN_VA_NULL),
-                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-    }
-  else
-    {
-      ffd->revprop_cache = NULL;
-    }
-
   /* if enabled, cache text deltas and their combinations */
   if (cache_txdeltas)
     {
@@ -654,70 +610,60 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       ffd->combined_window_cache = NULL;
     }
 
-  if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
-    {
-      SVN_ERR(create_cache(&(ffd->l2p_header_cache),
-                           NULL,
-                           membuffer,
-                           64, 16, /* entry size varies but we must cover
-                                      a reasonable number of revisions (1k) */
-                           svn_fs_fs__serialize_l2p_header,
-                           svn_fs_fs__deserialize_l2p_header,
-                           sizeof(pair_cache_key_t),
-                           apr_pstrcat(pool, prefix, "L2P_HEADER",
-                                       (char *)NULL),
-                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-      SVN_ERR(create_cache(&(ffd->l2p_page_cache),
-                           NULL,
-                           membuffer,
-                           64, 16, /* entry size varies but we must cover
-                                      a reasonable number of revisions (1k) */
-                           svn_fs_fs__serialize_l2p_page,
-                           svn_fs_fs__deserialize_l2p_page,
-                           sizeof(svn_fs_fs__page_cache_key_t),
-                           apr_pstrcat(pool, prefix, "L2P_PAGE",
-                                       (char *)NULL),
-                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-      SVN_ERR(create_cache(&(ffd->p2l_header_cache),
-                           NULL,
-                           membuffer,
-                           4, 1, /* Large entries. Rarely used. */
-                           svn_fs_fs__serialize_p2l_header,
-                           svn_fs_fs__deserialize_p2l_header,
-                           sizeof(pair_cache_key_t),
-                           apr_pstrcat(pool, prefix, "P2L_HEADER",
-                                       (char *)NULL),
-                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-      SVN_ERR(create_cache(&(ffd->p2l_page_cache),
-                           NULL,
-                           membuffer,
-                           4, 16, /* Variably sized entries. Rarely used. */
-                           svn_fs_fs__serialize_p2l_page,
-                           svn_fs_fs__deserialize_p2l_page,
-                           sizeof(svn_fs_fs__page_cache_key_t),
-                           apr_pstrcat(pool, prefix, "P2L_PAGE",
-                                       (char *)NULL),
-                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-    }
-  else
-    {
-      ffd->l2p_header_cache = NULL;
-      ffd->l2p_page_cache = NULL;
-      ffd->p2l_header_cache = NULL;
-      ffd->p2l_page_cache = NULL;
-    }
+  SVN_ERR(create_cache(&(ffd->l2p_header_cache),
+                       NULL,
+                       membuffer,
+                       64, 16, /* entry size varies but we must cover
+                                  a reasonable number of revisions (1k) */
+                       svn_fs_fs__serialize_l2p_header,
+                       svn_fs_fs__deserialize_l2p_header,
+                       sizeof(pair_cache_key_t),
+                       apr_pstrcat(pool, prefix, "L2P_HEADER",
+                                   (char *)NULL),
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
+  SVN_ERR(create_cache(&(ffd->l2p_page_cache),
+                       NULL,
+                       membuffer,
+                       64, 16, /* entry size varies but we must cover
+                                  a reasonable number of revisions (1k) */
+                       svn_fs_fs__serialize_l2p_page,
+                       svn_fs_fs__deserialize_l2p_page,
+                       sizeof(svn_fs_fs__page_cache_key_t),
+                       apr_pstrcat(pool, prefix, "L2P_PAGE",
+                                   (char *)NULL),
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
+  SVN_ERR(create_cache(&(ffd->p2l_header_cache),
+                       NULL,
+                       membuffer,
+                       4, 1, /* Large entries. Rarely used. */
+                       svn_fs_fs__serialize_p2l_header,
+                       svn_fs_fs__deserialize_p2l_header,
+                       sizeof(pair_cache_key_t),
+                       apr_pstrcat(pool, prefix, "P2L_HEADER",
+                                   (char *)NULL),
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
+  SVN_ERR(create_cache(&(ffd->p2l_page_cache),
+                       NULL,
+                       membuffer,
+                       4, 16, /* Variably sized entries. Rarely used. */
+                       svn_fs_fs__serialize_p2l_page,
+                       svn_fs_fs__deserialize_p2l_page,
+                       sizeof(svn_fs_fs__page_cache_key_t),
+                       apr_pstrcat(pool, prefix, "P2L_PAGE",
+                                   (char *)NULL),
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c Fri Nov 14 13:17:55 2014
@@ -44,6 +44,7 @@
 #include "rep-cache.h"
 #include "revprops.h"
 #include "transaction.h"
+#include "util.h"
 #include "verify.h"
 #include "svn_private_config.h"
 #include "private/svn_fs_util.h"
@@ -73,11 +74,28 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
      svn_fs_initialize pool.  It's unlikely that anyone will notice
      the modest expenditure; the alternative is to allocate each structure
      in a subpool, add a reference-count, and add a serialized destructor
-     to the FS vtable.  That's more machinery than it's worth. */
+     to the FS vtable.  That's more machinery than it's worth.
+
+     Picking an appropriate key for the shared data is tricky, because,
+     unfortunately, a filesystem UUID is not really unique.  It is implicitly
+     shared between hotcopied (1), dump / loaded (2) or naively copied (3)
+     filesystems.  We tackle this problem by using a combination of the UUID
+     and an instance ID as the key.  This allows us to avoid key clashing
+     in (1) and (2) for formats >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT, which
+     do support instance IDs.  For old formats the shared data (locks, shared
+     transaction data, ...) will still clash.
+
+     Speaking of (3), there is not so much we can do about it, except maybe
+     provide a convenient way of fixing things.  Naively copied filesystems
+     have identical filesystem UUIDs *and* instance IDs.  With the key being
+     a combination of these two, clashes can be fixed by changing either of
+     them (or both), e.g. with svn_fs_set_uuid(). */
 
   SVN_ERR_ASSERT(fs->uuid);
-  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, fs->uuid,
-                    SVN_VA_NULL);
+  SVN_ERR_ASSERT(ffd->instance_id);
+
+  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX,
+                    fs->uuid, ":", ffd->instance_id, SVN_VA_NULL);
   status = apr_pool_userdata_get(&val, key, common_pool);
   if (status)
     return svn_error_wrap_apr(status, _("Can't fetch FSFS shared data"));
@@ -92,21 +110,19 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
          intra-process synchronization when grabbing the repository write
          lock. */
       SVN_ERR(svn_mutex__init(&ffsd->fs_write_lock,
-                              TRUE, TRUE, common_pool));
+                              SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
 
       /* ... the pack lock ... */
       SVN_ERR(svn_mutex__init(&ffsd->fs_pack_lock,
-                              TRUE, TRUE, common_pool));
+                              SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
 
       /* ... not to mention locking the txn-current file. */
       SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
-                              TRUE, TRUE, common_pool));
+                              SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
 
       /* We also need a mutex for synchronizing access to the active
-         transaction list and free transaction pointer.  This one is
-         enabled unconditionally. */
-      SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock,
-                              TRUE, TRUE, common_pool));
+         transaction list and free transaction pointer. */
+      SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock, TRUE, common_pool));
 
       key = apr_pstrdup(common_pool, key);
       status = apr_pool_userdata_set(ffsd, key, NULL, common_pool);
@@ -202,6 +218,18 @@ fs_info(const void **fsfs_info,
   return SVN_NO_ERROR;
 }
 
+/* Wrapper around svn_fs_fs__set_uuid() adapting between function
+   signatures. */
+static svn_error_t *
+fs_set_uuid(svn_fs_t *fs,
+            const char *uuid,
+            apr_pool_t *pool)
+{
+  /* Whenever we set a new UUID, imply that FS will also be a different
+   * instance (on formats that support this). */
+  return svn_error_trace(svn_fs_fs__set_uuid(fs, uuid, NULL, pool));
+}
+
 
 
 /* The vtable associated with a specific open filesystem. */
@@ -210,7 +238,7 @@ static fs_vtable_t fs_vtable = {
   svn_fs_fs__revision_prop,
   svn_fs_fs__get_revision_proplist,
   svn_fs_fs__change_rev_prop,
-  svn_fs_fs__set_uuid,
+  fs_set_uuid,
   svn_fs_fs__revision_root,
   svn_fs_fs__begin_txn,
   svn_fs_fs__open_txn,
@@ -238,13 +266,22 @@ static svn_error_t *
 initialize_fs_struct(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
-  ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+  ffd->use_log_addressing = FALSE;
 
   fs->vtable = &fs_vtable;
   fs->fsap_data = ffd;
   return SVN_NO_ERROR;
 }
 
+/* Reset vtable and fsap_data fields in FS such that the FS is basically
+ * closed now.  Note that FS must not hold locks when you call this. */
+static void
+uninitialize_fs_struct(svn_fs_t *fs)
+{
+  fs->vtable = NULL;
+  fs->fsap_data = NULL;
+}
+
 /* This implements the fs_library_vtable_t.create() API.  Create a new
    fsfs-backed Subversion filesystem at path PATH and link it into
    *FS.  Perform temporary allocations in POOL, and fs-global allocations
@@ -312,20 +349,53 @@ fs_open_for_recovery(svn_fs_t *fs,
                      apr_pool_t *pool,
                      apr_pool_t *common_pool)
 {
+  svn_error_t * err;
+  svn_revnum_t youngest_rev;
+  apr_pool_t * subpool = svn_pool_create(pool);
+
   /* Recovery for FSFS is currently limited to recreating the 'current'
      file from the latest revision. */
 
   /* The only thing we have to watch out for is that the 'current' file
-     might not exist.  So we'll try to create it here unconditionally,
-     and just ignore any errors that might indicate that it's already
-     present. (We'll need it to exist later anyway as a source for the
-     new file's permissions). */
+     might not exist or contain garbage.  So we'll try to read it here
+     and provide or replace the existing file if we couldn't read it.
+     (We'll also need it to exist later anyway as a source for the new
+     file's permissions). */
 
-  /* Use a partly-filled fs pointer first to create 'current'.  This will fail
-     if 'current' already exists, but we don't care about that. */
+  /* Use a partly-filled fs pointer first to create 'current'. */
   fs->path = apr_pstrdup(fs->pool, path);
-  svn_error_clear(svn_io_file_create(svn_fs_fs__path_current(fs, pool),
-                                     "0 1 1\n", pool));
+
+  SVN_ERR(initialize_fs_struct(fs));
+
+  /* Figure out the repo format and check that we can even handle it. */
+  SVN_ERR(svn_fs_fs__read_format_file(fs, subpool));
+
+  /* Now, read 'current' and try to patch it if necessary. */
+  err = svn_fs_fs__youngest_rev(&youngest_rev, fs, subpool);
+  if (err)
+    {
+      const char *file_path;
+
+      /* 'current' file is missing or contains garbage.  Since we are trying
+       * to recover from whatever problem there is, being picky about the
+       * error code here won't do us much good.  If there is a persistent
+       * problem that we can't fix, it will show up when we try rewrite the
+       * file a few lines further below and we will report the failure back
+       * to the caller.
+       *
+       * Start recovery with HEAD = 0. */
+      svn_error_clear(err);
+      file_path = svn_fs_fs__path_current(fs, subpool);
+
+      /* Best effort to ensure the file exists and is valid.
+       * This may fail for r/o filesystems etc. */
+      SVN_ERR(svn_io_remove_file2(file_path, TRUE, subpool));
+      SVN_ERR(svn_io_file_create_empty(file_path, subpool));
+      SVN_ERR(svn_fs_fs__write_current(fs, 0, 1, 1, subpool));
+    }
+
+  uninitialize_fs_struct(fs);
+  svn_pool_destroy(subpool);
 
   /* Now open the filesystem properly by calling the vtable method directly. */
   return fs_open(fs, path, common_pool_lock, pool, common_pool);
@@ -413,11 +483,13 @@ fs_hotcopy(svn_fs_t *src_fs,
   if (cancel_func)
     SVN_ERR(cancel_func(cancel_baton));
 
-  /* Provide FFD for DST_FS, test / initialize target repo, remove FFD. */
+  /* Test target repo when in INCREMENTAL mode, initialize it when not.
+   * For this, we need our FS internal data structures to be temporarily
+   * available. */
   SVN_ERR(initialize_fs_struct(dst_fs));
   SVN_ERR(svn_fs_fs__hotcopy_prepare_target(src_fs, dst_fs, dst_path,
                                             incremental, pool));
-  dst_fs->fsap_data = NULL;
+  uninitialize_fs_struct(dst_fs);
 
   /* Now, the destination repo should open just fine. */
   SVN_ERR(fs_open(dst_fs, dst_path, common_pool_lock, pool, common_pool));
@@ -458,7 +530,7 @@ fs_delete_fs(const char *path,
              apr_pool_t *pool)
 {
   /* Remove everything. */
-  return svn_io_remove_dir2(path, FALSE, NULL, NULL, pool);
+  return svn_error_trace(svn_io_remove_dir2(path, FALSE, NULL, NULL, pool));
 }
 
 static const svn_version_t *

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h Fri Nov 14 13:17:55 2014
@@ -36,7 +36,6 @@
 #include "private/svn_fs_private.h"
 #include "private/svn_sqlite.h"
 #include "private/svn_mutex.h"
-#include "private/svn_named_atomic.h"
 
 #include "id.h"
 
@@ -58,7 +57,8 @@ extern "C" {
 #define PATH_PACK_LOCK_FILE   "pack-lock"        /* Pack lock file */
 #define PATH_REVS_DIR         "revs"             /* Directory of revisions */
 #define PATH_REVPROPS_DIR     "revprops"         /* Directory of revprops */
-#define PATH_TXNS_DIR         "transactions"     /* Directory of transactions */
+#define PATH_TXNS_DIR         "transactions"     /* Directory of transactions in
+                                                    repos w/o log addressing */
 #define PATH_NODE_ORIGINS_DIR "node-origins"     /* Lazy node-origin cache */
 #define PATH_TXN_PROTOS_DIR   "txn-protorevs"    /* Directory of proto-revs */
 #define PATH_TXN_CURRENT      "txn-current"      /* File with next txn key */
@@ -177,11 +177,24 @@ extern "C" {
 #define SVN_FS_FS__MIN_PACK_LOCK_FORMAT 7
 
 /* Minimum format number that stores mergeinfo-mode flag in changed paths */
-#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT 7
+#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGED_FORMAT 7
+
+/* Minimum format number that supports per-instance filesystem IDs. */
+#define SVN_FS_FS__MIN_INSTANCE_ID_FORMAT 7
 
 /* The minimum format number that supports a configuration file (fsfs.conf) */
 #define SVN_FS_FS__MIN_CONFIG_FILE 4
 
+/* On most operating systems apr implements file locks per process, not
+   per file.  On Windows apr implements the locking as per file handle
+   locks, so we don't have to add our own mutex for just in-process
+   synchronization. */
+#if APR_HAS_THREADS && !defined(WIN32)
+#define SVN_FS_FS__USE_LOCK_MUTEX 1
+#else
+#define SVN_FS_FS__USE_LOCK_MUTEX 0
+#endif
+
 /* Private FSFS-specific data shared between all svn_txn_t objects that
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are
@@ -289,19 +302,18 @@ typedef struct fs_fs_data_t
      layouts) or zero (for linear layouts). */
   int max_files_per_dir;
 
-  /* The first revision that uses logical addressing.  SVN_INVALID_REVNUM
-     if there is no such revision (pre-f7 or non-sharded).  May be a
-     future revision if the current shard started with physical addressing
-     and is not complete, yet. */
-  svn_revnum_t min_log_addressing_rev;
+  /* If set, this FS is using logical addressing. Otherwise, it is using
+     physical addressing. */
+  svn_boolean_t use_log_addressing;
 
-  /* Rev / pack file read granularity. */
+  /* Rev / pack file read granularity in bytes. */
   apr_int64_t block_size;
 
   /* Capacity in entries of log-to-phys index pages */
   apr_int64_t l2p_page_size;
 
-  /* Rev / pack file granularity covered by phys-to-log index pages */
+  /* Rev / pack file granularity (in bytes) covered by a single phys-to-log
+   * index page. */
   apr_int64_t p2l_page_size;
 
   /* If set, parse and cache *all* data of each block that we read
@@ -341,21 +353,6 @@ typedef struct fs_fs_data_t
      rep key (revision/offset) to svn_stringbuf_t. */
   svn_cache__t *fulltext_cache;
 
-  /* Access object to the atomics namespace used by revprop caching.
-     Will be NULL until the first access. */
-  svn_atomic_namespace__t *revprop_namespace;
-
-  /* Access object to the revprop "generation". Will be NULL until
-     the first access. */
-  svn_named_atomic__t *revprop_generation;
-
-  /* Access object to the revprop update timeout. Will be NULL until
-     the first access. */
-  svn_named_atomic__t *revprop_timeout;
-
-  /* Revision property cache.  Maps from (rev,generation) to apr_hash_t. */
-  svn_cache__t *revprop_cache;
-
   /* Node properties cache.  Maps from rep key to apr_hash_t. */
   svn_cache__t *properties_cache;
 
@@ -466,6 +463,12 @@ typedef struct fs_fs_data_t
   /* Pack after every commit. */
   svn_boolean_t pack_after_commit;
 
+  /* Per-instance filesystem ID, which provides an additional level of
+     uniqueness for filesystems that share the same UUID, but should
+     still be distinguishable (e.g. backups produced by svn_fs_hotcopy()
+     or dump / load cycles). */
+  const char *instance_id;
+
   /* Pointer to svn_fs_open. */
   svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *,
                                apr_pool_t *, apr_pool_t *);

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c Fri Nov 14 13:17:55 2014
@@ -86,7 +86,7 @@ are likely some errors because of that.
 /* Declarations. */
 
 static svn_error_t *
-get_youngest(svn_revnum_t *youngest_p, const char *fs_path, apr_pool_t *pool);
+get_youngest(svn_revnum_t *youngest_p, svn_fs_t *fs, apr_pool_t *pool);
 
 /* Pathname helper functions */
 
@@ -213,7 +213,7 @@ with_some_lock_file(with_lock_baton_t *b
           if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
             err = svn_fs_fs__update_min_unpacked_rev(fs, pool);
           if (!err)
-            err = get_youngest(&ffd->youngest_rev_cache, fs->path, pool);
+            err = get_youngest(&ffd->youngest_rev_cache, fs, pool);
         }
 
       if (!err)
@@ -457,18 +457,18 @@ check_format(int format)
 
 /* Read the format number and maximum number of files per directory
    from PATH and return them in *PFORMAT, *MAX_FILES_PER_DIR and
-   MIN_LOG_ADDRESSING_REV respectively.
+   USE_LOG_ADDRESSIONG respectively.
 
    *MAX_FILES_PER_DIR is obtained from the 'layout' format option, and
    will be set to zero if a linear scheme should be used.
-   *MIN_LOG_ADDRESSING_REV is obtained from the 'addressing' format option,
-   and will be set to SVN_INVALID_REVNUM for physical addressing.
+   *USE_LOG_ADDRESSIONG is obtained from the 'addressing' format option,
+   and will be set to FALSE for physical addressing.
 
    Use POOL for temporary allocation. */
 static svn_error_t *
 read_format(int *pformat,
             int *max_files_per_dir,
-            svn_revnum_t *min_log_addressing_rev,
+            svn_boolean_t *use_log_addressing,
             const char *path,
             apr_pool_t *pool)
 {
@@ -515,7 +515,7 @@ read_format(int *pformat,
 
   /* Set the default values for anything that can be set via an option. */
   *max_files_per_dir = 0;
-  *min_log_addressing_rev = SVN_INVALID_REVNUM;
+  *use_log_addressing = FALSE;
 
   /* Read any options. */
   while (!eos)
@@ -547,18 +547,13 @@ read_format(int *pformat,
         {
           if (strcmp(buf->data + 11, "physical") == 0)
             {
-              *min_log_addressing_rev = SVN_INVALID_REVNUM;
+              *use_log_addressing = FALSE;
               continue;
             }
 
-          if (strncmp(buf->data + 11, "logical ", 8) == 0)
+          if (strcmp(buf->data + 11, "logical") == 0)
             {
-              int value;
-
-              /* Check that the argument is numeric. */
-              SVN_ERR(check_format_file_buffer_numeric(buf->data, 19, path, pool));
-              SVN_ERR(svn_cstring_atoi(&value, buf->data + 19));
-              *min_log_addressing_rev = value;
+              *use_log_addressing = TRUE;
               continue;
             }
         }
@@ -572,7 +567,7 @@ read_format(int *pformat,
    * If the format file is inconsistent in that respect, something
    * probably went wrong.
    */
-  if (*min_log_addressing_rev != SVN_INVALID_REVNUM && !*max_files_per_dir)
+  if (*use_log_addressing && !*max_files_per_dir)
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
        _("'%s' specifies logical addressing for a non-sharded repository"),
        svn_dirent_local_style(path, pool));
@@ -610,13 +605,10 @@ svn_fs_fs__write_format(svn_fs_t *fs,
 
   if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
     {
-      if (ffd->min_log_addressing_rev == SVN_INVALID_REVNUM)
-        svn_stringbuf_appendcstr(sb, "addressing physical\n");
+      if (ffd->use_log_addressing)
+        svn_stringbuf_appendcstr(sb, "addressing logical\n");
       else
-        svn_stringbuf_appendcstr(sb,
-                                 apr_psprintf(pool,
-                                              "addressing logical %ld\n",
-                                              ffd->min_log_addressing_rev));
+        svn_stringbuf_appendcstr(sb, "addressing physical\n");
     }
 
   /* svn_io_write_version_file() does a load of magic to allow it to
@@ -644,6 +636,50 @@ svn_fs_fs__fs_supports_mergeinfo(svn_fs_
   return ffd->format >= SVN_FS_FS__MIN_MERGEINFO_FORMAT;
 }
 
+/* Check that BLOCK_SIZE is a valid block / page size, i.e. it is within
+ * the range of what the current system may address in RAM and it is a
+ * power of 2.  Assume that the element size within the block is ITEM_SIZE.
+ * Use SCRATCH_POOL for temporary allocations.
+ */
+static svn_error_t *
+verify_block_size(apr_int64_t block_size,
+                  apr_size_t item_size,
+                  const char *name,
+                  apr_pool_t *scratch_pool
+                 )
+{
+  /* Limit range. */
+  if (block_size <= 0)
+    return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+                             _("%s is too small for fsfs.conf setting '%s'."),
+                             apr_psprintf(scratch_pool,
+                                          "%" APR_INT64_T_FMT,
+                                          block_size),
+                             name);
+
+  if (block_size > SVN_MAX_OBJECT_SIZE / item_size)
+    return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+                             _("%s is too large for fsfs.conf setting '%s'."),
+                             apr_psprintf(scratch_pool,
+                                          "%" APR_INT64_T_FMT,
+                                          block_size),
+                             name);
+
+  /* Ensure it is a power of two.
+   * For positive X,  X & (X-1) will reset the lowest bit set.
+   * If the result is 0, at most one bit has been set. */
+  if (0 != (block_size & (block_size - 1)))
+    return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+                             _("%s is invalid for fsfs.conf setting '%s' "
+                               "because it is not a power of 2."),
+                             apr_psprintf(scratch_pool,
+                                          "%" APR_INT64_T_FMT,
+                                          block_size),
+                             name);
+
+  return SVN_NO_ERROR;
+}
+
 /* Read the configuration information of the file system at FS_PATH
  * and set the respective values in FFD.  Use pools as usual.
  */
@@ -717,8 +753,8 @@ read_config(fs_fs_data_t *ffd,
                                    CONFIG_SECTION_PACKED_REVPROPS,
                                    CONFIG_OPTION_REVPROP_PACK_SIZE,
                                    ffd->compress_packed_revprops
-                                       ? 0x100
-                                       : 0x40));
+                                       ? 0x10
+                                       : 0x4));
 
       ffd->revprop_pack_size *= 1024;
     }
@@ -743,15 +779,27 @@ read_config(fs_fs_data_t *ffd,
                                    CONFIG_OPTION_P2L_PAGE_SIZE,
                                    0x400));
 
+      /* Don't accept unreasonable or illegal values.
+       * Block size and P2L page size are in kbytes;
+       * L2P blocks are arrays of apr_off_t. */
+      SVN_ERR(verify_block_size(ffd->block_size, 0x400,
+                                CONFIG_OPTION_BLOCK_SIZE, scratch_pool));
+      SVN_ERR(verify_block_size(ffd->p2l_page_size, 0x400,
+                                CONFIG_OPTION_P2L_PAGE_SIZE, scratch_pool));
+      SVN_ERR(verify_block_size(ffd->l2p_page_size, sizeof(apr_off_t),
+                                CONFIG_OPTION_L2P_PAGE_SIZE, scratch_pool));
+
+      /* convert kBytes to bytes */
       ffd->block_size *= 0x400;
       ffd->p2l_page_size *= 0x400;
+      /* L2P pages are in entries - not in (k)Bytes */
     }
   else
     {
       /* should be irrelevant but we initialize them anyway */
-      ffd->block_size = 0x1000;
-      ffd->l2p_page_size = 0x2000;
-      ffd->p2l_page_size = 0x100000;
+      ffd->block_size = 0x1000; /* Matches default APR file buffer size. */
+      ffd->l2p_page_size = 0x2000;    /* Matches above default. */
+      ffd->p2l_page_size = 0x100000;  /* Matches above default in bytes. */
     }
 
   if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -910,20 +958,16 @@ write_config(svn_fs_t *fs,
 "### much larger than the limit set here.  The threshold will be applied"    NL
 "### before optional compression takes place."                               NL
 "### Large values will reduce disk space usage at the expense of increased"  NL
-"### latency and CPU usage reading and changing individual revprops.  They"  NL
-"### become an advantage when revprop caching has been enabled because a"    NL
-"### lot of data can be read in one go.  Values smaller than 4 kByte will"   NL
-"### not improve latency any further and quickly render revprop packing"     NL
-"### ineffective."                                                           NL
-"### revprop-pack-size is 64 kBytes by default for non-compressed revprop"   NL
-"### pack files and 256 kBytes when compression has been enabled."           NL
-"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 64"                                 NL
+"### latency and CPU usage reading and changing individual revprops."        NL
+"### Values smaller than 4 kByte will not improve latency any further and "  NL
+"### quickly render revprop packing ineffective."                            NL
+"### revprop-pack-size is 4 kBytes by default for non-compressed revprop"    NL
+"### pack files and 16 kBytes when compression has been enabled."            NL
+"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 4"                                  NL
 "###"                                                                        NL
 "### To save disk space, packed revprop files may be compressed.  Standard"  NL
 "### revprops tend to allow for very effective compression.  Reading and"    NL
-"### even more so writing, become significantly more CPU intensive.  With"   NL
-"### revprop caching enabled, the overhead can be offset by reduced I/O"     NL
-"### unless you often modify revprops after packing."                        NL
+"### even more so writing, become significantly more CPU intensive."         NL
 "### Compressing packed revprops is disabled by default."                    NL
 "# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = false"                       NL
 ""                                                                           NL
@@ -943,23 +987,18 @@ write_config(svn_fs_t *fs,
 "### may improve latency while still maximizing throughput.  If block-read"  NL
 "### has not been enabled, this will be capped to 4 kBytes."                 NL
 "### Can be changed at any time but must be a power of 2."                   NL
-"### block-size is 64 kBytes by default."                                    NL
+"### block-size is given in kBytes and with a default of 64 kBytes."         NL
 "# " CONFIG_OPTION_BLOCK_SIZE " = 64"                                        NL
 "###"                                                                        NL
 "### The log-to-phys index maps data item numbers to offsets within the"     NL
-"### rev or pack file.  A revision typically contains 2 .. 5 such items"     NL
-"### per changed path.  For each revision, at least one page is being"       NL
-"### allocated in the l2p index with unused parts resulting in no wasted"    NL
-"### space."                                                                 NL
-"### Changing this parameter only affects larger revisions with thousands"   NL
-"### of changed paths.  A smaller value means that more pages need to be"    NL
-"### allocated for such revisions, increasing the size of the page table"    NL
-"### meaning it takes longer to read that table (once).  Access to each"     NL
-"### page is then faster because less data has to read.  So, if you have"    NL
-"### several extremely large revisions (approaching 1 mio changes),  think"  NL
+"### rev or pack file.  This index is organized in pages of a fixed maximum" NL
+"### capacity.  To access an item, the page table and the respective page"   NL
+"### must be read."                                                          NL
+"### This parameter only affects revisions with thousands of changed paths." NL
+"### If you have several extremely large revisions (~1 mio changes), think"  NL
 "### about increasing this setting.  Reducing the value will rarely result"  NL
 "### in a net speedup."                                                      NL
-"### This is an expert setting.  Any non-zero value is possible."            NL
+"### This is an expert setting.  Must be a power of 2."                      NL
 "### l2p-page-size is 8192 entries by default."                              NL
 "# " CONFIG_OPTION_L2P_PAGE_SIZE " = 8192"                                   NL
 "###"                                                                        NL
@@ -976,7 +1015,7 @@ write_config(svn_fs_t *fs,
 "### smaller changes."                                                       NL
 "### For source code repositories, this should be about 16x the block-size." NL
 "### Must be a power of 2."                                                  NL
-"### p2l-page-size is 1024 kBytes by default."                               NL
+"### p2l-page-size is given in kBytes and with a default of 1024 kBytes."    NL
 "# " CONFIG_OPTION_P2L_PAGE_SIZE " = 1024"                                   NL
 ;
 #undef NL
@@ -990,8 +1029,14 @@ static svn_error_t *
 read_global_config(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  ffd->use_block_read
-    = svn_hash__get_bool(fs->config, SVN_FS_CONFIG_FSFS_BLOCK_READ, FALSE);
+
+  /* Providing a config hash is optional. */
+  if (fs->config)
+    ffd->use_block_read = svn_hash__get_bool(fs->config,
+                                             SVN_FS_CONFIG_FSFS_BLOCK_READ,
+                                             FALSE);
+  else
+    ffd->use_block_read = FALSE;
 
   /* Ignore the user-specified larger block size if we don't use block-read.
      Defaulting to 4k gives us the same access granularity in format 7 as in
@@ -1002,36 +1047,73 @@ read_global_config(svn_fs_t *fs)
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
+/* Read FS's UUID file and store the data in the FS struct. */
+static svn_error_t *
+read_uuid(svn_fs_t *fs,
+          apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_file_t *uuid_file;
-  int format, max_files_per_dir;
-  svn_revnum_t min_log_addressing_rev;
   char buf[APR_UUID_FORMATTED_LENGTH + 2];
   apr_size_t limit;
 
-  fs->path = apr_pstrdup(fs->pool, path);
+  /* Read the repository uuid. */
+  SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, scratch_pool),
+                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
+                           scratch_pool));
+
+  limit = sizeof(buf);
+  SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, scratch_pool));
+  fs->uuid = apr_pstrdup(fs->pool, buf);
 
-  /* Read the FS format number. */
-  SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
-                      path_format(fs, pool), pool));
+  /* Read the instance ID. */
+  if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+    {
+      limit = sizeof(buf);
+      SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit,
+                                      scratch_pool));
+      ffd->instance_id = apr_pstrdup(fs->pool, buf);
+    }
+  else
+    {
+      ffd->instance_id = fs->uuid;
+    }
+
+  SVN_ERR(svn_io_file_close(uuid_file, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__read_format_file(svn_fs_t *fs, apr_pool_t *scratch_pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  int format, max_files_per_dir;
+  svn_boolean_t use_log_addressing;
 
-  /* Now we've got a format number no matter what. */
+  /* Read info from format file. */
+  SVN_ERR(read_format(&format, &max_files_per_dir, &use_log_addressing,
+                      path_format(fs, scratch_pool), scratch_pool));
+
+  /* Now that we've got *all* info, store / update values in FFD. */
   ffd->format = format;
   ffd->max_files_per_dir = max_files_per_dir;
-  ffd->min_log_addressing_rev = min_log_addressing_rev;
+  ffd->use_log_addressing = use_log_addressing;
 
-  /* Read in and cache the repository uuid. */
-  SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool),
-                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+  return SVN_NO_ERROR;
+}
 
-  limit = sizeof(buf);
-  SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));
-  fs->uuid = apr_pstrdup(fs->pool, buf);
+svn_error_t *
+svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  fs->path = apr_pstrdup(fs->pool, path);
 
-  SVN_ERR(svn_io_file_close(uuid_file, pool));
+  /* Read the FS format file. */
+  SVN_ERR(svn_fs_fs__read_format_file(fs, pool));
+
+  /* Read in and cache the repository uuid. */
+  SVN_ERR(read_uuid(fs, pool));
 
   /* Read the min unpacked revision. */
   if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -1043,7 +1125,7 @@ svn_fs_fs__open(svn_fs_t *fs, const char
   /* Global configuration options. */
   SVN_ERR(read_global_config(fs));
 
-  return get_youngest(&(ffd->youngest_rev_cache), path, pool);
+  return get_youngest(&(ffd->youngest_rev_cache), fs, pool);
 }
 
 /* Wrapper around svn_io_file_create which ignores EEXIST. */
@@ -1079,13 +1161,13 @@ upgrade_body(void *baton, apr_pool_t *po
   svn_fs_t *fs = upgrade_baton->fs;
   fs_fs_data_t *ffd = fs->fsap_data;
   int format, max_files_per_dir;
-  svn_revnum_t min_log_addressing_rev;
+  svn_boolean_t use_log_addressing;
   const char *format_path = path_format(fs, pool);
   svn_node_kind_t kind;
   svn_boolean_t needs_revprop_shard_cleanup = FALSE;
 
   /* Read the FS format number and max-files-per-dir setting. */
-  SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
+  SVN_ERR(read_format(&format, &max_files_per_dir, &use_log_addressing,
                       format_path, pool));
 
   /* If the config file does not exist, create one. */
@@ -1126,10 +1208,8 @@ upgrade_body(void *baton, apr_pool_t *po
      dir, make that directory.  */
   if (format < SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
     {
-      /* We don't use path_txn_proto_rev() here because it expects
-         we've already bumped our format. */
       SVN_ERR(svn_io_make_dir_recursively(
-          svn_dirent_join(fs->path, PATH_TXN_PROTOS_DIR, pool), pool));
+          svn_fs_fs__path_txn_proto_revs(fs, pool), pool));
     }
 
   /* If our filesystem is new enough, write the min unpacked rev file. */
@@ -1154,20 +1234,24 @@ upgrade_body(void *baton, apr_pool_t *po
                                                pool));
     }
 
-  if (   format < SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT
-      && max_files_per_dir > 0)
-    {
-      min_log_addressing_rev
-        = (ffd->youngest_rev_cache / max_files_per_dir + 1)
-        * max_files_per_dir;
-    }
+  /* We will need the UUID info shortly ...
+     Read it before the format bump as the UUID file still uses the old
+     format. */
+  SVN_ERR(read_uuid(fs, pool));
 
-  /* Bump the format file. */
+  /* Update the format info in the FS struct.  Upgrade steps further
+     down will use the format from FS to create missing info. */
   ffd->format = SVN_FS_FS__FORMAT_NUMBER;
   ffd->max_files_per_dir = max_files_per_dir;
-  ffd->min_log_addressing_rev = min_log_addressing_rev;
+  ffd->use_log_addressing = use_log_addressing;
 
+  /* Always add / bump the instance ID such that no form of caching
+     accidentally uses outdated information.  Keep the UUID. */
+  SVN_ERR(svn_fs_fs__set_uuid(fs, fs->uuid, NULL, pool));
+
+  /* Bump the format file. */
   SVN_ERR(svn_fs_fs__write_format(fs, TRUE, pool));
+
   if (upgrade_baton->notify_func)
     SVN_ERR(upgrade_baton->notify_func(upgrade_baton->notify_baton,
                                        SVN_FS_FS__FORMAT_NUMBER,
@@ -1211,17 +1295,11 @@ svn_fs_fs__upgrade(svn_fs_t *fs,
    POOL. */
 static svn_error_t *
 get_youngest(svn_revnum_t *youngest_p,
-             const char *fs_path,
+             svn_fs_t *fs,
              apr_pool_t *pool)
 {
-  svn_stringbuf_t *buf;
-  SVN_ERR(svn_fs_fs__read_content(&buf,
-                                  svn_dirent_join(fs_path, PATH_CURRENT,
-                                                  pool),
-                                  pool));
-
-  *youngest_p = SVN_STR_TO_REV(buf->data);
-
+  apr_uint64_t dummy;
+  SVN_ERR(svn_fs_fs__read_current(youngest_p, &dummy, &dummy, fs, pool));
   return SVN_NO_ERROR;
 }
 
@@ -1233,12 +1311,33 @@ svn_fs_fs__youngest_rev(svn_revnum_t *yo
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
-  SVN_ERR(get_youngest(youngest_p, fs->path, pool));
+  SVN_ERR(get_youngest(youngest_p, fs, pool));
   ffd->youngest_rev_cache = *youngest_p;
 
   return SVN_NO_ERROR;
 }
 
+int
+svn_fs_fs__shard_size(svn_fs_t *fs)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  return ffd->max_files_per_dir;
+}
+
+svn_error_t *
+svn_fs_fs__min_unpacked_rev(svn_revnum_t *min_unpacked,
+                            svn_fs_t *fs,
+                            apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, pool));
+  *min_unpacked = ffd->min_unpacked_rev;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__ensure_revision_exists(svn_revnum_t rev,
                                   svn_fs_t *fs,
@@ -1256,7 +1355,7 @@ svn_fs_fs__ensure_revision_exists(svn_re
   if (rev <= ffd->youngest_rev_cache)
     return SVN_NO_ERROR;
 
-  SVN_ERR(get_youngest(&(ffd->youngest_rev_cache), fs->path, pool));
+  SVN_ERR(get_youngest(&(ffd->youngest_rev_cache), fs, pool));
 
   /* Check again. */
   if (rev <= ffd->youngest_rev_cache)
@@ -1330,10 +1429,15 @@ svn_fs_fs__file_text_rep_equal(svn_boole
     }
 
   /* Old repositories may not have the SHA1 checksum handy.
-     This check becomes expensive.  Skip it unless explicitly required. */
+     This check becomes expensive.  Skip it unless explicitly required.
+
+     We already have seen that the ID is different, so produce a likely
+     false negative as allowed by the API description - even though the
+     MD5 matched, there is an extremely slim chance that the SHA1 wouldn't.
+   */
   if (!strict)
     {
-      *equal = TRUE;
+      *equal = FALSE;
       return SVN_NO_ERROR;
     }
 
@@ -1465,7 +1569,7 @@ write_revision_zero(svn_fs_t *fs,
   svn_string_t date;
 
   /* Write out a rev file for revision 0. */
-  if (svn_fs_fs__use_log_addressing(fs, 0))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       apr_array_header_t *index_entries;
       svn_fs_fs__p2l_entry_t *entry;
@@ -1550,59 +1654,29 @@ write_revision_zero(svn_fs_t *fs,
 }
 
 svn_error_t *
-svn_fs_fs__create(svn_fs_t *fs,
-                  const char *path,
-                  apr_pool_t *pool)
+svn_fs_fs__create_file_tree(svn_fs_t *fs,
+                            const char *path,
+                            int format,
+                            int shard_size,
+                            svn_boolean_t use_log_addressing,
+                            apr_pool_t *pool)
 {
-  int format = SVN_FS_FS__FORMAT_NUMBER;
   fs_fs_data_t *ffd = fs->fsap_data;
 
   fs->path = apr_pstrdup(fs->pool, path);
-  /* See if compatibility with older versions was explicitly requested. */
-  if (fs->config)
-    {
-      svn_version_t *compatible_version;
-      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
-                                         pool));
-
-      /* select format number */
-      switch(compatible_version->minor)
-        {
-          case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
-                 _("FSFS is not compatible with Subversion prior to 1.1"));
-
-          case 1:
-          case 2:
-          case 3: format = 1;
-                  break;
-
-          case 4: format = 2;
-                  break;
-
-          case 5: format = 3;
-                  break;
-
-          case 6:
-          case 7: format = 4;
-                  break;
-
-          case 8: format = 6;
-                  break;
-
-          default:format = SVN_FS_FS__FORMAT_NUMBER;
-        }
-    }
   ffd->format = format;
 
-  /* Override the default linear layout if this is a new-enough format. */
+  /* Use an appropriate sharding mode if supported by the format. */
   if (format >= SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT)
-    ffd->max_files_per_dir = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR;
+    ffd->max_files_per_dir = shard_size;
+  else
+    ffd->max_files_per_dir = 0;
 
   /* Select the addressing mode depending on the format. */
   if (format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
-    ffd->min_log_addressing_rev = 0;
+    ffd->use_log_addressing = use_log_addressing;
   else
-    ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+    ffd->use_log_addressing = FALSE;
 
   /* Create the revision data directories. */
   if (ffd->max_files_per_dir)
@@ -1626,23 +1700,22 @@ svn_fs_fs__create(svn_fs_t *fs,
                                         pool));
 
   /* Create the transaction directory. */
-  SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(path, PATH_TXNS_DIR,
-                                                      pool),
+  SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_txns_dir(fs, pool),
                                       pool));
 
   /* Create the protorevs directory. */
   if (format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
-    SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(path, PATH_TXN_PROTOS_DIR,
-                                                      pool),
+    SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_txn_proto_revs(fs,
+                                                                       pool),
                                         pool));
 
   /* Create the 'current' file. */
-  SVN_ERR(svn_io_file_create(svn_fs_fs__path_current(fs, pool),
-                             (format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT
-                              ? "0\n" : "0 1 1\n"),
-                             pool));
+  SVN_ERR(svn_io_file_create_empty(svn_fs_fs__path_current(fs, pool), pool));
+  SVN_ERR(svn_fs_fs__write_current(fs, 0, 1, 1, pool));
+
+  /* Create the 'uuid' file. */
   SVN_ERR(svn_io_file_create_empty(svn_fs_fs__path_lock(fs, pool), pool));
-  SVN_ERR(svn_fs_fs__set_uuid(fs, NULL, pool));
+  SVN_ERR(svn_fs_fs__set_uuid(fs, NULL, NULL, pool));
 
   /* Create the fsfs.conf file if supported.  Older server versions would
      simply ignore the file but that might result in a different behavior
@@ -1675,38 +1748,110 @@ svn_fs_fs__create(svn_fs_t *fs,
                                  pool));
     }
 
+  ffd->youngest_rev_cache = 0;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__create(svn_fs_t *fs,
+                  const char *path,
+                  apr_pool_t *pool)
+{
+  int format = SVN_FS_FS__FORMAT_NUMBER;
+  int shard_size = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR;
+
+  /* Process the given filesystem config. */
+  if (fs->config)
+    {
+      svn_version_t *compatible_version;
+      const char *shard_size_str;
+      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+                                         pool));
+
+      /* select format number */
+      switch(compatible_version->minor)
+        {
+          case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
+                 _("FSFS is not compatible with Subversion prior to 1.1"));
+
+          case 1:
+          case 2:
+          case 3: format = 1;
+                  break;
+
+          case 4: format = 2;
+                  break;
+
+          case 5: format = 3;
+                  break;
+
+          case 6:
+          case 7: format = 4;
+                  break;
+
+          case 8: format = 6;
+                  break;
+
+          default:format = SVN_FS_FS__FORMAT_NUMBER;
+        }
+
+      shard_size_str = svn_hash_gets(fs->config, SVN_FS_CONFIG_FSFS_SHARD_SIZE);
+      if (shard_size_str)
+        {
+          apr_int64_t val;
+          SVN_ERR(svn_cstring_strtoi64(&val, shard_size_str, 0,
+                                       APR_INT32_MAX, 10));
+
+          shard_size = (int) val;
+        }
+    }
+
+  /* Actual FS creation. */
+  SVN_ERR(svn_fs_fs__create_file_tree(fs, path, format, shard_size, TRUE, pool));
+
   /* This filesystem is ready.  Stamp it with a format number. */
   SVN_ERR(svn_fs_fs__write_format(fs, FALSE, pool));
 
-  ffd->youngest_rev_cache = 0;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_fs__set_uuid(svn_fs_t *fs,
                     const char *uuid,
+                    const char *instance_id,
                     apr_pool_t *pool)
 {
-  char *my_uuid;
-  apr_size_t my_uuid_len;
+  fs_fs_data_t *ffd = fs->fsap_data;
   const char *uuid_path = path_uuid(fs, pool);
+  svn_stringbuf_t *contents = svn_stringbuf_create_empty(pool);
 
   if (! uuid)
     uuid = svn_uuid_generate(pool);
 
-  /* Make sure we have a copy in FS->POOL, and append a newline. */
-  my_uuid = apr_pstrcat(fs->pool, uuid, "\n", SVN_VA_NULL);
-  my_uuid_len = strlen(my_uuid);
+  if (! instance_id)
+    instance_id = svn_uuid_generate(pool);
+
+  svn_stringbuf_appendcstr(contents, uuid);
+  svn_stringbuf_appendcstr(contents, "\n");
+
+  if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+    {
+      svn_stringbuf_appendcstr(contents, instance_id);
+      svn_stringbuf_appendcstr(contents, "\n");
+    }
 
   /* We use the permissions of the 'current' file, because the 'uuid'
      file does not exist during repository creation. */
-  SVN_ERR(svn_io_write_atomic(uuid_path, my_uuid, my_uuid_len,
+  SVN_ERR(svn_io_write_atomic(uuid_path, contents->data, contents->len,
                               svn_fs_fs__path_current(fs, pool) /* perms */,
                               pool));
 
-  /* Remove the newline we added, and stash the UUID. */
-  my_uuid[my_uuid_len - 1] = '\0';
-  fs->uuid = my_uuid;
+  fs->uuid = apr_pstrdup(fs->pool, uuid);
+
+  if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+    ffd->instance_id = apr_pstrdup(fs->pool, instance_id);
+  else
+    ffd->instance_id = fs->uuid;
 
   return SVN_NO_ERROR;
 }
@@ -1782,9 +1927,9 @@ svn_fs_fs__get_node_origin(const svn_fs_
         = apr_hash_get(node_origins, node_id_ptr, len);
 
       if (origin_id_str)
-        *origin_id = svn_fs_fs__id_parse(apr_pstrdup(pool,
-                                                     origin_id_str->data),
-                                         pool);
+        SVN_ERR(svn_fs_fs__id_parse(origin_id,
+                                    apr_pstrdup(pool, origin_id_str->data),
+                                    pool));
     }
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h Fri Nov 14 13:17:55 2014
@@ -25,6 +25,11 @@
 
 #include "fs.h"
 
+/* Read the 'format' file of fsfs filesystem FS and store its info in FS.
+ * Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_fs_fs__read_format_file(svn_fs_t *fs, apr_pool_t *scratch_pool);
+
 /* Open the fsfs filesystem pointed to by PATH and associate it with
    filesystem object FS.  Use POOL for temporary allocations.
 
@@ -51,6 +56,17 @@ svn_error_t *svn_fs_fs__youngest_rev(svn
                                      svn_fs_t *fs,
                                      apr_pool_t *pool);
 
+/* Return the shard size of filesystem FS.  Return 0 for non-shared ones. */
+int
+svn_fs_fs__shard_size(svn_fs_t *fs);
+
+/* Set *MIN_UNPACKED to the oldest non-packed revision in filesystem FS.
+   Do any temporary allocation in POOL. */
+svn_error_t *
+svn_fs_fs__min_unpacked_rev(svn_revnum_t *min_unpacked,
+                            svn_fs_t *fs,
+                            apr_pool_t *pool);
+
 /* Return SVN_ERR_FS_NO_SUCH_REVISION if the given revision REV is newer
    than the current youngest revision in FS or is simply not a valid
    revision number, else return success. */
@@ -106,6 +122,25 @@ svn_error_t *svn_fs_fs__file_checksum(sv
 /* Return whether or not the given FS supports mergeinfo metadata. */
 svn_boolean_t svn_fs_fs__fs_supports_mergeinfo(svn_fs_t *fs);
 
+/* Under the repository db PATH, create a FSFS repository with FORMAT,
+ * the given SHARD_SIZE. If USE_LOG_ADDRESSING is non-zero, repository
+ * will use logical addressing. If not supported by the respective format,
+ * the latter two parameters will be ignored. FS will be updated.
+ *
+ * The only file not being written is the 'format' file.  This allows
+ * callers such as hotcopy to modify the contents before turning the
+ * tree into an accessible repository.
+ *
+ * Use POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_fs__create_file_tree(svn_fs_t *fs,
+                            const char *path,
+                            int format,
+                            int shard_size,
+                            svn_boolean_t use_log_addressing,
+                            apr_pool_t *pool);
+
 /* Create a fs_fs fileysystem referenced by FS at path PATH.  Get any
    temporary allocations from POOL.
 
@@ -115,11 +150,13 @@ svn_error_t *svn_fs_fs__create(svn_fs_t 
                                const char *path,
                                apr_pool_t *pool);
 
-/* Set the uuid of repository FS to UUID, if UUID is not NULL;
-   otherwise, set the uuid of FS to a newly generated UUID.  Perform
-   temporary allocations in POOL. */
+/* Set the uuid of repository FS to UUID and the instance ID to INSTANCE_ID.
+   If any of them is NULL, use a newly generated UUID / ID instead.  Ignore
+   INSTANCE_ID whenever instance IDs are not supported by the FS format.
+   Perform temporary allocations in POOL. */
 svn_error_t *svn_fs_fs__set_uuid(svn_fs_t *fs,
                                  const char *uuid,
+                                 const char *instance_id,
                                  apr_pool_t *pool);
 
 /* Return the path to the 'current' file in FS.