Author: kotkov Date: Tue Apr 26 19:16:29 2016 New Revision: 1741078 URL: http://svn.apache.org/viewvc?rev=1741078&view=rev Log: Lay the groundwork for fixing the commit_with_locked_rep_cache() test by factoring out a helper function.
* subversion/libsvn_subr/sqlite.c (rollback_transaction): New, factored out from ... (svn_sqlite__finish_transaction): ...this function. Modified: subversion/trunk/subversion/libsvn_subr/sqlite.c Modified: subversion/trunk/subversion/libsvn_subr/sqlite.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sqlite.c?rev=1741078&r1=1741077&r2=1741078&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_subr/sqlite.c (original) +++ subversion/trunk/subversion/libsvn_subr/sqlite.c Tue Apr 26 19:16:29 2016 @@ -1261,6 +1261,48 @@ reset_all_statements(svn_sqlite__db_t *d return err; } +static svn_error_t * +rollback_transaction(svn_sqlite__db_t *db, + svn_error_t *error_to_wrap) +{ + svn_sqlite__stmt_t *stmt; + svn_error_t *err; + + err = get_internal_statement(&stmt, db, STMT_INTERNAL_ROLLBACK_TRANSACTION); + if (!err) + { + err = svn_error_trace(svn_sqlite__step_done(stmt)); + + if (err && err->apr_err == SVN_ERR_SQLITE_BUSY) + { + /* ### Houston, we have a problem! + + We are trying to rollback but we can't because some + statements are still busy. This leaves the database + unusable for future transactions as the current transaction + is still open. + + As we are returning the actual error as the most relevant + error in the chain, our caller might assume that it can + retry/compensate on this error (e.g. SVN_WC_LOCKED), while + in fact the SQLite database is unusable until the statements + started within this transaction are reset and the transaction + aborted. + + We try to compensate by resetting all prepared but unreset + statements; but we leave the busy error in the chain anyway to + help diagnosing the original error and help in finding where + a reset statement is missing. */ + err = svn_error_trace(reset_all_statements(db, err)); + err = svn_error_compose_create( + svn_error_trace(svn_sqlite__step_done(stmt)), + err); + } + } + + return svn_error_compose_create(error_to_wrap, err); +} + svn_error_t * svn_sqlite__begin_transaction(svn_sqlite__db_t *db) { @@ -1303,44 +1345,7 @@ svn_sqlite__finish_transaction(svn_sqlit /* Commit or rollback the sqlite transaction. */ if (err) { - svn_error_t *err2; - - err2 = get_internal_statement(&stmt, db, - STMT_INTERNAL_ROLLBACK_TRANSACTION); - if (!err2) - { - err2 = svn_error_trace(svn_sqlite__step_done(stmt)); - - if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY) - { - /* ### Houston, we have a problem! - - We are trying to rollback but we can't because some - statements are still busy. This leaves the database - unusable for future transactions as the current transaction - is still open. - - As we are returning the actual error as the most relevant - error in the chain, our caller might assume that it can - retry/compensate on this error (e.g. SVN_WC_LOCKED), while - in fact the SQLite database is unusable until the statements - started within this transaction are reset and the transaction - aborted. - - We try to compensate by resetting all prepared but unreset - statements; but we leave the busy error in the chain anyway - to help diagnosing the original error and help in finding - where a reset statement is missing. */ - - err2 = svn_error_trace(reset_all_statements(db, err2)); - err2 = svn_error_compose_create( - svn_error_trace(svn_sqlite__step_done(stmt)), - err2); - - } - } - - return svn_error_compose_create(err, err2); + return svn_error_trace(rollback_transaction(db, err)); } SVN_ERR(get_internal_statement(&stmt, db, STMT_INTERNAL_COMMIT_TRANSACTION));