[PATCH v2 4/7] memtx: use ref counting to pin indexes for snapshot
Vladimir Davydov
vdavydov.dev at gmail.com
Mon Aug 19 19:53:17 MSK 2019
Currently, to prevent an index from going away while it is being
written to a snapshot, we postpone memtx_gc_task's free() invocation
until checkpointing is complete, see commit 94de0a081b3a ("Don't take
schema lock for checkpointing"). This works fine, but makes it rather
difficult to reuse snapshot iterators for other purposes, e.g. feeding
a consistent read view to a newly joined replica.
Let's instead use index reference counting for pinning indexes for
checkpointing. A reference is taken in a snapshot iterator constructor
and released when the snapshot iterator is destroyed.
---
src/box/memtx_engine.c | 26 +-------------------------
src/box/memtx_engine.h | 5 -----
src/box/memtx_hash.c | 15 +++++++++------
src/box/memtx_tree.c | 16 +++++++++-------
4 files changed, 19 insertions(+), 43 deletions(-)
diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
index 7c3dd846..c18177db 100644
--- a/src/box/memtx_engine.c
+++ b/src/box/memtx_engine.c
@@ -649,19 +649,6 @@ memtx_engine_wait_checkpoint(struct engine *engine,
return result;
}
-/**
- * Called after checkpointing is complete to free indexes dropped
- * while checkpointing was in progress, see memtx_engine_run_gc().
- */
-static void
-memtx_engine_gc_after_checkpoint(struct memtx_engine *memtx)
-{
- struct memtx_gc_task *task, *next;
- stailq_foreach_entry_safe(task, next, &memtx->gc_to_free, link)
- task->vtab->free(task);
- stailq_create(&memtx->gc_to_free);
-}
-
static void
memtx_engine_commit_checkpoint(struct engine *engine,
const struct vclock *vclock)
@@ -699,8 +686,6 @@ memtx_engine_commit_checkpoint(struct engine *engine,
checkpoint_delete(memtx->checkpoint);
memtx->checkpoint = NULL;
-
- memtx_engine_gc_after_checkpoint(memtx);
}
static void
@@ -885,15 +870,7 @@ memtx_engine_run_gc(struct memtx_engine *memtx, bool *stop)
task->vtab->run(task, &task_done);
if (task_done) {
stailq_shift(&memtx->gc_queue);
- /*
- * If checkpointing is in progress, the index may be
- * used by the checkpoint thread so we postpone freeing
- * until checkpointing is complete.
- */
- if (memtx->checkpoint == NULL)
- task->vtab->free(task);
- else
- stailq_add_entry(&memtx->gc_to_free, task, link);
+ task->vtab->free(task);
}
}
@@ -965,7 +942,6 @@ memtx_engine_new(const char *snap_dirname, bool force_recovery,
}
stailq_create(&memtx->gc_queue);
- stailq_create(&memtx->gc_to_free);
memtx->gc_fiber = fiber_new("memtx.gc", memtx_engine_gc_f);
if (memtx->gc_fiber == NULL)
goto fail;
diff --git a/src/box/memtx_engine.h b/src/box/memtx_engine.h
index fcf595e7..ccb51678 100644
--- a/src/box/memtx_engine.h
+++ b/src/box/memtx_engine.h
@@ -155,11 +155,6 @@ struct memtx_engine {
* memtx_gc_task::link.
*/
struct stailq gc_queue;
- /**
- * List of tasks awaiting to be freed once checkpointing
- * is complete, linked by memtx_gc_task::link.
- */
- struct stailq gc_to_free;
};
struct memtx_gc_task;
diff --git a/src/box/memtx_hash.c b/src/box/memtx_hash.c
index b53f115c..920f1032 100644
--- a/src/box/memtx_hash.c
+++ b/src/box/memtx_hash.c
@@ -399,7 +399,7 @@ memtx_hash_index_create_iterator(struct index *base, enum iterator_type type,
struct hash_snapshot_iterator {
struct snapshot_iterator base;
- struct light_index_core *hash_table;
+ struct memtx_hash_index *index;
struct light_index_iterator iterator;
};
@@ -414,7 +414,8 @@ hash_snapshot_iterator_free(struct snapshot_iterator *iterator)
assert(iterator->free == hash_snapshot_iterator_free);
struct hash_snapshot_iterator *it =
(struct hash_snapshot_iterator *) iterator;
- light_index_iterator_destroy(it->hash_table, &it->iterator);
+ light_index_iterator_destroy(&it->index->hash_table, &it->iterator);
+ index_unref(&it->index->base);
free(iterator);
}
@@ -430,7 +431,8 @@ hash_snapshot_iterator_next(struct snapshot_iterator *iterator,
assert(iterator->free == hash_snapshot_iterator_free);
struct hash_snapshot_iterator *it =
(struct hash_snapshot_iterator *) iterator;
- struct tuple **res = light_index_iterator_get_and_next(it->hash_table,
+ struct light_index_core *hash_table = &it->index->hash_table;
+ struct tuple **res = light_index_iterator_get_and_next(hash_table,
&it->iterator);
if (res == NULL) {
*data = NULL;
@@ -459,9 +461,10 @@ memtx_hash_index_create_snapshot_iterator(struct index *base)
it->base.next = hash_snapshot_iterator_next;
it->base.free = hash_snapshot_iterator_free;
- it->hash_table = &index->hash_table;
- light_index_iterator_begin(it->hash_table, &it->iterator);
- light_index_iterator_freeze(it->hash_table, &it->iterator);
+ it->index = index;
+ index_ref(base);
+ light_index_iterator_begin(&index->hash_table, &it->iterator);
+ light_index_iterator_freeze(&index->hash_table, &it->iterator);
return (struct snapshot_iterator *) it;
}
diff --git a/src/box/memtx_tree.c b/src/box/memtx_tree.c
index cbd888c5..831a2715 100644
--- a/src/box/memtx_tree.c
+++ b/src/box/memtx_tree.c
@@ -1205,7 +1205,7 @@ memtx_tree_index_end_build(struct index *base)
struct tree_snapshot_iterator {
struct snapshot_iterator base;
- struct memtx_tree *tree;
+ struct memtx_tree_index *index;
struct memtx_tree_iterator tree_iterator;
};
@@ -1215,8 +1215,8 @@ tree_snapshot_iterator_free(struct snapshot_iterator *iterator)
assert(iterator->free == tree_snapshot_iterator_free);
struct tree_snapshot_iterator *it =
(struct tree_snapshot_iterator *)iterator;
- struct memtx_tree *tree = (struct memtx_tree *)it->tree;
- memtx_tree_iterator_destroy(tree, &it->tree_iterator);
+ memtx_tree_iterator_destroy(&it->index->tree, &it->tree_iterator);
+ index_unref(&it->index->base);
free(iterator);
}
@@ -1227,13 +1227,14 @@ tree_snapshot_iterator_next(struct snapshot_iterator *iterator,
assert(iterator->free == tree_snapshot_iterator_free);
struct tree_snapshot_iterator *it =
(struct tree_snapshot_iterator *)iterator;
- struct memtx_tree_data *res =
- memtx_tree_iterator_get_elem(it->tree, &it->tree_iterator);
+ struct memtx_tree *tree = &it->index->tree;
+ struct memtx_tree_data *res = memtx_tree_iterator_get_elem(tree,
+ &it->tree_iterator);
if (res == NULL) {
*data = NULL;
return 0;
}
- memtx_tree_iterator_next(it->tree, &it->tree_iterator);
+ memtx_tree_iterator_next(tree, &it->tree_iterator);
*data = tuple_data_range(res->tuple, size);
return 0;
}
@@ -1257,7 +1258,8 @@ memtx_tree_index_create_snapshot_iterator(struct index *base)
it->base.free = tree_snapshot_iterator_free;
it->base.next = tree_snapshot_iterator_next;
- it->tree = &index->tree;
+ it->index = index;
+ index_ref(base);
it->tree_iterator = memtx_tree_iterator_first(&index->tree);
memtx_tree_iterator_freeze(&index->tree, &it->tree_iterator);
return (struct snapshot_iterator *) it;
--
2.20.1
More information about the Tarantool-patches
mailing list