mirror of
https://github.com/git/git
synced 2024-11-04 16:17:49 +00:00
Merge branch 'ps/reftable-reusable-iterator'
Code clean-up to make the reftable iterator closer to be reusable. * ps/reftable-reusable-iterator: reftable/merged: adapt interface to allow reuse of iterators reftable/stack: provide convenience functions to create iterators reftable/reader: adapt interface to allow reuse of iterators reftable/generic: adapt interface to allow reuse of iterators reftable/generic: move seeking of records into the iterator reftable/merged: simplify indices for subiterators reftable/merged: split up initialization and seeking of records reftable/reader: set up the reader when initializing table iterator reftable/reader: inline `reader_seek_internal()` reftable/reader: separate concerns of table iter and reftable reader reftable/reader: unify indexed and linear seeking reftable/reader: avoid copying index iterator reftable/block: use `size_t` to track restart point index
This commit is contained in:
commit
67ce50ba26
16 changed files with 381 additions and 364 deletions
|
@ -16,7 +16,6 @@
|
|||
#include "../reftable/reftable-record.h"
|
||||
#include "../reftable/reftable-error.h"
|
||||
#include "../reftable/reftable-iterator.h"
|
||||
#include "../reftable/reftable-merged.h"
|
||||
#include "../setup.h"
|
||||
#include "../strmap.h"
|
||||
#include "parse.h"
|
||||
|
@ -502,7 +501,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
|
|||
const char *prefix,
|
||||
int flags)
|
||||
{
|
||||
struct reftable_merged_table *merged_table;
|
||||
struct reftable_ref_iterator *iter;
|
||||
int ret;
|
||||
|
||||
|
@ -522,9 +520,8 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
|
|||
if (ret)
|
||||
goto done;
|
||||
|
||||
merged_table = reftable_stack_merged_table(stack);
|
||||
|
||||
ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix);
|
||||
reftable_stack_init_ref_iterator(stack, &iter->iter);
|
||||
ret = reftable_iterator_seek_ref(&iter->iter, prefix);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
@ -1052,8 +1049,6 @@ static int transaction_update_cmp(const void *a, const void *b)
|
|||
static int write_transaction_table(struct reftable_writer *writer, void *cb_data)
|
||||
{
|
||||
struct write_transaction_table_arg *arg = cb_data;
|
||||
struct reftable_merged_table *mt =
|
||||
reftable_stack_merged_table(arg->stack);
|
||||
uint64_t ts = reftable_stack_next_update_index(arg->stack);
|
||||
struct reftable_log_record *logs = NULL;
|
||||
struct ident_split committer_ident = {0};
|
||||
|
@ -1090,6 +1085,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
|
|||
struct reftable_log_record log = {0};
|
||||
struct reftable_iterator it = {0};
|
||||
|
||||
reftable_stack_init_log_iterator(arg->stack, &it);
|
||||
|
||||
/*
|
||||
* When deleting refs we also delete all reflog entries
|
||||
* with them. While it is not strictly required to
|
||||
|
@ -1099,7 +1096,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
|
|||
* Unfortunately, we have no better way than to delete
|
||||
* all reflog entries one by one.
|
||||
*/
|
||||
ret = reftable_merged_table_seek_log(mt, &it, u->refname);
|
||||
ret = reftable_iterator_seek_log(&it, u->refname);
|
||||
while (ret == 0) {
|
||||
struct reftable_log_record *tombstone;
|
||||
|
||||
|
@ -1317,7 +1314,6 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
|
|||
{
|
||||
struct write_copy_arg *arg = cb_data;
|
||||
uint64_t deletion_ts, creation_ts;
|
||||
struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack);
|
||||
struct reftable_ref_record old_ref = {0}, refs[2] = {0};
|
||||
struct reftable_log_record old_log = {0}, *logs = NULL;
|
||||
struct reftable_iterator it = {0};
|
||||
|
@ -1451,7 +1447,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
|
|||
* copy over all log entries from the old reflog. Last but not least,
|
||||
* when renaming we also have to delete all the old reflog entries.
|
||||
*/
|
||||
ret = reftable_merged_table_seek_log(mt, &it, arg->oldname);
|
||||
reftable_stack_init_log_iterator(arg->stack, &it);
|
||||
ret = reftable_iterator_seek_log(&it, arg->oldname);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -1657,7 +1654,6 @@ static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
|
|||
static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
|
||||
struct reftable_stack *stack)
|
||||
{
|
||||
struct reftable_merged_table *merged_table;
|
||||
struct reftable_reflog_iterator *iter;
|
||||
int ret;
|
||||
|
||||
|
@ -1674,9 +1670,8 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
|
|||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
merged_table = reftable_stack_merged_table(stack);
|
||||
|
||||
ret = reftable_merged_table_seek_log(merged_table, &iter->iter, "");
|
||||
reftable_stack_init_log_iterator(stack, &iter->iter);
|
||||
ret = reftable_iterator_seek_log(&iter->iter, "");
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -1734,7 +1729,6 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
|
|||
struct reftable_ref_store *refs =
|
||||
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
|
||||
struct reftable_stack *stack = stack_for(refs, refname, &refname);
|
||||
struct reftable_merged_table *mt = NULL;
|
||||
struct reftable_log_record log = {0};
|
||||
struct reftable_iterator it = {0};
|
||||
int ret;
|
||||
|
@ -1742,8 +1736,8 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
|
|||
if (refs->err < 0)
|
||||
return refs->err;
|
||||
|
||||
mt = reftable_stack_merged_table(stack);
|
||||
ret = reftable_merged_table_seek_log(mt, &it, refname);
|
||||
reftable_stack_init_log_iterator(stack, &it);
|
||||
ret = reftable_iterator_seek_log(&it, refname);
|
||||
while (!ret) {
|
||||
ret = reftable_iterator_next_log(&it, &log);
|
||||
if (ret < 0)
|
||||
|
@ -1771,7 +1765,6 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
|
|||
struct reftable_ref_store *refs =
|
||||
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
|
||||
struct reftable_stack *stack = stack_for(refs, refname, &refname);
|
||||
struct reftable_merged_table *mt = NULL;
|
||||
struct reftable_log_record *logs = NULL;
|
||||
struct reftable_iterator it = {0};
|
||||
size_t logs_alloc = 0, logs_nr = 0, i;
|
||||
|
@ -1780,8 +1773,8 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
|
|||
if (refs->err < 0)
|
||||
return refs->err;
|
||||
|
||||
mt = reftable_stack_merged_table(stack);
|
||||
ret = reftable_merged_table_seek_log(mt, &it, refname);
|
||||
reftable_stack_init_log_iterator(stack, &it);
|
||||
ret = reftable_iterator_seek_log(&it, refname);
|
||||
while (!ret) {
|
||||
struct reftable_log_record log = {0};
|
||||
|
||||
|
@ -1818,7 +1811,6 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
|
|||
struct reftable_ref_store *refs =
|
||||
reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
|
||||
struct reftable_stack *stack = stack_for(refs, refname, &refname);
|
||||
struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
|
||||
struct reftable_log_record log = {0};
|
||||
struct reftable_iterator it = {0};
|
||||
int ret;
|
||||
|
@ -1831,7 +1823,8 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
|
|||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
ret = reftable_merged_table_seek_log(mt, &it, refname);
|
||||
reftable_stack_init_log_iterator(stack, &it);
|
||||
ret = reftable_iterator_seek_log(&it, refname);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -1929,8 +1922,6 @@ struct write_reflog_delete_arg {
|
|||
static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data)
|
||||
{
|
||||
struct write_reflog_delete_arg *arg = cb_data;
|
||||
struct reftable_merged_table *mt =
|
||||
reftable_stack_merged_table(arg->stack);
|
||||
struct reftable_log_record log = {0}, tombstone = {0};
|
||||
struct reftable_iterator it = {0};
|
||||
uint64_t ts = reftable_stack_next_update_index(arg->stack);
|
||||
|
@ -1938,12 +1929,14 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
|
|||
|
||||
reftable_writer_set_limits(writer, ts, ts);
|
||||
|
||||
reftable_stack_init_log_iterator(arg->stack, &it);
|
||||
|
||||
/*
|
||||
* In order to delete a table we need to delete all reflog entries one
|
||||
* by one. This is inefficient, but the reftable format does not have a
|
||||
* better marker right now.
|
||||
*/
|
||||
ret = reftable_merged_table_seek_log(mt, &it, arg->refname);
|
||||
ret = reftable_iterator_seek_log(&it, arg->refname);
|
||||
while (ret == 0) {
|
||||
ret = reftable_iterator_next_log(&it, &log);
|
||||
if (ret < 0)
|
||||
|
@ -2079,7 +2072,6 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
|
|||
struct reftable_ref_store *refs =
|
||||
reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
|
||||
struct reftable_stack *stack = stack_for(refs, refname, &refname);
|
||||
struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
|
||||
struct reftable_log_record *logs = NULL;
|
||||
struct reftable_log_record *rewritten = NULL;
|
||||
struct reftable_ref_record ref_record = {0};
|
||||
|
@ -2098,7 +2090,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
|
|||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
ret = reftable_merged_table_seek_log(mt, &it, refname);
|
||||
reftable_stack_init_log_iterator(stack, &it);
|
||||
|
||||
ret = reftable_iterator_seek_log(&it, refname);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -326,9 +326,9 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t block_reader_restart_offset(const struct block_reader *br, int i)
|
||||
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
|
||||
{
|
||||
return get_be24(br->restart_bytes + 3 * i);
|
||||
return get_be24(br->restart_bytes + 3 * idx);
|
||||
}
|
||||
|
||||
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
|
||||
|
|
|
@ -12,32 +12,66 @@ license that can be found in the LICENSE file or at
|
|||
#include "reftable-iterator.h"
|
||||
#include "reftable-generic.h"
|
||||
|
||||
int reftable_table_seek_ref(struct reftable_table *tab,
|
||||
struct reftable_iterator *it, const char *name)
|
||||
void table_init_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ)
|
||||
{
|
||||
struct reftable_record rec = { .type = BLOCK_TYPE_REF,
|
||||
.u.ref = {
|
||||
.refname = (char *)name,
|
||||
} };
|
||||
return tab->ops->seek_record(tab->table_arg, it, &rec);
|
||||
|
||||
tab->ops->init_iter(tab->table_arg, it, typ);
|
||||
}
|
||||
|
||||
int reftable_table_seek_log(struct reftable_table *tab,
|
||||
struct reftable_iterator *it, const char *name)
|
||||
void reftable_table_init_ref_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
|
||||
.u.log = {
|
||||
.refname = (char *)name,
|
||||
.update_index = ~((uint64_t)0),
|
||||
} };
|
||||
return tab->ops->seek_record(tab->table_arg, it, &rec);
|
||||
table_init_iter(tab, it, BLOCK_TYPE_REF);
|
||||
}
|
||||
|
||||
void reftable_table_init_log_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
table_init_iter(tab, it, BLOCK_TYPE_LOG);
|
||||
}
|
||||
|
||||
int reftable_iterator_seek_ref(struct reftable_iterator *it,
|
||||
const char *name)
|
||||
{
|
||||
struct reftable_record want = {
|
||||
.type = BLOCK_TYPE_REF,
|
||||
.u.ref = {
|
||||
.refname = (char *)name,
|
||||
},
|
||||
};
|
||||
return it->ops->seek(it->iter_arg, &want);
|
||||
}
|
||||
|
||||
int reftable_iterator_seek_log_at(struct reftable_iterator *it,
|
||||
const char *name, uint64_t update_index)
|
||||
{
|
||||
struct reftable_record want = {
|
||||
.type = BLOCK_TYPE_LOG,
|
||||
.u.log = {
|
||||
.refname = (char *)name,
|
||||
.update_index = update_index,
|
||||
},
|
||||
};
|
||||
return it->ops->seek(it->iter_arg, &want);
|
||||
}
|
||||
|
||||
int reftable_iterator_seek_log(struct reftable_iterator *it,
|
||||
const char *name)
|
||||
{
|
||||
return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0));
|
||||
}
|
||||
|
||||
int reftable_table_read_ref(struct reftable_table *tab, const char *name,
|
||||
struct reftable_ref_record *ref)
|
||||
{
|
||||
struct reftable_iterator it = { NULL };
|
||||
int err = reftable_table_seek_ref(tab, &it, name);
|
||||
int err;
|
||||
|
||||
reftable_table_init_ref_iter(tab, &it);
|
||||
|
||||
err = reftable_iterator_seek_ref(&it, name);
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
|
@ -62,10 +96,13 @@ int reftable_table_print(struct reftable_table *tab) {
|
|||
struct reftable_ref_record ref = { NULL };
|
||||
struct reftable_log_record log = { NULL };
|
||||
uint32_t hash_id = reftable_table_hash_id(tab);
|
||||
int err = reftable_table_seek_ref(tab, &it, "");
|
||||
if (err < 0) {
|
||||
int err;
|
||||
|
||||
reftable_table_init_ref_iter(tab, &it);
|
||||
|
||||
err = reftable_iterator_seek_ref(&it, "");
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
err = reftable_iterator_next_ref(&it, &ref);
|
||||
|
@ -80,10 +117,12 @@ int reftable_table_print(struct reftable_table *tab) {
|
|||
reftable_iterator_destroy(&it);
|
||||
reftable_ref_record_release(&ref);
|
||||
|
||||
err = reftable_table_seek_log(tab, &it, "");
|
||||
if (err < 0) {
|
||||
reftable_table_init_log_iter(tab, &it);
|
||||
|
||||
err = reftable_iterator_seek_log(&it, "");
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
err = reftable_iterator_next_log(&it, &log);
|
||||
if (err > 0) {
|
||||
|
@ -152,11 +191,21 @@ int reftable_iterator_next_log(struct reftable_iterator *it,
|
|||
return err;
|
||||
}
|
||||
|
||||
int iterator_seek(struct reftable_iterator *it, struct reftable_record *want)
|
||||
{
|
||||
return it->ops->seek(it->iter_arg, want);
|
||||
}
|
||||
|
||||
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
|
||||
{
|
||||
return it->ops->next(it->iter_arg, rec);
|
||||
}
|
||||
|
||||
static int empty_iterator_seek(void *arg, struct reftable_record *want)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int empty_iterator_next(void *arg, struct reftable_record *rec)
|
||||
{
|
||||
return 1;
|
||||
|
@ -167,6 +216,7 @@ static void empty_iterator_close(void *arg)
|
|||
}
|
||||
|
||||
static struct reftable_iterator_vtable empty_vtable = {
|
||||
.seek = &empty_iterator_seek,
|
||||
.next = &empty_iterator_next,
|
||||
.close = &empty_iterator_close,
|
||||
};
|
||||
|
|
|
@ -14,19 +14,24 @@ license that can be found in the LICENSE file or at
|
|||
|
||||
/* generic interface to reftables */
|
||||
struct reftable_table_vtable {
|
||||
int (*seek_record)(void *tab, struct reftable_iterator *it,
|
||||
struct reftable_record *);
|
||||
void (*init_iter)(void *tab, struct reftable_iterator *it, uint8_t typ);
|
||||
uint32_t (*hash_id)(void *tab);
|
||||
uint64_t (*min_update_index)(void *tab);
|
||||
uint64_t (*max_update_index)(void *tab);
|
||||
};
|
||||
|
||||
void table_init_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ);
|
||||
|
||||
struct reftable_iterator_vtable {
|
||||
int (*seek)(void *iter_arg, struct reftable_record *want);
|
||||
int (*next)(void *iter_arg, struct reftable_record *rec);
|
||||
void (*close)(void *iter_arg);
|
||||
};
|
||||
|
||||
void iterator_set_empty(struct reftable_iterator *it);
|
||||
int iterator_seek(struct reftable_iterator *it, struct reftable_record *want);
|
||||
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,13 @@ static void filtering_ref_iterator_close(void *iter_arg)
|
|||
reftable_iterator_destroy(&fri->it);
|
||||
}
|
||||
|
||||
static int filtering_ref_iterator_seek(void *iter_arg,
|
||||
struct reftable_record *want)
|
||||
{
|
||||
struct filtering_ref_iterator *fri = iter_arg;
|
||||
return iterator_seek(&fri->it, want);
|
||||
}
|
||||
|
||||
static int filtering_ref_iterator_next(void *iter_arg,
|
||||
struct reftable_record *rec)
|
||||
{
|
||||
|
@ -38,11 +45,11 @@ static int filtering_ref_iterator_next(void *iter_arg,
|
|||
if (fri->double_check) {
|
||||
struct reftable_iterator it = { NULL };
|
||||
|
||||
err = reftable_table_seek_ref(&fri->tab, &it,
|
||||
ref->refname);
|
||||
if (err == 0) {
|
||||
reftable_table_init_ref_iter(&fri->tab, &it);
|
||||
|
||||
err = reftable_iterator_seek_ref(&it, ref->refname);
|
||||
if (err == 0)
|
||||
err = reftable_iterator_next_ref(&it, ref);
|
||||
}
|
||||
|
||||
reftable_iterator_destroy(&it);
|
||||
|
||||
|
@ -73,6 +80,7 @@ static int filtering_ref_iterator_next(void *iter_arg,
|
|||
}
|
||||
|
||||
static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
|
||||
.seek = &filtering_ref_iterator_seek,
|
||||
.next = &filtering_ref_iterator_next,
|
||||
.close = &filtering_ref_iterator_close,
|
||||
};
|
||||
|
@ -119,6 +127,12 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int indexed_table_ref_iter_seek(void *p, struct reftable_record *want)
|
||||
{
|
||||
BUG("seeking indexed table is not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
|
||||
{
|
||||
struct indexed_table_ref_iter *it = p;
|
||||
|
@ -175,6 +189,7 @@ int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
|
|||
}
|
||||
|
||||
static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
|
||||
.seek = &indexed_table_ref_iter_seek,
|
||||
.next = &indexed_table_ref_iter_next,
|
||||
.close = &indexed_table_ref_iter_close,
|
||||
};
|
||||
|
|
|
@ -25,34 +25,25 @@ struct merged_subiter {
|
|||
struct merged_iter {
|
||||
struct merged_subiter *subiters;
|
||||
struct merged_iter_pqueue pq;
|
||||
uint32_t hash_id;
|
||||
size_t stack_len;
|
||||
uint8_t typ;
|
||||
int suppress_deletions;
|
||||
ssize_t advance_index;
|
||||
};
|
||||
|
||||
static int merged_iter_init(struct merged_iter *mi)
|
||||
static void merged_iter_init(struct merged_iter *mi,
|
||||
struct reftable_merged_table *mt,
|
||||
uint8_t typ)
|
||||
{
|
||||
for (size_t i = 0; i < mi->stack_len; i++) {
|
||||
struct pq_entry e = {
|
||||
.index = i,
|
||||
.rec = &mi->subiters[i].rec,
|
||||
};
|
||||
int err;
|
||||
memset(mi, 0, sizeof(*mi));
|
||||
mi->advance_index = -1;
|
||||
mi->suppress_deletions = mt->suppress_deletions;
|
||||
|
||||
reftable_record_init(&mi->subiters[i].rec, mi->typ);
|
||||
err = iterator_next(&mi->subiters[i].iter,
|
||||
&mi->subiters[i].rec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
continue;
|
||||
|
||||
merged_iter_pqueue_add(&mi->pq, &e);
|
||||
REFTABLE_CALLOC_ARRAY(mi->subiters, mt->stack_len);
|
||||
for (size_t i = 0; i < mt->stack_len; i++) {
|
||||
reftable_record_init(&mi->subiters[i].rec, typ);
|
||||
table_init_iter(&mt->stack[i], &mi->subiters[i].iter, typ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
mi->stack_len = mt->stack_len;
|
||||
}
|
||||
|
||||
static void merged_iter_close(void *p)
|
||||
|
@ -83,6 +74,27 @@ static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want)
|
||||
{
|
||||
int err;
|
||||
|
||||
mi->advance_index = -1;
|
||||
|
||||
for (size_t i = 0; i < mi->stack_len; i++) {
|
||||
err = iterator_seek(&mi->subiters[i].iter, want);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
continue;
|
||||
|
||||
err = merged_iter_advance_subiter(mi, i);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merged_iter_next_entry(struct merged_iter *mi,
|
||||
struct reftable_record *rec)
|
||||
{
|
||||
|
@ -148,6 +160,11 @@ static int merged_iter_next_entry(struct merged_iter *mi,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int merged_iter_seek_void(void *it, struct reftable_record *want)
|
||||
{
|
||||
return merged_iter_seek(it, want);
|
||||
}
|
||||
|
||||
static int merged_iter_next_void(void *p, struct reftable_record *rec)
|
||||
{
|
||||
struct merged_iter *mi = p;
|
||||
|
@ -162,6 +179,7 @@ static int merged_iter_next_void(void *p, struct reftable_record *rec)
|
|||
}
|
||||
|
||||
static struct reftable_iterator_vtable merged_iter_vtable = {
|
||||
.seek = merged_iter_seek_void,
|
||||
.next = &merged_iter_next_void,
|
||||
.close = &merged_iter_close,
|
||||
};
|
||||
|
@ -235,81 +253,13 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
|
|||
return mt->min;
|
||||
}
|
||||
|
||||
static int reftable_table_seek_record(struct reftable_table *tab,
|
||||
struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
void merged_table_init_iter(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ)
|
||||
{
|
||||
return tab->ops->seek_record(tab->table_arg, it, rec);
|
||||
}
|
||||
|
||||
static int merged_table_seek_record(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
{
|
||||
struct merged_iter merged = {
|
||||
.typ = reftable_record_type(rec),
|
||||
.hash_id = mt->hash_id,
|
||||
.suppress_deletions = mt->suppress_deletions,
|
||||
.advance_index = -1,
|
||||
};
|
||||
struct merged_iter *p;
|
||||
int err;
|
||||
|
||||
REFTABLE_CALLOC_ARRAY(merged.subiters, mt->stack_len);
|
||||
for (size_t i = 0; i < mt->stack_len; i++) {
|
||||
err = reftable_table_seek_record(&mt->stack[i],
|
||||
&merged.subiters[merged.stack_len].iter, rec);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
if (!err)
|
||||
merged.stack_len++;
|
||||
}
|
||||
|
||||
err = merged_iter_init(&merged);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
p = reftable_malloc(sizeof(struct merged_iter));
|
||||
*p = merged;
|
||||
iterator_from_merged_iter(it, p);
|
||||
|
||||
out:
|
||||
if (err < 0)
|
||||
merged_iter_close(&merged);
|
||||
return err;
|
||||
}
|
||||
|
||||
int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name)
|
||||
{
|
||||
struct reftable_record rec = {
|
||||
.type = BLOCK_TYPE_REF,
|
||||
.u.ref = {
|
||||
.refname = (char *)name,
|
||||
},
|
||||
};
|
||||
return merged_table_seek_record(mt, it, &rec);
|
||||
}
|
||||
|
||||
int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name, uint64_t update_index)
|
||||
{
|
||||
struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
|
||||
.u.log = {
|
||||
.refname = (char *)name,
|
||||
.update_index = update_index,
|
||||
} };
|
||||
return merged_table_seek_record(mt, it, &rec);
|
||||
}
|
||||
|
||||
int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name)
|
||||
{
|
||||
uint64_t max = ~((uint64_t)0);
|
||||
return reftable_merged_table_seek_log_at(mt, it, name, max);
|
||||
struct merged_iter *mi = reftable_malloc(sizeof(*mi));
|
||||
merged_iter_init(mi, mt, typ);
|
||||
iterator_from_merged_iter(it, mi);
|
||||
}
|
||||
|
||||
uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
|
||||
|
@ -317,11 +267,11 @@ uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
|
|||
return mt->hash_id;
|
||||
}
|
||||
|
||||
static int reftable_merged_table_seek_void(void *tab,
|
||||
struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
static void reftable_merged_table_init_iter_void(void *tab,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ)
|
||||
{
|
||||
return merged_table_seek_record(tab, it, rec);
|
||||
merged_table_init_iter(tab, it, typ);
|
||||
}
|
||||
|
||||
static uint32_t reftable_merged_table_hash_id_void(void *tab)
|
||||
|
@ -340,7 +290,7 @@ static uint64_t reftable_merged_table_max_update_index_void(void *tab)
|
|||
}
|
||||
|
||||
static struct reftable_table_vtable merged_table_vtable = {
|
||||
.seek_record = reftable_merged_table_seek_void,
|
||||
.init_iter = reftable_merged_table_init_iter_void,
|
||||
.hash_id = reftable_merged_table_hash_id_void,
|
||||
.min_update_index = reftable_merged_table_min_update_index_void,
|
||||
.max_update_index = reftable_merged_table_max_update_index_void,
|
||||
|
|
|
@ -26,4 +26,10 @@ struct reftable_merged_table {
|
|||
|
||||
void merged_table_release(struct reftable_merged_table *mt);
|
||||
|
||||
struct reftable_iterator;
|
||||
|
||||
void merged_table_init_iter(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@ license that can be found in the LICENSE file or at
|
|||
|
||||
#include "basics.h"
|
||||
#include "blocksource.h"
|
||||
#include "constants.h"
|
||||
#include "reader.h"
|
||||
#include "record.h"
|
||||
#include "test_framework.h"
|
||||
|
@ -145,7 +146,10 @@ static void test_merged_between(void)
|
|||
int i;
|
||||
struct reftable_ref_record ref = { NULL };
|
||||
struct reftable_iterator it = { NULL };
|
||||
int err = reftable_merged_table_seek_ref(mt, &it, "a");
|
||||
int err;
|
||||
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
|
||||
err = reftable_iterator_seek_ref(&it, "a");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_iterator_next_ref(&it, &ref);
|
||||
|
@ -217,14 +221,15 @@ static void test_merged(void)
|
|||
struct reftable_reader **readers = NULL;
|
||||
struct reftable_merged_table *mt =
|
||||
merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3);
|
||||
|
||||
struct reftable_iterator it = { NULL };
|
||||
int err = reftable_merged_table_seek_ref(mt, &it, "a");
|
||||
int err;
|
||||
struct reftable_ref_record *out = NULL;
|
||||
size_t len = 0;
|
||||
size_t cap = 0;
|
||||
int i = 0;
|
||||
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
|
||||
err = reftable_iterator_seek_ref(&it, "a");
|
||||
EXPECT_ERR(err);
|
||||
EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID);
|
||||
EXPECT(reftable_merged_table_min_update_index(mt) == 1);
|
||||
|
@ -348,14 +353,15 @@ static void test_merged_logs(void)
|
|||
struct reftable_reader **readers = NULL;
|
||||
struct reftable_merged_table *mt = merged_table_from_log_records(
|
||||
logs, &bs, &readers, sizes, bufs, 3);
|
||||
|
||||
struct reftable_iterator it = { NULL };
|
||||
int err = reftable_merged_table_seek_log(mt, &it, "a");
|
||||
int err;
|
||||
struct reftable_log_record *out = NULL;
|
||||
size_t len = 0;
|
||||
size_t cap = 0;
|
||||
int i = 0;
|
||||
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
|
||||
err = reftable_iterator_seek_log(&it, "a");
|
||||
EXPECT_ERR(err);
|
||||
EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID);
|
||||
EXPECT(reftable_merged_table_min_update_index(mt) == 1);
|
||||
|
@ -377,7 +383,8 @@ static void test_merged_logs(void)
|
|||
GIT_SHA1_RAWSZ));
|
||||
}
|
||||
|
||||
err = reftable_merged_table_seek_log_at(mt, &it, "a", 2);
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
|
||||
err = reftable_iterator_seek_log_at(&it, "a", 2);
|
||||
EXPECT_ERR(err);
|
||||
reftable_log_record_release(&out[0]);
|
||||
err = reftable_iterator_next_log(&it, &out[0]);
|
||||
|
|
|
@ -224,8 +224,14 @@ struct table_iter {
|
|||
struct block_iter bi;
|
||||
int is_finished;
|
||||
};
|
||||
#define TABLE_ITER_INIT { \
|
||||
.bi = BLOCK_ITER_INIT \
|
||||
|
||||
static int table_iter_init(struct table_iter *ti, struct reftable_reader *r)
|
||||
{
|
||||
struct block_iter bi = BLOCK_ITER_INIT;
|
||||
memset(ti, 0, sizeof(*ti));
|
||||
ti->r = r;
|
||||
ti->bi = bi;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int table_iter_next_in_block(struct table_iter *ti,
|
||||
|
@ -363,50 +369,23 @@ static int table_iter_next(struct table_iter *ti, struct reftable_record *rec)
|
|||
}
|
||||
}
|
||||
|
||||
static int table_iter_next_void(void *ti, struct reftable_record *rec)
|
||||
{
|
||||
return table_iter_next(ti, rec);
|
||||
}
|
||||
|
||||
static void table_iter_close_void(void *ti)
|
||||
{
|
||||
table_iter_close(ti);
|
||||
}
|
||||
|
||||
static struct reftable_iterator_vtable table_iter_vtable = {
|
||||
.next = &table_iter_next_void,
|
||||
.close = &table_iter_close_void,
|
||||
};
|
||||
|
||||
static void iterator_from_table_iter(struct reftable_iterator *it,
|
||||
struct table_iter *ti)
|
||||
{
|
||||
assert(!it->ops);
|
||||
it->iter_arg = ti;
|
||||
it->ops = &table_iter_vtable;
|
||||
}
|
||||
|
||||
static int reader_table_iter_at(struct reftable_reader *r,
|
||||
struct table_iter *ti, uint64_t off,
|
||||
uint8_t typ)
|
||||
static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = reader_init_block_reader(r, &ti->br, off, typ);
|
||||
err = reader_init_block_reader(ti->r, &ti->br, off, typ);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
ti->r = r;
|
||||
ti->typ = block_reader_type(&ti->br);
|
||||
ti->block_off = off;
|
||||
block_iter_seek_start(&ti->bi, &ti->br);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reader_start(struct reftable_reader *r, struct table_iter *ti,
|
||||
uint8_t typ, int index)
|
||||
static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index)
|
||||
{
|
||||
struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
|
||||
struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ);
|
||||
uint64_t off = offs->offset;
|
||||
if (index) {
|
||||
off = offs->index_offset;
|
||||
|
@ -416,16 +395,16 @@ static int reader_start(struct reftable_reader *r, struct table_iter *ti,
|
|||
typ = BLOCK_TYPE_INDEX;
|
||||
}
|
||||
|
||||
return reader_table_iter_at(r, ti, off, typ);
|
||||
return table_iter_seek_to(ti, off, typ);
|
||||
}
|
||||
|
||||
static int reader_seek_linear(struct table_iter *ti,
|
||||
struct reftable_record *want)
|
||||
static int table_iter_seek_linear(struct table_iter *ti,
|
||||
struct reftable_record *want)
|
||||
{
|
||||
struct strbuf want_key = STRBUF_INIT;
|
||||
struct strbuf got_key = STRBUF_INIT;
|
||||
struct reftable_record rec;
|
||||
int err = -1;
|
||||
int err;
|
||||
|
||||
reftable_record_init(&rec, reftable_record_type(want));
|
||||
reftable_record_key(want, &want_key);
|
||||
|
@ -499,9 +478,8 @@ static int reader_seek_linear(struct table_iter *ti,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int reader_seek_indexed(struct reftable_reader *r,
|
||||
struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
static int table_iter_seek_indexed(struct table_iter *ti,
|
||||
struct reftable_record *rec)
|
||||
{
|
||||
struct reftable_record want_index = {
|
||||
.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT }
|
||||
|
@ -510,15 +488,9 @@ static int reader_seek_indexed(struct reftable_reader *r,
|
|||
.type = BLOCK_TYPE_INDEX,
|
||||
.u.idx = { .last_key = STRBUF_INIT },
|
||||
};
|
||||
struct table_iter index_iter = TABLE_ITER_INIT;
|
||||
struct table_iter empty = TABLE_ITER_INIT;
|
||||
struct table_iter next = TABLE_ITER_INIT;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
reftable_record_key(rec, &want_index.u.idx.last_key);
|
||||
err = reader_start(r, &index_iter, reftable_record_type(rec), 1);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* The index may consist of multiple levels, where each level may have
|
||||
|
@ -526,7 +498,7 @@ static int reader_seek_indexed(struct reftable_reader *r,
|
|||
* highest layer that identifies the relevant index block as well as
|
||||
* the record inside that block that corresponds to our wanted key.
|
||||
*/
|
||||
err = reader_seek_linear(&index_iter, &want_index);
|
||||
err = table_iter_seek_linear(ti, &want_index);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -552,123 +524,113 @@ static int reader_seek_indexed(struct reftable_reader *r,
|
|||
* all levels of the index only to find out that the key does
|
||||
* not exist.
|
||||
*/
|
||||
err = table_iter_next(&index_iter, &index_result);
|
||||
err = table_iter_next(ti, &index_result);
|
||||
if (err != 0)
|
||||
goto done;
|
||||
|
||||
err = reader_table_iter_at(r, &next, index_result.u.idx.offset,
|
||||
0);
|
||||
err = table_iter_seek_to(ti, index_result.u.idx.offset, 0);
|
||||
if (err != 0)
|
||||
goto done;
|
||||
|
||||
err = block_iter_seek_key(&next.bi, &next.br, &want_index.u.idx.last_key);
|
||||
err = block_iter_seek_key(&ti->bi, &ti->br, &want_index.u.idx.last_key);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
if (next.typ == reftable_record_type(rec)) {
|
||||
if (ti->typ == reftable_record_type(rec)) {
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (next.typ != BLOCK_TYPE_INDEX) {
|
||||
if (ti->typ != BLOCK_TYPE_INDEX) {
|
||||
err = REFTABLE_FORMAT_ERROR;
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
|
||||
table_iter_close(&index_iter);
|
||||
index_iter = next;
|
||||
next = empty;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
struct table_iter *malloced = reftable_calloc(1, sizeof(*malloced));
|
||||
*malloced = next;
|
||||
next = empty;
|
||||
iterator_from_table_iter(it, malloced);
|
||||
}
|
||||
|
||||
done:
|
||||
table_iter_close(&next);
|
||||
table_iter_close(&index_iter);
|
||||
reftable_record_release(&want_index);
|
||||
reftable_record_release(&index_result);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int reader_seek_internal(struct reftable_reader *r,
|
||||
struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
static int table_iter_seek(struct table_iter *ti,
|
||||
struct reftable_record *want)
|
||||
{
|
||||
struct reftable_reader_offsets *offs =
|
||||
reader_offsets_for(r, reftable_record_type(rec));
|
||||
uint64_t idx = offs->index_offset;
|
||||
struct table_iter ti = TABLE_ITER_INIT, *p;
|
||||
uint8_t typ = reftable_record_type(want);
|
||||
struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ);
|
||||
int err;
|
||||
|
||||
if (idx > 0)
|
||||
return reader_seek_indexed(r, it, rec);
|
||||
|
||||
err = reader_start(r, &ti, reftable_record_type(rec), 0);
|
||||
err = table_iter_seek_start(ti, reftable_record_type(want),
|
||||
!!offs->index_offset);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = reader_seek_linear(&ti, rec);
|
||||
if (err < 0)
|
||||
if (offs->index_offset)
|
||||
err = table_iter_seek_indexed(ti, want);
|
||||
else
|
||||
err = table_iter_seek_linear(ti, want);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
REFTABLE_ALLOC_ARRAY(p, 1);
|
||||
*p = ti;
|
||||
iterator_from_table_iter(it, p);
|
||||
|
||||
out:
|
||||
if (err)
|
||||
table_iter_close(&ti);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int reader_seek(struct reftable_reader *r, struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
static int table_iter_seek_void(void *ti, struct reftable_record *want)
|
||||
{
|
||||
uint8_t typ = reftable_record_type(rec);
|
||||
return table_iter_seek(ti, want);
|
||||
}
|
||||
|
||||
static int table_iter_next_void(void *ti, struct reftable_record *rec)
|
||||
{
|
||||
return table_iter_next(ti, rec);
|
||||
}
|
||||
|
||||
static void table_iter_close_void(void *ti)
|
||||
{
|
||||
table_iter_close(ti);
|
||||
}
|
||||
|
||||
static struct reftable_iterator_vtable table_iter_vtable = {
|
||||
.seek = &table_iter_seek_void,
|
||||
.next = &table_iter_next_void,
|
||||
.close = &table_iter_close_void,
|
||||
};
|
||||
|
||||
static void iterator_from_table_iter(struct reftable_iterator *it,
|
||||
struct table_iter *ti)
|
||||
{
|
||||
assert(!it->ops);
|
||||
it->iter_arg = ti;
|
||||
it->ops = &table_iter_vtable;
|
||||
}
|
||||
|
||||
static void reader_init_iter(struct reftable_reader *r,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ)
|
||||
{
|
||||
struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
|
||||
if (!offs->is_present) {
|
||||
|
||||
if (offs->is_present) {
|
||||
struct table_iter *ti;
|
||||
REFTABLE_ALLOC_ARRAY(ti, 1);
|
||||
table_iter_init(ti, r);
|
||||
iterator_from_table_iter(it, ti);
|
||||
} else {
|
||||
iterator_set_empty(it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reader_seek_internal(r, it, rec);
|
||||
}
|
||||
|
||||
int reftable_reader_seek_ref(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name)
|
||||
void reftable_reader_init_ref_iterator(struct reftable_reader *r,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
struct reftable_record rec = {
|
||||
.type = BLOCK_TYPE_REF,
|
||||
.u.ref = {
|
||||
.refname = (char *)name,
|
||||
},
|
||||
};
|
||||
return reader_seek(r, it, &rec);
|
||||
reader_init_iter(r, it, BLOCK_TYPE_REF);
|
||||
}
|
||||
|
||||
int reftable_reader_seek_log_at(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name,
|
||||
uint64_t update_index)
|
||||
void reftable_reader_init_log_iterator(struct reftable_reader *r,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
|
||||
.u.log = {
|
||||
.refname = (char *)name,
|
||||
.update_index = update_index,
|
||||
} };
|
||||
return reader_seek(r, it, &rec);
|
||||
}
|
||||
|
||||
int reftable_reader_seek_log(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name)
|
||||
{
|
||||
uint64_t max = ~((uint64_t)0);
|
||||
return reftable_reader_seek_log_at(r, it, name, max);
|
||||
reader_init_iter(r, it, BLOCK_TYPE_LOG);
|
||||
}
|
||||
|
||||
void reader_close(struct reftable_reader *r)
|
||||
|
@ -719,7 +681,8 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r,
|
|||
struct indexed_table_ref_iter *itr = NULL;
|
||||
|
||||
/* Look through the reverse index. */
|
||||
err = reader_seek(r, &oit, &want);
|
||||
reader_init_iter(r, &oit, BLOCK_TYPE_OBJ);
|
||||
err = iterator_seek(&oit, &want);
|
||||
if (err != 0)
|
||||
goto done;
|
||||
|
||||
|
@ -754,15 +717,15 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,
|
|||
struct reftable_iterator *it,
|
||||
uint8_t *oid)
|
||||
{
|
||||
struct table_iter ti_empty = TABLE_ITER_INIT;
|
||||
struct table_iter *ti = reftable_calloc(1, sizeof(*ti));
|
||||
struct table_iter *ti;
|
||||
struct filtering_ref_iterator *filter = NULL;
|
||||
struct filtering_ref_iterator empty = FILTERING_REF_ITERATOR_INIT;
|
||||
int oid_len = hash_size(r->hash_id);
|
||||
int err;
|
||||
|
||||
*ti = ti_empty;
|
||||
err = reader_start(r, ti, BLOCK_TYPE_REF, 0);
|
||||
REFTABLE_ALLOC_ARRAY(ti, 1);
|
||||
table_iter_init(ti, r);
|
||||
err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0);
|
||||
if (err < 0) {
|
||||
reftable_free(ti);
|
||||
return err;
|
||||
|
@ -800,10 +763,11 @@ uint64_t reftable_reader_min_update_index(struct reftable_reader *r)
|
|||
|
||||
/* generic table interface. */
|
||||
|
||||
static int reftable_reader_seek_void(void *tab, struct reftable_iterator *it,
|
||||
struct reftable_record *rec)
|
||||
static void reftable_reader_init_iter_void(void *tab,
|
||||
struct reftable_iterator *it,
|
||||
uint8_t typ)
|
||||
{
|
||||
return reader_seek(tab, it, rec);
|
||||
reader_init_iter(tab, it, typ);
|
||||
}
|
||||
|
||||
static uint32_t reftable_reader_hash_id_void(void *tab)
|
||||
|
@ -822,7 +786,7 @@ static uint64_t reftable_reader_max_update_index_void(void *tab)
|
|||
}
|
||||
|
||||
static struct reftable_table_vtable reader_vtable = {
|
||||
.seek_record = reftable_reader_seek_void,
|
||||
.init_iter = reftable_reader_init_iter_void,
|
||||
.hash_id = reftable_reader_hash_id_void,
|
||||
.min_update_index = reftable_reader_min_update_index_void,
|
||||
.max_update_index = reftable_reader_max_update_index_void,
|
||||
|
@ -877,8 +841,8 @@ int reftable_reader_print_blocks(const char *tablename)
|
|||
},
|
||||
};
|
||||
struct reftable_block_source src = { 0 };
|
||||
struct table_iter ti = TABLE_ITER_INIT;
|
||||
struct reftable_reader *r = NULL;
|
||||
struct table_iter ti = { 0 };
|
||||
size_t i;
|
||||
int err;
|
||||
|
||||
|
@ -890,11 +854,13 @@ int reftable_reader_print_blocks(const char *tablename)
|
|||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
table_iter_init(&ti, r);
|
||||
|
||||
printf("header:\n");
|
||||
printf(" block_size: %d\n", r->block_size);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sections); i++) {
|
||||
err = reader_start(r, &ti, sections[i].type, 0);
|
||||
err = table_iter_seek_start(&ti, sections[i].type, 0);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
if (err > 0)
|
||||
|
|
|
@ -239,7 +239,9 @@ static void test_log_write_read(void)
|
|||
err = init_reader(&rd, &source, "file.log");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_reader_seek_ref(&rd, &it, names[N - 1]);
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
|
||||
err = reftable_iterator_seek_ref(&it, names[N - 1]);
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_iterator_next_ref(&it, &ref);
|
||||
|
@ -252,7 +254,9 @@ static void test_log_write_read(void)
|
|||
reftable_iterator_destroy(&it);
|
||||
reftable_ref_record_release(&ref);
|
||||
|
||||
err = reftable_reader_seek_log(&rd, &it, "");
|
||||
reftable_reader_init_log_iterator(&rd, &it);
|
||||
|
||||
err = reftable_iterator_seek_log(&it, "");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
i = 0;
|
||||
|
@ -330,7 +334,8 @@ static void test_log_zlib_corruption(void)
|
|||
err = init_reader(&rd, &source, "file.log");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_reader_seek_log(&rd, &it, "refname");
|
||||
reftable_reader_init_log_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_log(&it, "refname");
|
||||
EXPECT(err == REFTABLE_ZLIB_ERROR);
|
||||
|
||||
reftable_iterator_destroy(&it);
|
||||
|
@ -358,7 +363,8 @@ static void test_table_read_write_sequential(void)
|
|||
err = init_reader(&rd, &source, "file.ref");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_reader_seek_ref(&rd, &it, "");
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, "");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
while (1) {
|
||||
|
@ -412,7 +418,8 @@ static void test_table_read_api(void)
|
|||
err = init_reader(&rd, &source, "file.ref");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_reader_seek_ref(&rd, &it, names[0]);
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, names[0]);
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_iterator_next_log(&it, &log);
|
||||
|
@ -457,7 +464,8 @@ static void test_table_read_write_seek(int index, int hash_id)
|
|||
}
|
||||
|
||||
for (i = 1; i < N; i++) {
|
||||
int err = reftable_reader_seek_ref(&rd, &it, names[i]);
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, names[i]);
|
||||
EXPECT_ERR(err);
|
||||
err = reftable_iterator_next_ref(&it, &ref);
|
||||
EXPECT_ERR(err);
|
||||
|
@ -472,7 +480,8 @@ static void test_table_read_write_seek(int index, int hash_id)
|
|||
strbuf_addstr(&pastLast, names[N - 1]);
|
||||
strbuf_addstr(&pastLast, "/");
|
||||
|
||||
err = reftable_reader_seek_ref(&rd, &it, pastLast.buf);
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, pastLast.buf);
|
||||
if (err == 0) {
|
||||
struct reftable_ref_record ref = { NULL };
|
||||
int err = reftable_iterator_next_ref(&it, &ref);
|
||||
|
@ -576,7 +585,8 @@ static void test_table_refs_for(int indexed)
|
|||
rd.obj_offsets.is_present = 0;
|
||||
}
|
||||
|
||||
err = reftable_reader_seek_ref(&rd, &it, "");
|
||||
reftable_reader_init_ref_iterator(&rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, "");
|
||||
EXPECT_ERR(err);
|
||||
reftable_iterator_destroy(&it);
|
||||
|
||||
|
@ -639,7 +649,8 @@ static void test_write_empty_table(void)
|
|||
err = reftable_new_reader(&rd, &source, "filename");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_reader_seek_ref(rd, &it, "");
|
||||
reftable_reader_init_ref_iterator(rd, &it);
|
||||
err = reftable_iterator_seek_ref(&it, "");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
err = reftable_iterator_next_ref(&it, &rec);
|
||||
|
@ -846,7 +857,8 @@ static void test_write_multiple_indices(void)
|
|||
* Seeking the log uses the log index now. In case there is any
|
||||
* confusion regarding indices we would notice here.
|
||||
*/
|
||||
err = reftable_reader_seek_log(reader, &it, "");
|
||||
reftable_reader_init_log_iterator(reader, &it);
|
||||
err = reftable_iterator_seek_log(&it, "");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
reftable_iterator_destroy(&it);
|
||||
|
@ -901,7 +913,8 @@ static void test_write_multi_level_index(void)
|
|||
/*
|
||||
* Seeking the last ref should work as expected.
|
||||
*/
|
||||
err = reftable_reader_seek_ref(reader, &it, "refs/heads/199");
|
||||
reftable_reader_init_ref_iterator(reader, &it);
|
||||
err = reftable_iterator_seek_ref(&it, "refs/heads/199");
|
||||
EXPECT_ERR(err);
|
||||
|
||||
reftable_iterator_destroy(&it);
|
||||
|
|
|
@ -21,11 +21,11 @@ struct reftable_table {
|
|||
void *table_arg;
|
||||
};
|
||||
|
||||
int reftable_table_seek_log(struct reftable_table *tab,
|
||||
struct reftable_iterator *it, const char *name);
|
||||
void reftable_table_init_ref_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
int reftable_table_seek_ref(struct reftable_table *tab,
|
||||
struct reftable_iterator *it, const char *name);
|
||||
void reftable_table_init_log_iter(struct reftable_table *tab,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
/* returns the hash ID from a generic reftable_table */
|
||||
uint32_t reftable_table_hash_id(struct reftable_table *tab);
|
||||
|
|
|
@ -21,12 +21,33 @@ struct reftable_iterator {
|
|||
void *iter_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Position the iterator at the ref record with given name such that the next
|
||||
* call to `next_ref()` would yield the record.
|
||||
*/
|
||||
int reftable_iterator_seek_ref(struct reftable_iterator *it,
|
||||
const char *name);
|
||||
|
||||
/* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0:
|
||||
* end of iteration.
|
||||
*/
|
||||
int reftable_iterator_next_ref(struct reftable_iterator *it,
|
||||
struct reftable_ref_record *ref);
|
||||
|
||||
/*
|
||||
* Position the iterator at the log record with given name and update index
|
||||
* such that the next call to `next_log()` would yield the record.
|
||||
*/
|
||||
int reftable_iterator_seek_log_at(struct reftable_iterator *it,
|
||||
const char *name, uint64_t update_index);
|
||||
|
||||
/*
|
||||
* Position the iterator at the newest log record with given name such that the
|
||||
* next call to `next_log()` would yield the record.
|
||||
*/
|
||||
int reftable_iterator_seek_log(struct reftable_iterator *it,
|
||||
const char *name);
|
||||
|
||||
/* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0:
|
||||
* end of iteration.
|
||||
*/
|
||||
|
|
|
@ -36,21 +36,6 @@ int reftable_new_merged_table(struct reftable_merged_table **dest,
|
|||
struct reftable_table *stack, size_t n,
|
||||
uint32_t hash_id);
|
||||
|
||||
/* returns an iterator positioned just before 'name' */
|
||||
int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name);
|
||||
|
||||
/* returns an iterator for log entry, at given update_index */
|
||||
int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name, uint64_t update_index);
|
||||
|
||||
/* like reftable_merged_table_seek_log_at but look for the newest entry. */
|
||||
int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
|
||||
struct reftable_iterator *it,
|
||||
const char *name);
|
||||
|
||||
/* returns the max update_index covered by this merged table. */
|
||||
uint64_t
|
||||
reftable_merged_table_max_update_index(struct reftable_merged_table *mt);
|
||||
|
|
|
@ -36,48 +36,17 @@ struct reftable_table;
|
|||
int reftable_new_reader(struct reftable_reader **pp,
|
||||
struct reftable_block_source *src, const char *name);
|
||||
|
||||
/* reftable_reader_seek_ref returns an iterator where 'name' would be inserted
|
||||
in the table. To seek to the start of the table, use name = "".
|
||||
/* Initialize a reftable iterator for reading refs. */
|
||||
void reftable_reader_init_ref_iterator(struct reftable_reader *r,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
example:
|
||||
|
||||
struct reftable_reader *r = NULL;
|
||||
int err = reftable_new_reader(&r, &src, "filename");
|
||||
if (err < 0) { ... }
|
||||
struct reftable_iterator it = {0};
|
||||
err = reftable_reader_seek_ref(r, &it, "refs/heads/master");
|
||||
if (err < 0) { ... }
|
||||
struct reftable_ref_record ref = {0};
|
||||
while (1) {
|
||||
err = reftable_iterator_next_ref(&it, &ref);
|
||||
if (err > 0) {
|
||||
break;
|
||||
}
|
||||
if (err < 0) {
|
||||
..error handling..
|
||||
}
|
||||
..found..
|
||||
}
|
||||
reftable_iterator_destroy(&it);
|
||||
reftable_ref_record_release(&ref);
|
||||
*/
|
||||
int reftable_reader_seek_ref(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name);
|
||||
/* Initialize a reftable iterator for reading logs. */
|
||||
void reftable_reader_init_log_iterator(struct reftable_reader *r,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
/* returns the hash ID used in this table. */
|
||||
uint32_t reftable_reader_hash_id(struct reftable_reader *r);
|
||||
|
||||
/* seek to logs for the given name, older than update_index. To seek to the
|
||||
start of the table, use name = "".
|
||||
*/
|
||||
int reftable_reader_seek_log_at(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name,
|
||||
uint64_t update_index);
|
||||
|
||||
/* seek to newest log entry for given name. */
|
||||
int reftable_reader_seek_log(struct reftable_reader *r,
|
||||
struct reftable_iterator *it, const char *name);
|
||||
|
||||
/* closes and deallocates a reader. */
|
||||
void reftable_reader_free(struct reftable_reader *);
|
||||
|
||||
|
|
|
@ -66,6 +66,24 @@ int reftable_stack_add(struct reftable_stack *st,
|
|||
void *write_arg),
|
||||
void *write_arg);
|
||||
|
||||
struct reftable_iterator;
|
||||
|
||||
/*
|
||||
* Initialize an iterator for the merged tables contained in the stack that can
|
||||
* be used to iterate through refs. The iterator is valid until the next reload
|
||||
* or write.
|
||||
*/
|
||||
void reftable_stack_init_ref_iterator(struct reftable_stack *st,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
/*
|
||||
* Initialize an iterator for the merged tables contained in the stack that can
|
||||
* be used to iterate through logs. The iterator is valid until the next reload
|
||||
* or write.
|
||||
*/
|
||||
void reftable_stack_init_log_iterator(struct reftable_stack *st,
|
||||
struct reftable_iterator *it);
|
||||
|
||||
/* returns the merged_table for seeking. This table is valid until the
|
||||
* next write or reload, and should not be closed or deleted.
|
||||
*/
|
||||
|
|
|
@ -133,6 +133,20 @@ int read_lines(const char *filename, char ***namesp)
|
|||
return err;
|
||||
}
|
||||
|
||||
void reftable_stack_init_ref_iterator(struct reftable_stack *st,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
merged_table_init_iter(reftable_stack_merged_table(st),
|
||||
it, BLOCK_TYPE_REF);
|
||||
}
|
||||
|
||||
void reftable_stack_init_log_iterator(struct reftable_stack *st,
|
||||
struct reftable_iterator *it)
|
||||
{
|
||||
merged_table_init_iter(reftable_stack_merged_table(st),
|
||||
it, BLOCK_TYPE_LOG);
|
||||
}
|
||||
|
||||
struct reftable_merged_table *
|
||||
reftable_stack_merged_table(struct reftable_stack *st)
|
||||
{
|
||||
|
@ -913,7 +927,8 @@ static int stack_write_compact(struct reftable_stack *st,
|
|||
goto done;
|
||||
}
|
||||
|
||||
err = reftable_merged_table_seek_ref(mt, &it, "");
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
|
||||
err = reftable_iterator_seek_ref(&it, "");
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -937,7 +952,8 @@ static int stack_write_compact(struct reftable_stack *st,
|
|||
}
|
||||
reftable_iterator_destroy(&it);
|
||||
|
||||
err = reftable_merged_table_seek_log(mt, &it, "");
|
||||
merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
|
||||
err = reftable_iterator_seek_log(&it, "");
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -1333,9 +1349,11 @@ int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
|
|||
int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
|
||||
struct reftable_log_record *log)
|
||||
{
|
||||
struct reftable_iterator it = { NULL };
|
||||
struct reftable_merged_table *mt = reftable_stack_merged_table(st);
|
||||
int err = reftable_merged_table_seek_log(mt, &it, refname);
|
||||
struct reftable_iterator it = {0};
|
||||
int err;
|
||||
|
||||
reftable_stack_init_log_iterator(st, &it);
|
||||
err = reftable_iterator_seek_log(&it, refname);
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
|
|
Loading…
Reference in a new issue