Skip to content

Commit 5bf96e0

Browse files
pks-tgitster
authored andcommitted
reftable/generic: move seeking of records into the iterator
Reftable iterators are created by seeking on the parent structure of a corresponding record. For example, to create an iterator for the merged table you would call `reftable_merged_table_seek_ref()`. Most notably, it is not posible to create an iterator and then seek it afterwards. While this may be a bit easier to reason about, it comes with two significant downsides. The first downside is that the logic to find records is split up between the parent data structure and the iterator itself. Conceptually, it is more straight forward if all that logic was contained in a single place, which should be the iterator. The second and more significant downside is that it is impossible to reuse iterators for multiple seeks. Whenever you want to look up a record, you need to re-create the whole infrastructure again, which is quite a waste of time. Furthermore, it is impossible to optimize seeks, such as when seeking the same record multiple times. To address this, we essentially split up the concerns properly such that the parent data structure is responsible for setting up the iterator via a new `init_iter()` callback, whereas the iterator handles seeks via a new `seek()` callback. This will eventually allow us to call `seek()` on the iterator multiple times, where every iterator can potentially optimize for certain cases. Note that at this point in time we are not yet ready to reuse the iterators. This will be left for a future patch series. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 701713a commit 5bf96e0

File tree

5 files changed

+177
-117
lines changed

5 files changed

+177
-117
lines changed

reftable/generic.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,39 @@ license that can be found in the LICENSE file or at
1212
#include "reftable-iterator.h"
1313
#include "reftable-generic.h"
1414

15+
void table_init_iter(struct reftable_table *tab,
16+
struct reftable_iterator *it,
17+
uint8_t typ)
18+
{
19+
20+
tab->ops->init_iter(tab->table_arg, it, typ);
21+
}
22+
1523
int reftable_table_seek_ref(struct reftable_table *tab,
1624
struct reftable_iterator *it, const char *name)
1725
{
18-
struct reftable_record rec = { .type = BLOCK_TYPE_REF,
19-
.u.ref = {
20-
.refname = (char *)name,
21-
} };
22-
return tab->ops->seek_record(tab->table_arg, it, &rec);
26+
struct reftable_record want = {
27+
.type = BLOCK_TYPE_REF,
28+
.u.ref = {
29+
.refname = (char *)name,
30+
},
31+
};
32+
table_init_iter(tab, it, BLOCK_TYPE_REF);
33+
return it->ops->seek(it->iter_arg, &want);
2334
}
2435

2536
int reftable_table_seek_log(struct reftable_table *tab,
2637
struct reftable_iterator *it, const char *name)
2738
{
28-
struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
29-
.u.log = {
30-
.refname = (char *)name,
31-
.update_index = ~((uint64_t)0),
32-
} };
33-
return tab->ops->seek_record(tab->table_arg, it, &rec);
39+
struct reftable_record want = {
40+
.type = BLOCK_TYPE_LOG,
41+
.u.log = {
42+
.refname = (char *)name,
43+
.update_index = ~((uint64_t)0),
44+
},
45+
};
46+
table_init_iter(tab, it, BLOCK_TYPE_LOG);
47+
return it->ops->seek(it->iter_arg, &want);
3448
}
3549

