Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:yukoff:openSUSE:Leap:42.1:Backports
subversion.5054
subversion-bnc923795.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File subversion-bnc923795.patch of Package subversion.5054
Index: subversion/libsvn_fs_fs/tree.c =================================================================== --- subversion/libsvn_fs_fs/tree.c.orig +++ subversion/libsvn_fs_fs/tree.c @@ -127,7 +127,6 @@ typedef struct fs_txn_root_data_t static svn_error_t * get_dag(dag_node_t **dag_node_p, svn_fs_root_t *root, const char *path, - svn_boolean_t needs_lock_cache, apr_pool_t *pool); static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev, @@ -178,34 +177,10 @@ typedef struct cache_entry_t */ enum { BUCKET_COUNT = 256 }; -/* Each pool that has received a DAG node, will hold at least on lock on - our cache to ensure that the node remains valid despite being allocated - in the cache's pool. This is the structure to represent the lock. - */ -typedef struct cache_lock_t -{ - /* pool holding the lock */ - apr_pool_t *pool; - - /* cache being locked */ - fs_fs_dag_cache_t *cache; - - /* next lock. NULL at EOL */ - struct cache_lock_t *next; - - /* previous lock. NULL at list head. Only then this==cache->first_lock */ - struct cache_lock_t *prev; -} cache_lock_t; - /* The actual cache structure. All nodes will be allocated in POOL. When the number of INSERTIONS (i.e. objects created form that pool) exceeds a certain threshold, the pool will be cleared and the cache with it. - - To ensure that nodes returned from this structure remain valid, the - cache will get locked for the lifetime of the _receiving_ pools (i.e. - those in which we would allocate the node if there was no cache.). - The cache will only be cleared FIRST_LOCK is 0. */ struct fs_fs_dag_cache_t { @@ -221,106 +196,23 @@ struct fs_fs_dag_cache_t /* Property lookups etc. have a very high locality (75% re-hit). Thus, remember the last hit location for optimistic lookup. */ apr_size_t last_hit; - - /* List of receiving pools that are still alive. */ - cache_lock_t *first_lock; }; -/* Cleanup function to be called when a receiving pool gets cleared. - Unlocks the cache once. - */ -static apr_status_t -unlock_cache(void *baton_void) -{ - cache_lock_t *lock = baton_void; - - /* remove lock from chain. Update the head */ - if (lock->next) - lock->next->prev = lock->prev; - if (lock->prev) - lock->prev->next = lock->next; - else - lock->cache->first_lock = lock->next; - - return APR_SUCCESS; -} - -/* Cleanup function to be called when the cache itself gets destroyed. - In that case, we must unregister all unlock requests. - */ -static apr_status_t -unregister_locks(void *baton_void) -{ - fs_fs_dag_cache_t *cache = baton_void; - cache_lock_t *lock; - - for (lock = cache->first_lock; lock; lock = lock->next) - apr_pool_cleanup_kill(lock->pool, - lock, - unlock_cache); - - return APR_SUCCESS; -} - fs_fs_dag_cache_t* svn_fs_fs__create_dag_cache(apr_pool_t *pool) { fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result)); result->pool = svn_pool_create(pool); - apr_pool_cleanup_register(pool, - result, - unregister_locks, - apr_pool_cleanup_null); - return result; } -/* Prevent the entries in CACHE from being destroyed, for as long as the - POOL lives. - */ -static void -lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool) -{ - /* we only need to lock / unlock once per pool. Since we will often ask - for multiple nodes with the same pool, we can reduce the overhead. - However, if e.g. pools are being used in an alternating pattern, - we may lock the cache more than once for the same pool (and register - just as many cleanup actions). - */ - cache_lock_t *lock = cache->first_lock; - - /* try to find an existing lock for POOL. - But limit the time spent on chasing pointers. */ - int limiter = 8; - while (lock && --limiter) - if (lock->pool == pool) - return; - - /* create a new lock and put it at the beginning of the lock chain */ - lock = apr_palloc(pool, sizeof(*lock)); - lock->cache = cache; - lock->pool = pool; - lock->next = cache->first_lock; - lock->prev = NULL; - - if (cache->first_lock) - cache->first_lock->prev = lock; - cache->first_lock = lock; - - /* instruct POOL to remove the look upon cleanup */ - apr_pool_cleanup_register(pool, - lock, - unlock_cache, - apr_pool_cleanup_null); -} - /* Clears the CACHE at regular intervals (destroying all cached nodes) */ static void auto_clear_dag_cache(fs_fs_dag_cache_t* cache) { - if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT) + if (cache->insertions > BUCKET_COUNT) { svn_pool_clear(cache->pool); @@ -433,18 +325,12 @@ locate_cache(svn_cache__t **cache, } } -/* Return NODE for PATH from ROOT's node cache, or NULL if the node - isn't cached; read it from the FS. *NODE remains valid until either - POOL or the FS gets cleared or destroyed (whichever comes first). - - Since locking can be expensive and POOL may be long-living, for - nodes that will not need to survive the next call to this function, - set NEEDS_LOCK_CACHE to FALSE. */ +/* Return NODE_P for PATH from ROOT's node cache, or NULL if the node + isn't cached; read it from the FS. *NODE_P is allocated in POOL. */ static svn_error_t * dag_node_cache_get(dag_node_t **node_p, svn_fs_root_t *root, const char *path, - svn_boolean_t needs_lock_cache, apr_pool_t *pool) { svn_boolean_t found; @@ -466,25 +352,23 @@ dag_node_cache_get(dag_node_t **node_p, if (bucket->node == NULL) { locate_cache(&cache, &key, root, path, pool); - SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, - ffd->dag_node_cache->pool)); + SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool)); if (found && node) { /* Patch up the FS, since this might have come from an old FS * object. */ svn_fs_fs__dag_set_fs(node, root->fs); - bucket->node = node; + + /* Retain the DAG node in L1 cache. */ + bucket->node = svn_fs_fs__dag_dup(node, + ffd->dag_node_cache->pool); } } else { - node = bucket->node; + /* Copy the node from L1 cache into the passed-in POOL. */ + node = svn_fs_fs__dag_dup(bucket->node, pool); } - - /* if we found a node, make sure it remains valid at least as long - as it would when allocated in POOL. */ - if (node && needs_lock_cache) - lock_cache(ffd->dag_node_cache, pool); } else { @@ -822,7 +706,7 @@ get_copy_inheritance(copy_id_inherit_t * SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path, child->node)); SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool)); - SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, FALSE, pool)); + SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); copyroot_id = svn_fs_fs__dag_get_id(copyroot_node); if (svn_fs_fs__id_compare(copyroot_id, child_id) == -1) @@ -938,7 +822,7 @@ open_path(parent_path_t **parent_path_p, { directory = svn_dirent_dirname(path, pool); if (directory[1] != 0) /* root nodes are covered anyway */ - SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool)); + SVN_ERR(dag_node_cache_get(&here, root, directory, pool)); } /* did the shortcut work? */ @@ -998,8 +882,7 @@ open_path(parent_path_t **parent_path_p, element if we already know the lookup to fail for the complete path. */ if (next || !(flags & open_path_uncached)) - SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, - TRUE, pool)); + SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, pool)); if (cached_node) child = cached_node; else @@ -1136,8 +1019,7 @@ make_path_mutable(svn_fs_root_t *root, parent_path->node)); SVN_ERR(svn_fs_fs__revision_root(©root_root, root->fs, copyroot_rev, pool)); - SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, - FALSE, pool)); + SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); child_id = svn_fs_fs__dag_get_id(parent_path->node); copyroot_id = svn_fs_fs__dag_get_id(copyroot_node); @@ -1174,16 +1056,11 @@ make_path_mutable(svn_fs_root_t *root, /* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the node we find, allocated in POOL. Return the error - SVN_ERR_FS_NOT_FOUND if this node doesn't exist. - - Since locking can be expensive and POOL may be long-living, for - nodes that will not need to survive the next call to this function, - set NEEDS_LOCK_CACHE to FALSE. */ + SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */ static svn_error_t * get_dag(dag_node_t **dag_node_p, svn_fs_root_t *root, const char *path, - svn_boolean_t needs_lock_cache, apr_pool_t *pool) { parent_path_t *parent_path; @@ -1192,7 +1069,7 @@ get_dag(dag_node_t **dag_node_p, /* First we look for the DAG in our cache (if the path may be canonical). */ if (*path == '/') - SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool)); + SVN_ERR(dag_node_cache_get(&node, root, path, pool)); if (! node) { @@ -1202,8 +1079,7 @@ get_dag(dag_node_t **dag_node_p, path = svn_fs__canonicalize_abspath(path, pool); /* Try again with the corrected path. */ - SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, - pool)); + SVN_ERR(dag_node_cache_get(&node, root, path, pool)); } if (! node) @@ -1281,7 +1157,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **i { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool); } return SVN_NO_ERROR; @@ -1296,7 +1172,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); return svn_fs_fs__dag_get_revision(revision, node, pool); } @@ -1311,7 +1187,7 @@ fs_node_created_path(const char **create { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, TRUE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); *created_path = svn_fs_fs__dag_get_created_path(node); return SVN_NO_ERROR; @@ -1375,7 +1251,7 @@ fs_node_prop(svn_string_t **value_p, dag_node_t *node; apr_hash_t *proplist; - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool)); *value_p = NULL; if (proplist) @@ -1398,7 +1274,7 @@ fs_node_proplist(apr_hash_t **table_p, apr_hash_t *table; dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool)); *table_p = table ? table : apr_hash_make(pool); @@ -1515,8 +1391,8 @@ fs_props_changed(svn_boolean_t *changed_ (SVN_ERR_FS_GENERAL, NULL, _("Cannot compare property value between two different filesystems")); - SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool)); - SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool)); + SVN_ERR(get_dag(&node1, root1, path1, pool)); + SVN_ERR(get_dag(&node2, root2, path2, pool)); return svn_fs_fs__dag_things_different(changed_p, NULL, node1, node2); } @@ -1529,7 +1405,7 @@ fs_props_changed(svn_boolean_t *changed_ static svn_error_t * get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool) { - return get_dag(node, root, "/", TRUE, pool); + return get_dag(node, root, "/", pool); } @@ -2193,7 +2069,7 @@ fs_dir_entries(apr_hash_t **table_p, dag_node_t *node; /* Get the entries for this path in the caller's pool. */ - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); return svn_fs_fs__dag_dir_entries(table_p, node, pool); } @@ -2365,7 +2241,7 @@ copy_helper(svn_fs_root_t *from_root, _("Copy from mutable tree not currently supported")); /* Get the NODE for FROM_PATH in FROM_ROOT.*/ - SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool)); + SVN_ERR(get_dag(&from_node, from_root, from_path, pool)); /* Build up the parent path from TO_PATH in TO_ROOT. If the last component does not exist, it's not that big a deal. We'll just @@ -2442,7 +2318,7 @@ copy_helper(svn_fs_root_t *from_root, pool)); /* Make a record of this modification in the changes table. */ - SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool)); + SVN_ERR(get_dag(&new_node, to_root, to_path, pool)); SVN_ERR(add_change(to_root->fs, txn_id, to_path, svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE, svn_fs_fs__dag_node_kind(from_node), @@ -2553,7 +2429,7 @@ fs_copied_from(svn_revnum_t *rev_p, { /* There is no cached entry, look it up the old-fashioned way. */ - SVN_ERR(get_dag(&node, root, path, TRUE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(©from_rev, node)); SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©from_path, node)); } @@ -2628,7 +2504,7 @@ fs_file_length(svn_filesize_t *length_p, dag_node_t *file; /* First create a dag_node_t from the root/path pair. */ - SVN_ERR(get_dag(&file, root, path, FALSE, pool)); + SVN_ERR(get_dag(&file, root, path, pool)); /* Now fetch its length */ return svn_fs_fs__dag_file_length(length_p, file, pool); @@ -2647,7 +2523,7 @@ fs_file_checksum(svn_checksum_t **checks { dag_node_t *file; - SVN_ERR(get_dag(&file, root, path, FALSE, pool)); + SVN_ERR(get_dag(&file, root, path, pool)); return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool); } @@ -2666,7 +2542,7 @@ fs_file_contents(svn_stream_t **contents svn_stream_t *file_stream; /* First create a dag_node_t from the root/path pair. */ - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); /* Then create a readable stream from the dag_node_t. */ SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool)); @@ -2689,7 +2565,7 @@ fs_try_process_file_contents(svn_boolean apr_pool_t *pool) { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, FALSE, pool)); + SVN_ERR(get_dag(&node, root, path, pool)); return svn_fs_fs__dag_try_process_file_contents(success, node, processor, baton, pool); @@ -3071,8 +2947,8 @@ fs_contents_changed(svn_boolean_t *chang (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2); } - SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool)); - SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool)); + SVN_ERR(get_dag(&node1, root1, path1, pool)); + SVN_ERR(get_dag(&node2, root2, path2, pool)); return svn_fs_fs__dag_things_different(NULL, changed_p, node1, node2); } @@ -3092,10 +2968,10 @@ fs_get_file_delta_stream(svn_txdelta_str dag_node_t *source_node, *target_node; if (source_root && source_path) - SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool)); + SVN_ERR(get_dag(&source_node, source_root, source_path, pool)); else source_node = NULL; - SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool)); + SVN_ERR(get_dag(&target_node, target_root, target_path, pool)); /* Create a delta stream that turns the source into the target. */ return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node, @@ -3588,7 +3464,7 @@ history_prev(void *baton, apr_pool_t *po SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool)); - SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, pool)); + SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, pool)); copy_dst = svn_fs_fs__dag_get_created_path(node); /* If our current path was the very destination of the copy, @@ -3785,7 +3661,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs svn_pool_clear(iterpool); kid_path = svn_fspath__join(this_path, dirent->name, iterpool); - SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool)); + SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool)); SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag)); SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag)); @@ -4031,7 +3907,7 @@ add_descendant_mergeinfo(svn_mergeinfo_c dag_node_t *this_dag; svn_boolean_t go_down; - SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool)); + SVN_ERR(get_dag(&this_dag, root, path, scratch_pool)); SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, this_dag)); if (go_down)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor