From 2d945f82f63a4df57b2bd9ba6551d99d4517f7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 2 Jun 2014 17:44:51 +0200 Subject: refs: copy the packed refs on iteration This lets us work without worrying about what's happening but work on a snapshot. --- src/refdb_fs.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src/refdb_fs.c') diff --git a/src/refdb_fs.c b/src/refdb_fs.c index dd8bf7916..0e36ca8ac 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -458,6 +458,7 @@ typedef struct { git_pool pool; git_vector loose; + git_sortedcache *cache; size_t loose_pos; size_t packed_pos; } refdb_fs_iter; @@ -468,6 +469,7 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) git_vector_free(&iter->loose); git_pool_clear(&iter->pool); + git_sortedcache_free(iter->cache); git__free(iter); } @@ -539,10 +541,14 @@ static int refdb_fs_backend__iterator_next( giterr_clear(); } - git_sortedcache_rlock(backend->refcache); + if (!iter->cache) { + if ((error = git_sortedcache_copy(&iter->cache, backend->refcache, 1, NULL, NULL)) < 0) + return error; + } - while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { - ref = git_sortedcache_entry(backend->refcache, iter->packed_pos++); + error = GIT_ITEROVER; + while (iter->packed_pos < git_sortedcache_entrycount(iter->cache)) { + ref = git_sortedcache_entry(iter->cache, iter->packed_pos++); if (!ref) /* stop now if another thread deleted refs and we past end */ break; @@ -556,7 +562,6 @@ static int refdb_fs_backend__iterator_next( break; } - git_sortedcache_runlock(backend->refcache); return error; } @@ -579,10 +584,14 @@ static int refdb_fs_backend__iterator_next_name( giterr_clear(); } - git_sortedcache_rlock(backend->refcache); + if (!iter->cache) { + if ((error = git_sortedcache_copy(&iter->cache, backend->refcache, 1, NULL, NULL)) < 0) + return error; + } - while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { - ref = git_sortedcache_entry(backend->refcache, iter->packed_pos++); + error = GIT_ITEROVER; + while (iter->packed_pos < git_sortedcache_entrycount(iter->cache)) { + ref = git_sortedcache_entry(iter->cache, iter->packed_pos++); if (!ref) /* stop now if another thread deleted refs and we past end */ break; @@ -596,7 +605,6 @@ static int refdb_fs_backend__iterator_next_name( break; } - git_sortedcache_runlock(backend->refcache); return error; } -- cgit v1.2.1