reftable/generic: adapt interface to allow reuse of iterators

Refactor the interfaces exposed by `struct reftable_table` and `struct reftable_iterator` such that they support iterator reuse. This is done by separating initialization of the iterator and seeking on it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 13, 2024 at 10:47 UTC d76f0d3f57184e05eeabbe7bb382ae87149f0dd9
4 files changed +68 -22
reftable/generic.c
+39 -14
@@ -20,8 +20,20 @@ void table_init_iter(struct reftable_table *tab,
20 tab->ops->init_iter(tab->table_arg, it, typ);
21 }
22
23 -int reftable_table_seek_ref(struct reftable_table *tab,
24 - struct reftable_iterator *it, const char *name)
23 +void reftable_table_init_ref_iter(struct reftable_table *tab,
24 + struct reftable_iterator *it)
25 +{
26 + table_init_iter(tab, it, BLOCK_TYPE_REF);
27 +}
28 +
29 +void reftable_table_init_log_iter(struct reftable_table *tab,
30 + struct reftable_iterator *it)
31 +{
32 + table_init_iter(tab, it, BLOCK_TYPE_LOG);
33 +}
34 +
35 +int reftable_iterator_seek_ref(struct reftable_iterator *it,
36 + const char *name)
37 {
38 struct reftable_record want = {
39 .type = BLOCK_TYPE_REF,
@@ -29,29 +41,37 @@ int reftable_table_seek_ref(struct reftable_table *tab,
41 .refname = (char *)name,
42 },
43 };
32 - table_init_iter(tab, it, BLOCK_TYPE_REF);
44 return it->ops->seek(it->iter_arg, &want);
45 }
46
36 -int reftable_table_seek_log(struct reftable_table *tab,
37 - struct reftable_iterator *it, const char *name)
47 +int reftable_iterator_seek_log_at(struct reftable_iterator *it,
48 + const char *name, uint64_t update_index)
49 {
50 struct reftable_record want = {
51 .type = BLOCK_TYPE_LOG,
52 .u.log = {
53 .refname = (char *)name,
43 - .update_index = ~((uint64_t)0),
54 + .update_index = update_index,
55 },
56 };
46 - table_init_iter(tab, it, BLOCK_TYPE_LOG);
57 return it->ops->seek(it->iter_arg, &want);
58 }
59
60 +int reftable_iterator_seek_log(struct reftable_iterator *it,
61 + const char *name)
62 +{
63 + return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0));
64 +}
65 +
66 int reftable_table_read_ref(struct reftable_table *tab, const char *name,
67 struct reftable_ref_record *ref)
68 {
69 struct reftable_iterator it = { NULL };
54 - int err = reftable_table_seek_ref(tab, &it, name);
70 + int err;
71 +
72 + reftable_table_init_ref_iter(tab, &it);
73 +
74 + err = reftable_iterator_seek_ref(&it, name);
75 if (err)
76 goto done;
77
@@ -76,10 +96,13 @@ int reftable_table_print(struct reftable_table *tab) {
96 struct reftable_ref_record ref = { NULL };
97 struct reftable_log_record log = { NULL };
98 uint32_t hash_id = reftable_table_hash_id(tab);
79 - int err = reftable_table_seek_ref(tab, &it, "");
80 - if (err < 0) {
99 + int err;
100 +
101 + reftable_table_init_ref_iter(tab, &it);
102 +
103 + err = reftable_iterator_seek_ref(&it, "");
104 + if (err < 0)
105 return err;
82 - }
106
107 while (1) {
108 err = reftable_iterator_next_ref(&it, &ref);
@@ -94,10 +117,12 @@ int reftable_table_print(struct reftable_table *tab) {
117 reftable_iterator_destroy(&it);
118 reftable_ref_record_release(&ref);
119
97 - err = reftable_table_seek_log(tab, &it, "");
98 - if (err < 0) {
120 + reftable_table_init_log_iter(tab, &it);
121 +
122 + err = reftable_iterator_seek_log(&it, "");
123 + if (err < 0)
124 return err;
100 - }
125 +
126 while (1) {
127 err = reftable_iterator_next_log(&it, &log);
128 if (err > 0) {
reftable/iter.c
+4 -4
@@ -45,11 +45,11 @@ static int filtering_ref_iterator_next(void *iter_arg,
45 if (fri->double_check) {
46 struct reftable_iterator it = { NULL };
47
48 - err = reftable_table_seek_ref(&fri->tab, &it,
49 - ref->refname);
50 - if (err == 0) {
48 + reftable_table_init_ref_iter(&fri->tab, &it);
49 +
50 + err = reftable_iterator_seek_ref(&it, ref->refname);
51 + if (err == 0)
52 err = reftable_iterator_next_ref(&it, ref);
52 - }
53
54 reftable_iterator_destroy(&it);
55
reftable/reftable-generic.h
+4 -4
@@ -21,11 +21,11 @@ struct reftable_table {
21 void *table_arg;
22 };
23
24 -int reftable_table_seek_log(struct reftable_table *tab,
25 - struct reftable_iterator *it, const char *name);
24 +void reftable_table_init_ref_iter(struct reftable_table *tab,
25 + struct reftable_iterator *it);
26
27 -int reftable_table_seek_ref(struct reftable_table *tab,
28 - struct reftable_iterator *it, const char *name);
27 +void reftable_table_init_log_iter(struct reftable_table *tab,
28 + struct reftable_iterator *it);
29
30 /* returns the hash ID from a generic reftable_table */
31 uint32_t reftable_table_hash_id(struct reftable_table *tab);
reftable/reftable-iterator.h
+21
@@ -21,12 +21,33 @@ struct reftable_iterator {
21 void *iter_arg;
22 };
23
24 +/*
25 + * Position the iterator at the ref record with given name such that the next
26 + * call to `next_ref()` would yield the record.
27 + */
28 +int reftable_iterator_seek_ref(struct reftable_iterator *it,
29 + const char *name);
30 +
31 /* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0:
32 * end of iteration.
33 */
34 int reftable_iterator_next_ref(struct reftable_iterator *it,
35 struct reftable_ref_record *ref);
36
37 +/*
38 + * Position the iterator at the log record with given name and update index
39 + * such that the next call to `next_log()` would yield the record.
40 + */
41 +int reftable_iterator_seek_log_at(struct reftable_iterator *it,
42 + const char *name, uint64_t update_index);
43 +
44 +/*
45 + * Position the iterator at the newest log record with given name such that the
46 + * next call to `next_log()` would yield the record.
47 + */
48 +int reftable_iterator_seek_log(struct reftable_iterator *it,
49 + const char *name);
50 +
51 /* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0:
52 * end of iteration.
53 */