stef...@apache.org wrote on Sun, Apr 17, 2011 at 14:48:34 -0000: > Author: stefan2 > Date: Sun Apr 17 14:48:33 2011 > New Revision: 1094150 > > URL: http://svn.apache.org/viewvc?rev=1094150&view=rev > Log: > Support concurrent transactions on FSFS: reset txn-local caches upon > closing the txn (i.e. don't wait until pool cleanup) and support concurrency > by simply disabling these caches permanently for the respective session > once a concurrency has been detected. > > * subversion/libsvn_fs_fs/fs.h > (fs_fs_data_t): add concurrent_transactions member > (svn_fs_fs__reset_txn_caches): declare new private API function > > * subversion/libsvn_fs_fs/caching.c > (txn_cleanup_baton_t): new utility struct > (remove_txn_cache): reset txn-local only if they match the ones to clean up > (init_txn_callbacks): new destructor init utility > (svn_fs_fs__initialize_txn_caches): gracefully support multiple concurrent > txns > in the *same* FSFS session by permanently disabling txn-local caches > (svn_fs_fs__reset_txn_caches): implement new private API function > > * subversion/libsvn_fs_fs/fs_fs.c > (purge_shared_txn_body): reset txn-local caches immediately at the end > of the given txn > * subversion/libsvn_fs_fs/tree.c > (svn_fs_fs__commit_txn): dito > > Modified: > subversion/trunk/subversion/libsvn_fs_fs/caching.c > subversion/trunk/subversion/libsvn_fs_fs/fs.h > subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c > subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h > subversion/trunk/subversion/libsvn_fs_fs/tree.c > > Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1094150&r1=1094149&r2=1094150&view=diff > ============================================================================== > --- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original) > +++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Sun Apr 17 14:48:33 > 2011 > @@ -331,17 +331,51 @@ svn_fs_fs__initialize_caches(svn_fs_t *f > return SVN_NO_ERROR; > } > > +/* Baton to be used for the remove_txn_cache() pool cleanup function, */ > +struct txn_cleanup_baton_t > +{ > + /* the cache to reset */ > + svn_cache__t *txn_cache; > + > + /* the position where to reset it */ > + svn_cache__t **to_reset; > +}; > + > /* APR pool cleanup handler that will reset the cache pointer given in > BATON_VOID. */ > static apr_status_t > remove_txn_cache(void *baton_void) > { > - svn_cache__t **cache_p = baton_void; > - *cache_p = NULL; > + struct txn_cleanup_baton_t *baton = baton_void; > + > + /* be careful not to hurt performance by resetting newer txn's caches */ > + if (*baton->to_reset == baton->txn_cache) > + *baton->to_reset = NULL; >
If I understand correctly, this line actually has the same effect as svn_fs_fs__reset_txn_caches() --- namely, it zeroes out the FFD->txn_dir_cache member? Perhaps you could add a comment to save future readers a bit of mental double-pointer arithmetic? > return APR_SUCCESS; > } > > +static svn_error_t * > +init_txn_callbacks(svn_cache__t **cache, > + apr_pool_t *pool) > +{ > + if (cache != NULL) > + { This condition will always be true. Did you mean 'if (*cache)' ? > + struct txn_cleanup_baton_t *baton; > + > + baton = apr_palloc(pool, sizeof(*baton)); > + baton->txn_cache = *cache; > + baton->to_reset = cache; > + > + apr_pool_cleanup_register(pool, > + baton, > + remove_txn_cache, > + apr_pool_cleanup_null); > + } > + > + return SVN_NO_ERROR; > +} > + > svn_error_t * > svn_fs_fs__initialize_txn_caches(svn_fs_t *fs, > const char *txn_id, > @@ -361,9 +395,15 @@ svn_fs_fs__initialize_txn_caches(svn_fs_ > ":", svn_uuid_generate(pool), ":", > (char *)NULL); > > - /* There must be no concurrent transactions in progress for the same > - FSFS access / session object. Maybe, you forgot to clean POOL. */ > - SVN_ERR_ASSERT(ffd->txn_dir_cache == NULL); > + /* We don't support caching for concurrent transactions in the SAME > + * FSFS session. Maybe, you forgot to clean POOL. */ > + if (ffd->txn_dir_cache != NULL || ffd->concurrent_transactions) > + { > + ffd->txn_dir_cache = NULL; > + ffd->concurrent_transactions = TRUE; > + > + return SVN_NO_ERROR; > + } > Why is this safe? Is it because svn_fs_fs__initialize_txn_caches() is called from all the relevant codepaths? (presumably the relevant codepaths are those that create txns) > /* create a txn-local directory cache */ > if (svn_fs__get_global_membuffer_cache()) > @@ -386,10 +426,17 @@ svn_fs_fs__initialize_txn_caches(svn_fs_ > pool)); > > /* reset the transaction-specific cache if the pool gets cleaned up. */ > - apr_pool_cleanup_register(pool, > - &(ffd->txn_dir_cache), > - remove_txn_cache, > - apr_pool_cleanup_null); > + init_txn_callbacks(&(ffd->txn_dir_cache), pool); > > return SVN_NO_ERROR; > } > + > +void > +svn_fs_fs__reset_txn_caches(svn_fs_t *fs) > +{ > + /* we can always just reset the caches. This may degrade performance but > + * can never cause in incorrect behavior. */ > + > + fs_fs_data_t *ffd = fs->fsap_data; > + ffd->txn_dir_cache = NULL; > +} > \ No newline at end of file