You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/03/05 21:34:28 UTC

svn commit: r1297221 [2/7] - in /subversion/branches/ev2-export: ./ build/ac-macros/ build/generator/ build/win32/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings/swig/include...

Modified: subversion/branches/ev2-export/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/util.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/util.c Mon Mar  5 20:34:22 2012
@@ -240,3 +240,163 @@ svn_client__assert_homogeneous_target_ty
 
   return SVN_NO_ERROR;
 }
+
+struct shim_callbacks_baton
+{
+  svn_wc_context_t *wc_ctx;
+  const char *anchor_abspath;
+};
+
+static svn_error_t *
+rationalize_shim_path(const char **local_abspath,
+                      struct shim_callbacks_baton *scb,
+                      const char *path,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL */
+      const char *wcroot_abspath;
+      const char *wcroot_url;
+      const char *relpath;
+
+      SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, scb->wc_ctx,
+                                  scb->anchor_abspath,
+                                  scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__node_get_url(&wcroot_url, scb->wc_ctx, wcroot_abspath,
+                                   scratch_pool, scratch_pool));
+      relpath = svn_uri_skip_ancestor(wcroot_url, path, scratch_pool);
+      *local_abspath = svn_dirent_join(wcroot_abspath, relpath, result_pool);
+    }
+  else
+    *local_abspath = svn_dirent_join(scb->anchor_abspath, path, result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  const char *local_abspath;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *props = apr_hash_make(result_pool);
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  SVN_ERR(svn_wc_get_pristine_props(props, scb->wc_ctx, local_abspath,
+                                    result_pool, scratch_pool));
+
+  if (!*props)
+    *props = apr_hash_make(result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  svn_node_kind_t node_kind;
+  const char *local_abspath;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *kind = svn_kind_unknown;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  SVN_ERR(svn_wc_read_kind(&node_kind, scb->wc_ctx, local_abspath, FALSE,
+                           scratch_pool));
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  const char *local_abspath;
+  svn_stream_t *pristine_stream;
+  svn_stream_t *temp_stream;
+  svn_error_t *err;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  err = svn_wc_get_pristine_contents2(&pristine_stream, scb->wc_ctx,
+                                      local_abspath, scratch_pool,
+                                      scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+
+  SVN_ERR(svn_stream_open_unique(&temp_stream, filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 result_pool, scratch_pool));
+  SVN_ERR(svn_stream_copy3(pristine_stream, temp_stream, NULL, NULL,
+                           scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_delta_shim_callbacks_t *
+svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
+                               const char *anchor_abspath,
+                               apr_pool_t *result_pool)
+{
+  svn_delta_shim_callbacks_t *callbacks =
+                            svn_delta_shim_callbacks_default(result_pool);
+  struct shim_callbacks_baton *scb = apr_pcalloc(result_pool, sizeof(*scb));
+
+  scb->wc_ctx = wc_ctx;
+  scb->anchor_abspath = apr_pstrdup(result_pool, anchor_abspath);
+
+  callbacks->fetch_props_func = fetch_props_func;
+  callbacks->fetch_kind_func = fetch_kind_func;
+  callbacks->fetch_base_func = fetch_base_func;
+  callbacks->fetch_baton = scb;
+
+  return callbacks;
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/compat.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/compat.c Mon Mar  5 20:34:22 2012
@@ -108,7 +108,11 @@ svn_compat_wrap_file_rev_handler(svn_fil
 struct ev2_edit_baton
 {
   svn_editor_t *editor;
+
   apr_hash_t *paths;
+  apr_array_header_t *path_order;
+  int paths_processed;
+
   apr_pool_t *edit_pool;
   struct svn_delta__extra_baton *exb;
   svn_boolean_t closed;
@@ -200,10 +204,12 @@ add_action(struct ev2_edit_baton *eb,
 
   if (action_list == NULL)
     {
+      const char *path_dup = apr_pstrdup(eb->edit_pool, path);
+
       action_list = apr_array_make(eb->edit_pool, 1,
                                    sizeof(struct path_action *));
-      apr_hash_set(eb->paths, apr_pstrdup(eb->edit_pool, path),
-                   APR_HASH_KEY_STRING, action_list);
+      apr_hash_set(eb->paths, path_dup, APR_HASH_KEY_STRING, action_list);
+      APR_ARRAY_PUSH(eb->path_order, const char *) = path_dup;
     }
 
   APR_ARRAY_PUSH(action_list, struct path_action *) = p_action;
@@ -229,7 +235,7 @@ get_children(struct ev2_edit_baton *eb,
       /* Sanitize our paths. */
       if (*p == '/')
         p++;
-      
+
       /* Find potential children. */
       child = svn_relpath_skip_ancestor(path, p);
       if (!child || !*child)
@@ -245,7 +251,7 @@ get_children(struct ev2_edit_baton *eb,
 
   return children;
 }
-                  
+
 
 static svn_error_t *
 process_actions(void *edit_baton,
@@ -260,7 +266,7 @@ process_actions(void *edit_baton,
   svn_boolean_t need_copy = FALSE;
   const char *copyfrom_path;
   svn_revnum_t copyfrom_rev;
-  apr_array_header_t *children;
+  apr_array_header_t *children = NULL;
   svn_stream_t *contents = NULL;
   svn_checksum_t *checksum = NULL;
   svn_revnum_t delete_revnum = SVN_INVALID_REVNUM;
@@ -351,7 +357,7 @@ process_actions(void *edit_baton,
               struct path_checksum_args *pca = action->args;
 
               /* We can only set text on files. */
-              kind = svn_node_file;
+              kind = svn_kind_file;
 
               SVN_ERR(svn_io_file_checksum2(&checksum, pca->path,
                                             svn_checksum_sha1, scratch_pool));
@@ -463,29 +469,21 @@ run_ev2_actions(void *edit_baton,
                 apr_pool_t *scratch_pool)
 {
   struct ev2_edit_baton *eb = edit_baton;
-  apr_array_header_t *sorted_hash;
   apr_pool_t *iterpool;
-  int i;
-
-  /* Sort the paths touched by this edit.
-   * Ev2 doesn't really have any particular need for depth-first-ness, but
-   * we want to ensure all parent directories are handled before children in
-   * the case of adds (which does introduce an element of depth-first-ness). */
-  sorted_hash = svn_sort__hash(eb->paths, svn_sort_compare_items_as_paths,
-                               scratch_pool);
 
   iterpool = svn_pool_create(scratch_pool);
-  for (i = 0; i < sorted_hash->nelts; i++)
-    {
-      svn_sort__item_t *item = &APR_ARRAY_IDX(sorted_hash, i, svn_sort__item_t);
-      apr_array_header_t *actions = item->value;
-      const char *path = item->key;
+
+  /* Possibly pick up where we left off. Ocassionally, we do some of these
+     as part of close_edit() and then some more as part of abort_edit()  */
+  for (; eb->paths_processed < eb->path_order->nelts; ++eb->paths_processed)
+    {
+      const char *path = APR_ARRAY_IDX(eb->path_order, eb->paths_processed,
+                                       const char *);
+      apr_array_header_t *actions = apr_hash_get(eb->paths, path,
+                                                 APR_HASH_KEY_STRING);
 
       svn_pool_clear(iterpool);
       SVN_ERR(process_actions(edit_baton, path, actions, iterpool));
-
-      /* Remove this item from the hash. */
-      apr_hash_set(eb->paths, path, APR_HASH_KEY_STRING, NULL);
     }
   svn_pool_destroy(iterpool);
 
@@ -651,7 +649,7 @@ ev2_absent_directory(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  
+
   *kind = svn_kind_dir;
   SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
 
@@ -802,7 +800,7 @@ ev2_apply_textdelta(void *file_baton,
                     &hb->apply_handler, &hb->apply_baton);
 
   hb->pool = handler_pool;
-                    
+
   *handler_baton = hb;
   *handler = window_handler;
 
@@ -854,7 +852,7 @@ ev2_absent_file(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  
+
   *kind = svn_kind_file;
   SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
 
@@ -904,7 +902,7 @@ ev2_abort_edit(void *edit_baton,
  *  - EXB: An 'extra baton' which is used to communicate between the shims.
  *         Its callbacks should be invoked at the appropriate time by this
  *         shim.
- */ 
+ */
 svn_error_t *
 svn_delta__delta_from_editor(const svn_delta_editor_t **deditor,
                   void **dedit_baton,
@@ -942,6 +940,7 @@ svn_delta__delta_from_editor(const svn_d
 
   eb->editor = editor;
   eb->paths = apr_hash_make(pool);
+  eb->path_order = apr_array_make(pool, 1, sizeof(const char *));
   eb->edit_pool = pool;
   eb->found_abs_paths = found_abs_paths;
   *eb->found_abs_paths = FALSE;
@@ -1122,7 +1121,7 @@ build(struct editor_baton *eb,
              actual structures, not pointers to them. */
           svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
           if (!prop->value)
-            APR_ARRAY_PUSH(operation->prop_dels, const char *) = 
+            APR_ARRAY_PUSH(operation->prop_dels, const char *) =
                                         apr_pstrdup(eb->edit_pool, prop->name);
           else
             apr_hash_set(operation->prop_mods,
@@ -1551,7 +1550,8 @@ drive_tree(struct operation *op,
     {
       /* Open or create our baton. */
       if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
-        SVN_ERR(editor->open_directory(path, parent_op->baton, op->base_revision,
+        SVN_ERR(editor->open_directory(path, parent_op->baton,
+                                       op->base_revision,
                                        scratch_pool, &op->baton));
 
       else if (op->operation == OP_ADD || op->operation == OP_REPLACE)
@@ -1591,7 +1591,7 @@ drive_tree(struct operation *op,
          I don't know that that's a valid assumption... */
 
       void *file_baton = NULL;
-      
+
       /* Open or create our baton. */
       if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
         SVN_ERR(editor->open_file(path, parent_op->baton, op->base_revision,
@@ -1666,7 +1666,7 @@ drive_root(struct operation *root,
       svn_pool_clear(iterpool);
       SVN_ERR(drive_tree(child, root, editor, make_abs_paths, iterpool));
     }
-  
+
   /* We need to close the root directory, but leave it to our caller to call
      close_ or abort_edit(). */
   SVN_ERR(editor->close_directory(root->baton, scratch_pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/editor.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/editor.c Mon Mar  5 20:34:22 2012
@@ -33,7 +33,7 @@
 /* This enables runtime checks of the editor API constraints.  This may
    introduce additional memory and runtime overhead, and should not be used
    in production builds.
-   
+
    ### Remove before release? */
 #define ENABLE_ORDERING_CHECK
 #endif
@@ -420,7 +420,8 @@ svn_editor_add_file(svn_editor_t *editor
 {
   svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(checksum != NULL);
+  SVN_ERR_ASSERT(checksum != NULL
+                    && checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
   SVN_ERR_ASSERT(contents != NULL);
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
@@ -539,6 +540,8 @@ svn_editor_alter_file(svn_editor_t *edit
   SVN_ERR_ASSERT((checksum != NULL && contents != NULL)
                  || (checksum == NULL && contents == NULL));
   SVN_ERR_ASSERT(props != NULL || checksum != NULL);
+  if (checksum)
+    SVN_ERR_ASSERT(checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
 

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c Mon Mar  5 20:34:22 2012
@@ -645,7 +645,7 @@ decode_window(svn_txdelta_window_t *wind
       svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
 
       /* these may in fact simply return references to insend */
-      
+
       SVN_ERR(zlib_decode(insend, newlen, ndout,
                           SVN_DELTA_WINDOW_SIZE));
       SVN_ERR(zlib_decode(data, insend - data, instout,

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c Mon Mar  5 20:34:22 2012
@@ -291,7 +291,7 @@ svn_txdelta__remove_copy(svn_txdelta__op
       /*  we can't modify svn_txdelta_target ops -> stop there */
       if (op->action_code == svn_txdelta_target)
         break;
-      
+
       /*  handle the case that we cannot remove the op entirely */
       if (op->length + len > max_len)
         {
@@ -303,18 +303,18 @@ svn_txdelta__remove_copy(svn_txdelta__op
                op->length -= max_len - len;
                len = max_len;
             }
-          
+
           break;
         }
-        
+
       /* drop the op entirely */
       if (op->action_code == svn_txdelta_new)
         build_baton->new_data->len -= op->length;
-      
+
       len += op->length;
       --build_baton->num_ops;
     }
-    
+
   return len;
 }
 

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c Mon Mar  5 20:34:22 2012
@@ -257,14 +257,18 @@ reverse_match_length(const char *a, cons
       break;
 
   pos -= sizeof(apr_size_t);
-    
+
 #endif
 
+  /* If we find a mismatch at -pos, pos-1 characters matched.
+   */
   while (++pos <= max_len)
-    if (a[-pos] != b[-pos])
-      break;
-    
-  return pos-1;
+    if (a[0-pos] != b[0-pos])
+      return pos - 1;
+
+  /* No mismatch found -> at least MAX_LEN machting chars.
+   */
+  return max_len;
 }
 
 
@@ -390,7 +394,7 @@ compute_delta(svn_txdelta__ops_baton_t *
   apr_size_t lo = 0, pending_insert_start = 0;
 
   /* Optimization: directly compare window starts. If more than 4
-   * bytes match, we can immediately create a matching windows. 
+   * bytes match, we can immediately create a matching windows.
    * Shorter sequences result in a net data increase. */
   lo = match_length(a, b, asize > bsize ? bsize : asize);
   if ((lo > 4) || (lo == bsize))
@@ -442,7 +446,7 @@ compute_delta(svn_txdelta__ops_baton_t *
             svn_txdelta__insert_op(build_baton, svn_txdelta_new,
                                    0, lo - pending_insert_start,
                                    b + pending_insert_start, pool);
-          else 
+          else
             {
               /* the match borders on the previous op. Maybe, we found a
                * match that is better than / overlapping the previous one. */

Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c Mon Mar  5 20:34:22 2012
@@ -155,7 +155,7 @@ get_library_vtable_direct(fs_library_vta
 
     /* Invoke the FS module's initfunc function with the common
        pool protected by a lock. */
-    SVN_MUTEX__WITH_LOCK(common_pool_lock, 
+    SVN_MUTEX__WITH_LOCK(common_pool_lock,
                          initfunc(my_version, vtable, common_pool));
   }
   fs_version = (*vtable)->get_version();
@@ -357,7 +357,7 @@ svn_fs_create(svn_fs_t **fs_p, const cha
 
   /* Perform the actual creation. */
   *fs_p = fs_new(fs_config, pool);
-  
+
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->create(*fs_p, path, pool, common_pool));
   return SVN_NO_ERROR;
@@ -394,7 +394,9 @@ svn_error_t *
 svn_fs_verify(const char *path,
               svn_cancel_func_t cancel_func,
               void *cancel_baton,
-              apr_pool_t *pool) 
+              svn_revnum_t start,
+              svn_revnum_t end,
+              apr_pool_t *pool)
 {
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
@@ -404,7 +406,7 @@ svn_fs_verify(const char *path,
 
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->verify_fs(fs, path, cancel_func, cancel_baton,
-                                         pool, common_pool));
+                                         start, end, pool, common_pool));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h Mon Mar  5 20:34:22 2012
@@ -90,6 +90,8 @@ typedef struct fs_library_vtable_t
   svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
                             /* ### notification? */
                             svn_cancel_func_t cancel_func, void *cancel_baton,
+                            svn_revnum_t start,
+                            svn_revnum_t end,
                             apr_pool_t *pool,
                             apr_pool_t *common_pool);
   svn_error_t *(*delete_fs)(const char *path, apr_pool_t *pool);

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c Mon Mar  5 20:34:22 2012
@@ -378,7 +378,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, bdb_cache_pool));
   apr_pool_cleanup_register(bdb_cache_pool, NULL, clear_cache,
                             apr_pool_cleanup_null);
@@ -493,7 +493,7 @@ static svn_error_t *
 svn_fs_bdb__close_internal(bdb_env_t *bdb)
 {
   svn_error_t *err = SVN_NO_ERROR;
-  
+
   if (--bdb->refcount != 0)
     {
       /* If the environment is panicked and automatic recovery is not
@@ -543,7 +543,7 @@ svn_fs_bdb__close(bdb_env_baton_t *bdb_b
 
   /* This may run during final pool cleanup when the lock is NULL. */
   SVN_MUTEX__WITH_LOCK(bdb_cache_lock, svn_fs_bdb__close_internal(bdb));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -587,7 +587,7 @@ cleanup_env_baton(void *data)
 
 
 static svn_error_t *
-svn_fs_bdb__open_internal(bdb_env_baton_t **bdb_batonp, 
+svn_fs_bdb__open_internal(bdb_env_baton_t **bdb_batonp,
                           const char *path,
                           u_int32_t flags, int mode,
                           apr_pool_t *pool)
@@ -643,7 +643,7 @@ svn_fs_bdb__open_internal(bdb_env_baton_
           svn_error_clear(bdb_close(bdb));
           return svn_error_trace(err);
         }
-        
+
       apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, bdb);
       bdb->flags = flags;
       bdb->refcount = 1;
@@ -669,11 +669,11 @@ svn_fs_bdb__open(bdb_env_baton_t **bdb_b
                  u_int32_t flags, int mode,
                  apr_pool_t *pool)
 {
-  SVN_MUTEX__WITH_LOCK(bdb_cache_lock, 
-                       svn_fs_bdb__open_internal(bdb_batonp, 
-                                                 path, 
-                                                 flags, 
-                                                 mode, 
+  SVN_MUTEX__WITH_LOCK(bdb_cache_lock,
+                       svn_fs_bdb__open_internal(bdb_batonp,
+                                                 path,
+                                                 flags,
+                                                 mode,
                                                  pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c Mon Mar  5 20:34:22 2012
@@ -333,9 +333,10 @@ bdb_write_config(svn_fs_t *fs)
     "#\n"
     "# Make sure you read the documentation at:\n"
     "#\n"
-    "#   http://www.oracle.com/technology/documentation/berkeley-db/db/ref/lock/max.html\n"
+    "#   http://docs.oracle.com/cd/E17076_02/html/programmer_reference/lock_max.html\n"
     "#\n"
     "# before tweaking these values.\n"
+    "#\n"
     "set_lk_max_locks   2000\n"
     "set_lk_max_lockers 2000\n"
     "set_lk_max_objects 2000\n"
@@ -344,9 +345,9 @@ bdb_write_config(svn_fs_t *fs)
     "#\n"
     "# Make sure you read the documentation at:\n"
     "#\n"
-    "#   http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_lg_bsize.html\n"
-    "#   http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_lg_max.html\n"
-    "#   http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/limits.html\n"
+    "#   http://docs.oracle.com/cd/E17076_02/html/api_reference/C/envset_lg_bsize.html\n"
+    "#   http://docs.oracle.com/cd/E17076_02/html/api_reference/C/envset_lg_max.html\n"
+    "#   http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_limits.html\n"
     "#\n"
     "# Increase the size of the in-memory log buffer from the default\n"
     "# of 32 Kbytes to 256 Kbytes.  Decrease the log file size from\n"
@@ -354,24 +355,28 @@ bdb_write_config(svn_fs_t *fs)
     "# space required for hot backups.  The size of the log file must be\n"
     "# at least four times the size of the in-memory log buffer.\n"
     "#\n"
-    "# Note: Decreasing the in-memory buffer size below 256 Kbytes\n"
-    "# will hurt commit performance. For details, see this post from\n"
-    "# Daniel Berlin <da...@dberlin.org>:\n"
+    "# Note: Decreasing the in-memory buffer size below 256 Kbytes will hurt\n"
+    "# hurt commit performance. For details, see:\n"
+    "#\n"
+    "#   http://svn.haxx.se/dev/archive-2002-02/0141.shtml\n"
     "#\n"
-    "# http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgId=161960\n"
     "set_lg_bsize     262144\n"
     "set_lg_max      1048576\n"
     "#\n"
     "# If you see \"log region out of memory\" errors, bump lg_regionmax.\n"
-    "# See http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
-    "# and http://svn.haxx.se/users/archive-2004-10/1001.shtml for more.\n"
+    "# For more information, see:\n"
+    "#\n"
+    "#   http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
+    "#   http://svn.haxx.se/users/archive-2004-10/1000.shtml\n"
+    "#\n"
     "set_lg_regionmax 131072\n"
     "#\n"
     /* ### Configure this with "svnadmin create --bdb-cache-size" */
     "# The default cache size in BDB is only 256k. As explained in\n"
-    "# http://svn.haxx.se/dev/archive-2004-12/0369.shtml, this is too\n"
+    "# http://svn.haxx.se/dev/archive-2004-12/0368.shtml, this is too\n"
     "# small for most applications. Bump this number if \"db_stat -m\"\n"
     "# shows too many cache misses.\n"
+    "#\n"
     "set_cachesize    0 1048576 1\n";
 
   /* Run-time configurable options.
@@ -397,11 +402,12 @@ bdb_write_config(svn_fs_t *fs)
       "# Disable fsync of log files on transaction commit. Read the\n"
       "# documentation about DB_TXN_NOSYNC at:\n"
       "#\n"
-      "#   http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
+      "#   http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
       "#\n"
-      "# [requires Berkeley DB 4.0]\n",
+      "# [requires Berkeley DB 4.0]\n"
+      "#\n",
       /* inactive */
-      "# set_flags DB_TXN_NOSYNC\n",
+      "#set_flags DB_TXN_NOSYNC\n",
       /* active */
       "set_flags DB_TXN_NOSYNC\n" },
     /* Controlled by "svnadmin create --bdb-log-keep" */
@@ -411,11 +417,12 @@ bdb_write_config(svn_fs_t *fs)
       "# Enable automatic removal of unused transaction log files.\n"
       "# Read the documentation about DB_LOG_AUTOREMOVE at:\n"
       "#\n"
-      "#   http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
+      "#   http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
       "#\n"
-      "# [requires Berkeley DB 4.2]\n",
+      "# [requires Berkeley DB 4.2]\n"
+      "#\n",
       /* inactive */
-      "# set_flags DB_LOG_AUTOREMOVE\n",
+      "#set_flags DB_LOG_AUTOREMOVE\n",
       /* active */
       "set_flags DB_LOG_AUTOREMOVE\n" },
   };
@@ -876,6 +883,8 @@ static svn_error_t *
 base_verify(svn_fs_t *fs, const char *path,
             svn_cancel_func_t cancel_func,
             void *cancel_baton,
+            svn_revnum_t start,
+            svn_revnum_t end,
             apr_pool_t *pool,
             apr_pool_t *common_pool)
 {

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure Mon Mar  5 20:34:22 2012
@@ -104,8 +104,8 @@ structure summary" section of this docum
 NODE-REVISION: how we represent a node revision
 
 We represent a given revision of a file or directory node using a list
-skel (see skel.h for an explanation of skels).  A node revision skel
-has the form:
+skel (see include/private/svn_skel.h for an explanation of skels).
+A node revision skel has the form:
 
     (HEADER PROP-KEY KIND-SPECIFIC ...)
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c Mon Mar  5 20:34:22 2012
@@ -339,6 +339,27 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   SVN_ERR(init_callbacks(ffd->fulltext_cache, fs, no_handler, pool));
 
+  /* initialize revprop cache, if full-text caching has been enabled */
+  if (cache_fulltexts)
+    {
+      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,
+                           APR_HASH_KEY_STRING,
+                           apr_pstrcat(pool, prefix, "REVPROP",
+                                       (char *)NULL),
+                           fs->pool));
+    }
+  else
+    {
+      ffd->revprop_cache = NULL;
+    }
+
+  SVN_ERR(init_callbacks(ffd->revprop_cache, fs, no_handler, pool));
+
   /* initialize txdelta window cache, if that has been enabled */
   if (cache_txdeltas)
     {

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Mon Mar  5 20:34:22 2012
@@ -92,7 +92,7 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
                               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, 
+      SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
                               SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
 
       SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock,
@@ -243,6 +243,8 @@ static svn_error_t *
 fs_verify(svn_fs_t *fs, const char *path,
           svn_cancel_func_t cancel_func,
           void *cancel_baton,
+          svn_revnum_t start,
+          svn_revnum_t end,
           apr_pool_t *pool,
           apr_pool_t *common_pool)
 {
@@ -251,7 +253,7 @@ fs_verify(svn_fs_t *fs, const char *path
   SVN_ERR(svn_fs_fs__open(fs, path, pool));
   SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
   SVN_ERR(fs_serialized_init(fs, common_pool, pool));
-  return svn_fs_fs__verify(fs, cancel_func, cancel_baton, pool);
+  return svn_fs_fs__verify(fs, cancel_func, cancel_baton, start, end, pool);
 }
 
 static svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h Mon Mar  5 20:34:22 2012
@@ -60,6 +60,8 @@ extern "C" {
 #define PATH_LOCKS_DIR        "locks"            /* Directory of locks */
 #define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
                                                     has not been packed. */
+#define PATH_REVPROP_GEN      "revprop-gen"      /* File containing the
+                                                    revprop change counter */
 /* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
 #define PATH_CONFIG           "fsfs.conf"        /* Configuration */
 
@@ -198,7 +200,8 @@ typedef struct fs_fs_shared_data_t
   apr_pool_t *common_pool;
 } fs_fs_shared_data_t;
 
-/* Private (non-shared) FSFS-specific data for each svn_fs_t object. */
+/* Private (non-shared) FSFS-specific data for each svn_fs_t object.
+   Any caches in here may be NULL. */
 typedef struct fs_fs_data_t
 {
   /* The format number of this FS. */
@@ -224,17 +227,28 @@ typedef struct fs_fs_data_t
      (svn_fs_id_t *).  (Not threadsafe.) */
   svn_cache__t *rev_root_id_cache;
 
-  /* DAG node cache for immutable nodes */
+  /* DAG node cache for immutable nodes.  Maps (revision, fspath)
+     to (dag_node_t *). */
   svn_cache__t *rev_node_cache;
 
   /* A cache of the contents of immutable directories; maps from
-     unparsed FS ID to ###x. */
+     unparsed FS ID to a apr_hash_t * mapping (const char *) dirent
+     names to (svn_fs_dirent_t *). */
   svn_cache__t *dir_cache;
 
   /* Fulltext cache; currently only used with memcached.  Maps from
-     rep key to svn_string_t. */
+     rep key (revision/offset) to svn_string_t. */
   svn_cache__t *fulltext_cache;
 
+  /* Revprop "generation" that is valid for this svn_fs_t.
+     It is the revprop change counter read once from "revprop-gen".
+     Will be read upon first access.  0 means that the value has not
+     been read from disk, yet. */
+  apr_int64_t revprop_generation;
+  
+  /* Revision property cache.  Maps from (rev,generation) to apr_hash_t. */
+  svn_cache__t *revprop_cache;
+
   /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
      a manifest; and a manifest is a mapping from (svn_revnum_t) revision
      number offset within a shard to (apr_off_t) byte-offset in the
@@ -244,7 +258,7 @@ typedef struct fs_fs_data_t
   /* Cache for txdelta_window_t objects; the key is (revFilePath, offset) */
   svn_cache__t *txdelta_window_cache;
 
-  /* Cache for combined windows as svn_stringbuf_t objects; 
+  /* Cache for combined windows as svn_stringbuf_t objects;
      the key is (revFilePath, offset) */
   svn_cache__t *combined_window_cache;
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Mon Mar  5 20:34:22 2012
@@ -81,7 +81,7 @@
 /* Begin deltification after a node history exceeded this this limit.
    Useful values are 4 to 64 with 16 being a good compromise between
    computational overhead and pository size savings.
-   Should be a power of 2.  
+   Should be a power of 2.
    Values < 2 will result in standard skip-delta behavior. */
 #define SVN_FS_FS_MAX_LINEAR_DELTIFICATION 16
 
@@ -225,6 +225,12 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
 }
 
 static const char *
+path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
+{
+  return svn_dirent_join(fs->path, PATH_REVPROP_GEN, pool);
+}
+
+static const char *
 path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind,
                 apr_pool_t *pool)
 {
@@ -800,7 +806,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
       err = svn_error_compose_create(
               err,
               unlock_proto_rev_list_locked(fs, txn_id, *lockcookie, pool));
-      
+
       *lockcookie = NULL;
     }
 
@@ -870,25 +876,39 @@ get_file_offset(apr_off_t *offset_p, apr
 }
 
 
-/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+/* Check that BUF, a nul-terminated buffer of text from file PATH,
    contains only digits at OFFSET and beyond, raising an error if not.
+   TITLE contains a user-visible description of the file, usually the
+   short file name.
 
    Uses POOL for temporary allocation. */
 static svn_error_t *
-check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
-                                 const char *path, apr_pool_t *pool)
+check_file_buffer_numeric(const char *buf, apr_off_t offset,
+                          const char *path, const char *title,
+                          apr_pool_t *pool)
 {
   const char *p;
 
   for (p = buf + offset; *p; p++)
     if (!svn_ctype_isdigit(*p))
       return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
-        _("Format file '%s' contains unexpected non-digit '%c' within '%s'"),
-        svn_dirent_local_style(path, pool), *p, buf);
+        _("%s file '%s' contains unexpected non-digit '%c' within '%s'"),
+        title, svn_dirent_local_style(path, pool), *p, buf);
 
   return SVN_NO_ERROR;
 }
 
+/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+   contains only digits at OFFSET and beyond, raising an error if not.
+
+   Uses POOL for temporary allocation. */
+static svn_error_t *
+check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
+                                 const char *path, apr_pool_t *pool)
+{
+  return check_file_buffer_numeric(buf, offset, path, "Format", pool);
+}
+
 /* Read the format number and maximum number of files per directory
    from PATH and return them in *PFORMAT and *MAX_FILES_PER_DIR
    respectively.
@@ -1548,6 +1568,16 @@ ensure_revision_exists(svn_fs_t *fs,
                            _("No such revision %ld"), rev);
 }
 
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+                           svn_fs_t *fs,
+                           apr_pool_t *pool)
+{
+  /* Different order of parameters. */
+  SVN_ERR(ensure_revision_exists(fs, rev, pool));
+  return SVN_NO_ERROR;
+}
+
 /* Open the correct revision file for REV.  If the filesystem FS has
    been packed, *FILE will be set to the packed file; otherwise, set *FILE
    to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
@@ -2677,6 +2707,105 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   return SVN_NO_ERROR;
 }
 
+/* Reads the revprop_gen file and writes the content into the
+   REVPROP_GENERATION member of FS.  Use pool for allocations. */
+static svn_error_t *
+read_revprop_generation(svn_fs_t *fs,
+                        apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  
+  const char *path = path_revprop_generation(fs, pool);
+  svn_error_t *err;
+  char buf[80];
+  int i;
+
+  /* Read the raw data from the file, if it exists. If it does
+     not, set the generation to "1" and return.
+     We don't want to have this function fail.  So, patiently
+     retry a couple of times the case the OS denied us access. */
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  for (i = 0; i < RECOVERABLE_RETRY_COUNT; ++i)
+    {
+      apr_file_t *file;
+      apr_size_t len = sizeof(buf);
+      
+      svn_pool_clear(iterpool);
+
+      err = svn_io_file_open(&file, path, APR_READ | APR_BUFFERED,
+                            APR_OS_DEFAULT, iterpool);
+      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+        {
+          /* No-one changed a revprop -> we are still at gen 1. */
+          ffd->revprop_generation = 1;
+          svn_error_clear(err);
+          return SVN_NO_ERROR;
+        }
+      svn_error_clear(err);
+
+      RETRY_RECOVERABLE(err, file,
+                        svn_io_read_length_line(file,
+                                                buf,
+                                                &len,
+                                                iterpool));
+      IGNORE_RECOVERABLE(err, svn_io_file_close(file,
+                                                iterpool));
+
+      break;
+    }
+  SVN_ERR(err);
+
+  svn_pool_destroy(iterpool);
+
+  /* Check that the first line contains only digits. */
+  SVN_ERR(check_file_buffer_numeric(buf, 0, path, 
+                                    "Revprop generations", pool));
+  SVN_ERR(svn_cstring_atoi64(&ffd->revprop_generation, buf));
+
+  /* Graceful behavior in case someone put a "0" in the file. */
+  if (ffd->revprop_generation <= 0)
+    ffd->revprop_generation = 1;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+check_revprop_generation(svn_fs_t *fs,
+                         apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  
+  return ffd->revprop_generation == 0
+    ? read_revprop_generation(fs, pool)
+    : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+increment_revprop_generation(svn_fs_t *fs,
+                             apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  
+  const char *path = path_revprop_generation(fs, pool);
+  const char *tmp_filename;
+  svn_string_t *generation;
+
+  SVN_ERR(read_revprop_generation(fs, pool));
+
+  /* Increment the key and add a trailing \n to the string so the
+     txn-current file has a newline in it. */
+  ++ffd->revprop_generation;
+  generation = svn_string_createf(pool, "%" APR_INT64_T_FMT "\n",
+                                  ffd->revprop_generation);
+
+  SVN_ERR(svn_io_write_unique(&tmp_filename,
+                              svn_dirent_dirname(path, pool),
+                              generation->data, generation->len,
+                              svn_io_file_del_none, pool));
+  return move_into_place(tmp_filename, path, 
+                         svn_fs_fs__path_current(fs, pool), pool);
+}
+
 /* Set the revision property list of revision REV in filesystem FS to
    PROPLIST.  Use POOL for temporary allocations. */
 static svn_error_t *
@@ -2693,6 +2822,10 @@ set_revision_proplist(svn_fs_t *fs,
       const char *tmp_path;
       const char *perms_reference;
       svn_stream_t *stream;
+      svn_node_kind_t kind;
+
+      /* test whether revprops already exist for this revision */
+      SVN_ERR(svn_io_check_path(final_path, &kind, pool));
 
       /* ### do we have a directory sitting around already? we really shouldn't
          ### have to get the dirname here. */
@@ -2709,6 +2842,12 @@ set_revision_proplist(svn_fs_t *fs,
       SVN_ERR(svn_fs_fs__path_rev_absolute(&perms_reference, fs, rev, pool));
       SVN_ERR(move_into_place(tmp_path, final_path, perms_reference, pool));
 
+      /* Invalidate all cached revprops for this FS and for all other
+         users that haven't read any revprops, YET.  Since writing revprops
+         implies a write lock, there can be no races. */
+      if (kind != svn_node_none)
+        SVN_ERR(increment_revprop_generation(fs, pool));
+
       return SVN_NO_ERROR;
     }
 
@@ -2722,8 +2861,22 @@ revision_proplist(apr_hash_t **proplist_
                   apr_pool_t *pool)
 {
   apr_hash_t *proplist;
+  fs_fs_data_t *ffd = fs->fsap_data;
+  const char *key;
 
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
+  SVN_ERR(check_revprop_generation(fs, pool));
+
+  /* Try cache lookup first. */
+  key = svn_fs_fs__combine_two_numbers(rev, ffd->revprop_generation, pool);
+  if (ffd->revprop_cache)
+    {
+      svn_boolean_t is_cached;
+      SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
+                              ffd->revprop_cache, key, pool));
+      if (is_cached)
+        return SVN_NO_ERROR;
+    }
 
   /* if (1); null condition for easier merging to revprop-packing */
     {
@@ -2779,6 +2932,10 @@ revision_proplist(apr_hash_t **proplist_
       svn_pool_destroy(iterpool);
     }
 
+  /* Cache the result, if caching has been activated. */
+  if (ffd->revprop_cache)
+    SVN_ERR(svn_cache__set(ffd->revprop_cache, key, proplist, pool));
+
   *proplist_p = proplist;
 
   return SVN_NO_ERROR;
@@ -2879,7 +3036,7 @@ create_rep_state(struct rep_state **rep_
          ### going to jump straight to this comment anyway! */
       return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
                                "Corrupt representation '%s'",
-                               rep 
+                               rep
                                ? representation_string(rep, ffd->format, TRUE,
                                                        TRUE, pool)
                                : "(null)");
@@ -2895,7 +3052,7 @@ struct rep_read_baton
 
   /* If not NULL, this is the base for the first delta window in rs_list */
   svn_stringbuf_t *base_window;
-  
+
   /* The state of all prior delta representations. */
   apr_array_header_t *rs_list;
 
@@ -3139,14 +3296,14 @@ build_rep_list(apr_array_header_t **list
       SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
       if (is_cached)
         {
-          /* We already have a reconstructed window in our cache. 
+          /* We already have a reconstructed window in our cache.
              Write a pseudo rep_state with the full length. */
           rs->off = rs->start;
           rs->end = rs->start + (*window_p)->len;
           *src_state = rs;
           return SVN_NO_ERROR;
         }
-      
+
       if (rep_args->is_delta == FALSE)
         {
           /* This is a plaintext, so just return the current rep_state. */
@@ -3205,7 +3362,7 @@ rep_read_get_baton(struct rep_read_baton
   else
     b->current_fulltext = NULL;
 
-  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window, 
+  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
                          &b->src_state, fs, rep,
                          b->filehandle_pool));
 
@@ -3286,7 +3443,7 @@ get_combined_window(svn_stringbuf_t **re
     {
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       SVN_ERR(read_window(&window, rb->chunk_index, rs, window_pool));
-      
+
       APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
       if (window->src_ops == 0)
         {
@@ -3294,7 +3451,7 @@ get_combined_window(svn_stringbuf_t **re
           break;
         }
     }
-    
+
   /* Combine in the windows from the other delta reps. */
   pool = svn_pool_create(rb->pool);
   for (--i; i >= 0; --i)
@@ -3307,7 +3464,7 @@ get_combined_window(svn_stringbuf_t **re
       new_pool = svn_pool_create(rb->pool);
       buf = svn_stringbuf_create_ensure(window->tview_len, new_pool);
       buf->len = window->tview_len;
-      
+
       svn_txdelta_apply_instructions(window, source ? source->data : NULL,
                                      buf->data, &buf->len);
       if (buf->len != window->tview_len)
@@ -3327,7 +3484,7 @@ get_combined_window(svn_stringbuf_t **re
     }
 
   svn_pool_destroy(window_pool);
-  
+
   *result = buf;
   return SVN_NO_ERROR;
 }
@@ -3519,7 +3676,7 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      const char *fulltext_key = NULL;
+      const char *fulltext_cache_key = NULL;
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
@@ -3528,10 +3685,11 @@ read_representation(svn_stream_t **conte
         {
           svn_stringbuf_t *fulltext;
           svn_boolean_t is_cached;
-          fulltext_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
+          fulltext_cache_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
                                       rep->revision, rep->offset);
           SVN_ERR(svn_cache__get((void **) &fulltext, &is_cached,
-                                 ffd->fulltext_cache, fulltext_key, pool));
+                                 ffd->fulltext_cache, fulltext_cache_key,
+                                 pool));
           if (is_cached)
             {
               *contents_p = svn_stream_from_stringbuf(fulltext, pool);
@@ -3539,7 +3697,7 @@ read_representation(svn_stream_t **conte
             }
         }
 
-      SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_key, pool));
+      SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool));
 
       *contents_p = svn_stream_create(rb, pool);
       svn_stream_set_read(*contents_p, rep_read_contents);
@@ -5268,7 +5426,7 @@ choose_delta_base(representation_t **rep
   count = noderev->predecessor_count;
   count = count & (count - 1);
 
-  /* We use skip delta for limiting the number of delta operations 
+  /* We use skip delta for limiting the number of delta operations
      along very long node histories.  Close to HEAD however, we create
      a linear history to minimize delta size.  */
   walk = noderev->predecessor_count - count;
@@ -5387,8 +5545,8 @@ rep_write_get_baton(struct rep_write_bat
    limited by both, POOL and REP lifetime.
  */
 static svn_error_t *
-get_shared_rep(representation_t **old_rep, 
-               svn_fs_t *fs, 
+get_shared_rep(representation_t **old_rep,
+               svn_fs_t *fs,
                representation_t *rep,
                apr_hash_t *reps_hash,
                apr_pool_t *pool)
@@ -5408,7 +5566,7 @@ get_shared_rep(representation_t **old_re
     *old_rep = apr_hash_get(reps_hash,
                             rep->sha1_checksum->digest,
                             APR_SHA1_DIGESTSIZE);
-   
+
   /* If we haven't found anything yet, try harder and consult our DB. */
   if (*old_rep == NULL)
     {
@@ -5447,7 +5605,7 @@ get_shared_rep(representation_t **old_re
       (*old_rep)->md5_checksum = rep->md5_checksum;
       (*old_rep)->uniquifier = rep->uniquifier;
     }
-    
+
   return SVN_NO_ERROR;
 }
 
@@ -5771,7 +5929,7 @@ write_hash_delta_rep(representation_t *r
 {
   svn_txdelta_window_handler_t diff_wh;
   void *diff_whb;
-  
+
   svn_stream_t *file_stream;
   svn_stream_t *stream;
   representation_t *base_rep;
@@ -5779,8 +5937,8 @@ write_hash_delta_rep(representation_t *r
   svn_stream_t *source;
   const char *header;
 
-  apr_off_t rep_end = 0; 
-  apr_off_t delta_start = 0; 
+  apr_off_t rep_end = 0;
+  apr_off_t delta_start = 0;
 
   struct write_hash_baton *whb;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -5809,7 +5967,7 @@ write_hash_delta_rep(representation_t *r
 
   SVN_ERR(get_file_offset(&delta_start, file, pool));
   file_stream = svn_stream_from_aprfile2(file, TRUE, pool);
-  
+
   /* Prepare to write the svndiff data. */
   svn_txdelta_to_svndiff3(&diff_wh,
                           &diff_whb,
@@ -5865,6 +6023,8 @@ write_hash_delta_rep(representation_t *r
 /* Sanity check ROOT_NODEREV, a candidate for being the root node-revision
    of (not yet committed) revision REV in FS.  Use POOL for temporary
    allocations.
+
+   If you change this function, consider updating svn_fs_fs__verify() too.
  */
 static svn_error_t *
 validate_root_noderev(svn_fs_t *fs,
@@ -5911,8 +6071,11 @@ validate_root_noderev(svn_fs_t *fs,
       return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                _("predecessor count for "
                                  "the root node-revision is wrong: "
-                                 "found %d, committing r%ld"),
-                                 root_noderev->predecessor_count, rev);
+                                 "found (%d+%ld != %d), committing r%ld"),
+                                 head_predecessor_count,
+                                 rev - head_revnum, /* This is equal to 1. */
+                                 root_noderev->predecessor_count,
+                                 rev);
     }
 
   return SVN_NO_ERROR;
@@ -6053,7 +6216,7 @@ write_final_rev(const svn_fs_id_t **new_
                                    proplist, fs, noderev, reps_hash,
                                    pool));
 #else
-      SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist, 
+      SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
                              fs, reps_hash, pool));
 #endif
     }
@@ -6112,15 +6275,15 @@ write_final_rev(const svn_fs_id_t **new_
       if (noderev->prop_rep && noderev->prop_rep->revision == rev)
         {
           /* Add new property reps to hash and on-disk cache. */
-          representation_t *copy 
+          representation_t *copy
             = svn_fs_fs__rep_copy(noderev->prop_rep, reps_pool);
 
           SVN_ERR_ASSERT(reps_to_cache && reps_pool);
           APR_ARRAY_PUSH(reps_to_cache, representation_t *) = copy;
 
-          apr_hash_set(reps_hash, 
-                        copy->sha1_checksum->digest, 
-                        APR_SHA1_DIGESTSIZE, 
+          apr_hash_set(reps_hash,
+                        copy->sha1_checksum->digest,
+                        APR_SHA1_DIGESTSIZE,
                         copy);
         }
     }
@@ -6746,6 +6909,9 @@ svn_fs_fs__create(svn_fs_t *fs,
                                  "", pool));
     }
 
+  /* Create the revprop generation tracking file. */
+  SVN_ERR(increment_revprop_generation(fs, pool));
+
   /* This filesystem is ready.  Stamp it with a format number. */
   SVN_ERR(write_format(path_format(fs, pool),
                        ffd->format, ffd->max_files_per_dir, FALSE, pool));
@@ -7878,7 +8044,7 @@ svn_fs_fs__pack(svn_fs_t *fs,
 
 /** Verifying. **/
 
-/* Body of svn_fs_fs__verify().
+/* Used by svn_fs_fs__verify().
    Implements svn_fs_fs__walk_rep_reference().walker.  */
 static svn_error_t *
 verify_walker(representation_t *rep,
@@ -7899,23 +8065,93 @@ svn_error_t *
 svn_fs_fs__verify(svn_fs_t *fs,
                   svn_cancel_func_t cancel_func,
                   void *cancel_baton,
+                  svn_revnum_t start,
+                  svn_revnum_t end,
                   apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_boolean_t exists;
+  svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
     return SVN_NO_ERROR;
 
-  /* Do not attempt to walk the rep-cache database if its file does not exists,
-     since doing so would create it --- which may confuse the administrator. */
+  /* Input validation. */
+  if (! SVN_IS_VALID_REVNUM(start))
+    start = 0;
+  if (! SVN_IS_VALID_REVNUM(end))
+    end = youngest;
+  SVN_ERR(ensure_revision_exists(fs, start, iterpool));
+  SVN_ERR(ensure_revision_exists(fs, end, iterpool));
+
+  /* rep-cache verification. */
   SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
   if (exists)
-    /* Don't take any lock. */
+    /* Do not attempt to walk the rep-cache database if its file does not exist,
+       since doing so would create it --- which may confuse the administrator.
+       Don't take any lock. */
     SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
                                           cancel_func, cancel_baton,
+                                          start, end,
                                           pool));
 
+  /* Issue #4129: bogus pred-counts on the root node-rev. */
+  {
+    svn_revnum_t i;
+    int predecessor_predecessor_count;
+
+    /* Compute PREDECESSOR_PREDECESSOR_COUNT. */
+    if (start == 0)
+      /* The value that passes the if() at the end of the loop. */
+      predecessor_predecessor_count = -1;
+    else
+      {
+        svn_fs_id_t *root_id;
+        node_revision_t *root_noderev;
+        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, start-1, iterpool));
+        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+                                             iterpool));
+        predecessor_predecessor_count = root_noderev->predecessor_count;
+      }
+
+    for (i = start; i <= end; i++)
+      {
+        /* ### Caching.
+
+           svn_fs_fs__rev_get_root() consults caches, which in verify we
+           don't want.  But we can't easily bypass that, as
+           svn_fs_revision_root()+svn_fs_node_id()'s implementation uses
+           svn_fs_fs__rev_get_root() too.
+
+           ### A future revision will make fs_verify() disable caches when it
+           ### opens ffd.
+         */
+        svn_fs_id_t *root_id;
+        node_revision_t *root_noderev;
+
+        if ((i % 128) == 0) /* uneducated guess */
+          svn_pool_clear(iterpool);
+
+        /* Fetch ROOT_NODEREV. */
+        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, i, iterpool));
+        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+                                             iterpool));
+
+        /* Check correctness. (Compare validate_root_noderev().) */
+        if (1+predecessor_predecessor_count != root_noderev->predecessor_count)
+          return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                   _("predecessor count for "
+                                     "the root node-revision is wrong: "
+                                     "r%ld has %d, but r%ld has %d"),
+                                   i, root_noderev->predecessor_count,
+                                   i-1, predecessor_predecessor_count);
+
+        predecessor_predecessor_count = root_noderev->predecessor_count;
+      }
+  }
+
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -8079,7 +8315,7 @@ hotcopy_io_copy_dir_recursively(const ch
           else if (this_entry.filetype == APR_DIR) /* recurse */
             {
               const char *src_target;
-              
+
               /* Prevent infinite recursion by filtering off our
                  newly created destination path. */
               if (strcmp(src, dst_parent) == 0
@@ -8284,7 +8520,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f
   for (rev = start_rev; rev < end_rev; rev++)
     {
       const char *rev_path;
-      
+
       svn_pool_clear(iterpool);
 
       /* If necessary, update paths for shard. */
@@ -8726,6 +8962,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_
 {
   fs_fs_data_t *src_ffd = src_fs->fsap_data;
   fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
+  svn_node_kind_t kind;
 
   dst_fs->path = apr_pstrdup(pool, dst_path);
 
@@ -8789,6 +9026,14 @@ hotcopy_create_empty_dest(svn_fs_t *src_
                                  "", pool));
     }
 
+  /* Copy the revprop generation file if it exists in SRC_FS. */
+  SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
+                            &kind, pool));
+  if (kind == svn_node_file)
+    SVN_ERR(svn_io_copy_file(path_revprop_generation(src_fs, pool),
+                             path_revprop_generation(dst_fs, pool),
+                             TRUE, pool));
+    
   dst_ffd->youngest_rev_cache = 0;
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h Mon Mar  5 20:34:22 2012
@@ -42,6 +42,8 @@ svn_error_t *svn_fs_fs__upgrade(svn_fs_t
 svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
                                svn_cancel_func_t cancel_func,
                                void *cancel_baton,
+                               svn_revnum_t start,
+                               svn_revnum_t end,
                                apr_pool_t *pool);
 
 /* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
@@ -106,6 +108,12 @@ svn_error_t *svn_fs_fs__youngest_rev(svn
                                      svn_fs_t *fs,
                                      apr_pool_t *pool);
 
+/* Return an error iff REV does not exist in FS. */
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+                           svn_fs_t *fs,
+                           apr_pool_t *pool);
+
 /* Set *ROOT_ID to the node-id for the root of revision REV in
    filesystem FS.  Do any allocations in POOL. */
 svn_error_t *svn_fs_fs__rev_get_root(svn_fs_id_t **root_id,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql Mon Mar  5 20:34:22 2012
@@ -33,6 +33,11 @@ CREATE TABLE rep_cache (
   expanded_size INTEGER NOT NULL
   );
 
+/* There isn't an implicit index on a TEXT column, so create an explicit one. */
+CREATE INDEX I_HASH on REP_CACHE (hash);
+
+/* The index didn't exist until 1.7.5; therefore, some USER_VERSION=1
+   rep-cache.db files out there DO NOT contain an I_HASH index. */
 PRAGMA USER_VERSION = 1;
 
 
@@ -47,9 +52,15 @@ INSERT OR FAIL INTO rep_cache (hash, rev
 VALUES (?1, ?2, ?3, ?4, ?5)
 
 
--- STMT_GET_ALL_REPS
+-- STMT_GET_REPS_FOR_RANGE
 SELECT hash, revision, offset, size, expanded_size
 FROM rep_cache
+WHERE revision >= ?1 AND revision <= ?2
+
+
+-- STMT_GET_MAX_REV
+SELECT MAX(revision)
+FROM rep_cache
 
 
 -- STMT_DEL_REPS_YOUNGER_THAN_REV

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c Mon Mar  5 20:34:22 2012
@@ -56,24 +56,9 @@ rep_has_been_born(representation_t *rep,
                   svn_fs_t *fs,
                   apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fsap_data;
-  svn_revnum_t youngest;
-
   SVN_ERR_ASSERT(rep);
 
-  youngest = ffd->youngest_rev_cache;
-  if (youngest < rep->revision)
-  {
-    /* Stale cache. */
-    SVN_ERR(svn_fs_fs__youngest_rev(&youngest, fs, pool));
-
-    /* Fresh cache. */
-    if (youngest < rep->revision)
-      return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                               _("Youngest revision is r%ld, but "
-                                 "rep-cache contains r%ld"),
-                               youngest, rep->revision);
-  }
+  SVN_ERR(svn_fs_fs__revision_exists(rep->revision, fs, pool));
 
   return SVN_NO_ERROR;
 }
@@ -141,11 +126,13 @@ svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
                               svn_error_t *(*walker)(representation_t *,
                                                      void *,
-                                                     svn_fs_t *, 
+                                                     svn_fs_t *,
                                                      apr_pool_t *),
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -161,9 +148,25 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
   if (! ffd->rep_cache_db)
     SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool));
 
+  /* Check global invariants. */
+  if (start == 0)
+    {
+      svn_sqlite__stmt_t *stmt2;
+      svn_revnum_t max;
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt2, ffd->rep_cache_db,
+                                        STMT_GET_MAX_REV));
+      SVN_ERR(svn_sqlite__step(&have_row, stmt2));
+      max = svn_sqlite__column_revnum(stmt2, 0);
+      SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
+      SVN_ERR(svn_sqlite__reset(stmt2));
+    }
+
   /* Get the statement. (There are no arguments to bind.) */
   SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
-                                    STMT_GET_ALL_REPS));
+                                    STMT_GET_REPS_FOR_RANGE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "rr",
+                            start, end));
 
   /* Walk the cache entries. */
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -171,7 +174,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
     {
       representation_t *rep;
       const char *sha1_digest;
-      
+
       /* Clear ITERPOOL occasionally. */
       if (iterations++ % 16 == 0)
         svn_pool_clear(iterpool);
@@ -191,10 +194,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
       rep->size = svn_sqlite__column_int64(stmt, 3);
       rep->expanded_size = svn_sqlite__column_int64(stmt, 4);
 
-      /* Sanity check. */
-      if (rep)
-        SVN_ERR(rep_has_been_born(rep, fs, iterpool));
-
       /* Walk. */
       SVN_ERR(walker(rep, walker_baton, fs, iterpool));
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h Mon Mar  5 20:34:22 2012
@@ -50,11 +50,13 @@ svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
                               svn_error_t *(*walker)(representation_t *rep,
                                                      void *walker_baton,
-                                                     svn_fs_t *fs, 
+                                                     svn_fs_t *fs,
                                                      apr_pool_t *scratch_pool),
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               apr_pool_t *pool);
 
 /* Return the representation REP in FS which has fulltext CHECKSUM.

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure Mon Mar  5 20:34:22 2012
@@ -266,7 +266,7 @@ Within a revision:
   "r<rev>/<offset>" txn-id fields.
 
   In Format 3 and above, this uniqueness is done by changing a temporary
-  id of "_<base36>" to "<rev>-<base36>".  Note that this means that the
+  id of "_<base36>" to "<base36>-<rev>".  Note that this means that the
   originating revision of a line of history or a copy can be determined
   by looking at the node ID.
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c Mon Mar  5 20:34:22 2012
@@ -136,7 +136,7 @@ serialize_svn_string(svn_temp_serializer
    * Thus, we cannot use svn_temp_serializer__add_string. */
   svn_temp_serializer__push(context,
                             (const void * const *)&string->data,
-                            string->len);
+                            string->len + 1);
 
   /* back to the caller's nesting level */
   svn_temp_serializer__pop(context);
@@ -579,6 +579,142 @@ svn_fs_fs__deserialize_manifest(void **o
   return SVN_NO_ERROR;
 }
 
+/* Auxilliary structure representing the content of a properties hash.
+   This structure is much easier to (de-)serialize than an apr_hash.
+ */
+typedef struct properties_data_t
+{
+  /* number of entries in the hash */
+  apr_size_t count;
+
+  /* reference to the keys */
+  const char **keys;
+
+  /* reference to the values */
+  const svn_string_t **values;
+} properties_data_t;
+
+/* Serialize COUNT C-style strings from *STRINGS into CONTEXT. */
+static void
+serialize_cstring_array(svn_temp_serializer__context_t *context,
+                        const char ***strings,
+                        apr_size_t count)
+{
+  apr_size_t i;
+  const char **entries = *strings;
+  
+  /* serialize COUNT entries pointers (the array) */
+  svn_temp_serializer__push(context,
+                            (const void * const *)strings,
+                            count * sizeof(const char*));
+
+  /* serialize array elements */
+  for (i = 0; i < count; ++i)
+    svn_temp_serializer__add_string(context, &entries[i]);
+
+  svn_temp_serializer__pop(context);
+}
+
+/* Serialize COUNT svn_string_t* items from *STRINGS into CONTEXT. */
+static void
+serialize_svn_string_array(svn_temp_serializer__context_t *context,
+                           const svn_string_t ***strings,
+                           apr_size_t count)
+{
+  apr_size_t i;
+  const svn_string_t **entries = *strings;
+  
+  /* serialize COUNT entries pointers (the array) */
+  svn_temp_serializer__push(context,
+                            (const void * const *)strings,
+                            count * sizeof(const char*));
+
+  /* serialize array elements */
+  for (i = 0; i < count; ++i)
+    serialize_svn_string(context, &entries[i]);
+
+  svn_temp_serializer__pop(context);
+}
+
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+                                apr_size_t *data_len,
+                                void *in,
+                                apr_pool_t *pool)
+{
+  apr_hash_t *hash = in;
+  properties_data_t properties;
+  svn_temp_serializer__context_t *context;
+  apr_hash_index_t *hi;
+  svn_stringbuf_t *serialized;
+  apr_size_t i;
+
+  /* create our auxilliary data structure */
+  properties.count = apr_hash_count(hash);
+  properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
+  properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
+  
+  /* populate it with the hash entries */
+  for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
+    {
+      properties.keys[i] = svn__apr_hash_index_key(hi);
+      properties.values[i] = svn__apr_hash_index_val(hi);
+    }
+  
+  /* serialize it */
+  context = svn_temp_serializer__init(&properties,
+                                      sizeof(properties),
+                                      properties.count * 100,
+                                      pool);
+
+  properties.keys[i] = "";
+  serialize_cstring_array(context, &properties.keys, properties.count + 1);
+  serialize_svn_string_array(context, &properties.values, properties.count);
+
+  /* return the serialized result */
+  serialized = svn_temp_serializer__get(context);
+
+  *data = serialized->data;
+  *data_len = serialized->len;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+                                  char *data,
+                                  apr_size_t data_len,
+                                  apr_pool_t *pool)
+{
+  apr_hash_t *hash = apr_hash_make(pool);
+  properties_data_t *properties = (properties_data_t *)data;
+  size_t i;
+
+  /* de-serialize our auxilliary data structure */
+  svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
+  svn_temp_deserializer__resolve(properties, (void**)&properties->values);
+  
+  /* de-serialize each entry and put it into the hash */
+  for (i = 0; i < properties->count; ++i)
+    {
+      apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
+      svn_temp_deserializer__resolve(properties->keys, 
+                                     (void**)&properties->keys[i]);
+      
+      deserialize_svn_string(properties->values, 
+                             (svn_string_t **)&properties->values[i]);
+      
+      apr_hash_set(hash, 
+                   properties->keys[i], len, 
+                   properties->values[i]);
+    }
+
+  /* done */
+  *out = hash;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__serialize_id(char **data,
                         apr_size_t *data_len,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h Mon Mar  5 20:34:22 2012
@@ -113,6 +113,26 @@ svn_fs_fs__deserialize_manifest(void **o
                                 apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__serialize_func_t for a properties hash
+ * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+                                apr_size_t *data_len,
+                                void *in,
+                                apr_pool_t *pool);
+
+/**
+ * Implements #svn_cache__deserialize_func_t for a properties hash
+ * (@a *out is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+                                  char *data,
+                                  apr_size_t data_len,
+                                  apr_pool_t *pool);
+
+/**
  * Implements #svn_cache__serialize_func_t for #svn_fs_id_t
  */
 svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c Mon Mar  5 20:34:22 2012
@@ -115,7 +115,7 @@ typedef struct fs_rev_root_data_t
 typedef struct fs_txn_root_data_t
 {
   /* Cache of txn DAG nodes (without their nested noderevs, because
-   * it's mutable). */
+   * it's mutable). Same keys/values as ffd->rev_node_cache. */
   svn_cache__t *txn_node_cache;
 } fs_txn_root_data_t;
 
@@ -2807,8 +2807,10 @@ find_youngest_copyroot(svn_revnum_t *rev
                        parent_path_t *parent_path,
                        apr_pool_t *pool)
 {
-  svn_revnum_t rev_mine, rev_parent = -1;
-  const char *path_mine, *path_parent;
+  svn_revnum_t rev_mine;
+  svn_revnum_t rev_parent = SVN_INVALID_REVNUM;
+  const char *path_mine;
+  const char *path_parent = NULL;
 
   /* First find our parent's youngest copyroot. */
   if (parent_path->parent)

Modified: subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c Mon Mar  5 20:34:22 2012
@@ -1304,6 +1304,15 @@ svn_ra_print_ra_libraries(svn_stringbuf_
 }
 
 
+svn_error_t *
+svn_ra__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                       svn_delta_shim_callbacks_t *callbacks)
+{
+  SVN_ERR(session->vtable->register_editor_shim_callbacks(session, callbacks));
+  return SVN_NO_ERROR;
+}
+
+
 /* Return the library version number. */
 const svn_version_t *
 svn_ra_version(void)

Modified: subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h Mon Mar  5 20:34:22 2012
@@ -293,6 +293,8 @@ typedef struct svn_ra__vtable_t {
                                   svn_revnum_t end_revision,
                                   svn_revnum_t *revision_deleted,
                                   apr_pool_t *pool);
+  svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
 
 } svn_ra__vtable_t;
 

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c Mon Mar  5 20:34:22 2012
@@ -153,7 +153,7 @@ cache_init(void *baton, apr_pool_t *pool
       SVN_ERR(svn_error_quick_wrap(svn_cstring_atoui64(&memory_cache_size,
                                                        memory_cache_size_str),
                                    _("memory-cache-size invalid")));
-      settings.cache_size = 1024 * 1024 * memory_cache_size; 
+      settings.cache_size = 1024 * 1024 * memory_cache_size;
       svn_cache_config_set(&settings);
     }
 
@@ -1505,6 +1505,15 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  /* This is currenly a no-op, since we don't provide our own editor, just
+     use the one the libsvn_repos hands back to us. */
+  return SVN_NO_ERROR;
+}
+
 /*----------------------------------------------------------------*/
 
 static const svn_version_t *
@@ -1551,7 +1560,8 @@ static const svn_ra__vtable_t ra_local_v
   svn_ra_local__replay,
   svn_ra_local__has_capability,
   svn_ra_local__replay_range,
-  svn_ra_local__get_deleted_rev
+  svn_ra_local__get_deleted_rev,
+  svn_ra_local__register_editor_shim_callbacks
 };
 
 

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c Mon Mar  5 20:34:22 2012
@@ -1570,8 +1570,6 @@ svn_error_t * svn_ra_neon__get_commit_ed
   svn_delta_editor_t *commit_editor;
   commit_ctx_t *cc;
   apr_hash_index_t *hi;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                svn_delta_shim_callbacks_default(pool);
 
   /* Build the main commit editor's baton. */
   cc = apr_pcalloc(pool, sizeof(*cc));
@@ -1622,7 +1620,7 @@ svn_error_t * svn_ra_neon__get_commit_ed
   *edit_baton = cc;
 
   SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
-                                   shim_callbacks, pool, pool));
+                                   ras->shim_callbacks, pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c Mon Mar  5 20:34:22 2012
@@ -166,7 +166,7 @@ log_start_element(int *elem, void *baton
       lb->want_cdata = lb->cdata;
       svn_stringbuf_setempty(lb->cdata);
       lb->cdata_encoding = NULL;
-          
+
       /* Some tags might contain encoded CDATA. */
       if ((elm->id == ELEM_comment) ||
           (elm->id == ELEM_creator_displayname) ||
@@ -280,7 +280,7 @@ maybe_decode_log_cdata(const svn_string_
   return SVN_NO_ERROR;
 }
 
-                       
+
 
 /*
  * This implements the `svn_ra_neon__xml_endelm_cb' prototype.

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h Mon Mar  5 20:34:22 2012
@@ -131,6 +131,9 @@ typedef struct svn_ra_neon__session_t {
      deadprop-count property.*/
   svn_tristate_t supports_deadprop_count;
 
+  /* Ev2 shim callbacks. */
+  svn_delta_shim_callbacks_t *shim_callbacks;
+
   /*** HTTP v2 protocol stuff. ***
    *
    * We assume that if mod_dav_svn sends one of the special v2 OPTIONs
@@ -1181,6 +1184,10 @@ svn_ra_neon__get_deadprop_count_support(
                                         const char *final_url,
                                         apr_pool_t *pool);
 
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c Mon Mar  5 20:34:22 2012
@@ -1229,7 +1229,8 @@ static const svn_ra__vtable_t neon_vtabl
   svn_ra_neon__replay,
   svn_ra_neon__has_capability,
   svn_ra_neon__replay_range,
-  svn_ra_neon__get_deleted_rev
+  svn_ra_neon__get_deleted_rev,
+  svn_ra_neon__register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c Mon Mar  5 20:34:22 2012
@@ -38,6 +38,7 @@
 #include "svn_utf.h"
 #include "svn_xml.h"
 #include "svn_props.h"
+#include "../libsvn_ra/ra_loader.h"
 
 #include "private/svn_fspath.h"
 #include "svn_private_config.h"
@@ -1649,3 +1650,13 @@ svn_ra_neon__get_deadprop_count_support(
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_neon__session_t *ras = session->priv;
+
+  ras->shim_callbacks = callbacks;
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Mon Mar  5 20:34:22 2012
@@ -328,7 +328,7 @@ checkout_dir(dir_context_t *dir)
       return SVN_NO_ERROR;
     }
 
-  /* Is this directory or one of our parent dirs newly added? 
+  /* Is this directory or one of our parent dirs newly added?
    * If so, we're already implicitly checked out. */
   while (p_dir)
     {
@@ -2319,8 +2319,6 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   svn_delta_editor_t *editor;
   commit_context_t *ctx;
   apr_hash_index_t *hi;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   ctx = apr_pcalloc(pool, sizeof(*ctx));
 
@@ -2368,7 +2366,8 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   *edit_baton = ctx;
 
   SVN_ERR(svn_editor__insert_shims(ret_editor, edit_baton, *ret_editor,
-                                   *edit_baton, shim_callbacks, pool, pool));
+                                   *edit_baton, session->shim_callbacks,
+                                   pool, pool));
 
   return SVN_NO_ERROR;
 }