diff options
-rw-r--r-- | reftable/block.c | 2 | ||||
-rw-r--r-- | reftable/reader.c | 47 |
2 files changed, 28 insertions, 21 deletions
diff --git a/reftable/block.c b/reftable/block.c index 2d8d0668b3..0c4e71eae3 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -188,6 +188,8 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, uint8_t *restart_bytes = NULL; uint8_t *uncompressed = NULL; + reftable_block_done(&br->block); + if (!reftable_is_block_type(typ)) { err = REFTABLE_FORMAT_ERROR; goto done; diff --git a/reftable/reader.c b/reftable/reader.c index b77b639751..dd4de294a1 100644 --- a/reftable/reader.c +++ b/reftable/reader.c @@ -312,26 +312,20 @@ static void table_iter_close(struct table_iter *ti) block_iter_close(&ti->bi); } -static int table_iter_next_block(struct table_iter *dest, - struct table_iter *src) +static int table_iter_next_block(struct table_iter *ti) { - uint64_t next_block_off = src->block_off + src->br.full_block_size; + uint64_t next_block_off = ti->block_off + ti->br.full_block_size; int err; - dest->r = src->r; - dest->typ = src->typ; - dest->block_off = next_block_off; - - err = reader_init_block_reader(src->r, &dest->br, next_block_off, src->typ); + err = reader_init_block_reader(ti->r, &ti->br, next_block_off, ti->typ); if (err > 0) - dest->is_finished = 1; - if (err) { - table_iter_block_done(dest); + ti->is_finished = 1; + if (err) return err; - } - dest->is_finished = 0; - block_iter_seek_start(&dest->bi, &dest->br); + ti->block_off = next_block_off; + ti->is_finished = 0; + block_iter_seek_start(&ti->bi, &ti->br); return 0; } @@ -342,7 +336,6 @@ static int table_iter_next(struct table_iter *ti, struct reftable_record *rec) return REFTABLE_API_ERROR; while (1) { - struct table_iter next = TABLE_ITER_INIT; int err; if (ti->is_finished) @@ -362,14 +355,11 @@ static int table_iter_next(struct table_iter *ti, struct reftable_record *rec) * table and retry. If there are no more blocks then the * iterator is drained. */ - err = table_iter_next_block(&next, ti); + err = table_iter_next_block(ti); if (err) { ti->is_finished = 1; return err; } - - table_iter_close(ti); - *ti = next; } } @@ -453,9 +443,24 @@ static int reader_seek_linear(struct table_iter *ti, * have no other way to do this. */ while (1) { - struct table_iter next = TABLE_ITER_INIT; + struct table_iter next = *ti; + + /* + * We must be careful to not modify underlying data of `ti` + * because we may find that `next` does not contain our desired + * block, but that `ti` does. In that case, we would discard + * `next` and continue with `ti`. + * + * This also means that we cannot reuse allocated memory for + * `next` here. While it would be great if we could, it should + * in practice not be too bad given that we should only ever + * end up doing linear seeks with at most three blocks. As soon + * as we have more than three blocks we would have an index, so + * we would not do a linear search there anymore. + */ + memset(&next.br.block, 0, sizeof(next.br.block)); - err = table_iter_next_block(&next, ti); + err = table_iter_next_block(&next); if (err < 0) goto done; if (err > 0) |