subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ar...@apache.org
Subject svn commit: r1204374 [14/29] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/ contrib/client-side/emacs/ notes/ notes/wc-ng/ subversion/bindings/javahl/native...
Date Mon, 21 Nov 2011 07:08:07 GMT
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c Mon Nov 21 07:07:56 2011
@@ -63,6 +63,12 @@ struct parse_baton
   svn_repos_notify_t *notify;
   apr_pool_t *pool;
 
+  /* Start and end (inclusive) of revision range we'll pay attention
+     to, or a pair of SVN_INVALID_REVNUMs if we're not filtering by
+     revisions. */
+  svn_revnum_t start_rev;
+  svn_revnum_t end_rev;
+
   /* A hash mapping copy-from revisions and mergeinfo range revisions
      (svn_revnum_t *) in the dump stream to their corresponding revisions
      (svn_revnum_t *) in the loaded repository.  The hash and its
@@ -84,13 +90,13 @@ struct parse_baton
 struct revision_baton
 {
   svn_revnum_t rev;
-
   svn_fs_txn_t *txn;
   svn_fs_root_t *txn_root;
 
   const svn_string_t *datestamp;
 
   apr_int32_t rev_offset;
+  svn_boolean_t skipped;
 
   struct parse_baton *pb;
   apr_pool_t *pool;
@@ -320,8 +326,8 @@ renumber_mergeinfo_revs(svn_string_t **f
     }
 
   if (predates_stream_mergeinfo)
-      SVN_ERR(svn_mergeinfo_merge(final_mergeinfo, predates_stream_mergeinfo,
-                                  subpool));
+      SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
+                                   subpool, subpool));
 
   SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
 
@@ -451,7 +457,14 @@ make_revision_baton(apr_hash_t *headers,
 
   if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
                           APR_HASH_KEY_STRING)))
-    rb->rev = SVN_STR_TO_REV(val);
+    {
+      rb->rev = SVN_STR_TO_REV(val);
+
+      /* If we're filtering revisions, is this one we'll skip? */
+      rb->skipped = (SVN_IS_VALID_REVNUM(pb->start_rev)
+                     && ((rb->rev < pb->start_rev) ||
+                         (rb->rev > pb->end_rev)));
+    }
 
   return rb;
 }
@@ -476,7 +489,7 @@ new_revision_record(void **revision_bato
      It might be positive or negative. */
   rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
 
-  if (rb->rev > 0)
+  if ((rb->rev > 0) && (! rb->skipped))
     {
       /* Create a new fs txn. */
       SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
@@ -493,6 +506,14 @@ new_revision_record(void **revision_bato
       if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
         pb->oldest_old_rev = rb->rev;
     }
+  
+  /* If we're skipping this revision, try to notify someone. */
+  if (rb->skipped && pb->notify_func)
+    {
+      pb->notify->action = svn_repos_notify_load_skipped_rev;
+      pb->notify->old_revision = rb->rev;
+      pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
+    }
 
   /* If we're parsing revision 0, only the revision are (possibly)
      interesting to us: when loading the stream into an empty
@@ -607,6 +628,13 @@ new_node_record(void **node_baton,
 
   SVN_ERR(make_node_baton(&nb, headers, rb, pool));
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    {
+      *node_baton = nb;
+      return SVN_NO_ERROR;
+    }
+
   /* Make sure we have an action we recognize. */
   if (nb->action < svn_node_action_change
         || nb->action > svn_node_action_replace)
@@ -652,6 +680,10 @@ set_revision_property(void *baton,
 {
   struct revision_baton *rb = baton;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   if (rb->rev > 0)
     {
       if (rb->pb->validate_props)
@@ -691,6 +723,10 @@ set_node_property(void *baton,
   struct revision_baton *rb = nb->rb;
   struct parse_baton *pb = rb->pb;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
     {
       svn_string_t *renumbered_mergeinfo;
@@ -764,6 +800,10 @@ remove_node_props(void *baton)
   apr_hash_t *proplist;
   apr_hash_index_t *hi;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   SVN_ERR(svn_fs_node_proplist(&proplist,
                                rb->txn_root, nb->path, nb->pool));
 
@@ -788,6 +828,10 @@ apply_textdelta(svn_txdelta_window_handl
   struct node_baton *nb = node_baton;
   struct revision_baton *rb = nb->rb;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   return svn_fs_apply_textdelta(handler, handler_baton,
                                 rb->txn_root, nb->path,
                                 svn_checksum_to_cstring(nb->base_checksum,
@@ -805,6 +849,10 @@ set_fulltext(svn_stream_t **stream,
   struct node_baton *nb = node_baton;
   struct revision_baton *rb = nb->rb;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   return svn_fs_apply_text(stream,
                            rb->txn_root, nb->path,
                            svn_checksum_to_cstring(nb->result_checksum,
@@ -820,6 +868,10 @@ close_node(void *baton)
   struct revision_baton *rb = nb->rb;
   struct parse_baton *pb = rb->pb;
 
+  /* If we're skipping this revision, we're done here. */
+  if (rb->skipped)
+    return SVN_NO_ERROR;
+
   if (pb->notify_func)
     {
       pb->notify->action = svn_repos_notify_load_node_done;
@@ -839,7 +891,9 @@ close_revision(void *baton)
   svn_revnum_t committed_rev;
   svn_error_t *err;
 
-  if (rb->rev <= 0)
+  /* If we're skipping this revision or it has an invalid revision
+     number, we're done here. */
+  if (rb->skipped || (rb->rev <= 0))
     return SVN_NO_ERROR;
 
   /* Run the pre-commit hook, if so commanded. */
@@ -943,9 +997,11 @@ close_revision(void *baton)
 
 
 svn_error_t *
-svn_repos_get_fs_build_parser3(const svn_repos_parse_fns2_t **callbacks,
+svn_repos_get_fs_build_parser4(const svn_repos_parse_fns2_t **callbacks,
                                void **parse_baton,
                                svn_repos_t *repos,
+                               svn_revnum_t start_rev,
+                               svn_revnum_t end_rev,
                                svn_boolean_t use_history,
                                svn_boolean_t validate_props,
                                enum svn_repos_load_uuid uuid_action,
@@ -960,6 +1016,13 @@ svn_repos_get_fs_build_parser3(const svn
   if (parent_dir)
     parent_dir = svn_relpath_canonicalize(parent_dir, pool);
 
+  SVN_ERR_ASSERT((SVN_IS_VALID_REVNUM(start_rev) &&
+                  SVN_IS_VALID_REVNUM(end_rev))
+                 || ((! SVN_IS_VALID_REVNUM(start_rev)) &&
+                     (! SVN_IS_VALID_REVNUM(end_rev))));
+  if (SVN_IS_VALID_REVNUM(start_rev))
+    SVN_ERR_ASSERT(start_rev <= end_rev);
+
   parser->new_revision_record = new_revision_record;
   parser->new_node_record = new_node_record;
   parser->uuid_record = uuid_record;
@@ -985,6 +1048,8 @@ svn_repos_get_fs_build_parser3(const svn
   pb->rev_map = apr_hash_make(pool);
   pb->oldest_old_rev = SVN_INVALID_REVNUM;
   pb->last_rev_mapped = SVN_INVALID_REVNUM;
+  pb->start_rev = start_rev;
+  pb->end_rev = end_rev;
 
   *callbacks = parser;
   *parse_baton = pb;
@@ -994,8 +1059,10 @@ svn_repos_get_fs_build_parser3(const svn
 
 
 svn_error_t *
-svn_repos_load_fs3(svn_repos_t *repos,
+svn_repos_load_fs4(svn_repos_t *repos,
                    svn_stream_t *dumpstream,
+                   svn_revnum_t start_rev,
+                   svn_revnum_t end_rev,
                    enum svn_repos_load_uuid uuid_action,
                    const char *parent_dir,
                    svn_boolean_t use_pre_commit_hook,
@@ -1013,8 +1080,9 @@ svn_repos_load_fs3(svn_repos_t *repos,
 
   /* This is really simple. */
 
-  SVN_ERR(svn_repos_get_fs_build_parser3(&parser, &parse_baton,
+  SVN_ERR(svn_repos_get_fs_build_parser4(&parser, &parse_baton,
                                          repos,
+                                         start_rev, end_rev,
                                          TRUE, /* look for copyfrom revs */
                                          validate_props,
                                          uuid_action,

Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/log.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/log.c Mon Nov 21 07:07:56 2011
@@ -665,7 +665,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
           APR_ARRAY_PUSH(query_paths, const char *) = changed_path;
           SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, root,
                                         query_paths, svn_mergeinfo_inherited,
-                                        FALSE, FALSE, iterpool));
+                                        FALSE, TRUE, iterpool, iterpool));
           tmp_mergeinfo = apr_hash_get(tmp_catalog, changed_path,
                                         APR_HASH_KEY_STRING);
           if (tmp_mergeinfo)
@@ -684,7 +684,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
           APR_ARRAY_PUSH(query_paths, const char *) = base_path;
           SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, base_root,
                                         query_paths, svn_mergeinfo_inherited,
-                                        FALSE, FALSE, iterpool));
+                                        FALSE, TRUE, iterpool, iterpool));
           tmp_mergeinfo = apr_hash_get(tmp_catalog, base_path,
                                         APR_HASH_KEY_STRING);
           if (tmp_mergeinfo)
@@ -711,17 +711,16 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
           if (prev_mergeinfo_value)
             SVN_ERR(svn_mergeinfo_parse(&prev_mergeinfo,
                                         prev_mergeinfo_value->data, iterpool));
-          SVN_ERR(svn_mergeinfo_diff(&deleted, &added, prev_mergeinfo,
-                                     mergeinfo, FALSE, iterpool));
+          SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
+                                      mergeinfo, FALSE, result_pool,
+                                      iterpool));
 
           /* Toss interesting stuff into our return catalogs. */
           hash_path = apr_pstrdup(result_pool, changed_path);
           apr_hash_set(*deleted_mergeinfo_catalog, hash_path,
-                       APR_HASH_KEY_STRING, svn_mergeinfo_dup(deleted,
-                                                              result_pool));
+                       APR_HASH_KEY_STRING, deleted);
           apr_hash_set(*added_mergeinfo_catalog, hash_path,
-                       APR_HASH_KEY_STRING, svn_mergeinfo_dup(added,
-                                                              result_pool));
+                       APR_HASH_KEY_STRING, added);
         }
     }
 
@@ -795,8 +794,9 @@ get_combined_mergeinfo_changes(svn_merge
       const char *prev_path;
       svn_revnum_t appeared_rev, prev_rev;
       svn_fs_root_t *prev_root;
-      svn_mergeinfo_catalog_t catalog;
-      svn_mergeinfo_t prev_mergeinfo, mergeinfo, deleted, added;
+      svn_mergeinfo_catalog_t catalog, inherited_catalog;
+      svn_mergeinfo_t prev_mergeinfo, mergeinfo, deleted, added,
+        prev_inherited_mergeinfo, inherited_mergeinfo;
       apr_array_header_t *query_paths;
 
       svn_pool_clear(iterpool);
@@ -836,8 +836,8 @@ get_combined_mergeinfo_changes(svn_merge
       query_paths = apr_array_make(iterpool, 1, sizeof(const char *));
       APR_ARRAY_PUSH(query_paths, const char *) = prev_path;
       err = svn_fs_get_mergeinfo2(&catalog, prev_root, query_paths,
-                                  svn_mergeinfo_inherited, FALSE, FALSE,
-                                  iterpool);
+                                  svn_mergeinfo_inherited, FALSE, TRUE,
+                                  iterpool, iterpool);
       if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND ||
                   err->apr_err == SVN_ERR_FS_NOT_DIRECTORY ||
                   err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR))
@@ -847,30 +847,66 @@ get_combined_mergeinfo_changes(svn_merge
           continue;
         }
       SVN_ERR(err);
+
+      /* Issue #4022 'svn log -g interprets change in inherited mergeinfo due
+         to move as a merge': A copy where the source and destination inherit
+         mergeinfo from the same parent means the inherited mergeinfo of the
+         source and destination will differ, but this diffrence is not
+         indicative of a merge unless the mergeinfo on the inherited parent
+         has actually changed.
+
+         To check for this we must fetch the "raw" previous inherited
+         mergeinfo and the "raw" mergeinfo @REV then compare these. */
+      SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, prev_root, query_paths,
+                                    svn_mergeinfo_nearest_ancestor, FALSE,
+                                    FALSE, /* adjust_inherited_mergeinfo */
+                                    iterpool, iterpool));
+
       prev_mergeinfo = apr_hash_get(catalog, prev_path, APR_HASH_KEY_STRING);
+      prev_inherited_mergeinfo = apr_hash_get(inherited_catalog, prev_path, APR_HASH_KEY_STRING);
 
       /* Fetch the current mergeinfo (as of REV, and including
          inherited stuff) for this path. */
       APR_ARRAY_IDX(query_paths, 0, const char *) = path;
       SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, query_paths,
-                                    svn_mergeinfo_inherited, FALSE, FALSE,
-                                    iterpool));
+                                    svn_mergeinfo_inherited, FALSE, TRUE,
+                                    iterpool, iterpool));
+
+      /* Issue #4022 again, fetch the raw inherited mergeinfo. */
+      SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, root, query_paths,
+                                    svn_mergeinfo_nearest_ancestor, FALSE,
+                                    FALSE, /* adjust_inherited_mergeinfo */
+                                    iterpool, iterpool));
+
       mergeinfo = apr_hash_get(catalog, path, APR_HASH_KEY_STRING);
+      inherited_mergeinfo = apr_hash_get(inherited_catalog, path, APR_HASH_KEY_STRING);
 
       if (!prev_mergeinfo && !mergeinfo)
         continue;
 
+      /* Last bit of issue #4022 checking. */
+      if (prev_inherited_mergeinfo && inherited_mergeinfo)
+        {
+          svn_boolean_t inherits_same_mergeinfo;
+
+          SVN_ERR(svn_mergeinfo__equals(&inherits_same_mergeinfo,
+                                        prev_inherited_mergeinfo,
+                                        inherited_mergeinfo,
+                                        TRUE, iterpool));
+          /* If a copy rather than an actual merge brought about an
+             inherited mergeinfo change then we are finished. */
+          if (inherits_same_mergeinfo)
+            continue;
+        }
+
       /* Compare, constrast, and combine the results. */
-      SVN_ERR(svn_mergeinfo_diff(&deleted, &added, prev_mergeinfo,
-                                 mergeinfo, FALSE, iterpool));
-      SVN_ERR(svn_mergeinfo_merge(*deleted_mergeinfo,
-                                  svn_mergeinfo_dup(deleted, result_pool),
-                                  result_pool));
-      SVN_ERR(svn_mergeinfo_merge(*added_mergeinfo,
-                                  svn_mergeinfo_dup(added, result_pool),
-                                  result_pool));
+      SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
+                                  mergeinfo, FALSE, result_pool, iterpool));
+      SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo, deleted,
+                                   result_pool, iterpool));
+      SVN_ERR(svn_mergeinfo_merge2(*added_mergeinfo, added,
+                                   result_pool, iterpool));
      }