3650
int reftable_table_read_ref(struct reftable_table *tab, const char *name,
@@ -152,11 +166,21 @@ int reftable_iterator_next_log(struct reftable_iterator *it,
152166
return err;
153167
}
154168

169+
int iterator_seek(struct reftable_iterator *it, struct reftable_record *want)
170+
{
171+
return it->ops->seek(it->iter_arg, want);
172+
}
173+
155174
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
156175
{
157176
return it->ops->next(it->iter_arg, rec);
158177
}
159178

179+
static int empty_iterator_seek(void *arg, struct reftable_record *want)
180+
{
181+
return 0;
182+
}
183+
160184
static int empty_iterator_next(void *arg, struct reftable_record *rec)
161185
{
162186
return 1;
@@ -167,6 +191,7 @@ static void empty_iterator_close(void *arg)
167191
}
168192

169193
static struct reftable_iterator_vtable empty_vtable = {
194+
.seek = &empty_iterator_seek,
170195
.next = &empty_iterator_next,
171196
.close = &empty_iterator_close,
172197
};

reftable/generic.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,24 @@ license that can be found in the LICENSE file or at
1414

1515
/* generic interface to reftables */
1616
struct reftable_table_vtable {
17-
int (*seek_record)(void *tab, struct reftable_iterator *it,
18-
struct reftable_record *);
17+
void (*init_iter)(void *tab, struct reftable_iterator *it, uint8_t typ);
1918
uint32_t (*hash_id)(void *tab);
2019
uint64_t (*min_update_index)(void *tab);
2120
uint64_t (*max_update_index)(void *tab);
2221
};
2322

23+
void table_init_iter(struct reftable_table *tab,
24+
struct reftable_iterator *it,
25+
uint8_t typ);
26+
2427
struct reftable_iterator_vtable {
28+
int (*seek)(void *iter_arg, struct reftable_record *want);
2529
int (*next)(void *iter_arg, struct reftable_record *rec);
2630
void (*close)(void *iter_arg);
2731
};
2832

2933
void iterator_set_empty(struct reftable_iterator *it);
34+
int iterator_seek(struct reftable_iterator *it, struct reftable_record *want);
3035
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec);
3136

3237
#endif

reftable/iter.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ static void filtering_ref_iterator_close(void *iter_arg)
2323
reftable_iterator_destroy(&fri->it);
2424
}
2525

26+
static int filtering_ref_iterator_seek(void *iter_arg,
27+
struct reftable_record *want)
28+
{
29+
struct filtering_ref_iterator *fri = iter_arg;
30+
return iterator_seek(&fri->it, want);
31+
}
32+
2633
static int filtering_ref_iterator_next(void *iter_arg,
2734
struct reftable_record *rec)
2835
{
@@ -73,6 +80,7 @@ static int filtering_ref_iterator_next(void *iter_arg,
7380
}
7481

7582
static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
83+
.seek = &filtering_ref_iterator_seek,
7684
.next = &filtering_ref_iterator_next,
7785
.close = &filtering_ref_iterator_close,
7886
};
@@ -119,6 +127,12 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
119127
return 0;
120128
}
121129

130+
static int indexed_table_ref_iter_seek(void *p, struct reftable_record *want)
131+
{
132+
BUG("seeking indexed table is not supported");
133+
return -1;
134+
}
135+
122136
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
123137
{
124138
struct indexed_table_ref_iter *it = p;
@@ -175,6 +189,7 @@ int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
175189
}
176190

177191
static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
192+
.seek = &indexed_table_ref_iter_seek,
178193
.next = &indexed_table_ref_iter_next,
179194
.close = &indexed_table_ref_iter_close,
180195
};

reftable/merged.c

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ struct merged_iter {
3131
};
3232

3333
static void merged_iter_init(struct merged_iter *mi,
34-
struct reftable_merged_table *mt)
34+
struct reftable_merged_table *mt,
35+
uint8_t typ)
3536
{
3637
memset(mi, 0, sizeof(*mi));
3738
mi->advance_index = -1;
3839
mi->suppress_deletions = mt->suppress_deletions;
40+
3941
REFTABLE_CALLOC_ARRAY(mi->subiters, mt->stack_len);
42+
for (size_t i = 0; i < mt->stack_len; i++) {
43+
reftable_record_init(&mi->subiters[i].rec, typ);
44+
table_init_iter(&mt->stack[i], &mi->subiters[i].iter, typ);
45+
}
4046
mi->stack_len = mt->stack_len;
4147
}
4248

@@ -68,6 +74,27 @@ static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
6874
return 0;
6975
}
7076

77+
static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want)
78+
{
79+
int err;
80+
81+
mi->advance_index = -1;
82+
83+
for (size_t i = 0; i < mi->stack_len; i++) {
84+
err = iterator_seek(&mi->subiters[i].iter, want);
85+
if (err < 0)
86+
return err;
87+
if (err > 0)
88+
continue;
89+
90+
err = merged_iter_advance_subiter(mi, i);
91+
if (err < 0)
92+
return err;
93+
}
94+
95+
return 0;
96+
}
97+
7198
static int merged_iter_next_entry(struct merged_iter *mi,
7299
struct reftable_record *rec)
73100
{
@@ -133,6 +160,11 @@ static int merged_iter_next_entry(struct merged_iter *mi,
133160
return 0;
134161
}
135162

163+
static int merged_iter_seek_void(void *it, struct reftable_record *want)
164+
{
165+
return merged_iter_seek(it, want);
166+
}
167+
136168
static int merged_iter_next_void(void *p, struct reftable_record *rec)
137169
{
138170
struct merged_iter *mi = p;
@@ -147,6 +179,7 @@ static int merged_iter_next_void(void *p, struct reftable_record *rec)
147179
}
148180

149181
static struct reftable_iterator_vtable merged_iter_vtable = {
182+
.seek = merged_iter_seek_void,
150183
.next = &merged_iter_next_void,
151184
.close = &merged_iter_close,
152185
};
@@ -220,47 +253,13 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
220253
return mt->min;
221254
}
222255

