summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-06-02 17:44:51 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2014-06-02 17:50:30 +0200
commit2d945f82f63a4df57b2bd9ba6551d99d4517f7f4 (patch)
tree06990a0491b78b0c03dd5cf25d74c56c08a1364f
parent4ee2543c5ac1e7ed2f849968a7396f04d83fee54 (diff)
downloadlibgit2-cmn/ref-iter-concurrent.tar.gz
refs: copy the packed refs on iterationcmn/ref-iter-concurrent
This lets us work without worrying about what's happening but work on a snapshot.
-rw-r--r--src/refdb_fs.c24
1 files changed, 16 insertions, 8 deletions
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;
}