-  svn_pool_destroy(iterpool);
 
   /* Merge all the mergeinfos which are, or are children of, one of
      our paths of interest into one giant delta mergeinfo.  */
@@ -891,20 +927,22 @@ get_combined_mergeinfo_changes(svn_merge
       for (i = 0; i < paths->nelts; i++)
         {
           const char *path = APR_ARRAY_IDX(paths, i, const char *);
-          if (! svn_dirent_is_ancestor(path, changed_path))
+          if (! svn_fspath__skip_ancestor(path, changed_path))
             continue;
+          svn_pool_clear(iterpool);
           deleted = apr_hash_get(deleted_mergeinfo_catalog, key, klen);
-          SVN_ERR(svn_mergeinfo_merge(*deleted_mergeinfo,
-                                      svn_mergeinfo_dup(deleted, result_pool),
-                                      result_pool));
-          SVN_ERR(svn_mergeinfo_merge(*added_mergeinfo,
-                                      svn_mergeinfo_dup(added, result_pool),
-                                      result_pool));
+          SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo,
+                                       svn_mergeinfo_dup(deleted, result_pool),
+                                       result_pool, iterpool));
+          SVN_ERR(svn_mergeinfo_merge2(*added_mergeinfo,
+                                       svn_mergeinfo_dup(added, result_pool),
+                                       result_pool, iterpool));
 
           break;
         }
     }
 
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -1026,8 +1064,9 @@ fill_log_entry(svn_log_entry_t *log_entr
 
    If DESCENDING_ORDER is true, send child messages in descending order.
 
-   If REVPROPS is NULL, retrieve all revprops; else, retrieve only the
-   revprops named in the array (i.e. retrieve none if the array is empty).
+   If REVPROPS is NULL, retrieve all revision properties; else, retrieve
+   only the revision properties named by the (const char *) array elements
+   (i.e. retrieve none if the array is empty).
 
    LOG_TARGET_HISTORY_AS_MERGEINFO, HANDLING_MERGED_REVISION, and
    NESTED_MERGES are as per the arguments of the same name to DO_LOGS.  If
@@ -1103,8 +1142,7 @@ send_log(svn_revnum_t rev,
               apr_array_header_t *rangelist =
                 svn__apr_hash_index_val(hi2);
 
-              if (svn_fspath__is_ancestor(mergeinfo_path,
-                                          changed_path))
+              if (svn_fspath__skip_ancestor(mergeinfo_path, changed_path))
                 {
                   int i;
 
@@ -1741,8 +1779,8 @@ store_search(svn_mergeinfo_t processed,
       apr_hash_set(mergeinfo, apr_pstrdup(processed_pool, path),
                    APR_HASH_KEY_STRING, ranges);
     }
-  SVN_ERR(svn_mergeinfo_merge(processed, mergeinfo,
-                              apr_hash_pool_get(processed)));
+  SVN_ERR(svn_mergeinfo_merge2(processed, mergeinfo,
+                               apr_hash_pool_get(processed), scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2113,10 +2151,10 @@ get_paths_history_as_mergeinfo(svn_merge
 
       SVN_ERR(svn_mergeinfo__mergeinfo_from_segments(
         &path_history_mergeinfo, loc_seg_baton.history_segments, iterpool));
-      SVN_ERR(svn_mergeinfo_merge(*paths_history_mergeinfo,
-                                  svn_mergeinfo_dup(path_history_mergeinfo,
-                                                    result_pool),
-                                  result_pool));
+      SVN_ERR(svn_mergeinfo_merge2(*paths_history_mergeinfo,
+                                   svn_mergeinfo_dup(path_history_mergeinfo,
+                                                     result_pool),
+                                   result_pool, iterpool));
     }
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;

Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c Mon Nov 21 07:07:56 2011
@@ -136,7 +136,7 @@ struct path_driver_cb_baton
   void *authz_read_baton;
 
   const char *base_path; /* relpath */
-  int base_path_len;
+  size_t base_path_len;
 
   svn_revnum_t low_water_mark;
   /* Stack of active copy operations. */
@@ -372,7 +372,7 @@ path_driver_cb_func(void **dir_baton,
   svn_fs_root_t *source_root = cb->compare_root;
   const char *source_fspath = NULL;
   const char *base_path = cb->base_path;
-  int base_path_len = cb->base_path_len;
+  size_t base_path_len = cb->base_path_len;
 
   *dir_baton = NULL;
 
@@ -573,8 +573,9 @@ path_driver_cb_func(void **dir_baton,
                                                   struct copy_info);
           if (info->copyfrom_path)
             {
-              const char *relpath = svn_relpath__is_child(info->path,
-                                                          edit_path, pool);
+              const char *relpath = svn_relpath_skip_ancestor(info->path,
+                                                              edit_path);
+              SVN_ERR_ASSERT(relpath && *relpath);
               SVN_ERR(svn_fs_revision_root(&source_root,
                                            svn_fs_root_fs(root),
                                            info->copyfrom_rev, pool));

Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c Mon Nov 21 07:07:56 2011
@@ -32,17 +32,19 @@
 #include "svn_props.h"
 #include "repos.h"
 #include "svn_private_config.h"
+
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
 
 #define NUM_CACHED_SOURCE_ROOTS 4
 
-/* Theory of operation: we write report operations out to a temporary
-   file as we receive them.  When the report is finished, we read the
+/* Theory of operation: we write report operations out to a spill-buffer
+   as we receive them.  When the report is finished, we read the
    operations back out again, using them to guide the progression of
    the delta between the source and target revs.
 
-   Temporary file format: we use a simple ad-hoc format to store the
+   Spill-buffer content format: we use a simple ad-hoc format to store the
    report operations.  Each report operation is the concatention of
    the following ("+/-" indicates the single character '+' or '-';
    <length> and <revnum> are written out as decimal strings):
@@ -122,8 +124,8 @@ typedef struct report_baton_t
   svn_repos_authz_func_t authz_read_func;
   void *authz_read_baton;
 
-  /* The temporary file in which we are stashing the report. */
-  apr_file_t *tempfile;
+  /* The spill-buffer holding the report. */
+  svn_spillbuf_reader_t *reader;
 
   /* For the actual editor drive, we'll need a lookahead path info
      entry, a cache of FS roots, and a pool to store them. */
@@ -158,14 +160,14 @@ static svn_error_t *delta_dirs(report_ba
 /* --- READING PREVIOUSLY STORED REPORT INFORMATION --- */
 
 static svn_error_t *
-read_number(apr_uint64_t *num, apr_file_t *temp, apr_pool_t *pool)
+read_number(apr_uint64_t *num, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   char c;
 
   *num = 0;
   while (1)
     {
-      SVN_ERR(svn_io_file_getc(&c, temp, pool));
+      SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
       if (c == ':')
         break;
       *num = *num * 10 + (c - '0');
@@ -174,13 +176,14 @@ read_number(apr_uint64_t *num, apr_file_
 }
 
 static svn_error_t *
-read_string(const char **str, apr_file_t *temp, apr_pool_t *pool)
+read_string(const char **str, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   apr_uint64_t len;
   apr_size_t size;
+  apr_size_t amt;
   char *buf;
 
-  SVN_ERR(read_number(&len, temp, pool));
+  SVN_ERR(read_number(&len, reader, pool));
 
   /* Len can never be less than zero.  But could len be so large that
      len + 1 wraps around and we end up passing 0 to apr_palloc(),
@@ -201,22 +204,26 @@ read_string(const char **str, apr_file_t
 
   size = (apr_size_t)len;
   buf = apr_palloc(pool, size+1);
-  SVN_ERR(svn_io_file_read_full2(temp, buf, size, NULL, NULL, pool));
+  if (size > 0)
+    {
+      SVN_ERR(svn_spillbuf__reader_read(&amt, reader, buf, size, pool));
+      SVN_ERR_ASSERT(amt == size);
+    }
   buf[len] = 0;
   *str = buf;
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-read_rev(svn_revnum_t *rev, apr_file_t *temp, apr_pool_t *pool)
+read_rev(svn_revnum_t *rev, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   char c;
   apr_uint64_t num;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   if (c == '+')
     {
-      SVN_ERR(read_number(&num, temp, pool));
+      SVN_ERR(read_number(&num, reader, pool));
       *rev = (svn_revnum_t) num;
     }
   else
@@ -225,15 +232,15 @@ read_rev(svn_revnum_t *rev, apr_file_t *
 }
 
 /* Read a single character to set *DEPTH (having already read '+')
-   from TEMP.  PATH is the path to which the depth applies, and is
+   from READER.  PATH is the path to which the depth applies, and is
    used for error reporting only. */
 static svn_error_t *
-read_depth(svn_depth_t *depth, apr_file_t *temp, const char *path,
+read_depth(svn_depth_t *depth, svn_spillbuf_reader_t *reader, const char *path,
            apr_pool_t *pool)
 {
   char c;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   switch (c)
     {
     case 'X':
@@ -260,14 +267,16 @@ read_depth(svn_depth_t *depth, apr_file_
   return SVN_NO_ERROR;
 }
 
-/* Read a report operation *PI out of TEMP.  Set *PI to NULL if we
+/* Read a report operation *PI out of READER.  Set *PI to NULL if we
    have reached the end of the report. */
 static svn_error_t *
-read_path_info(path_info_t **pi, apr_file_t *temp, apr_pool_t *pool)
+read_path_info(path_info_t **pi,
+               svn_spillbuf_reader_t *reader,
+               apr_pool_t *pool)
 {
   char c;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   if (c == '-')
     {
       *pi = NULL;
@@ -275,23 +284,23 @@ read_path_info(path_info_t **pi, apr_fil
     }
 
   *pi = apr_palloc(pool, sizeof(**pi));
-  SVN_ERR(read_string(&(*pi)->path, temp, pool));
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(read_string(&(*pi)->path, reader, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_string(&(*pi)->link_path, temp, pool));
+    SVN_ERR(read_string(&(*pi)->link_path, reader, pool));
   else
     (*pi)->link_path = NULL;
-  SVN_ERR(read_rev(&(*pi)->rev, temp, pool));
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(read_rev(&(*pi)->rev, reader, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_depth(&((*pi)->depth), temp, (*pi)->path, pool));
+    SVN_ERR(read_depth(&((*pi)->depth), reader, (*pi)->path, pool));
   else
     (*pi)->depth = svn_depth_infinity;
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   (*pi)->start_empty = (c == '+');
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_string(&(*pi)->lock_token, temp, pool));
+    SVN_ERR(read_string(&(*pi)->lock_token, reader, pool));
   else
     (*pi)->lock_token = NULL;
   (*pi)->pool = pool;
@@ -306,7 +315,7 @@ relevant(path_info_t *pi, const char *pr
           (!*prefix || pi->path[plen] == '/'));
 }
 
-/* Fetch the next pathinfo from B->tempfile for a descendant of
+/* Fetch the next pathinfo from B->reader for a descendant of
    PREFIX.  If the next pathinfo is for an immediate child of PREFIX,
    set *ENTRY to the path component of the report information and
    *INFO to the path information for that entry.  If the next pathinfo
@@ -353,7 +362,7 @@ fetch_path_info(report_baton_t *b, const
           *entry = relpath;
           *info = b->lookahead;
           subpool = svn_pool_create(b->pool);
-          SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+          SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
         }
     }
   return SVN_NO_ERROR;
@@ -371,7 +380,7 @@ skip_path_info(report_baton_t *b, const 
     {
       svn_pool_destroy(b->lookahead->pool);
       subpool = svn_pool_create(b->pool);
-      SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+      SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
     }
   return SVN_NO_ERROR;
 }
@@ -1233,6 +1242,8 @@ drive(report_baton_t *b, svn_revnum_t s_
 
   /* Collect information about the source and target nodes. */
   s_fullpath = svn_fspath__join(b->fs_base, b->s_operand, pool);
+  /* ### Weird: When I have a file external defined as "^/A/a X/xa",
+   * ### S_FULLPATH becomes "/A/a/xa" here, which is complete nonsense. */
   SVN_ERR(get_source_root(b, &s_root, s_rev));
   SVN_ERR(fake_dirent(&s_entry, s_root, s_fullpath, pool));
   SVN_ERR(fake_dirent(&t_entry, b->t_root, b->t_path, pool));
@@ -1277,7 +1288,6 @@ drive(report_baton_t *b, svn_revnum_t s_
 static svn_error_t *
 finish_report(report_baton_t *b, apr_pool_t *pool)
 {
-  apr_off_t offset;
   path_info_t *info;
   apr_pool_t *subpool;
   svn_revnum_t s_rev;
@@ -1286,14 +1296,12 @@ finish_report(report_baton_t *b, apr_poo
   /* Save our pool to manage the lookahead and fs_root cache with. */
   b->pool = pool;
 
-  /* Add an end marker and rewind the temporary file. */
-  SVN_ERR(svn_io_file_write_full(b->tempfile, "-", 1, NULL, pool));
-  offset = 0;
-  SVN_ERR(svn_io_file_seek(b->tempfile, APR_SET, &offset, pool));
+  /* Add the end marker. */
+  SVN_ERR(svn_spillbuf__reader_write(b->reader, "-", 1, pool));
 
   /* Read the first pathinfo from the report and verify that it is a top-level
      set_path entry. */
-  SVN_ERR(read_path_info(&info, b->tempfile, pool));
+  SVN_ERR(read_path_info(&info, b->reader, pool));
   if (!info || strcmp(info->path, b->s_operand) != 0
       || info->link_path || !SVN_IS_VALID_REVNUM(info->rev))
     return svn_error_create(SVN_ERR_REPOS_BAD_REVISION_REPORT, NULL,
@@ -1302,7 +1310,7 @@ finish_report(report_baton_t *b, apr_poo
 
   /* Initialize the lookahead pathinfo. */
   subpool = svn_pool_create(pool);
-  SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+  SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
 
   if (b->lookahead && strcmp(b->lookahead->path, b->s_operand) == 0)
     {
@@ -1320,7 +1328,7 @@ finish_report(report_baton_t *b, apr_poo
           b->lookahead->depth = info->depth;
         }
       info = b->lookahead;
-      SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+      SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
     }
 
   /* Open the target root and initialize the source root cache. */
@@ -1342,7 +1350,7 @@ finish_report(report_baton_t *b, apr_poo
 
 /* --- COLLECTING THE REPORT INFORMATION --- */
 
-/* Record a report operation into the temporary file.  Return an error
+/* Record a report operation into the spill buffer.  Return an error
    if DEPTH is svn_depth_unknown. */
 static svn_error_t *
 write_path_info(report_baton_t *b, const char *path, const char *lpath,
@@ -1381,7 +1389,7 @@ write_path_info(report_baton_t *b, const
   rep = apr_psprintf(pool, "+%" APR_SIZE_T_FMT ":%s%s%s%s%c%s",
                      strlen(path), path, lrep, rrep, drep,
                      start_empty ? '+' : '-', ltrep);
-  return svn_io_file_write_full(b->tempfile, rep, strlen(rep), NULL, pool);
+  return svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool);
 }
 
 svn_error_t *
@@ -1420,20 +1428,14 @@ svn_error_t *
 svn_repos_finish_report(void *baton, apr_pool_t *pool)
 {
   report_baton_t *b = baton;
-  svn_error_t *finish_err, *close_err;
-
-  finish_err = finish_report(b, pool);
-  close_err = svn_io_file_close(b->tempfile, pool);
 
-  return svn_error_trace(svn_error_compose_create(finish_err, close_err));
+  return svn_error_trace(finish_report(b, pool));
 }
 
 svn_error_t *
 svn_repos_abort_report(void *baton, apr_pool_t *pool)
 {
-  report_baton_t *b = baton;
-
-  return svn_error_trace(svn_io_file_close(b->tempfile, pool));
+  return SVN_NO_ERROR;
 }
 
 /* --- BEGINNING THE REPORT --- */
@@ -1482,10 +1484,9 @@ svn_repos_begin_report2(void **report_ba
   b->authz_read_baton = authz_read_baton;
   b->revision_infos = apr_hash_make(pool);
   b->pool = pool;
-
-  SVN_ERR(svn_io_open_unique_file3(&b->tempfile, NULL, NULL,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   pool, pool));
+  b->reader = svn_spillbuf__reader_create(1000 /* blocksize */,
+                                          1000000 /* maxsize */,
+                                          pool);
 
   /* Hand reporter back to client. */
   *report_baton = b;

Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c Mon Nov 21 07:07:56 2011
@@ -590,7 +590,7 @@ svn_repos__prev_location(svn_revnum_t *a
                          apr_pool_t *pool)
 {
   svn_fs_root_t *root, *copy_root;
-  const char *copy_path, *copy_src_path, *remainder = "";
+  const char *copy_path, *copy_src_path, *remainder;
   svn_revnum_t copy_src_rev;
 
   /* Initialize return variables. */
@@ -623,8 +623,7 @@ svn_repos__prev_location(svn_revnum_t *a
   */
   SVN_ERR(svn_fs_copied_from(&copy_src_rev, &copy_src_path,
                              copy_root, copy_path, pool));
-  if (! strcmp(copy_path, path) == 0)
-    remainder = svn_fspath__is_child(copy_path, path, pool);
+  remainder = svn_fspath__skip_ancestor(copy_path, path);
   if (prev_path)
     *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
   if (appeared_rev)
@@ -983,31 +982,27 @@ get_path_mergeinfo(apr_hash_t **mergeinf
                    svn_fs_t *fs,
                    const char *path,
                    svn_revnum_t revnum,
-                   apr_pool_t *pool)
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
 {
   svn_mergeinfo_catalog_t tmp_catalog;
   svn_fs_root_t *root;
-  apr_pool_t *subpool = svn_pool_create(pool);
-  apr_array_header_t *paths = apr_array_make(subpool, 1,
+  apr_array_header_t *paths = apr_array_make(scratch_pool, 1,
                                              sizeof(const char *));
 
   APR_ARRAY_PUSH(paths, const char *) = path;
 
-  SVN_ERR(svn_fs_revision_root(&root, fs, revnum, subpool));
+  SVN_ERR(svn_fs_revision_root(&root, fs, revnum, scratch_pool));
   /* We do not need to call svn_repos_fs_get_mergeinfo() (which performs authz)
      because we will filter out unreadable revisions in
      find_interesting_revision(), above */
   SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, root, paths,
-                                svn_mergeinfo_inherited, FALSE, FALSE,
-                                subpool));
+                                svn_mergeinfo_inherited, FALSE, TRUE,
+                                result_pool, scratch_pool));
 
   *mergeinfo = apr_hash_get(tmp_catalog, path, APR_HASH_KEY_STRING);
-  if (*mergeinfo)
-    *mergeinfo = svn_mergeinfo_dup(*mergeinfo, pool);
-  else
-    *mergeinfo = apr_hash_make(pool);
-
-  svn_pool_destroy(subpool);
+  if (!*mergeinfo)
+    *mergeinfo = apr_hash_make(result_pool);
 
   return SVN_NO_ERROR;
 }
@@ -1044,9 +1039,9 @@ static svn_error_t *
 get_merged_mergeinfo(apr_hash_t **merged_mergeinfo,
                      svn_repos_t *repos,
                      struct path_revision *old_path_rev,
-                     apr_pool_t *pool)
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
-  apr_pool_t *subpool = svn_pool_create(pool);
   apr_hash_t *curr_mergeinfo, *prev_mergeinfo, *deleted, *changed;
   svn_error_t *err;
   svn_fs_root_t *root;
@@ -1056,8 +1051,8 @@ get_merged_mergeinfo(apr_hash_t **merged
   /* Getting/parsing/diffing svn:mergeinfo is expensive, so only do it
      if there is a property change. */
   SVN_ERR(svn_fs_revision_root(&root, repos->fs, old_path_rev->revnum,
-                               subpool));
-  SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, subpool));
+                               scratch_pool));
+  SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, scratch_pool));
   while (1)
     {
       svn_fs_path_change2_t *changed_path = apr_hash_get(changed_paths,
@@ -1067,17 +1062,17 @@ get_merged_mergeinfo(apr_hash_t **merged
         break;
       if (svn_fspath__is_root(path, strlen(path)))
         {
-          svn_pool_destroy(subpool);
           *merged_mergeinfo = NULL;
           return SVN_NO_ERROR;
         }
-      path = svn_fspath__dirname(path, subpool);
+      path = svn_fspath__dirname(path, scratch_pool);
     }
 
   /* First, find the mergeinfo difference for old_path_rev->revnum, and
      old_path_rev->revnum - 1. */
   err = get_path_mergeinfo(&curr_mergeinfo, repos->fs, old_path_rev->path,
-                           old_path_rev->revnum, subpool);
+                           old_path_rev->revnum, scratch_pool,
+                           scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -1086,7 +1081,6 @@ get_merged_mergeinfo(apr_hash_t **merged
              best we can do is ignore it and act is if there are
              no mergeinfo differences. */
           svn_error_clear(err);
-          svn_pool_destroy(subpool);
           *merged_mergeinfo = NULL;
           return SVN_NO_ERROR;
         }
@@ -1097,14 +1091,14 @@ get_merged_mergeinfo(apr_hash_t **merged
     }
 
   err = get_path_mergeinfo(&prev_mergeinfo, repos->fs, old_path_rev->path,
-                           old_path_rev->revnum - 1, subpool);
+                           old_path_rev->revnum - 1, scratch_pool,
+                           scratch_pool);
   if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND
               || err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR))
     {
       /* If the path doesn't exist in the previous revision or it does exist
          but has invalid mergeinfo (Issue #3896), assume no merges. */
       svn_error_clear(err);
-      svn_pool_destroy(subpool);
       *merged_mergeinfo = NULL;
       return SVN_NO_ERROR;
     }
@@ -1112,18 +1106,17 @@ get_merged_mergeinfo(apr_hash_t **merged
     SVN_ERR(err);
 
   /* Then calculate and merge the differences. */
-  SVN_ERR(svn_mergeinfo_diff(&deleted, &changed, prev_mergeinfo, curr_mergeinfo,
-                             FALSE, subpool));
-  SVN_ERR(svn_mergeinfo_merge(changed, deleted, subpool));
+  SVN_ERR(svn_mergeinfo_diff2(&deleted, &changed, prev_mergeinfo,
+                              curr_mergeinfo, FALSE, result_pool,
+                              scratch_pool));
+  SVN_ERR(svn_mergeinfo_merge2(changed, deleted, result_pool, scratch_pool));
 
   /* Store the result. */
   if (apr_hash_count(changed))
-    *merged_mergeinfo = svn_mergeinfo_dup(changed, pool);
+    *merged_mergeinfo = changed;
   else
     *merged_mergeinfo = NULL;
 
-  svn_pool_destroy(subpool);
-
   return SVN_NO_ERROR;
 }
 
@@ -1206,7 +1199,7 @@ find_interesting_revisions(apr_array_hea
 
       if (include_merged_revisions)
         SVN_ERR(get_merged_mergeinfo(&path_rev->merged_mergeinfo, repos,
-                                     path_rev, result_pool));
+                                     path_rev, result_pool, iterpool));
       else
         path_rev->merged_mergeinfo = NULL;
 

Propchange: subversion/branches/svn-bisect/subversion/libsvn_subr/adler32.c
            ('svn:mergeinfo' removed)

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c Mon Nov 21 07:07:56 2011
@@ -30,6 +30,7 @@
 #include "svn_private_config.h"
 
 #include "cache.h"
+#include "private/svn_mutex.h"
 
 /* The (internal) cache object. */
 typedef struct inprocess_cache_t {
@@ -80,12 +81,10 @@ typedef struct inprocess_cache_t {
    */
   apr_size_t data_size;
 
-#if APR_HAS_THREADS
   /* A lock for intra-process synchronization to the cache, or NULL if
    * the cache's creator doesn't feel the cache needs to be
    * thread-safe. */
-  apr_thread_mutex_t *mutex;
-#endif
+  svn_mutex__t *mutex;
 } inprocess_cache_t;
 
 /* A cache page; all items on the page are allocated from the same
@@ -182,39 +181,28 @@ duplicate_key(inprocess_cache_t *cache,
     return apr_pmemdup(pool, key, cache->klen);
 }
 
-/* If applicable, locks CACHE's mutex. */
 static svn_error_t *
-lock_cache(inprocess_cache_t *cache)
+inprocess_cache_get_internal(char **buffer,
+                             apr_size_t *size,
+                             inprocess_cache_t *cache,
+                             const void *key,
+                             apr_pool_t *result_pool)
 {
-#if APR_HAS_THREADS
-  apr_status_t status;
-  if (! cache->mutex)
-    return SVN_NO_ERROR;
-
-  status = apr_thread_mutex_lock(cache->mutex);
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
-#endif
+  struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
 
-  return SVN_NO_ERROR;
-}
-
-/* If applicable, unlocks CACHE's mutex, then returns ERR. */
-static svn_error_t *
-unlock_cache(inprocess_cache_t *cache,
-             svn_error_t *err)
-{
-#if APR_HAS_THREADS
-  apr_status_t status;
-  if (! cache->mutex)
-    return err;
+  *buffer = NULL;
+  if (entry)
+    {
+      SVN_ERR(move_page_to_front(cache, entry->page));
 
-  status = apr_thread_mutex_unlock(cache->mutex);
-  if (status && !err)
-    return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
-#endif
+      /* duplicate the buffer entry */
+      *buffer = apr_palloc(result_pool, entry->size);
+      memcpy(*buffer, entry->value, entry->size);
 
-  return err;
+      *size = entry->size;
+    }
+    
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -225,38 +213,24 @@ inprocess_cache_get(void **value_p,
                     apr_pool_t *result_pool)
 {
   inprocess_cache_t *cache = cache_void;
-  svn_error_t *err = NULL;
-  struct cache_entry *entry;
   char* buffer;
+  apr_size_t size;
 
-  SVN_ERR(lock_cache(cache));
-
-  entry = apr_hash_get(cache->hash, key, cache->klen);
-  if (! entry)
-    {
-      *found = FALSE;
-      return unlock_cache(cache, SVN_NO_ERROR);
-    }
-
-  SVN_ERR(move_page_to_front(cache, entry->page));
-
-  /* duplicate the buffer entry */
-  buffer = apr_palloc(result_pool, entry->size);
-  memcpy(buffer, entry->value, entry->size);
-
-  /* the cache is no longer being accessed */
-  SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
-
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       inprocess_cache_get_internal(&buffer,
+                                                    &size,
+                                                    cache,
+                                                    key,
+                                                    result_pool));
+    
   /* deserialize the buffer content. Usually, this will directly
      modify the buffer content directly.
    */
-  *found = TRUE;
-  if (entry->value)
-    err = cache->deserialize_func(value_p, buffer, entry->size, result_pool);
-  else
-    *value_p = NULL;
-
-  return err;
+  *value_p = NULL;
+  *found = buffer != NULL;
+  return buffer && size
+    ? cache->deserialize_func(value_p, buffer, size, result_pool)
+    : SVN_NO_ERROR;
 }
 
 /* Removes PAGE from the LRU list, removes all of its entries from
@@ -292,16 +266,12 @@ erase_page(inprocess_cache_t *cache,
 
 
 static svn_error_t *
-inprocess_cache_set(void *cache_void,
-                    const void *key,
-                    void *value,
-                    apr_pool_t *scratch_pool)
+inprocess_cache_set_internal(inprocess_cache_t *cache,
+                             const void *key,
+                             void *value,
+                             apr_pool_t *scratch_pool)
 {
-  inprocess_cache_t *cache = cache_void;
   struct cache_entry *existing_entry;
-  svn_error_t *err = SVN_NO_ERROR;
-
-  SVN_ERR(lock_cache(cache));
 
   existing_entry = apr_hash_get(cache->hash, key, cache->klen);
 
@@ -333,11 +303,13 @@ inprocess_cache_set(void *cache_void,
       cache->data_size -= existing_entry->size;
       if (value)
         {
-          err = cache->serialize_func((char **)&existing_entry->value,
-                                      &existing_entry->size,
-                                      value,
-                                      page->page_pool);
+          SVN_ERR(cache->serialize_func((char **)&existing_entry->value,
+                                        &existing_entry->size,
+                                        value,
+                                        page->page_pool));
           cache->data_size += existing_entry->size;
+          if (existing_entry->size == 0)
+            existing_entry->value = NULL;
         }
       else
         {
@@ -345,7 +317,7 @@ inprocess_cache_set(void *cache_void,
           existing_entry->size = 0;
         }
 
-      goto cleanup;
+      return SVN_NO_ERROR;
     }
 
   /* Do we not have a partial page to put it on, but we are allowed to
@@ -383,11 +355,13 @@ inprocess_cache_set(void *cache_void,
     new_entry->key = duplicate_key(cache, key, page->page_pool);
     if (value)
       {
-        err = cache->serialize_func((char **)&new_entry->value,
-                                    &new_entry->size,
-                                    value,
-                                    page->page_pool);
+        SVN_ERR(cache->serialize_func((char **)&new_entry->value,
+                                      &new_entry->size,
+                                      value,
+                                      page->page_pool));
         cache->data_size += new_entry->size;
+        if (new_entry->size == 0)
+          new_entry->value = NULL;
       }
     else
       {
@@ -395,9 +369,6 @@ inprocess_cache_set(void *cache_void,
         new_entry->size = 0;
       }
 
-    if (err)
-      goto cleanup;
-
     /* Add the entry to the page's list. */
     new_entry->page = page;
     new_entry->next_entry = page->first_entry;
@@ -418,8 +389,24 @@ inprocess_cache_set(void *cache_void,
       }
   }
 
- cleanup:
-  return unlock_cache(cache, err);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set(void *cache_void,
+                    const void *key,
+                    void *value,
+                    apr_pool_t *scratch_pool)
+{
+  inprocess_cache_t *cache = cache_void;
+
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       inprocess_cache_set_internal(cache,
+                                                    key,
+                                                    value,
+                                                    scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 /* Baton type for svn_cache__iter. */
@@ -455,10 +442,33 @@ inprocess_cache_iter(svn_boolean_t *comp
   b.user_cb = user_cb;
   b.user_baton = user_baton;
 
-  SVN_ERR(lock_cache(cache));
-  return unlock_cache(cache,
-                      svn_iter_apr_hash(completed, cache->hash, iter_cb, &b,
-                                        scratch_pool));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       svn_iter_apr_hash(completed, cache->hash, 
+                                         iter_cb, &b, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_get_partial_internal(void **value_p,
+                                     svn_boolean_t *found,
+                                     inprocess_cache_t *cache,
+                                     const void *key,
+                                     svn_cache__partial_getter_func_t func,
+                                     void *baton,
+                                     apr_pool_t *result_pool)
+{
+  struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+  if (! entry)
+    {
+      *found = FALSE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(move_page_to_front(cache, entry->page));
+
+  *found = TRUE;
+  return func(value_p, entry->value, entry->size, baton, result_pool);
 }
 
 static svn_error_t *
@@ -471,23 +481,40 @@ inprocess_cache_get_partial(void **value
                             apr_pool_t *result_pool)
 {
   inprocess_cache_t *cache = cache_void;
-  struct cache_entry *entry;
 
-  SVN_ERR(lock_cache(cache));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       inprocess_cache_get_partial_internal(value_p,
+                                                            found,
+                                                            cache,
+                                                            key,
+                                                            func,
+                                                            baton,
+                                                            result_pool));
 
-  entry = apr_hash_get(cache->hash, key, cache->klen);
-  if (! entry)
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set_partial_internal(inprocess_cache_t *cache,
+                                     const void *key,
+                                     svn_cache__partial_setter_func_t func,
+                                     void *baton,
+                                     apr_pool_t *scratch_pool)
+{
+  struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+  if (entry)
     {
-      *found = FALSE;
-      return unlock_cache(cache, SVN_NO_ERROR);
-    }
+      SVN_ERR(move_page_to_front(cache, entry->page));
 
-  SVN_ERR(move_page_to_front(cache, entry->page));
+      cache->data_size -= entry->size;
+      SVN_ERR(func((char **)&entry->value,
+                  &entry->size,
+                  baton,
+                  entry->page->page_pool));
+      cache->data_size += entry->size;
+    }
 
-  *found = TRUE;
-  return unlock_cache(cache,
-                      func(value_p, entry->value, entry->size, baton,
-                           result_pool));
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -498,25 +525,15 @@ inprocess_cache_set_partial(void *cache_
                             apr_pool_t *scratch_pool)
 {
   inprocess_cache_t *cache = cache_void;
-  struct cache_entry *entry;
-  svn_error_t *err = SVN_NO_ERROR;
-
-  SVN_ERR(lock_cache(cache));
-
-  entry = apr_hash_get(cache->hash, key, cache->klen);
-  if (! entry)
-    return unlock_cache(cache, err);
 
-  SVN_ERR(move_page_to_front(cache, entry->page));
-
-  cache->data_size -= entry->size;
-  err = func((char **)&entry->value,
-             &entry->size,
-             baton,
-             entry->page->page_pool);
-  cache->data_size += entry->size;
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       inprocess_cache_set_partial_internal(cache,
+                                                            key,
+                                                            func,
+                                                            baton,
+                                                            scratch_pool));
 
-  return unlock_cache(cache, err);
+  return SVN_NO_ERROR;
 }
 
 static svn_boolean_t
@@ -532,15 +549,10 @@ inprocess_cache_is_cachable(void *cache_
 }
 
 static svn_error_t *
-inprocess_cache_get_info(void *cache_void,
-                         svn_cache__info_t *info,
-                         svn_boolean_t reset,
-                         apr_pool_t *result_pool)
+inprocess_cache_get_info_internal(inprocess_cache_t *cache,
+                                  svn_cache__info_t *info,
+                                  apr_pool_t *result_pool)
 {
-  inprocess_cache_t *cache = cache_void;
-
-  SVN_ERR(lock_cache(cache));
-
   info->id = apr_pstrdup(result_pool, cache->id);
 
   info->used_entries = apr_hash_count(cache->hash);
@@ -552,10 +564,26 @@ inprocess_cache_get_info(void *cache_voi
                    + cache->items_per_page * sizeof(struct cache_page)
                    + info->used_entries * sizeof(struct cache_entry);
 
-  return unlock_cache(cache, SVN_NO_ERROR);
+  return SVN_NO_ERROR;
 }
 
 
+static svn_error_t *
+inprocess_cache_get_info(void *cache_void,
+                         svn_cache__info_t *info,
+                         svn_boolean_t reset,
+                         apr_pool_t *result_pool)
+{
+  inprocess_cache_t *cache = cache_void;
+
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       inprocess_cache_get_info_internal(cache,
+                                                         info,
+                                                         result_pool));
+
+  return SVN_NO_ERROR;
+}
+
 static svn_cache__vtable_t inprocess_cache_vtable = {
   inprocess_cache_get,
   inprocess_cache_set,
@@ -602,17 +630,7 @@ svn_cache__create_inprocess(svn_cache__t
   /* The sentinel doesn't need a pool.  (We're happy to crash if we
    * accidentally try to treat it like a real page.) */
 
-#if APR_HAS_THREADS
-  if (thread_safe)
-    {
-      apr_status_t status = apr_thread_mutex_create(&(cache->mutex),
-                                                    APR_THREAD_MUTEX_DEFAULT,
-                                                    pool);
-      if (status)
-        return svn_error_wrap_apr(status,
-                                  _("Can't create cache mutex"));
-    }
-#endif
+  SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
 
   cache->cache_pool = pool;
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c Mon Nov 21 07:07:56 2011
@@ -30,6 +30,7 @@
 #include "cache.h"
 #include "svn_string.h"
 #include "private/svn_dep_compat.h"
+#include "private/svn_mutex.h"
 
 /*
  * This svn_cache__t implementation actually consists of two parts:
@@ -423,13 +424,11 @@ struct svn_membuffer_t
    */
   apr_uint64_t total_hits;
 
-#if APR_HAS_THREADS
   /* A lock for intra-process synchronization to the cache, or NULL if
    * the cache's creator doesn't feel the cache needs to be
    * thread-safe.
    */
-  apr_thread_mutex_t *mutex;
-#endif
+  svn_mutex__t *mutex;
 };
 
 /* Align integer VALUE to the next ITEM_ALIGNMENT boundary.
@@ -440,43 +439,6 @@ struct svn_membuffer_t
  */
 #define ALIGN_POINTER(pointer) ((void*)ALIGN_VALUE((apr_size_t)(char*)(pointer)))
 
-/* Acquire the cache mutex, if necessary.
- */
-static svn_error_t *
-lock_cache(svn_membuffer_t *cache)
-{
-#if APR_HAS_THREADS
-  if (cache->mutex)
-  {
-    apr_status_t status = apr_thread_mutex_lock(cache->mutex);
-    if (status)
-      return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
-  }
-#endif
-
-  return SVN_NO_ERROR;
-}
-
-/* Release the cache mutex, if necessary.
- */
-static svn_error_t *
-unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
-{
-#if APR_HAS_THREADS
-  if (cache->mutex)
-  {
-    apr_status_t status = apr_thread_mutex_unlock(cache->mutex);
-    if (err)
-      return err;
-
-    if (status)
-      return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
-  }
-#endif
-
-  return err;
-}
-
 /* Resolve a dictionary entry reference, i.e. return the entry
  * for the given IDX.
  */
@@ -713,7 +675,7 @@ initialize_group(svn_membuffer_t *cache,
 static entry_t *
 find_entry(svn_membuffer_t *cache,
            apr_uint32_t group_index,
-           unsigned char *to_find,
+           const unsigned char *to_find,
            svn_boolean_t find_empty)
 {
   entry_t *group;
@@ -1076,25 +1038,10 @@ svn_cache__membuffer_cache_create(svn_me
           return svn_error_wrap_apr(APR_ENOMEM, _("OOM"));
         }
 
-#if APR_HAS_THREADS
       /* A lock for intra-process synchronization to the cache, or NULL if
        * the cache's creator doesn't feel the cache needs to be
        * thread-safe. */
-
-      c[seg].mutex = NULL;
-      if (thread_safe)
-        {
-          apr_status_t status =
-              apr_thread_mutex_create(&(c[seg].mutex),
-                                      APR_THREAD_MUTEX_DEFAULT,
-                                      pool);
-          if (status)
-            return svn_error_wrap_apr(status, _("Can't create cache mutex"));
-        }
-#else
-      if (thread_safe)
-        return svn_error_wrap_apr(APR_ENOTIMPL, _("APR doesn't support threads"));
-#endif
+      SVN_ERR(svn_mutex__init(&c[seg].mutex, thread_safe, pool));
     }
 
   /* done here
@@ -1104,48 +1051,30 @@ svn_cache__membuffer_cache_create(svn_me
 }
 
 
-/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+/* Try to insert the serialized item given in BUFFER with SIZE into
+ * the group GROUP_INDEX of CACHE and uniquely identify it by hash 
+ * value TO_FIND. 
+ * 
  * However, there is no guarantee that it will actually be put into
- * the cache. If there is already some data associated to the KEY,
+ * the cache. If there is already some data associated with TO_FIND,
  * it will be removed from the cache even if the new data cannot
  * be inserted.
- *
- * The SERIALIZER is called to transform the ITEM into a single,
- * flat data buffer. Temporary allocations may be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
  */
 static svn_error_t *
-membuffer_cache_set(svn_membuffer_t *cache,
-                    const void *key,
-                    apr_size_t key_len,
-                    void *item,
-                    svn_cache__serialize_func_t serializer,
-                    DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                    apr_pool_t *scratch_pool)
+membuffer_cache_set_internal(svn_membuffer_t *cache,
+                             const unsigned char *to_find,
+                             apr_uint32_t group_index,
+                             char *buffer,
+                             apr_size_t size,
+                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                             apr_pool_t *scratch_pool)
 {
-  apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  char *buffer;
-  apr_size_t size;
-
-  /* find the entry group that will hold the key.
-   */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
-  if (group_index == NO_INDEX)
-    return SVN_NO_ERROR;
-
-  /* Serialize data data.
-   */
-  if (item)
-    SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
-
-  /* The actual cache data access needs to sync'ed
-   */
-  SVN_ERR(lock_cache(cache));
-
   /* if necessary, enlarge the insertion window.
    */
-  if (   item != NULL
+  if (   buffer != NULL
       && cache->data_size / 4 > size
       && ensure_data_insertable(cache, size))
     {
@@ -1153,7 +1082,7 @@ membuffer_cache_set(svn_membuffer_t *cac
        * Get an unused entry for the key and and initialize it with
        * the serialized item's (future) posion within data buffer.
        */
-      entry = find_entry(cache, group_index, to_find, TRUE);
+      entry_t *entry = find_entry(cache, group_index, to_find, TRUE);
       entry->size = size;
       entry->offset = cache->current_data;
 
@@ -1182,44 +1111,76 @@ membuffer_cache_set(svn_membuffer_t *cac
        */
       find_entry(cache, group_index, to_find, TRUE);
     }
-
-  /* done here -> unlock the cache
-   */
-  return unlock_cache(cache, SVN_NO_ERROR);
+  return SVN_NO_ERROR;
 }
 
-/* Look for the *ITEM identified by KEY. If no item has been stored
- * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
- * re-construct the proper object from the serialized data.
- * Allocations will be done in POOL.
+/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+ * However, there is no guarantee that it will actually be put into
+ * the cache. If there is already some data associated to the KEY,
+ * it will be removed from the cache even if the new data cannot
+ * be inserted.
+ *
+ * The SERIALIZER is called to transform the ITEM into a single,
+ * flat data buffer. Temporary allocations may be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_get(svn_membuffer_t *cache,
+membuffer_cache_set(svn_membuffer_t *cache,
                     const void *key,
                     apr_size_t key_len,
-                    void **item,
-                    svn_cache__deserialize_func_t deserializer,
+                    void *item,
+                    svn_cache__serialize_func_t serializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                    apr_pool_t *result_pool)
+                    apr_pool_t *scratch_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  char *buffer;
+  char *buffer = NULL;
   apr_size_t size;
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
   if (group_index == NO_INDEX)
-    {
-      /* Some error occured, return "item not found".
-       */
-      *item = NULL;
-      return SVN_NO_ERROR;
-    }
+    return SVN_NO_ERROR;
+
+  /* Serialize data data.
+   */
+  if (item)
+    SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
 
-  SVN_ERR(lock_cache(cache));
+  /* The actual cache data access needs to sync'ed
+   */
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_set_internal(cache,
+                                                    to_find,
+                                                    group_index,
+                                                    buffer,
+                                                    size,
+                                                    DEBUG_CACHE_MEMBUFFER_TAG
+                                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no item has been stored for KEY, 
+ * *BUFFER will be NULL. Otherwise, return a copy of the serialized
+ * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will 
+ * be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_internal(svn_membuffer_t *cache,
+                             apr_uint32_t group_index,
+                             const unsigned char *to_find,
+                             char **buffer,
+                             apr_size_t *item_size,
+                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                             apr_pool_t *result_pool)
+{
+  entry_t *entry;
+  apr_size_t size;
 
   /* The actual cache data access needs to sync'ed
    */
@@ -1229,13 +1190,15 @@ membuffer_cache_get(svn_membuffer_t *cac
     {
       /* no such entry found.
        */
-      *item = NULL;
-      return unlock_cache(cache, SVN_NO_ERROR);
+      *buffer = NULL;
+      *item_size = 0;
+  
+      return SVN_NO_ERROR;
     }
-
+    
   size = ALIGN_VALUE(entry->size);
-  buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
-  memcpy(buffer, (const char*)cache->data + entry->offset, size);
+  *buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
+  memcpy(*buffer, (const char*)cache->data + entry->offset, size);
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
@@ -1258,45 +1221,91 @@ membuffer_cache_get(svn_membuffer_t *cac
   cache->hit_count++;
   cache->total_hits++;
 
-  SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
-
-  /* re-construct the original data object from its serialized form.
-   */
-  return deserializer(item, buffer, entry->size, result_pool);
+  *item_size = entry->size;
+  
+  return SVN_NO_ERROR;
 }
 
-/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
- * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
- * the DESERIALIZER is called with that entry and the BATON provided
- * and will extract the desired information. The result is set in *ITEM.
+/* Look for the *ITEM identified by KEY. If no item has been stored
+ * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
+ * re-construct the proper object from the serialized data.
  * Allocations will be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_get_partial(svn_membuffer_t *cache,
-                            const void *key,
-                            apr_size_t key_len,
-                            void **item,
-                            svn_boolean_t *found,
-                            svn_cache__partial_getter_func_t deserializer,
-                            void *baton,
-                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                            apr_pool_t *result_pool)
+membuffer_cache_get(svn_membuffer_t *cache,
+                    const void *key,
+                    apr_size_t key_len,
+                    void **item,
+                    svn_cache__deserialize_func_t deserializer,
+                    DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                    apr_pool_t *result_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  svn_error_t *err = SVN_NO_ERROR;
+  char *buffer;
+  apr_size_t size;
 
+  /* find the entry group that will hold the key.
+   */
   group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+  if (group_index == NO_INDEX)
+    {
+      /* Some error occured, return "item not found".
+       */
+      *item = NULL;
+      return SVN_NO_ERROR;
+    }
 
-  SVN_ERR(lock_cache(cache));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_get_internal(cache,
+                                                    group_index,
+                                                    to_find,
+                                                    &buffer,
+                                                    &size,
+                                                    DEBUG_CACHE_MEMBUFFER_TAG
+                                                    result_pool));
 
-  entry = find_entry(cache, group_index, to_find, FALSE);
+  /* re-construct the original data object from its serialized form.
+   */
+  if (buffer == NULL)
+    {
+      *item = NULL;
+      return SVN_NO_ERROR;
+    }
+    
+  return deserializer(item, buffer, size, result_pool);
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. FOUND indicates whether that entry exists.
+ * If not found, *ITEM will be NULL.
+ * 
+ * Otherwise, the DESERIALIZER is called with that entry and the BATON 
+ * provided and will extract the desired information. The result is set
+ * in *ITEM. Allocations will be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_partial_internal(svn_membuffer_t *cache,
+                                     apr_uint32_t group_index,
+                                     const unsigned char *to_find,
+                                     void **item,
+                                     svn_boolean_t *found,
+                                     svn_cache__partial_getter_func_t deserializer,
+                                     void *baton,
+                                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                                     apr_pool_t *result_pool)
+{
+  entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
   cache->total_reads++;
   if (entry == NULL)
     {
       *item = NULL;
       *found = FALSE;
+      
+      return SVN_NO_ERROR;
     }
   else
     {
@@ -1324,50 +1333,75 @@ membuffer_cache_get_partial(svn_membuffe
 
 #endif
 
-      err = deserializer(item,
-                         (const char*)cache->data + entry->offset,
-                         entry->size,
-                         baton,
-                         result_pool);
+      return deserializer(item,
+                          (const char*)cache->data + entry->offset,
+                          entry->size,
+                          baton,
+                          result_pool);
     }
-
-  /* done here -> unlock the cache
-   */
-  return unlock_cache(cache, err);
 }
 
-/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
- * has been found, the function returns without modifying the cache.
- * Otherwise, FUNC is called with that entry and the BATON provided
- * and may modify the cache entry. Allocations will be done in POOL.
+/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
+ * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
+ * the DESERIALIZER is called with that entry and the BATON provided
+ * and will extract the desired information. The result is set in *ITEM.
+ * Allocations will be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_set_partial(svn_membuffer_t *cache,
+membuffer_cache_get_partial(svn_membuffer_t *cache,
                             const void *key,
                             apr_size_t key_len,
-                            svn_cache__partial_setter_func_t func,
+                            void **item,
+                            svn_boolean_t *found,
+                            svn_cache__partial_getter_func_t deserializer,
                             void *baton,
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                            apr_pool_t *scratch_pool)
+                            apr_pool_t *result_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  svn_error_t *err = SVN_NO_ERROR;
 
-  /* cache item lookup
-   */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
 
-  SVN_ERR(lock_cache(cache));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_get_partial_internal
+                           (cache, group_index, to_find, item, found,
+                            deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
+                            result_pool));
 
-  entry = find_entry(cache, group_index, to_find, FALSE);
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no entry has been found, the function
+ * returns without modifying the cache.
+ * 
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_set_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_set_partial_internal(svn_membuffer_t *cache,
+                                     apr_uint32_t group_index,
+                                     const unsigned char *to_find,
+                                     svn_cache__partial_setter_func_t func,
+                                     void *baton,
+                                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                                     apr_pool_t *scratch_pool)
+{
+  /* cache item lookup
+   */
+  entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
   cache->total_reads++;
 
   /* this function is a no-op if the item is not in cache
    */
   if (entry != NULL)
     {
+      svn_error_t *err;
+
       /* access the serialized cache item */
       char *data = (char*)cache->data + entry->offset;
       char *orig_data = data;
@@ -1441,9 +1475,39 @@ membuffer_cache_set_partial(svn_membuffe
         }
     }
 
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
+ * has been found, the function returns without modifying the cache.
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ */
+static svn_error_t *
+membuffer_cache_set_partial(svn_membuffer_t *cache,
+                            const void *key,
+                            apr_size_t key_len,
+                            svn_cache__partial_setter_func_t func,
+                            void *baton,
+                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                            apr_pool_t *scratch_pool)
+{
+  apr_uint32_t group_index;
+  unsigned char to_find[KEY_SIZE];
+
+  /* cache item lookup
+   */
+  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_set_partial_internal
+                           (cache, group_index, to_find, func, baton,
+                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                            scratch_pool));
+
   /* done here -> unlock the cache
    */
-  return unlock_cache(cache, err);
+  return SVN_NO_ERROR;
 }
 
 /* Implement the svn_cache__t interface on top of a shared membuffer cache.
@@ -1652,6 +1716,8 @@ svn_membuffer_cache_iter(svn_boolean_t *
                           _("Can't iterate a membuffer-based cache"));
 }
 
+/* Implement svn_cache__vtable_t.get_partial
+ */
 static svn_error_t *
 svn_membuffer_cache_get_partial(void **value_p,
                                 svn_boolean_t *found,
@@ -1695,6 +1761,8 @@ svn_membuffer_cache_get_partial(void **v
   return SVN_NO_ERROR;
 }
 
+/* Implement svn_cache__vtable_t.set_partial
+ */
 static svn_error_t *
 svn_membuffer_cache_set_partial(void *cache_void,
                                 const void *key,
@@ -1728,6 +1796,8 @@ svn_membuffer_cache_set_partial(void *ca
   return SVN_NO_ERROR;
 }
 
+/* Implement svn_cache__vtable_t.is_cachable
+ */
 static svn_boolean_t
 svn_membuffer_cache_is_cachable(void *cache_void, apr_size_t size)
 {
@@ -1740,6 +1810,25 @@ svn_membuffer_cache_is_cachable(void *ca
       && (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
 }
 
+/* Add statistics of SEGMENT to INFO.
+ */
+static svn_error_t *
+svn_membuffer_get_segment_info(svn_membuffer_t *segment,
+                               svn_cache__info_t *info)
+{
+  info->data_size += segment->data_size;
+  info->used_size += segment->data_used;
+  info->total_size += segment->data_size +
+      segment->group_count * GROUP_SIZE * sizeof(entry_t);
+
+  info->used_entries += segment->used_entries;
+  info->total_entries += segment->group_count * GROUP_SIZE;
+
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.get_info
+ */
 static svn_error_t *
 svn_membuffer_cache_get_info(void *cache_void,
                              svn_cache__info_t *info,
@@ -1765,18 +1854,8 @@ svn_membuffer_cache_get_info(void *cache
   for (i = 0; i < cache->membuffer->segment_count; ++i)
     {
       svn_membuffer_t *segment = cache->membuffer + i;
-
-      SVN_ERR(lock_cache(segment));
-
-      info->data_size += segment->data_size;
-      info->used_size += segment->data_used;
-      info->total_size += segment->data_size +
-          segment->group_count * GROUP_SIZE * sizeof(entry_t);
-
-      info->used_entries += segment->used_entries;
-      info->total_entries += segment->group_count * GROUP_SIZE;
-
-      SVN_ERR(unlock_cache(segment, SVN_NO_ERROR));
+      SVN_MUTEX__WITH_LOCK(segment->mutex, 
+                           svn_membuffer_get_segment_info(segment, info));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c Mon Nov 21 07:07:56 2011
@@ -37,7 +37,6 @@
 
 #include <apr_errno.h>          /* for apr_strerror */
 #include <apr_general.h>        /* for apr_initialize/apr_terminate */
-#include <apr_atomic.h>         /* for apr_atomic_init */
 #include <apr_strings.h>        /* for apr_snprintf */
 #include <apr_pools.h>
 
@@ -74,6 +73,7 @@ svn_cmdline_init(const char *progname, F
   apr_status_t status;
   apr_pool_t *pool;
   svn_error_t *err;
+  char prefix_buf[64];  /* 64 is probably bigger than most program names */
 
 #ifndef WIN32
   {
@@ -198,11 +198,17 @@ svn_cmdline_init(const char *progname, F
       return EXIT_FAILURE;
     }
 
-  /* This has to happen before any pools are created. */
+  strncpy(prefix_buf, progname, sizeof(prefix_buf) - 3);
+  prefix_buf[sizeof(prefix_buf) - 3] = '\0';
+  strcat(prefix_buf, ": ");
+
+  /* DSO pool must be created before any other pools used by the
+     application so that pool cleanup doesn't unload DSOs too
+     early. See docstring of svn_dso_initialize2(). */
   if ((err = svn_dso_initialize2()))
     {
-      if (error_stream && err->message)
-        fprintf(error_stream, "%s", err->message);
+      if (error_stream)
+        svn_handle_error2(err, error_stream, TRUE, prefix_buf);
 
       svn_error_clear(err);
       return EXIT_FAILURE;
@@ -224,8 +230,8 @@ svn_cmdline_init(const char *progname, F
 
   if ((err = svn_nls_init()))
     {
-      if (error_stream && err->message)
-        fprintf(error_stream, "%s", err->message);
+      if (error_stream)
+        svn_handle_error2(err, error_stream, TRUE, prefix_buf);
 
       svn_error_clear(err);
       return EXIT_FAILURE;
@@ -631,7 +637,7 @@ svn_cmdline__print_xml_prop(svn_stringbu
   const char *encoding = NULL;
 
   if (*outstr == NULL)
-    *outstr = svn_stringbuf_create("", pool);
+    *outstr = svn_stringbuf_create_empty(pool);
 
   if (svn_xml_is_xml_safe(propval->data, propval->len))
     {

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config.c Mon Nov 21 07:07:56 2011
@@ -88,8 +88,8 @@ svn_config_create(svn_config_t **cfgp,
   cfg->pool = result_pool;
   cfg->x_pool = svn_pool_create(result_pool);
   cfg->x_values = FALSE;
-  cfg->tmp_key = svn_stringbuf_create("", result_pool);
-  cfg->tmp_value = svn_stringbuf_create("", result_pool);
+  cfg->tmp_key = svn_stringbuf_create_empty(result_pool);
+  cfg->tmp_value = svn_stringbuf_create_empty(result_pool);
   cfg->section_names_case_sensitive = section_names_case_sensitive;
 
   *cfgp = cfg;

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c Mon Nov 21 07:07:56 2011
@@ -386,9 +386,9 @@ svn_config__parse_file(svn_config_t *cfg
                                            pool);
   ctx.line = 1;
   ctx.have_ungotten_char = FALSE;
-  ctx.section = svn_stringbuf_create("", pool);
-  ctx.option = svn_stringbuf_create("", pool);
-  ctx.value = svn_stringbuf_create("", pool);
+  ctx.section = svn_stringbuf_create_empty(pool);
+  ctx.option = svn_stringbuf_create_empty(pool);
+  ctx.value = svn_stringbuf_create_empty(pool);
 
   do
     {
@@ -1071,6 +1071,11 @@ svn_config_ensure(const char *config_dir
         "### Set interactive-conflicts to 'no' to disable interactive"       NL
         "### conflict resolution prompting.  It defaults to 'yes'."          NL
         "# interactive-conflicts = no"                                       NL
+        "### Set memory-cache-size to define the size of the memory cache"   NL
+        "### used by the client when accessing a FSFS repository via"        NL
+        "### ra_local (the file:// scheme). The value represents the number" NL
+        "### of MB used by the cache."                                       NL
+        "# memory-cache-size = 16"                                           NL
         ""                                                                   NL
         "### Section for configuring automatic properties."                  NL
         "[auto-props]"                                                       NL

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c Mon Nov 21 07:07:56 2011
@@ -200,9 +200,9 @@ svn_config__parse_registry(svn_config_t 
 
 
   subpool = svn_pool_create(pool);
-  section = svn_stringbuf_create("", subpool);
-  option = svn_stringbuf_create("", subpool);
-  value = svn_stringbuf_create("", subpool);
+  section = svn_stringbuf_create_empty(subpool);
+  option = svn_stringbuf_create_empty(subpool);
+  value = svn_stringbuf_create_empty(subpool);
 
   /* The top-level values belong to the [DEFAULT] section */
   svn_err = parse_section(cfg, hkey, SVN_CONFIG__DEFAULT_SECTION,

Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c Mon Nov 21 07:07:56 2011
@@ -1073,6 +1073,53 @@ svn_rangelist_inheritable(apr_array_head
                                                     pool, pool));
 }
 
+svn_error_t *
+svn_rangelist_merge(apr_array_header_t **rangelist,
+                    const apr_array_header_t *changes,
+                    apr_pool_t *pool)
+{
+  return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
+                                              pool, pool));
+}
+
+svn_error_t *
+svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
+                   svn_mergeinfo_t from, svn_mergeinfo_t to,
+                   svn_boolean_t consider_inheritance,
+                   apr_pool_t *pool)
+{
+  return svn_error_trace(svn_mergeinfo_diff2(deleted, added, from, to,
+                                             consider_inheritance, pool,
+                                             pool));
+}
+
+svn_error_t *
+svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo,
+                    svn_mergeinfo_t changes,
+                    apr_pool_t *pool)
+{
+  return svn_error_trace(svn_mergeinfo_merge2(mergeinfo, changes, pool,
+                         pool));
+}
+
+svn_error_t *
+svn_mergeinfo_remove(svn_mergeinfo_t *mergeinfo, svn_mergeinfo_t eraser,
+                     svn_mergeinfo_t whiteboard, apr_pool_t *pool)
+{
+  return svn_mergeinfo_remove2(mergeinfo, eraser, whiteboard, TRUE, pool,
+                               pool);
+}
+
+svn_error_t *
+svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo,
+                        svn_mergeinfo_t mergeinfo1,
+                        svn_mergeinfo_t mergeinfo2,
+                        apr_pool_t *pool)
+{
+  return svn_mergeinfo_intersect2(mergeinfo, mergeinfo1, mergeinfo2,
+                                  TRUE, pool, pool);
+}
+
 /*** From config.c ***/
 
 svn_error_t *
@@ -1126,12 +1173,3 @@ svn_xml_make_header(svn_stringbuf_t **st
 {
   svn_xml_make_header2(str, NULL, pool);
 }
-
-svn_error_t *
-svn_rangelist_merge(apr_array_header_t **rangelist,
-                    const apr_array_header_t *changes,
-                    apr_pool_t *pool)
-{
-  return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
-                                              pool, pool));
-}



Mime
View raw message