Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0B915DB17 for ; Thu, 22 Nov 2012 18:00:50 +0000 (UTC) Received: (qmail 31246 invoked by uid 500); 22 Nov 2012 18:00:49 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 31214 invoked by uid 500); 22 Nov 2012 18:00:49 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 31205 invoked by uid 99); 22 Nov 2012 18:00:49 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 22 Nov 2012 18:00:49 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 22 Nov 2012 18:00:48 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id EDE8C2388AB9; Thu, 22 Nov 2012 18:00:27 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1412632 - in /subversion/trunk/subversion/libsvn_wc: props.c update_editor.c wc_db.c wc_db.h Date: Thu, 22 Nov 2012 18:00:26 -0000 To: commits@subversion.apache.org From: rhuijben@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121122180027.EDE8C2388AB9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rhuijben Date: Thu Nov 22 18:00:24 2012 New Revision: 1412632 URL: http://svn.apache.org/viewvc?rev=1412632&view=rev Log: Improve performance of fetching inherited properties from the local working copy by reducing the number of db transactions required while walking up the tree. Some of the optimizations also help other common code paths. * subversion/libsvn_wc/props.c (svn_wc__internal_get_iprops): Use svn_wc_db__is_switched() instead of wrapper that doesn't detect switched files, etc. * subversion/libsvn_wc/update_editor.c (svn_wc__check_wc_root): Call svn_wc_db__is_switched() to do the real work. The implementation of this function has been moved to that function. * subversion/libsvn_wc/wc_db.c (svn_wc__db_read_cached_iprops): Avoid calling read_info for an easy out, as that by itself is just as expensive as the hard work. Don't call the op_depth_of() function that performs another db transaction, just to ignore the result. Make sure the result of 'no iprops stored' doesn't change. (db_is_switched_baton_t): New struct. (db_is_switched): New function. (svn_wc_db__is_switched): New function. * subversion/libsvn_wc/wc_db.h (svn_wc_db__is_switched): New function. Modified: subversion/trunk/subversion/libsvn_wc/props.c subversion/trunk/subversion/libsvn_wc/update_editor.c subversion/trunk/subversion/libsvn_wc/wc_db.c subversion/trunk/subversion/libsvn_wc/wc_db.h Modified: subversion/trunk/subversion/libsvn_wc/props.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1412632&r1=1412631&r2=1412632&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/props.c (original) +++ subversion/trunk/subversion/libsvn_wc/props.c Thu Nov 22 18:00:24 2012 @@ -2382,14 +2382,17 @@ svn_wc__internal_get_iprops(apr_array_he while (TRUE) { apr_hash_t *actual_props; + svn_boolean_t is_switched; svn_pool_clear(iterpool); - SVN_ERR(svn_wc__internal_is_wc_root(&is_wc_root, db, parent_abspath, - iterpool)); + SVN_ERR(svn_wc_db__is_switched(&is_wc_root, &is_switched, NULL, + db, parent_abspath, iterpool)); - if (is_wc_root) + if (is_switched || is_wc_root) { + is_wc_root = TRUE; + /* If the WC root is also the root of the repository then by definition there are no inheritable properties to be had, but checking for that is just as expensive as fetching them Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1412632&r1=1412631&r2=1412632&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/update_editor.c (original) +++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Nov 22 18:00:24 2012 @@ -4998,107 +4998,10 @@ svn_wc__check_wc_root(svn_boolean_t *wc_ const char *local_abspath, apr_pool_t *scratch_pool) { - const char *parent_abspath, *name; - const char *repos_relpath, *repos_root, *repos_uuid; - svn_wc__db_status_t status; - svn_kind_t my_kind; - - if (!kind) - kind = &my_kind; - - /* Initialize our return values to the most common (code-wise) values. */ - *wc_root = TRUE; - if (switched) - *switched = FALSE; - - SVN_ERR(svn_wc__db_read_info(&status, kind, NULL, &repos_relpath, - &repos_root, &repos_uuid, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - db, local_abspath, - scratch_pool, scratch_pool)); - - if (repos_relpath == NULL) - { - /* If we inherit our URL, then we can't be a root, nor switched. */ - *wc_root = FALSE; - return SVN_NO_ERROR; - } - if (*kind != svn_kind_dir) - { - /* File/symlinks cannot be a root. */ - *wc_root = FALSE; - } - else if (status == svn_wc__db_status_added - || status == svn_wc__db_status_deleted) - { - *wc_root = FALSE; - } - else if (status == svn_wc__db_status_server_excluded - || status == svn_wc__db_status_excluded - || status == svn_wc__db_status_not_present) - { - return svn_error_createf( - SVN_ERR_WC_PATH_NOT_FOUND, NULL, - _("The node '%s' was not found."), - svn_dirent_local_style(local_abspath, scratch_pool)); - } - else if (svn_dirent_is_root(local_abspath, strlen(local_abspath))) - return SVN_NO_ERROR; - - if (!*wc_root && switched == NULL ) - return SVN_NO_ERROR; /* No more info needed */ - - svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool); - - /* Check if the node is recorded in the parent */ - if (*wc_root) - { - svn_boolean_t is_root; - SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool)); - - if (is_root) - { - /* We're not in the (versioned) parent directory's list of - children, so we must be the root of a distinct working copy. */ - return SVN_NO_ERROR; - } - } - - { - const char *parent_repos_root; - const char *parent_repos_relpath; - const char *parent_repos_uuid; - - SVN_ERR(svn_wc__db_scan_base_repos(&parent_repos_relpath, - &parent_repos_root, - &parent_repos_uuid, - db, parent_abspath, - scratch_pool, scratch_pool)); - - if (strcmp(repos_root, parent_repos_root) != 0 - || strcmp(repos_uuid, parent_repos_uuid) != 0) - { - /* This should never happen (### until we get mixed-repos working - copies). If we're in the parent, then we should be from the - same repository. For this situation, just declare us the root - of a separate, unswitched working copy. */ - return SVN_NO_ERROR; - } - - *wc_root = FALSE; - - if (switched) - { - const char *expected_relpath = svn_relpath_join(parent_repos_relpath, - name, scratch_pool); - - *switched = (strcmp(expected_relpath, repos_relpath) != 0); - } - } - - return SVN_NO_ERROR; + return svn_error_trace( + svn_wc_db__is_switched(wc_root, switched, kind, + db, local_abspath, + scratch_pool)); } svn_error_t * Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1412632&r1=1412631&r2=1412632&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Nov 22 18:00:24 2012 @@ -9025,54 +9025,33 @@ svn_wc__db_read_cached_iprops(apr_array_ const char *local_relpath; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; - const char *repos_root_url; - svn_revnum_t revision; - int op_depth; - const char *repos_relpath; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); - SVN_ERR(svn_wc__db_read_info(NULL, NULL, - &revision, &repos_relpath, &repos_root_url, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, db, local_abspath, result_pool, - scratch_pool)); - - if (repos_relpath && repos_relpath[0] == '\0') - { - /* LOCAL_ABSPATH reflects the root of the repository, so there is - no parents to inherit from. */ - *iprops = apr_array_make(result_pool, 0, - sizeof(svn_prop_inherited_item_t *)); + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, + db, local_abspath, + scratch_pool, scratch_pool)); + VERIFY_USABLE_WCROOT(wcroot); + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_IPROPS)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + if (!have_row) + { + /* No cached iprops. */ + *iprops = NULL; } else { - SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, - db, local_abspath, - scratch_pool, - scratch_pool)); - VERIFY_USABLE_WCROOT(wcroot); - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_IPROPS)); - SVN_ERR(op_depth_of(&op_depth, wcroot, local_relpath)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); + SVN_ERR(svn_sqlite__column_iprops(iprops, stmt, 0, result_pool, + scratch_pool)); + if (!*iprops) + *iprops = apr_array_make(result_pool, 0, + sizeof(svn_prop_inherited_item_t *)); - if (!have_row) - { - /* No cached iprops. */ - *iprops = NULL; - } - else - { - SVN_ERR(svn_sqlite__column_iprops(iprops, stmt, 0, result_pool, - scratch_pool)); - } + } - SVN_ERR(svn_sqlite__reset(stmt)); - } + SVN_ERR(svn_sqlite__reset(stmt)); return SVN_NO_ERROR; } @@ -12475,6 +12454,125 @@ svn_wc__db_is_wcroot(svn_boolean_t *is_r return SVN_NO_ERROR; } +/* Baton for db_is_switched */ +struct db_is_switched_baton_t +{ + svn_boolean_t *is_switched; + svn_kind_t *kind; +}; + +/* This implements svn_wc__db_txn_callback_t for svn_wc_db__is_switched */ +static svn_error_t * +db_is_switched(void *baton, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + apr_pool_t *scratch_pool) +{ + struct db_is_switched_baton_t *isb = baton; + svn_wc__db_status_t status; + apr_int64_t repos_id; + const char *repos_relpath; + const char *name; + const char *parent_local_relpath; + apr_int64_t parent_repos_id; + const char *parent_repos_relpath; + + SVN_ERR_ASSERT(*local_relpath != '\0'); /* Handled in wrapper */ + + SVN_ERR(read_info(&status, isb->kind, NULL, &repos_relpath, &repos_id, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + wcroot, local_relpath, scratch_pool, scratch_pool)); + + if (! repos_relpath) + { + /* Node is shadowed; easy out */ + if (isb->is_switched) + *isb->is_switched = FALSE; + + return SVN_NO_ERROR; + } + else if (status == svn_wc__db_status_server_excluded + || status == svn_wc__db_status_excluded + || status == svn_wc__db_status_not_present) + { + return svn_error_createf( + SVN_ERR_WC_PATH_NOT_FOUND, NULL, + _("The node '%s' was not found."), + path_for_error_message(wcroot, local_relpath, + scratch_pool)); + } + + if (! isb->is_switched) + return SVN_NO_ERROR; + + svn_relpath_split(&parent_local_relpath, &name, local_relpath, scratch_pool); + + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL, + &parent_repos_relpath, + &parent_repos_id, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + wcroot, parent_local_relpath, + scratch_pool, scratch_pool)); + + if (repos_id != parent_repos_id) + *isb->is_switched = TRUE; + else + { + const char *expected_relpath; + + expected_relpath = svn_relpath_join(parent_repos_relpath, name, + scratch_pool); + + *isb->is_switched = (strcmp(expected_relpath, repos_relpath) != 0); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc_db__is_switched(svn_boolean_t *is_wcroot, + svn_boolean_t *is_switched, + svn_kind_t *kind, + svn_wc__db_t *db, + const char *local_abspath, + apr_pool_t *scratch_pool) +{ + svn_wc__db_wcroot_t *wcroot; + const char *local_relpath; + struct db_is_switched_baton_t isb; + + SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); + + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db, + local_abspath, scratch_pool, scratch_pool)); + VERIFY_USABLE_WCROOT(wcroot); + + if (is_switched) + *is_switched = FALSE; + + if (*local_relpath == '\0') + { + /* Easy out */ + if (is_wcroot) + *is_wcroot = TRUE; + + if (kind) + *kind = svn_kind_dir; + return SVN_NO_ERROR; + } + + if (is_wcroot) + *is_wcroot = FALSE; + + isb.is_switched = is_switched; + isb.kind = kind; + + return svn_error_trace(svn_wc__db_with_txn(wcroot, local_relpath, + db_is_switched, &isb, + scratch_pool)); +} + svn_error_t * svn_wc__db_temp_wcroot_tempdir(const char **temp_dir_abspath, Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1412632&r1=1412631&r2=1412632&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.h (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Nov 22 18:00:24 2012 @@ -2288,6 +2288,21 @@ svn_wc__db_is_wcroot(svn_boolean_t *is_r const char *local_abspath, apr_pool_t *scratch_pool); +/* Checks if LOCAL_ABSPATH is a working copy root, switched and a directory. + With these answers we can answer all 'is anchor' questions that we need for + the different ra operations with just a single sqlite transaction and + filestat. + + All output arguments can be null to specify that the result is not + interesting to the caller + */ +svn_error_t * +svn_wc_db__is_switched(svn_boolean_t *is_wcroot, + svn_boolean_t *is_switched, + svn_kind_t *kind, + svn_wc__db_t *db, + const char *local_abspath, + apr_pool_t *scratch_pool); /* @} */