You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/07/22 11:34:29 UTC

svn commit: r1149519 - in /subversion/trunk/subversion: include/svn_mergeinfo.h libsvn_subr/deprecated.c libsvn_subr/mergeinfo.c

Author: stsp
Date: Fri Jul 22 09:34:28 2011
New Revision: 1149519

URL: http://svn.apache.org/viewvc?rev=1149519&view=rev
Log:
Add svn_rangelist_merge2() which modifies the rangelist in-place to produce
its result, instead of allocating a new rangelist, and also uses the dual-pool
paradigm. The previous svn_rangelist_merge() implementation was awkward
to call from within a loop without potentially using a lot of memory (see
r1148566 for an example).

Suggested by: philip

* subversion/include/svn_mergeinfo.h
  (svn_rangelist_merge2): Declare.
  (svn_rangelist_merge): Deprecate.

* subversion/libsvn_subr/deprecated.c
  (svn_rangelist_merge): Implement as a wrapper around svn_rangelist_merge2().
   
* subversion/libsvn_subr/mergeinfo.c
  (svn_rangelist_merge): Rename to ...
  (svn_rangelist_merge2): ... this. Change the RANGELIST parameter to
   an apr_array_header_t* (rather than apr_array_header_t**). Replace
   the POOL parameter with RESULT_POOL and SCRATCH_POOL parameters.
   Produce the merged rangelist in place, allocating any elements newly
   added to the array in RESULT_POOL.

Modified:
    subversion/trunk/subversion/include/svn_mergeinfo.h
    subversion/trunk/subversion/libsvn_subr/deprecated.c
    subversion/trunk/subversion/libsvn_subr/mergeinfo.c

Modified: subversion/trunk/subversion/include/svn_mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_mergeinfo.h?rev=1149519&r1=1149518&r2=1149519&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_mergeinfo.h (original)
+++ subversion/trunk/subversion/include/svn_mergeinfo.h Fri Jul 22 09:34:28 2011
@@ -270,20 +270,38 @@ svn_rangelist_diff(apr_array_header_t **
                    apr_pool_t *pool);
 
 /** Merge two rangelists consisting of @c svn_merge_range_t *
- * elements, @a *rangelist and @a changes, placing the results in
- * @a *rangelist.  Either rangelist may be empty.
+ * elements, @a rangelist and @a changes, placing the results in
+ * @a rangelist. New elements added to @a rangelist are allocated
+ * in @a result_pool. Either rangelist may be empty.
  *
  * When intersecting rangelists are merged, the inheritability of
  * the resulting svn_merge_range_t depends on the inheritability of the
  * operands: see svn_mergeinfo_merge().
  *
- * Note: @a *rangelist and @a changes must be sorted as said by @c
- * svn_sort_compare_ranges().  @a *rangelist is guaranteed to remain
+ * Note: @a rangelist and @a changes must be sorted as said by @c
+ * svn_sort_compare_ranges().  @a rangelist is guaranteed to remain
  * in sorted order and be compacted to the minimal number of ranges
  * needed to represent the merged result.
  *
+ * Use @a scratch_pool for temporary allocations.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_rangelist_merge2(apr_array_header_t *rangelist,
+                     const apr_array_header_t *changes,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool);
+
+/** Like svn_rangelist_merge2(), but with @a rangelist as an input/output
+ * argument. This function always allocates a new rangelist in @a pool and
+ * returns its result in @a *rangelist. It does not modify @a *rangelist
+ * in place. If not used carefully, this function can use up a lot of memory
+ * if called in a loop.
+ *
  * @since New in 1.5.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_rangelist_merge(apr_array_header_t **rangelist,
                     const apr_array_header_t *changes,

Modified: subversion/trunk/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/deprecated.c?rev=1149519&r1=1149518&r2=1149519&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_subr/deprecated.c Fri Jul 22 09:34:28 2011
@@ -1126,3 +1126,12 @@ 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));
+}

Modified: subversion/trunk/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/mergeinfo.c?rev=1149519&r1=1149518&r2=1149519&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/mergeinfo.c Fri Jul 22 09:34:28 2011
@@ -37,6 +37,7 @@
 #include "private/svn_string_private.h"
 #include "svn_private_config.h"
 #include "svn_hash.h"
+#include "private/svn_dep_compat.h"
 
 /* Attempt to combine two ranges, IN1 and IN2. If they are adjacent or
    overlapping, and their inheritability allows them to be combined, put
@@ -707,23 +708,26 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer
   return err;
 }
 
-
 svn_error_t *
-svn_rangelist_merge(apr_array_header_t **rangelist,
-                    const apr_array_header_t *changes,
-                    apr_pool_t *pool)
+svn_rangelist_merge2(apr_array_header_t *rangelist,
+                     const apr_array_header_t *changes,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
   int i, j;
-  apr_array_header_t *output = apr_array_make(pool, 1,
-                                              sizeof(svn_merge_range_t *));
+  apr_array_header_t *original_rangelist;
+  
+  original_rangelist = apr_array_copy(scratch_pool, rangelist);
+  apr_array_clear(rangelist);
+
   i = 0;
   j = 0;
-  while (i < (*rangelist)->nelts && j < changes->nelts)
+  while (i < (original_rangelist)->nelts && j < changes->nelts)
     {
       svn_merge_range_t *elt1, *elt2;
       int res;
 
-      elt1 = APR_ARRAY_IDX(*rangelist, i, svn_merge_range_t *);
+      elt1 = APR_ARRAY_IDX(original_rangelist, i, svn_merge_range_t *);
       elt2 = APR_ARRAY_IDX(changes, j, svn_merge_range_t *);
 
       res = svn_sort_compare_ranges(&elt1, &elt2);
@@ -734,46 +738,45 @@ svn_rangelist_merge(apr_array_header_t *
              result. */
           if (elt1->inheritable || elt2->inheritable)
             elt1->inheritable = TRUE;
-          SVN_ERR(combine_with_lastrange(elt1, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt1, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           i++;
           j++;
         }
       else if (res < 0)
         {
-          SVN_ERR(combine_with_lastrange(elt1, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt1, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           i++;
         }
       else
         {
-          SVN_ERR(combine_with_lastrange(elt2, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt2, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           j++;
         }
     }
   /* Copy back any remaining elements.
      Only one of these loops should end up running, if anything. */
 
-  SVN_ERR_ASSERT(!(i < (*rangelist)->nelts && j < changes->nelts));
+  SVN_ERR_ASSERT(!(i < (original_rangelist)->nelts && j < changes->nelts));
 
-  for (; i < (*rangelist)->nelts; i++)
+  for (; i < (original_rangelist)->nelts; i++)
     {
-      svn_merge_range_t *elt = APR_ARRAY_IDX(*rangelist, i,
+      svn_merge_range_t *elt = APR_ARRAY_IDX(original_rangelist, i,
                                              svn_merge_range_t *);
-      SVN_ERR(combine_with_lastrange(elt, output,
-                                     TRUE, pool, pool));
+      SVN_ERR(combine_with_lastrange(elt, rangelist, TRUE, result_pool,
+                                     scratch_pool));
     }
 
 
   for (; j < changes->nelts; j++)
     {
       svn_merge_range_t *elt = APR_ARRAY_IDX(changes, j, svn_merge_range_t *);
-      SVN_ERR(combine_with_lastrange(elt, output,
-                                     TRUE, pool, pool));
+      SVN_ERR(combine_with_lastrange(elt, rangelist,
+                                     TRUE, result_pool, scratch_pool));
     }
 
-  *rangelist = output;
   return SVN_NO_ERROR;
 }