reftable/stack: provide convenience functions to create iterators

There exist a bunch of call sites in the reftable backend that want to create iterators for a reftable stack. This is rather convoluted right now, where you always have to go via the merged table. And it is about to become even more convoluted when we split up iterator initialization and seeking in the next commit. Introduce convenience functions that allow the caller to create an iterator from a reftable stack directly without going through the merged table. Adapt callers accordingly. 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 08efe69212fc158fb17294fc3396fa9d048d2285
5 files changed +63 -30
refs/reftable-backend.c
+21 -27
@@ -15,7 +15,6 @@
15 #include "../reftable/reftable-record.h"
16 #include "../reftable/reftable-error.h"
17 #include "../reftable/reftable-iterator.h"
18 -#include "../reftable/reftable-merged.h"
18 #include "../setup.h"
19 #include "../strmap.h"
20 #include "parse.h"
@@ -462,7 +461,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
461 const char *prefix,
462 int flags)
463 {
465 - struct reftable_merged_table *merged_table;
464 struct reftable_ref_iterator *iter;
465 int ret;
466
@@ -482,9 +480,8 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
480 if (ret)
481 goto done;
482
485 - merged_table = reftable_stack_merged_table(stack);
486 -
487 - ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix);
483 + reftable_stack_init_ref_iterator(stack, &iter->iter);
484 + ret = reftable_iterator_seek_ref(&iter->iter, prefix);
485 if (ret)
486 goto done;
487
@@ -1015,8 +1012,6 @@ static int transaction_update_cmp(const void *a, const void *b)
1012 static int write_transaction_table(struct reftable_writer *writer, void *cb_data)
1013 {
1014 struct write_transaction_table_arg *arg = cb_data;
1018 - struct reftable_merged_table *mt =
1019 - reftable_stack_merged_table(arg->stack);
1015 uint64_t ts = reftable_stack_next_update_index(arg->stack);
1016 struct reftable_log_record *logs = NULL;
1017 struct ident_split committer_ident = {0};
@@ -1051,6 +1046,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
1046 struct reftable_log_record log = {0};
1047 struct reftable_iterator it = {0};
1048
1049 + reftable_stack_init_log_iterator(arg->stack, &it);
1050 +
1051 /*
1052 * When deleting refs we also delete all reflog entries
1053 * with them. While it is not strictly required to
@@ -1060,7 +1057,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
1057 * Unfortunately, we have no better way than to delete
1058 * all reflog entries one by one.
1059 */
1063 - ret = reftable_merged_table_seek_log(mt, &it, u->refname);
1060 + ret = reftable_iterator_seek_log(&it, u->refname);
1061 while (ret == 0) {
1062 struct reftable_log_record *tombstone;
1063
@@ -1354,7 +1351,6 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
1351 {
1352 struct write_copy_arg *arg = cb_data;
1353 uint64_t deletion_ts, creation_ts;
1357 - struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack);
1354 struct reftable_ref_record old_ref = {0}, refs[2] = {0};
1355 struct reftable_log_record old_log = {0}, *logs = NULL;
1356 struct reftable_iterator it = {0};
@@ -1488,7 +1484,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
1484 * copy over all log entries from the old reflog. Last but not least,
1485 * when renaming we also have to delete all the old reflog entries.
1486 */
1491 - ret = reftable_merged_table_seek_log(mt, &it, arg->oldname);
1487 + reftable_stack_init_log_iterator(arg->stack, &it);
1488 + ret = reftable_iterator_seek_log(&it, arg->oldname);
1489 if (ret < 0)
1490 goto done;
1491
@@ -1694,7 +1691,6 @@ static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
1691 static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
1692 struct reftable_stack *stack)
1693 {
1697 - struct reftable_merged_table *merged_table;
1694 struct reftable_reflog_iterator *iter;
1695 int ret;
1696
@@ -1711,9 +1707,8 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
1707 if (ret < 0)
1708 goto done;
1709
1714 - merged_table = reftable_stack_merged_table(stack);
1715 -
1716 - ret = reftable_merged_table_seek_log(merged_table, &iter->iter, "");
1710 + reftable_stack_init_log_iterator(stack, &iter->iter);
1711 + ret = reftable_iterator_seek_log(&iter->iter, "");
1712 if (ret < 0)
1713 goto done;
1714
@@ -1771,7 +1766,6 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
1766 struct reftable_ref_store *refs =
1767 reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
1768 struct reftable_stack *stack = stack_for(refs, refname, &refname);
1774 - struct reftable_merged_table *mt = NULL;
1769 struct reftable_log_record log = {0};
1770 struct reftable_iterator it = {0};
1771 int ret;
@@ -1779,8 +1773,8 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
1773 if (refs->err < 0)
1774 return refs->err;
1775
1782 - mt = reftable_stack_merged_table(stack);
1783 - ret = reftable_merged_table_seek_log(mt, &it, refname);
1776 + reftable_stack_init_log_iterator(stack, &it);
1777 + ret = reftable_iterator_seek_log(&it, refname);
1778 while (!ret) {
1779 ret = reftable_iterator_next_log(&it, &log);
1780 if (ret < 0)
@@ -1808,7 +1802,6 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
1802 struct reftable_ref_store *refs =
1803 reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
1804 struct reftable_stack *stack = stack_for(refs, refname, &refname);
1811 - struct reftable_merged_table *mt = NULL;
1805 struct reftable_log_record *logs = NULL;
1806 struct reftable_iterator it = {0};
1807 size_t logs_alloc = 0, logs_nr = 0, i;
@@ -1817,8 +1810,8 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
1810 if (refs->err < 0)
1811 return refs->err;
1812
1820 - mt = reftable_stack_merged_table(stack);
1821 - ret = reftable_merged_table_seek_log(mt, &it, refname);
1813 + reftable_stack_init_log_iterator(stack, &it);
1814 + ret = reftable_iterator_seek_log(&it, refname);
1815 while (!ret) {
1816 struct reftable_log_record log = {0};
1817
@@ -1855,7 +1848,6 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
1848 struct reftable_ref_store *refs =
1849 reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
1850 struct reftable_stack *stack = stack_for(refs, refname, &refname);
1858 - struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
1851 struct reftable_log_record log = {0};
1852 struct reftable_iterator it = {0};
1853 int ret;
@@ -1868,7 +1860,8 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
1860 if (ret < 0)
1861 goto done;
1862
1871 - ret = reftable_merged_table_seek_log(mt, &it, refname);
1863 + reftable_stack_init_log_iterator(stack, &it);
1864 + ret = reftable_iterator_seek_log(&it, refname);
1865 if (ret < 0)
1866 goto done;
1867
@@ -1966,8 +1959,6 @@ struct write_reflog_delete_arg {
1959 static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data)
1960 {
1961 struct write_reflog_delete_arg *arg = cb_data;
1969 - struct reftable_merged_table *mt =
1970 - reftable_stack_merged_table(arg->stack);
1962 struct reftable_log_record log = {0}, tombstone = {0};
1963 struct reftable_iterator it = {0};
1964 uint64_t ts = reftable_stack_next_update_index(arg->stack);
@@ -1975,12 +1966,14 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
1966
1967 reftable_writer_set_limits(writer, ts, ts);
1968
1969 + reftable_stack_init_log_iterator(arg->stack, &it);
1970 +
1971 /*
1972 * In order to delete a table we need to delete all reflog entries one
1973 * by one. This is inefficient, but the reftable format does not have a
1974 * better marker right now.
1975 */
1983 - ret = reftable_merged_table_seek_log(mt, &it, arg->refname);
1976 + ret = reftable_iterator_seek_log(&it, arg->refname);
1977 while (ret == 0) {
1978 ret = reftable_iterator_next_log(&it, &log);
1979 if (ret < 0)
@@ -2116,7 +2109,6 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
2109 struct reftable_ref_store *refs =
2110 reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
2111 struct reftable_stack *stack = stack_for(refs, refname, &refname);
2119 - struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
2112 struct reftable_log_record *logs = NULL;
2113 struct reftable_log_record *rewritten = NULL;
2114 struct reftable_ref_record ref_record = {0};
@@ -2135,7 +2127,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
2127 if (ret < 0)
2128 goto done;
2129
2138 - ret = reftable_merged_table_seek_log(mt, &it, refname);
2130 + reftable_stack_init_log_iterator(stack, &it);
2131 +
2132 + ret = reftable_iterator_seek_log(&it, refname);
2133 if (ret < 0)
2134 goto done;
2135
reftable/merged.c
+3 -3
@@ -253,9 +253,9 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
253 return mt->min;
254 }
255
256 -static void merged_table_init_iter(struct reftable_merged_table *mt,
257 - struct reftable_iterator *it,
258 - uint8_t typ)
256 +void merged_table_init_iter(struct reftable_merged_table *mt,
257 + struct reftable_iterator *it,
258 + uint8_t typ)
259 {
260 struct merged_iter *mi = reftable_malloc(sizeof(*mi));
261 merged_iter_init(mi, mt, typ);
reftable/merged.h
+6
@@ -26,4 +26,10 @@ struct reftable_merged_table {
26
27 void merged_table_release(struct reftable_merged_table *mt);
28
29 +struct reftable_iterator;
30 +
31 +void merged_table_init_iter(struct reftable_merged_table *mt,
32 + struct reftable_iterator *it,
33 + uint8_t typ);
34 +
35 #endif
reftable/reftable-stack.h
+18
@@ -66,6 +66,24 @@ int reftable_stack_add(struct reftable_stack *st,
66 void *write_arg),
67 void *write_arg);
68
69 +struct reftable_iterator;
70 +
71 +/*
72 + * Initialize an iterator for the merged tables contained in the stack that can
73 + * be used to iterate through refs. The iterator is valid until the next reload
74 + * or write.
75 + */
76 +void reftable_stack_init_ref_iterator(struct reftable_stack *st,
77 + struct reftable_iterator *it);
78 +
79 +/*
80 + * Initialize an iterator for the merged tables contained in the stack that can
81 + * be used to iterate through logs. The iterator is valid until the next reload
82 + * or write.
83 + */
84 +void reftable_stack_init_log_iterator(struct reftable_stack *st,
85 + struct reftable_iterator *it);
86 +
87 /* returns the merged_table for seeking. This table is valid until the
88 * next write or reload, and should not be closed or deleted.
89 */
reftable/stack.c
+15
@@ -10,6 +10,7 @@ https://developers.google.com/open-source/licenses/bsd
10
11 #include "../write-or-die.h"
12 #include "system.h"
13 +#include "constants.h"
14 #include "merged.h"
15 #include "reader.h"
16 #include "reftable-error.h"
@@ -130,6 +131,20 @@ int read_lines(const char *filename, char ***namesp)
131 return err;
132 }
133
134 +void reftable_stack_init_ref_iterator(struct reftable_stack *st,
135 + struct reftable_iterator *it)
136 +{
137 + merged_table_init_iter(reftable_stack_merged_table(st),
138 + it, BLOCK_TYPE_REF);
139 +}
140 +
141 +void reftable_stack_init_log_iterator(struct reftable_stack *st,
142 + struct reftable_iterator *it)
143 +{
144 + merged_table_init_iter(reftable_stack_merged_table(st),
145 + it, BLOCK_TYPE_LOG);
146 +}
147 +
148 struct reftable_merged_table *
149 reftable_stack_merged_table(struct reftable_stack *st)
150 {