223-
static int reftable_table_seek_record(struct reftable_table *tab,
224-
struct reftable_iterator *it,
225-
struct reftable_record *rec)
226-
{
227-
return tab->ops->seek_record(tab->table_arg, it, rec);
228-
}
229-
230-
static int merged_table_seek_record(struct reftable_merged_table *mt,
231-
struct reftable_iterator *it,
232-
struct reftable_record *rec)
256+
static void merged_table_init_iter(struct reftable_merged_table *mt,
257+
struct reftable_iterator *it,
258+
uint8_t typ)
233259
{
234-
struct merged_iter merged, *p;
235-
int err;
236-
237-
merged_iter_init(&merged, mt);
238-
239-
for (size_t i = 0; i < mt->stack_len; i++) {
240-
reftable_record_init(&merged.subiters[i].rec,
241-
reftable_record_type(rec));
242-
243-
err = reftable_table_seek_record(&mt->stack[i],
244-
&merged.subiters[i].iter, rec);
245-
if (err < 0)
246-
goto out;
247-
if (err > 0)
248-
continue;
249-
250-
err = merged_iter_advance_subiter(&merged, i);
251-
if (err < 0)
252-
goto out;
253-
}
254-
255-
p = reftable_malloc(sizeof(*p));
256-
*p = merged;
257-
iterator_from_merged_iter(it, p);
258-
err = 0;
259-
260-
out:
261-
if (err < 0)
262-
merged_iter_close(&merged);
263-
return err;
260+
struct merged_iter *mi = reftable_malloc(sizeof(*mi));
261+
merged_iter_init(mi, mt, typ);
262+
iterator_from_merged_iter(it, mi);
264263
}
265264

266265
int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
@@ -273,7 +272,8 @@ int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
273272
.refname = (char *)name,
274273
},
275274
};
276-
return merged_table_seek_record(mt, it, &rec);
275+
merged_table_init_iter(mt, it, BLOCK_TYPE_REF);
276+
return iterator_seek(it, &rec);
277277
}
278278

279279
int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
@@ -285,7 +285,8 @@ int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
285285
.refname = (char *)name,
286286
.update_index = update_index,
287287
} };
288-
return merged_table_seek_record(mt, it, &rec);
288+
merged_table_init_iter(mt, it, BLOCK_TYPE_LOG);
289+
return iterator_seek(it, &rec);
289290
}
290291

291292
int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
@@ -301,11 +302,11 @@ uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
301302
return mt->hash_id;
302303
}
303304

304-
static int reftable_merged_table_seek_void(void *tab,
305-
struct reftable_iterator *it,
306-
struct reftable_record *rec)
305+
static void reftable_merged_table_init_iter_void(void *tab,
306+
struct reftable_iterator *it,
307+
uint8_t typ)
307308
{
308-
return merged_table_seek_record(tab, it, rec);
309+
merged_table_init_iter(tab, it, typ);
309310
}
310311

311312
static uint32_t reftable_merged_table_hash_id_void(void *tab)
@@ -324,7 +325,7 @@ static uint64_t reftable_merged_table_max_update_index_void(void *tab)
324325
}
325326

326327
static struct reftable_table_vtable merged_table_vtable = {
327-
.seek_record = reftable_merged_table_seek_void,
328+
.init_iter = reftable_merged_table_init_iter_void,
328329
.hash_id = reftable_merged_table_hash_id_void,
329330
.min_update_index = reftable_merged_table_min_update_index_void,
330331
.max_update_index = reftable_merged_table_max_update_index_void,

0 commit comments

Comments
 (0)