Author: julianfoad
Date: Mon Oct  4 15:11:45 2010
New Revision: 1004280

URL: http://svn.apache.org/viewvc?rev=1004280&view=rev
Log:
Vastly simplify the WC-DB function 'gather_children()', removing the row-
counting DB queries and several subroutines.

Indicative timing measurements showed an improvement in typical queries and
a slight penalty in some queries when the number of children is huge.

* subversion/libsvn_wc/wc_db.c
  (count_children, union_children, single_table_children): Delete.
  (gather_children): Don't count the children first and make special cases
    depending on the counts, just add the children directly into a hash and
    return an array of the hash's keys, like union_children() did.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_COUNT_BASE_NODE_CHILDREN, STMT_COUNT_BASE_NODE_CHILDREN_1,
   STMT_COUNT_WORKING_NODE_CHILDREN, STMT_COUNT_WORKING_NODE_CHILDREN_1):
    Delete.

* subversion/tests/cmdline/diff_tests.py
  (diff_repos_wc_add_with_props): Tweak to ignore output ordering.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/tests/cmdline/diff_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1004280&r1=1004279&r2=1004280&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Mon Oct  4 15:11:45 
2010
@@ -129,23 +129,6 @@ INSERT OR IGNORE INTO working_node (
   wc_id, local_relpath, parent_relpath, presence, kind)
 VALUES (?1, ?2, ?3, 'incomplete', 'unknown');
 
--- STMT_COUNT_BASE_NODE_CHILDREN
-SELECT COUNT(*) FROM base_node
-WHERE wc_id = ?1 AND parent_relpath = ?2;
-
--- STMT_COUNT_BASE_NODE_CHILDREN_1
-SELECT COUNT(*) FROM nodes
-WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0;
-
--- STMT_COUNT_WORKING_NODE_CHILDREN
-SELECT COUNT(*) FROM working_node
-WHERE wc_id = ?1 AND parent_relpath = ?2;
-
--- STMT_COUNT_WORKING_NODE_CHILDREN_1
-SELECT COUNT(*) FROM (SELECT DISTINCT local_relpath FROM nodes
-                      WHERE wc_id = ?1 AND parent_relpath = ?2
-                      AND op_depth > 0);
-
 -- STMT_SELECT_BASE_NODE_CHILDREN
 SELECT local_relpath FROM base_node
 WHERE wc_id = ?1 AND parent_relpath = ?2;

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1004280&r1=1004279&r2=1004280&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Mon Oct  4 15:11:45 2010
@@ -1238,25 +1238,6 @@ insert_working_node(void *baton,
 }
 
 
