Skip to content

Commit 82c39c6

Browse files
pks-tgitster
authored andcommitted
refs/iterator: provide infrastructure to re-seek iterators
Reftable iterators need to be scrapped after they have either been exhausted or aren't useful to the caller anymore, and it is explicitly not possible to reuse them for iterations. But enabling for reuse of iterators may allow us to tune them by reusing internal state of an iterator. The reftable iterators for example can already be reused internally, but we're not able to expose this to any users outside of the reftable backend. Introduce a new `.seek` function in the ref iterator vtable that allows callers to seek an iterator multiple times. It is expected to be functionally the same as calling `refs_ref_iterator_begin()` with a different (or the same) prefix. Note that it is not possible to adjust parameters other than the seeked prefix for now, so exclude patterns, trimmed prefixes and flags will remain unchanged. We do not have a usecase for changing these parameters right now, but if we ever find one we can adapt accordingly. Implement the callback for trivial cases. The other iterators will be implemented in subsequent commits. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cec2b6f commit 82c39c6

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

refs/debug.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
169169
return res;
170170
}
171171

172+
static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
173+
const char *prefix)
174+
{
175+
struct debug_ref_iterator *diter =
176+
(struct debug_ref_iterator *)ref_iterator;
177+
int res = diter->iter->vtable->seek(diter->iter, prefix);
178+
trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res);
179+
return res;
180+
}
181+
172182
static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
173183
struct object_id *peeled)
174184
{
@@ -189,6 +199,7 @@ static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
189199

190200
static struct ref_iterator_vtable debug_ref_iterator_vtable = {
191201
.advance = debug_ref_iterator_advance,
202+
.seek = debug_ref_iterator_seek,
192203
.peel = debug_ref_iterator_peel,
193204
.release = debug_ref_iterator_release,
194205
};

refs/iterator.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator)
1515
return ref_iterator->vtable->advance(ref_iterator);
1616
}
1717

18+
int ref_iterator_seek(struct ref_iterator *ref_iterator,
19+
const char *prefix)
20+
{
21+
return ref_iterator->vtable->seek(ref_iterator, prefix);
22+
}
23+
1824
int ref_iterator_peel(struct ref_iterator *ref_iterator,
1925
struct object_id *peeled)
2026
{
@@ -50,6 +56,12 @@ static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED)
5056
return ITER_DONE;
5157
}
5258

59+
static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
60+
const char *prefix UNUSED)
61+
{
62+
return 0;
63+
}
64+
5365
static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
5466
struct object_id *peeled UNUSED)
5567
{
@@ -62,6 +74,7 @@ static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
6274

6375
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
6476
.advance = empty_ref_iterator_advance,
77+
.seek = empty_ref_iterator_seek,
6578
.peel = empty_ref_iterator_peel,
6679
.release = empty_ref_iterator_release,
6780
};
@@ -373,6 +386,16 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
373386
return ok;
374387
}
375388

389+
static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
390+
const char *prefix)
391+
{
392+
struct prefix_ref_iterator *iter =
393+
(struct prefix_ref_iterator *)ref_iterator;
394+
free(iter->prefix);
395+
iter->prefix = xstrdup_or_null(prefix);
396+
return ref_iterator_seek(iter->iter0, prefix);
397+
}
398+
376399
static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
377400
struct object_id *peeled)
378401
{
@@ -392,6 +415,7 @@ static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
392415

393416
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
394417
.advance = prefix_ref_iterator_advance,
418+
.seek = prefix_ref_iterator_seek,
395419
.peel = prefix_ref_iterator_peel,
396420
.release = prefix_ref_iterator_release,
397421
};

refs/refs-internal.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,22 @@ struct ref_iterator {
327327
*/
328328
int ref_iterator_advance(struct ref_iterator *ref_iterator);
329329

330+
/*
331+
* Seek the iterator to the first reference with the given prefix.
332+
* The prefix is matched as a literal string, without regard for path
333+
* separators. If prefix is NULL or the empty string, seek the iterator to the
334+
* first reference again.
335+
*
336+
* This function is expected to behave as if a new ref iterator with the same
337+
* prefix had been created, but allows reuse of iterators and thus may allow
338+
* the backend to optimize. Parameters other than the prefix that have been
339+
* passed when creating the iterator will remain unchanged.
340+
*
341+
* Returns 0 on success, a negative error code otherwise.
342+
*/
343+
int ref_iterator_seek(struct ref_iterator *ref_iterator,
344+
const char *prefix);
345+
330346
/*
331347
* If possible, peel the reference currently being viewed by the
332348
* iterator. Return 0 on success.
@@ -445,6 +461,13 @@ void base_ref_iterator_init(struct ref_iterator *iter,
445461
*/
446462
typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator);
447463

464+
/*
465+
* Seek the iterator to the first reference matching the given prefix. Should
466+
* behave the same as if a new iterator was created with the same prefix.
467+
*/
468+
typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
469+
const char *prefix);
470+
448471
/*
449472
* Peels the current ref, returning 0 for success or -1 for failure.
450473
*/
@@ -459,6 +482,7 @@ typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
459482

460483
struct ref_iterator_vtable {
461484
ref_iterator_advance_fn *advance;
485+
ref_iterator_seek_fn *seek;
462486
ref_iterator_peel_fn *peel;
463487
ref_iterator_release_fn *release;
464488
};

0 commit comments

Comments
 (0)