[PATCH v2 00/10] reftable: fix reload with active iterators
From: Patrick Steinhardt <hidden>
Date: 2024-08-23 14:12:31
Hi,
this is the second version of my patch series that fixes issues in the
reftable libary caused by having concurrent readers and writers.
Changes compared to v1:
- Remove a spurious change that renamed `init_reader()` to
`reader_init()`. That function went away in the subsequent commit
anyway.
- Fix a typo in a commit message.
- Fix some assertions in one of the added tests.
Thanks!
Patrick
Patrick Steinhardt (10):
reftable/blocksource: drop malloc block source
reftable/stack: inline `stack_compact_range_stats()`
reftable/reader: rename `reftable_new_reader()`
reftable/reader: inline `init_reader()`
reftable/reader: inline `reader_close()`
reftable/stack: fix broken refnames in `write_n_ref_tables()`
reftable/reader: introduce refcounting
reftable/reader: keep readers alive during iteration
reftable/stack: reorder swapping in the reloaded stack contents
reftable/stack: fix segfault when reload with reused readers fails
reftable/block_test.c | 3 +-
reftable/blocksource.c | 20 -----
reftable/blocksource.h | 2 -
reftable/reader.c | 149 ++++++++++++++++---------------
reftable/reader.h | 5 +-
reftable/readwrite_test.c | 85 +++++++++---------
reftable/reftable-reader.h | 19 ++--
reftable/stack.c | 90 +++++++++++--------
reftable/stack_test.c | 116 +++++++++++++++++++++++-
t/helper/test-reftable.c | 4 +-
t/unit-tests/t-reftable-merged.c | 10 +--
11 files changed, 312 insertions(+), 191 deletions(-)
Range-diff against v1:
1: fee3d3523eb = 1: fee3d3523eb reftable/blocksource: drop malloc block source
2: 3c0cf2bf46f = 2: 3c0cf2bf46f reftable/stack: inline `stack_compact_range_stats()`
3: e658b372f04 ! 3: b4cf97bf758 reftable/reader: rename `reftable_new_reader()`
@@ reftable/reader.c: int reftable_reader_print_blocks(const char *tablename)
goto done;
- ## reftable/reader.h ##
-@@ reftable/reader.h: struct reftable_reader {
- struct reftable_reader_offsets log_offsets;
- };
-
--int init_reader(struct reftable_reader *r, struct reftable_block_source *source,
-+int reader_init(struct reftable_reader *r, struct reftable_block_source *source,
- const char *name);
- void reader_close(struct reftable_reader *r);
- const char *reader_name(struct reftable_reader *r);
-
## reftable/readwrite_test.c ##
@@ reftable/readwrite_test.c: static void test_write_empty_table(void)
4: f628b7dafb9 ! 4: 3b667097501 reftable/reader: inline `init_reader()`
@@ reftable/reader.h: struct reftable_reader {
struct reftable_reader_offsets log_offsets;
};
--int reader_init(struct reftable_reader *r, struct reftable_block_source *source,
+-int init_reader(struct reftable_reader *r, struct reftable_block_source *source,
- const char *name);
void reader_close(struct reftable_reader *r);
const char *reader_name(struct reftable_reader *r);
5: 4a9fe150427 = 5: b129d8a8687 reftable/reader: inline `reader_close()`
6: 4965402e7bf = 6: e3b28709b5f reftable/stack: fix broken refnames in `write_n_ref_tables()`
7: fc0ed68d467 = 7: 6535d1ca9de reftable/reader: introduce refcounting
8: 02682056288 ! 8: 8d08c3bc515 reftable/reader: keep readers alive during iteration
@@ Metadata
## Commit message ##
reftable/reader: keep readers alive during iteration
- The lifetime of a table iterator may surive the lifetime of a reader
+ The lifetime of a table iterator may survive the lifetime of a reader
when the stack gets reloaded. Keep the reader from being released by
increasing its refcount while the iterator is still being used.
@@ reftable/stack_test.c: static void test_reftable_stack_compaction_concurrent_cle
+ EXPECT(st2->merged->readers_len == 2);
+ err = reftable_stack_compact_all(st2, NULL);
+ EXPECT_ERR(err);
++ EXPECT(st2->merged->readers_len == 1);
+
+ /*
+ * Verify that we can continue to use the old iterator even after we
@@ reftable/stack_test.c: static void test_reftable_stack_compaction_concurrent_cle
+ */
+ err = reftable_stack_reload(st1);
+ EXPECT_ERR(err);
-+ EXPECT(st2->merged->readers_len == 1);
++ EXPECT(st1->merged->readers_len == 1);
+ err = reftable_iterator_next_ref(&it, &rec);
+ EXPECT_ERR(err);
+ EXPECT(!strcmp(rec.refname, "refs/heads/branch-0000"));
9: d98316fbf4c = 9: 5aee91de25e reftable/stack: reorder swapping in the reloaded stack contents
10: b777818ea99 = 10: 4a8d45cc9b4 reftable/stack: fix segfault when reload with reused readers fails
--
2.46.0.164.g477ce5ccd6.dirty