-/* Return the number of children under PARENT_RELPATH in the given WC_ID.
-   The table is implicitly defined by the STMT_IDX query.  */
-static svn_error_t *
-count_children(int *count,
-               int stmt_idx,
-               svn_sqlite__db_t *sdb,
-               apr_int64_t wc_id,
-               const char *parent_relpath)
-{
-  svn_sqlite__stmt_t *stmt;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
-  SVN_ERR(svn_sqlite__step_row(stmt));
-  *count = svn_sqlite__column_int(stmt, 0);
-  return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
 /* Each name is allocated in RESULT_POOL and stored into CHILDREN as a key
    pointed to the same name.  */
 static svn_error_t *
@@ -1287,94 +1268,6 @@ add_children_to_hash(apr_hash_t *childre
 }
 
 
-/* When children of PARENT_RELPATH are in both BASE_NODE and WORKING_NODE,
-   this function can be used to union those two sets, returning the set
-   in *CHILDREN (allocated in RESULT_POOL).  */
-static svn_error_t *
-union_children(const apr_array_header_t **children,
-               svn_sqlite__db_t *sdb,
-               apr_int64_t wc_id,
-               const char *parent_relpath,
-               apr_pool_t *result_pool,
-               apr_pool_t *scratch_pool)
-{
-  /* ### it would be nice to pre-size this hash table.  */
-  apr_hash_t *names = apr_hash_make(scratch_pool);
-#ifdef SVN_WC__NODES
-  apr_hash_t *names_nodes = apr_hash_make(scratch_pool);
-#endif
-  apr_array_header_t *names_array;
-
-  /* All of the names get allocated in RESULT_POOL.  */
-#ifndef SVN_WC__NODES_ONLY
-  SVN_ERR(add_children_to_hash(names, STMT_SELECT_BASE_NODE_CHILDREN,
-                               sdb, wc_id, parent_relpath, result_pool));
-  SVN_ERR(add_children_to_hash(names, STMT_SELECT_WORKING_NODE_CHILDREN,
-                               sdb, wc_id, parent_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
-  SVN_ERR(add_children_to_hash(names_nodes, STMT_SELECT_BASE_NODE_CHILDREN_1,
-                               sdb, wc_id, parent_relpath, result_pool));
-  SVN_ERR(add_children_to_hash(names_nodes, 
STMT_SELECT_WORKING_NODE_CHILDREN_1,
-                               sdb, wc_id, parent_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
-  SVN_ERR_ASSERT(apr_hash_count(names) == apr_hash_count(names_nodes));
-#else
-  names = names_nodes;
-#endif
-#endif
-
-  SVN_ERR(svn_hash_keys(&names_array, names, result_pool));
-  *children = names_array;
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Return all the children of PARENT_RELPATH from a single table, implicitly
-   defined by STMT_IDX. If the caller happens to know the count of children,
-   it should be passed as START_SIZE to pre-allocate space in the *CHILDREN
-   return value.
-
-   If the caller doesn't know the count, then it should pass a reasonable
-   idea of how many children may be present.  */
-static svn_error_t *
-single_table_children(const apr_array_header_t **children,
-                      int stmt_idx,
-                      int start_size,
-                      svn_sqlite__db_t *sdb,
-                      apr_int64_t wc_id,
-                      const char *parent_relpath,
-                      apr_pool_t *result_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  apr_array_header_t *child_names;
-  svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
-
-  /* ### should test the node to ensure it is a directory */
-
-  child_names = apr_array_make(result_pool, start_size, sizeof(const char *));
-
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  while (have_row)
-    {
-      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
-
-      APR_ARRAY_PUSH(child_names, const char *) =
-        svn_relpath_basename(child_relpath, result_pool);
-
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-
-  *children = child_names;
-
-  return svn_sqlite__reset(stmt);
-}
-
-
 /* Return in *CHILDREN all of the children of the directory LOCAL_ABSPATH.
    If BASE_ONLY is true, then *only* the children from BASE_NODE are
    returned (those in WORKING_NODE are ignored). The result children are
@@ -1389,12 +1282,13 @@ gather_children(const apr_array_header_t
 {
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
-  int base_count;
-  int working_count;
+  apr_hash_t *names_hash = apr_hash_make(scratch_pool);
+#ifndef SVN_WC__NODES_ONLY
+#endif
 #ifdef SVN_WC__NODES
-  int base_count_nodes, working_count_nodes;
-  const apr_array_header_t *children_nodes;
+  apr_hash_t *names_hash_1 = apr_hash_make(scratch_pool);
 #endif
+  apr_array_header_t *names_array;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -1404,111 +1298,35 @@ gather_children(const apr_array_header_t
                                              scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
-  if (base_only)
-    {
-      /* 10 is based on Subversion's average of 8.7 files per versioned
-         directory in its repository.
-
-         ### note "files". should redo count with subdirs included */
-#ifndef SVN_WC__NODES_ONLY
-      SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
-                                    10 /* start_size */,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
-      SVN_ERR(single_table_children(&children_nodes,
-                                    STMT_SELECT_BASE_NODE_CHILDREN_1,
-                                    10 /* start_size */,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
+  /* All of the names get allocated in RESULT_POOL.  */
 #ifndef SVN_WC__NODES_ONLY
-      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
-      *children = children_nodes;
-#endif
-#endif
-      return SVN_NO_ERROR;
-    }
+  SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_BASE_NODE_CHILDREN,
+                               pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                               local_relpath, result_pool));
+  if (! base_only)
+    SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_WORKING_NODE_CHILDREN,
+                                 pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                 local_relpath, result_pool));
 
-#ifndef SVN_WC__NODES_ONLY
-  SVN_ERR(count_children(&base_count, STMT_COUNT_BASE_NODE_CHILDREN,
-                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
-  SVN_ERR(count_children(&working_count, STMT_COUNT_WORKING_NODE_CHILDREN,
-                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
 #endif
 #ifdef SVN_WC__NODES
-  SVN_ERR(count_children(&base_count_nodes, STMT_COUNT_BASE_NODE_CHILDREN_1,
-                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
-  SVN_ERR(count_children(&working_count_nodes,
-                         STMT_COUNT_WORKING_NODE_CHILDREN_1,
-                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(add_children_to_hash(names_hash_1, STMT_SELECT_BASE_NODE_CHILDREN_1,
+                               pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                               local_relpath, result_pool));
+  if (! base_only)
+    SVN_ERR(add_children_to_hash(names_hash_1, 
STMT_SELECT_WORKING_NODE_CHILDREN_1,
+                                 pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                 local_relpath, result_pool));
 #ifndef SVN_WC__NODES_ONLY
-  SVN_ERR_ASSERT(base_count == base_count_nodes);
-  SVN_ERR_ASSERT(working_count == working_count_nodes);
+  SVN_ERR_ASSERT(apr_hash_count(names_hash) == apr_hash_count(names_hash_1));
 #else
-  base_count = base_count_nodes;
-  working_count = working_count_nodes;
+  names_hash = names_hash_1;
 #endif
 #endif
 
-  if (base_count == 0)
-    {
-      if (working_count == 0)
-        {
-          *children = apr_array_make(result_pool, 0, sizeof(const char *));
-          return SVN_NO_ERROR;
-        }
-
-#ifndef SVN_WC__NODES_ONLY
-      SVN_ERR(single_table_children(children, 
STMT_SELECT_WORKING_NODE_CHILDREN,
-                                    working_count,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
-      SVN_ERR(single_table_children(&children_nodes,
-                                    STMT_SELECT_WORKING_NODE_CHILDREN_1,
-                                    working_count,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
-      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
-      *children = children_nodes;
-#endif
-#endif
-      return SVN_NO_ERROR;
-    }
-  if (working_count == 0)
-    {
-#ifndef SVN_WC__NODES_ONLY
-      SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
-                                    base_count,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
-      SVN_ERR(single_table_children(&children_nodes,
-                                    STMT_SELECT_BASE_NODE_CHILDREN_1,
-                                    base_count,
-                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                    local_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
-      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
-      *children = children_nodes;
-#endif
-#endif
-      return SVN_NO_ERROR;
-    }
-
-  /* ### it would be nice to pass BASE_COUNT and WORKING_COUNT, but there is
-     ### nothing union_children() can do with those.  */
-  return svn_error_return(union_children(children, 
-                                         pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                         local_relpath,
-                                         result_pool, scratch_pool));
+  SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
+  *children = names_array;
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/trunk/subversion/tests/cmdline/diff_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=1004280&r1=1004279&r2=1004280&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Mon Oct  4 15:11:45 
2010
@@ -2409,8 +2409,12 @@ def diff_repos_wc_add_with_props(sbox):
   diff_X_bar_base_r3 = make_diff_header("X/bar", "revision 0",
                                                  "revision 3") + diff_X_bar
 
-  expected_output_r1_base = diff_X_r1_base + diff_X_bar_r1_base + 
diff_foo_r1_base
-  expected_output_base_r3 = diff_foo_base_r3 + diff_X_bar_base_r3 + 
diff_X_base_r3
+  expected_output_r1_base = svntest.verify.UnorderedOutput(diff_X_r1_base +
+                                                           diff_X_bar_r1_base +
+                                                           diff_foo_r1_base)
+  expected_output_base_r3 = svntest.verify.UnorderedOutput(diff_foo_base_r3 +
+                                                           diff_X_bar_base_r3 +
+                                                           diff_X_base_r3)
 
   os.chdir(sbox.wc_dir)
 


Reply via email to