On 20 April 2014 22:35, <stef...@apache.org> wrote: > Author: stefan2 > Date: Sun Apr 20 18:35:43 2014 > New Revision: 1588815 > > URL: http://svn.apache.org/r1588815 > Log: > Enable FSFS to take out more than file lock at once through a single call. > Use that functionality to take out the new pack lock for upgrade, hotcopy > and recovery. Also, disallow new TXNs during upgrade and recovery. > > The core is the introduction of a new data type describing a lock to take > out, which can be nested / chained. Switch all existing lock function to > using that infrastructure. > [...]
> + switch (lock_id) > + { > + case write_lock: baton->mutex = ffsd->fs_write_lock; > + baton->lock_path = path_lock(baton->fs, > + baton->lock_pool); > + baton->is_global_lock = TRUE; > + break; Please use standard indentation. > + > + case txn_lock: baton->mutex = ffsd->txn_current_lock; > + baton->lock_path = svn_fs_fs__path_txn_current_lock > + (baton->fs, baton->lock_pool); > + baton->is_global_lock = FALSE; > + break; > + > + case pack_lock: baton->mutex = ffsd->fs_pack_lock; > + baton->lock_path = path_pack_lock(baton->fs, > + baton->lock_pool); > + baton->is_global_lock = FALSE; > + break; > + } > +} > + > +/* Return the baton for the innermost lock of a (potential) lock chain. > + The baton shall take out LOCK_ID from FS and execute BODY with BATON > + while the lock is being held. Allocate the result in a sub-pool of POOL. > + */ > +static with_lock_baton_t * > +create_lock_baton(svn_fs_t *fs, > + lock_id_t lock_id, > + svn_error_t *(*body)(void *baton, > + apr_pool_t *pool), > + void *baton, > + apr_pool_t *pool) > +{ > + apr_pool_t *lock_pool = svn_pool_create(pool); > + with_lock_baton_t *result = apr_pcalloc(lock_pool, sizeof(*result)); > + > + result->fs = fs; > + result->body = body; > + result->baton = baton; > + result->lock_pool = lock_pool; > + result->is_inner_most_lock = TRUE; > + result->is_outer_most_lock = TRUE; > + > + init_lock_baton(result, lock_id); > + > + return result; > +} > + > +/* Return a baton that wraps NESTED and requests LOCK_ID as additional lock. > + */ > +static with_lock_baton_t * > +chain_lock_baton(lock_id_t lock_id, > + with_lock_baton_t *nested) > +{ > + apr_pool_t *lock_pool = nested->lock_pool; > + with_lock_baton_t *result = apr_pcalloc(lock_pool, sizeof(*result)); > + > + result->fs = nested->fs; > + result->body = with_lock; > + result->baton = nested; > + result->lock_pool = lock_pool; > + result->is_inner_most_lock = FALSE; > + result->is_outer_most_lock = TRUE; > + nested->is_outer_most_lock = FALSE; > + > + init_lock_baton(result, lock_id); > + > + return result; > +} > + I don't see bugs in the code above, but it is very hard to read and understand what is going on and what fields are initialized in different cases. > svn_error_t * > svn_fs_fs__with_write_lock(svn_fs_t *fs, > svn_error_t *(*body)(void *baton, > @@ -203,16 +358,9 @@ svn_fs_fs__with_write_lock(svn_fs_t *fs, > void *baton, > apr_pool_t *pool) > { > - fs_fs_data_t *ffd = fs->fsap_data; > - fs_fs_shared_data_t *ffsd = ffd->shared; > - > - SVN_MUTEX__WITH_LOCK(ffsd->fs_write_lock, > - with_some_lock_file(fs, body, baton, > - path_lock(fs, pool), > - TRUE, > - pool)); > - > - return SVN_NO_ERROR; > + return svn_error_trace( > + with_lock(create_lock_baton(fs, write_lock, body, baton, pool), > + pool)); > } > > svn_error_t * > @@ -222,20 +370,11 @@ svn_fs_fs__with_pack_lock(svn_fs_t *fs, > void *baton, > apr_pool_t *pool) > { > - fs_fs_data_t *ffd = fs->fsap_data; > - fs_fs_shared_data_t *ffsd = ffd->shared; > - > - SVN_MUTEX__WITH_LOCK(ffsd->fs_pack_lock, > - with_some_lock_file(fs, body, baton, > - path_pack_lock(fs, pool), > - FALSE, > - pool)); > - > - return SVN_NO_ERROR; > + return svn_error_trace( > + with_lock(create_lock_baton(fs, pack_lock, body, baton, pool), > + pool)); > } > > -/* Run BODY (with BATON and POOL) while the txn-current file > - of FS is locked. */ > svn_error_t * > svn_fs_fs__with_txn_current_lock(svn_fs_t *fs, > svn_error_t *(*body)(void *baton, > @@ -243,18 +382,34 @@ svn_fs_fs__with_txn_current_lock(svn_fs_ > void *baton, > apr_pool_t *pool) > { > + return svn_error_trace( > + with_lock(create_lock_baton(fs, txn_lock, body, baton, pool), > + pool)); > +} > + > +svn_error_t * > +svn_fs_fs__with_all_locks(svn_fs_t *fs, > + svn_boolean_t allow_new_txns, > + svn_error_t *(*body)(void *baton, > + apr_pool_t *pool), > + void *baton, > + apr_pool_t *pool) I think that the following function signature will be much easier to use and *implement*. svn_fs_fs__with_locks_many(svn_fs_t *fs, svn_boolean_t write_lock, svn_boolean_t txn_lock, svn_booelan_t pack_lock, ...) Seriously, could you tell me in what order locks are obtained without debugger? May be I'm dumb but I cannot answer this question. Coding in way that only author understand the code is bad thing especially for open source project IMHO. [..] -- Ivan Zhakov CTO | VisualSVN | http://www.visualsvn.com