diff options
54 files changed, 1635 insertions, 1274 deletions
diff --git a/Documentation/howto/recover-corrupted-object-harder.adoc b/Documentation/howto/recover-corrupted-object-harder.adoc index 5efb4fe81f..86a1ba75cf 100644 --- a/Documentation/howto/recover-corrupted-object-harder.adoc +++ b/Documentation/howto/recover-corrupted-object-harder.adoc @@ -125,7 +125,7 @@ static int try_zlib(unsigned char *buf, int len) { /* make this absurdly large so we don't have to loop */ static unsigned char out[1024*1024]; - z_stream z; + struct z_stream_s z; int ret; memset(&z, 0, sizeof(z)); @@ -278,7 +278,7 @@ int main(int argc, char **argv) static unsigned char buf[25 * 1024 * 1024]; static unsigned char out[25 * 1024 * 1024]; int len; - z_stream z; + struct z_stream_s z; int ret; len = read(0, buf, sizeof(buf)); @@ -1377,10 +1377,10 @@ UNIT_TEST_PROGRAMS += t-reftable-basics UNIT_TEST_PROGRAMS += t-reftable-block UNIT_TEST_PROGRAMS += t-reftable-merged UNIT_TEST_PROGRAMS += t-reftable-pq -UNIT_TEST_PROGRAMS += t-reftable-reader UNIT_TEST_PROGRAMS += t-reftable-readwrite UNIT_TEST_PROGRAMS += t-reftable-record UNIT_TEST_PROGRAMS += t-reftable-stack +UNIT_TEST_PROGRAMS += t-reftable-table UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o @@ -2737,10 +2737,10 @@ REFTABLE_OBJS += reftable/blocksource.o REFTABLE_OBJS += reftable/iter.o REFTABLE_OBJS += reftable/merged.o REFTABLE_OBJS += reftable/pq.o -REFTABLE_OBJS += reftable/reader.o REFTABLE_OBJS += reftable/record.o REFTABLE_OBJS += reftable/stack.o REFTABLE_OBJS += reftable/system.o +REFTABLE_OBJS += reftable/table.o REFTABLE_OBJS += reftable/tree.o REFTABLE_OBJS += reftable/writer.o diff --git a/compat/zlib-compat.h b/compat/zlib-compat.h index 0c60e3af33..ac08276622 100644 --- a/compat/zlib-compat.h +++ b/compat/zlib-compat.h @@ -4,8 +4,8 @@ #ifdef HAVE_ZLIB_NG # include <zlib-ng.h> -# define z_stream zng_stream -#define gz_header_s zng_gz_header_s +# define z_stream_s zng_stream_s +# define gz_header_s zng_gz_header_s # define crc32(crc, buf, len) zng_crc32(crc, buf, len) diff --git a/git-zlib.h b/git-zlib.h index 1e8d9aabcb..0e66fefa8c 100644 --- a/git-zlib.h +++ b/git-zlib.h @@ -4,7 +4,7 @@ #include "compat/zlib-compat.h" typedef struct git_zstream { - z_stream z; + struct z_stream_s z; unsigned long avail_in; unsigned long avail_out; unsigned long total_in; diff --git a/meson.build b/meson.build index 410bbf93da..7ec38823cc 100644 --- a/meson.build +++ b/meson.build @@ -446,10 +446,10 @@ libgit_sources = [ 'reftable/iter.c', 'reftable/merged.c', 'reftable/pq.c', - 'reftable/reader.c', 'reftable/record.c', 'reftable/stack.c', 'reftable/system.c', + 'reftable/table.c', 'reftable/tree.c', 'reftable/writer.c', 'remote.c', diff --git a/reftable/basics.c b/reftable/basics.c index 8c4a4433e4..9988ebd635 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #define REFTABLE_ALLOW_BANNED_ALLOCATORS #include "basics.h" diff --git a/reftable/basics.h b/reftable/basics.h index fd59cbb772..d8888c1262 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BASICS_H #define BASICS_H @@ -18,13 +18,6 @@ https://developers.google.com/open-source/licenses/bsd #define REFTABLE_UNUSED __attribute__((__unused__)) -struct reftable_buf { - size_t alloc; - size_t len; - char *buf; -}; -#define REFTABLE_BUF_INIT { 0 } - /* * Initialize the buffer such that it is ready for use. This is equivalent to * using REFTABLE_BUF_INIT for stack-allocated variables. diff --git a/reftable/block.c b/reftable/block.c index 251a8e9fd3..471faa1642 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -1,15 +1,16 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "block.h" #include "blocksource.h" #include "constants.h" +#include "iter.h" #include "record.h" #include "reftable-error.h" #include "system.h" @@ -160,7 +161,7 @@ int block_writer_finish(struct block_writer *w) * Log records are stored zlib-compressed. Note that the compression * also spans over the restart points we have just written. */ - if (block_writer_type(w) == BLOCK_TYPE_LOG) { + if (block_writer_type(w) == REFTABLE_BLOCK_TYPE_LOG) { int block_header_skip = 4 + w->header_off; uLongf src_len = w->next - block_header_skip, compressed_len; int ret; @@ -210,61 +211,86 @@ int block_writer_finish(struct block_writer *w) return w->next; } -int block_reader_init(struct block_reader *br, struct reftable_block *block, - uint32_t header_off, uint32_t table_block_size, - uint32_t hash_size) +static int read_block(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t sz) +{ + size_t size = block_source_size(source); + block_source_release_data(dest); + if (off >= size) + return 0; + if (off + sz > size) + sz = size - off; + return block_source_read_data(source, dest, off, sz); +} + +int reftable_block_init(struct reftable_block *block, + struct reftable_block_source *source, + uint32_t offset, uint32_t header_size, + uint32_t table_block_size, uint32_t hash_size) { + uint32_t guess_block_size = table_block_size ? + table_block_size : DEFAULT_BLOCK_SIZE; uint32_t full_block_size = table_block_size; - uint8_t typ = block->data[header_off]; - uint32_t sz = reftable_get_be24(block->data + header_off + 1); - int err = 0; - uint16_t restart_count = 0; - uint32_t restart_start = 0; - uint8_t *restart_bytes = NULL; + uint16_t restart_count; + uint32_t restart_off; + uint32_t block_size; + uint8_t block_type; + int err; - reftable_block_done(&br->block); + err = read_block(source, &block->block_data, offset, guess_block_size); + if (err < 0) + goto done; - if (!reftable_is_block_type(typ)) { - err = REFTABLE_FORMAT_ERROR; + block_type = block->block_data.data[header_size]; + if (!reftable_is_block_type(block_type)) { + err = REFTABLE_FORMAT_ERROR; goto done; } - if (typ == BLOCK_TYPE_LOG) { - uint32_t block_header_skip = 4 + header_off; - uLong dst_len = sz - block_header_skip; - uLong src_len = block->len - block_header_skip; + block_size = reftable_get_be24(block->block_data.data + header_size + 1); + if (block_size > guess_block_size) { + err = read_block(source, &block->block_data, offset, block_size); + if (err < 0) + goto done; + } + + if (block_type == REFTABLE_BLOCK_TYPE_LOG) { + uint32_t block_header_skip = 4 + header_size; + uLong dst_len = block_size - block_header_skip; + uLong src_len = block->block_data.len - block_header_skip; /* Log blocks specify the *uncompressed* size in their header. */ - REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, sz, - br->uncompressed_cap); - if (!br->uncompressed_data) { + REFTABLE_ALLOC_GROW_OR_NULL(block->uncompressed_data, block_size, + block->uncompressed_cap); + if (!block->uncompressed_data) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } /* Copy over the block header verbatim. It's not compressed. */ - memcpy(br->uncompressed_data, block->data, block_header_skip); + memcpy(block->uncompressed_data, block->block_data.data, block_header_skip); - if (!br->zstream) { - REFTABLE_CALLOC_ARRAY(br->zstream, 1); - if (!br->zstream) { + if (!block->zstream) { + REFTABLE_CALLOC_ARRAY(block->zstream, 1); + if (!block->zstream) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - err = inflateInit(br->zstream); + err = inflateInit(block->zstream); } else { - err = inflateReset(br->zstream); + err = inflateReset(block->zstream); } if (err != Z_OK) { err = REFTABLE_ZLIB_ERROR; goto done; } - br->zstream->next_in = block->data + block_header_skip; - br->zstream->avail_in = src_len; - br->zstream->next_out = br->uncompressed_data + block_header_skip; - br->zstream->avail_out = dst_len; + block->zstream->next_in = block->block_data.data + block_header_skip; + block->zstream->avail_in = src_len; + block->zstream->next_out = block->uncompressed_data + block_header_skip; + block->zstream->avail_out = dst_len; /* * We know both input as well as output size, and we know that @@ -273,72 +299,71 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, * here to instruct zlib to inflate the data in one go, which * is more efficient than using `Z_NO_FLUSH`. */ - err = inflate(br->zstream, Z_FINISH); + err = inflate(block->zstream, Z_FINISH); if (err != Z_STREAM_END) { err = REFTABLE_ZLIB_ERROR; goto done; } err = 0; - if (br->zstream->total_out + block_header_skip != sz) { + if (block->zstream->total_out + block_header_skip != block_size) { err = REFTABLE_FORMAT_ERROR; goto done; } /* We're done with the input data. */ - reftable_block_done(block); - block->data = br->uncompressed_data; - block->len = sz; - full_block_size = src_len + block_header_skip - br->zstream->avail_in; + block_source_release_data(&block->block_data); + block->block_data.data = block->uncompressed_data; + block->block_data.len = block_size; + full_block_size = src_len + block_header_skip - block->zstream->avail_in; } else if (full_block_size == 0) { - full_block_size = sz; - } else if (sz < full_block_size && sz < block->len && - block->data[sz] != 0) { + full_block_size = block_size; + } else if (block_size < full_block_size && block_size < block->block_data.len && + block->block_data.data[block_size] != 0) { /* If the block is smaller than the full block size, it is padded (data followed by '\0') or the next block is unaligned. */ - full_block_size = sz; + full_block_size = block_size; } - restart_count = reftable_get_be16(block->data + sz - 2); - restart_start = sz - 2 - 3 * restart_count; - restart_bytes = block->data + restart_start; + restart_count = reftable_get_be16(block->block_data.data + block_size - 2); + restart_off = block_size - 2 - 3 * restart_count; - /* transfer ownership. */ - br->block = *block; - block->data = NULL; - block->len = 0; + block->block_type = block_type; + block->hash_size = hash_size; + block->restart_off = restart_off; + block->full_block_size = full_block_size; + block->header_off = header_size; + block->restart_count = restart_count; - br->hash_size = hash_size; - br->block_len = restart_start; - br->full_block_size = full_block_size; - br->header_off = header_off; - br->restart_count = restart_count; - br->restart_bytes = restart_bytes; + err = 0; done: + if (err < 0) + reftable_block_release(block); return err; } -void block_reader_release(struct block_reader *br) +void reftable_block_release(struct reftable_block *block) { - inflateEnd(br->zstream); - reftable_free(br->zstream); - reftable_free(br->uncompressed_data); - reftable_block_done(&br->block); + inflateEnd(block->zstream); + reftable_free(block->zstream); + reftable_free(block->uncompressed_data); + block_source_release_data(&block->block_data); + memset(block, 0, sizeof(*block)); } -uint8_t block_reader_type(const struct block_reader *r) +uint8_t reftable_block_type(const struct reftable_block *b) { - return r->block.data[r->header_off]; + return b->block_data.data[b->header_off]; } -int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key) +int reftable_block_first_key(const struct reftable_block *block, struct reftable_buf *key) { - int off = br->header_off + 4, n; + int off = block->header_off + 4, n; struct string_view in = { - .buf = br->block.data + off, - .len = br->block_len - off, + .buf = block->block_data.data + off, + .len = block->restart_off - off, }; uint8_t extra = 0; @@ -353,33 +378,36 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k return 0; } -static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx) +static uint32_t block_restart_offset(const struct reftable_block *b, size_t idx) +{ + return reftable_get_be24(b->block_data.data + b->restart_off + 3 * idx); +} + +void block_iter_init(struct block_iter *it, const struct reftable_block *block) { - return reftable_get_be24(br->restart_bytes + 3 * idx); + it->block = block; + block_iter_seek_start(it); } -void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) +void block_iter_seek_start(struct block_iter *it) { - it->block = br->block.data; - it->block_len = br->block_len; - it->hash_size = br->hash_size; reftable_buf_reset(&it->last_key); - it->next_off = br->header_off + 4; + it->next_off = it->block->header_off + 4; } struct restart_needle_less_args { int error; struct reftable_buf needle; - const struct block_reader *reader; + const struct reftable_block *block; }; static int restart_needle_less(size_t idx, void *_args) { struct restart_needle_less_args *args = _args; - uint32_t off = block_reader_restart_offset(args->reader, idx); + uint32_t off = block_restart_offset(args->block, idx); struct string_view in = { - .buf = args->reader->block.data + off, - .len = args->reader->block_len - off, + .buf = args->block->block_data.data + off, + .len = args->block->restart_off - off, }; uint64_t prefix_len, suffix_len; uint8_t extra; @@ -412,14 +440,14 @@ static int restart_needle_less(size_t idx, void *_args) int block_iter_next(struct block_iter *it, struct reftable_record *rec) { struct string_view in = { - .buf = (unsigned char *) it->block + it->next_off, - .len = it->block_len - it->next_off, + .buf = (unsigned char *) it->block->block_data.data + it->next_off, + .len = it->block->restart_off - it->next_off, }; struct string_view start = in; uint8_t extra = 0; int n = 0; - if (it->next_off >= it->block_len) + if (it->next_off >= it->block->restart_off) return 1; n = reftable_decode_key(&it->last_key, &extra, in); @@ -429,7 +457,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec) return REFTABLE_FORMAT_ERROR; string_view_consume(&in, n); - n = reftable_record_decode(rec, it->last_key, extra, in, it->hash_size, + n = reftable_record_decode(rec, it->last_key, extra, in, it->block->hash_size, &it->scratch); if (n < 0) return -1; @@ -444,8 +472,6 @@ void block_iter_reset(struct block_iter *it) reftable_buf_reset(&it->last_key); it->next_off = 0; it->block = NULL; - it->block_len = 0; - it->hash_size = 0; } void block_iter_close(struct block_iter *it) @@ -454,12 +480,11 @@ void block_iter_close(struct block_iter *it) reftable_buf_release(&it->scratch); } -int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct reftable_buf *want) +int block_iter_seek_key(struct block_iter *it, struct reftable_buf *want) { struct restart_needle_less_args args = { .needle = *want, - .reader = br, + .block = it->block, }; struct reftable_record rec; int err = 0; @@ -477,7 +502,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, * restart point. While that works alright, we would end up scanning * too many record. */ - i = binsearch(br->restart_count, &restart_needle_less, &args); + i = binsearch(it->block->restart_count, &restart_needle_less, &args); if (args.error) { err = REFTABLE_FORMAT_ERROR; goto done; @@ -502,21 +527,18 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, * starting from the preceding restart point. */ if (i > 0) - it->next_off = block_reader_restart_offset(br, i - 1); + it->next_off = block_restart_offset(it->block, i - 1); else - it->next_off = br->header_off + 4; - it->block = br->block.data; - it->block_len = br->block_len; - it->hash_size = br->hash_size; + it->next_off = it->block->header_off + 4; - err = reftable_record_init(&rec, block_reader_type(br)); + err = reftable_record_init(&rec, reftable_block_type(it->block)); if (err < 0) goto done; /* * We're looking for the last entry less than the wanted key so that * the next call to `block_reader_next()` would yield the wanted - * record. We thus don't want to position our reader at the sought + * record. We thus don't want to position our iterator at the sought * after record, but one before. To do so, we have to go one entry too * far and then back up. */ @@ -561,6 +583,61 @@ done: return err; } +static int block_iter_seek_void(void *it, struct reftable_record *want) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct block_iter *bi = it; + int err; + + if (bi->block->block_type != want->type) + return REFTABLE_API_ERROR; + + err = reftable_record_key(want, &buf); + if (err < 0) + goto out; + + err = block_iter_seek_key(it, &buf); + if (err < 0) + goto out; + + err = 0; + +out: + reftable_buf_release(&buf); + return err; +} + +static int block_iter_next_void(void *it, struct reftable_record *rec) +{ + return block_iter_next(it, rec); +} + +static void block_iter_close_void(void *it) +{ + block_iter_close(it); +} + +static struct reftable_iterator_vtable block_iter_vtable = { + .seek = &block_iter_seek_void, + .next = &block_iter_next_void, + .close = &block_iter_close_void, +}; + +int reftable_block_init_iterator(const struct reftable_block *b, + struct reftable_iterator *it) +{ + struct block_iter *bi; + + REFTABLE_CALLOC_ARRAY(bi, 1); + block_iter_init(bi, b); + + assert(!it->ops); + it->iter_arg = bi; + it->ops = &block_iter_vtable; + + return 0; +} + void block_writer_release(struct block_writer *bw) { deflateEnd(bw->zstream); @@ -571,14 +648,3 @@ void block_writer_release(struct block_writer *bw) reftable_buf_release(&bw->last_key); /* the block is not owned. */ } - -void reftable_block_done(struct reftable_block *blockp) -{ - struct reftable_block_source source = blockp->source; - if (blockp && source.ops) - source.ops->return_block(source.arg, blockp); - blockp->data = NULL; - blockp->len = 0; - blockp->source.ops = NULL; - blockp->source.arg = NULL; -} diff --git a/reftable/block.h b/reftable/block.h index 64732eba7d..d6dfaae33e 100644 --- a/reftable/block.h +++ b/reftable/block.h @@ -1,16 +1,17 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BLOCK_H #define BLOCK_H #include "basics.h" #include "record.h" +#include "reftable-block.h" #include "reftable-blocksource.h" /* @@ -18,7 +19,7 @@ https://developers.google.com/open-source/licenses/bsd * allocation overhead. */ struct block_writer { - z_stream *zstream; + struct z_stream_s *zstream; unsigned char *compressed; size_t compressed_cap; @@ -62,53 +63,11 @@ int block_writer_finish(struct block_writer *w); /* clears out internally allocated block_writer members. */ void block_writer_release(struct block_writer *bw); -struct z_stream; - -/* Read a block. */ -struct block_reader { - /* offset of the block header; nonzero for the first block in a - * reftable. */ - uint32_t header_off; - - /* the memory block */ - struct reftable_block block; - uint32_t hash_size; - - /* Uncompressed data for log entries. */ - z_stream *zstream; - unsigned char *uncompressed_data; - size_t uncompressed_cap; - - /* size of the data, excluding restart data. */ - uint32_t block_len; - uint8_t *restart_bytes; - uint16_t restart_count; - - /* size of the data in the file. For log blocks, this is the compressed - * size. */ - uint32_t full_block_size; -}; - -/* initializes a block reader. */ -int block_reader_init(struct block_reader *br, struct reftable_block *bl, - uint32_t header_off, uint32_t table_block_size, - uint32_t hash_size); - -void block_reader_release(struct block_reader *br); - -/* Returns the block type (eg. 'r' for refs) */ -uint8_t block_reader_type(const struct block_reader *r); - -/* Decodes the first key in the block */ -int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key); - -/* Iterate over entries in a block */ +/* Iterator for records contained in a single block. */ struct block_iter { /* offset within the block of the next entry to read. */ uint32_t next_off; - const unsigned char *block; - size_t block_len; - uint32_t hash_size; + const struct reftable_block *block; /* key for last entry we read. */ struct reftable_buf last_key; @@ -120,12 +79,23 @@ struct block_iter { .scratch = REFTABLE_BUF_INIT, \ } -/* Position `it` at start of the block */ -void block_iter_seek_start(struct block_iter *it, const struct block_reader *br); +/* + * Initialize the block iterator with the given block. The iterator will be + * positioned at the first record contained in the block. The block must remain + * valid until the end of the iterator's lifetime. It is valid to re-initialize + * iterators multiple times. + */ +void block_iter_init(struct block_iter *it, const struct reftable_block *block); -/* Position `it` to the `want` key in the block */ -int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct reftable_buf *want); +/* Position the initialized iterator at the first record of its block. */ +void block_iter_seek_start(struct block_iter *it); + +/* + * Position the initialized iterator at the desired record key. It is not an + * error in case the record cannot be found. If so, a subsequent call to + * `block_iter_next()` will indicate that the iterator is exhausted. + */ +int block_iter_seek_key(struct block_iter *it, struct reftable_buf *want); /* return < 0 for error, 0 for OK, > 0 for EOF. */ int block_iter_next(struct block_iter *it, struct reftable_record *rec); @@ -142,7 +112,4 @@ size_t header_size(int version); /* size of file footer, depending on format version */ size_t footer_size(int version); -/* returns a block to its source. */ -void reftable_block_done(struct reftable_block *ret); - #endif diff --git a/reftable/blocksource.c b/reftable/blocksource.c index 78c1be2337..573c81287f 100644 --- a/reftable/blocksource.c +++ b/reftable/blocksource.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" @@ -13,7 +13,42 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-blocksource.h" #include "reftable-error.h" -static void reftable_buf_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest) +void block_source_release_data(struct reftable_block_data *data) +{ + struct reftable_block_source source = data->source; + if (data && source.ops) + source.ops->release_data(source.arg, data); + data->data = NULL; + data->len = 0; + data->source.ops = NULL; + data->source.arg = NULL; +} + +void block_source_close(struct reftable_block_source *source) +{ + if (!source->ops) { + return; + } + + source->ops->close(source->arg); + source->ops = NULL; +} + +ssize_t block_source_read_data(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t size) +{ + ssize_t result = source->ops->read_data(source->arg, dest, off, size); + dest->source = *source; + return result; +} + +uint64_t block_source_size(struct reftable_block_source *source) +{ + return source->ops->size(source->arg); +} + +static void reftable_buf_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest) { if (dest->len) memset(dest->data, 0xff, dest->len); @@ -24,8 +59,8 @@ static void reftable_buf_close(void *b REFTABLE_UNUSED) { } -static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest, - uint64_t off, uint32_t size) +static ssize_t reftable_buf_read_data(void *v, struct reftable_block_data *dest, + uint64_t off, uint32_t size) { struct reftable_buf *b = v; assert(off + size <= b->len); @@ -44,8 +79,8 @@ static uint64_t reftable_buf_size(void *b) static struct reftable_block_source_vtable reftable_buf_vtable = { .size = &reftable_buf_size, - .read_block = &reftable_buf_read_block, - .return_block = &reftable_buf_return_block, + .read_data = &reftable_buf_read_data, + .release_data = &reftable_buf_release_data, .close = &reftable_buf_close, }; @@ -67,7 +102,7 @@ static uint64_t file_size(void *b) return ((struct file_block_source *)b)->size; } -static void file_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest REFTABLE_UNUSED) +static void file_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest REFTABLE_UNUSED) { } @@ -78,8 +113,8 @@ static void file_close(void *v) reftable_free(b); } -static ssize_t file_read_block(void *v, struct reftable_block *dest, uint64_t off, - uint32_t size) +static ssize_t file_read_data(void *v, struct reftable_block_data *dest, uint64_t off, + uint32_t size) { struct file_block_source *b = v; assert(off + size <= b->size); @@ -90,8 +125,8 @@ static ssize_t file_read_block(void *v, struct reftable_block *dest, uint64_t of static struct reftable_block_source_vtable file_vtable = { .size = &file_size, - .read_block = &file_read_block, - .return_block = &file_return_block, + .read_data = &file_read_data, + .release_data = &file_release_data, .close = &file_close, }; diff --git a/reftable/blocksource.h b/reftable/blocksource.h index a84a3ccd89..a110e05958 100644 --- a/reftable/blocksource.h +++ b/reftable/blocksource.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BLOCKSOURCE_H #define BLOCKSOURCE_H @@ -12,9 +12,34 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" struct reftable_block_source; +struct reftable_block_data; struct reftable_buf; -/* Create an in-memory block source for reading reftables */ +/* + * Close the block source and the underlying resource. This is a no-op in case + * the block source is zero-initialized. + */ +void block_source_close(struct reftable_block_source *source); + +/* + * Read a block of length `size` from the source at the given `off`. + */ +ssize_t block_source_read_data(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t size); + +/* + * Return the total length of the underlying resource. + */ +uint64_t block_source_size(struct reftable_block_source *source); + +/* + * Return a block to its original source, releasing any resources associated + * with it. + */ +void block_source_release_data(struct reftable_block_data *data); + +/* Create an in-memory block source for reading reftables. */ void block_source_from_buf(struct reftable_block_source *bs, struct reftable_buf *buf); diff --git a/reftable/constants.h b/reftable/constants.h index f6beb843eb..e3b1aaa516 100644 --- a/reftable/constants.h +++ b/reftable/constants.h @@ -1,19 +1,15 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef CONSTANTS_H #define CONSTANTS_H -#define BLOCK_TYPE_LOG 'g' -#define BLOCK_TYPE_INDEX 'i' -#define BLOCK_TYPE_REF 'r' -#define BLOCK_TYPE_OBJ 'o' -#define BLOCK_TYPE_ANY 0 +#include "reftable-constants.h" #define MAX_RESTARTS ((1 << 16) - 1) #define DEFAULT_BLOCK_SIZE 4096 diff --git a/reftable/error.c b/reftable/error.c index 660d029617..c7cab2dbc4 100644 --- a/reftable/error.c +++ b/reftable/error.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" #include "reftable-error.h" diff --git a/reftable/iter.c b/reftable/iter.c index f520382e70..2ecc52b336 100644 --- a/reftable/iter.c +++ b/reftable/iter.c @@ -1,19 +1,20 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "iter.h" #include "system.h" #include "block.h" +#include "blocksource.h" #include "constants.h" -#include "reader.h" #include "reftable-error.h" +#include "table.h" int iterator_seek(struct reftable_iterator *it, struct reftable_record *want) { @@ -113,7 +114,7 @@ static void indexed_table_ref_iter_close(void *p) { struct indexed_table_ref_iter *it = p; block_iter_close(&it->cur); - reftable_block_done(&it->block_reader.block); + block_source_release_data(&it->block.block_data); reftable_free(it->offsets); reftable_buf_release(&it->oid); } @@ -127,11 +128,10 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) return 1; } - reftable_block_done(&it->block_reader.block); + block_source_release_data(&it->block.block_data); off = it->offsets[it->offset_idx++]; - err = reader_init_block_reader(it->r, &it->block_reader, off, - BLOCK_TYPE_REF); + err = table_init_block(it->table, &it->block, off, REFTABLE_BLOCK_TYPE_REF); if (err < 0) { return err; } @@ -139,7 +139,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) /* indexed block does not exist. */ return REFTABLE_FORMAT_ERROR; } - block_iter_seek_start(&it->cur, &it->block_reader); + block_iter_init(&it->cur, &it->block); return 0; } @@ -181,7 +181,7 @@ static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec) } int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, - struct reftable_reader *r, uint8_t *oid, + struct reftable_table *t, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len) { struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT; @@ -195,7 +195,7 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, } *itr = empty; - itr->r = r; + itr->table = t; err = reftable_buf_add(&itr->oid, oid, oid_len); if (err < 0) @@ -246,7 +246,7 @@ int reftable_iterator_seek_ref(struct reftable_iterator *it, const char *name) { struct reftable_record want = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref = { .refname = (char *)name, }, @@ -258,7 +258,7 @@ int reftable_iterator_next_ref(struct reftable_iterator *it, struct reftable_ref_record *ref) { struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u = { .ref = *ref }, @@ -272,7 +272,7 @@ 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, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log = { .refname = (char *)name, .update_index = update_index, @@ -291,7 +291,7 @@ int reftable_iterator_next_log(struct reftable_iterator *it, struct reftable_log_record *log) { struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u = { .log = *log, }, diff --git a/reftable/iter.h b/reftable/iter.h index 40f98893b8..cc920970a5 100644 --- a/reftable/iter.h +++ b/reftable/iter.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef ITER_H #define ITER_H @@ -59,7 +59,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *, * but using the object index. */ struct indexed_table_ref_iter { - struct reftable_reader *r; + struct reftable_table *table; struct reftable_buf oid; /* mutable */ @@ -68,7 +68,7 @@ struct indexed_table_ref_iter { /* Points to the next offset to read. */ int offset_idx; int offset_len; - struct block_reader block_reader; + struct reftable_block block; struct block_iter cur; int is_finished; }; @@ -83,7 +83,7 @@ void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it, /* Takes ownership of `offsets` */ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, - struct reftable_reader *r, uint8_t *oid, + struct reftable_table *t, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len); #endif diff --git a/reftable/merged.c b/reftable/merged.c index 4ff1553772..733de07454 100644 --- a/reftable/merged.c +++ b/reftable/merged.c @@ -1,21 +1,21 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "merged.h" #include "constants.h" #include "iter.h" #include "pq.h" -#include "reader.h" #include "record.h" #include "reftable-merged.h" #include "reftable-error.h" #include "system.h" +#include "table.h" struct merged_subiter { struct reftable_iterator iter; @@ -192,7 +192,7 @@ static void iterator_from_merged_iter(struct reftable_iterator *it, } int reftable_merged_table_new(struct reftable_merged_table **dest, - struct reftable_reader **readers, size_t n, + struct reftable_table **tables, size_t n, enum reftable_hash hash_id) { struct reftable_merged_table *m = NULL; @@ -200,10 +200,10 @@ int reftable_merged_table_new(struct reftable_merged_table **dest, uint64_t first_min = 0; for (size_t i = 0; i < n; i++) { - uint64_t min = reftable_reader_min_update_index(readers[i]); - uint64_t max = reftable_reader_max_update_index(readers[i]); + uint64_t min = reftable_table_min_update_index(tables[i]); + uint64_t max = reftable_table_max_update_index(tables[i]); - if (reftable_reader_hash_id(readers[i]) != hash_id) { + if (reftable_table_hash_id(tables[i]) != hash_id) { return REFTABLE_FORMAT_ERROR; } if (i == 0 || min < first_min) { @@ -218,8 +218,8 @@ int reftable_merged_table_new(struct reftable_merged_table **dest, if (!m) return REFTABLE_OUT_OF_MEMORY_ERROR; - m->readers = readers; - m->readers_len = n; + m->tables = tables; + m->tables_len = n; m->min = first_min; m->max = last_max; m->hash_id = hash_id; @@ -254,20 +254,20 @@ int merged_table_init_iter(struct reftable_merged_table *mt, struct merged_iter *mi = NULL; int ret; - if (mt->readers_len) { - REFTABLE_CALLOC_ARRAY(subiters, mt->readers_len); + if (mt->tables_len) { + REFTABLE_CALLOC_ARRAY(subiters, mt->tables_len); if (!subiters) { ret = REFTABLE_OUT_OF_MEMORY_ERROR; goto out; } } - for (size_t i = 0; i < mt->readers_len; i++) { + for (size_t i = 0; i < mt->tables_len; i++) { ret = reftable_record_init(&subiters[i].rec, typ); if (ret < 0) goto out; - ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ); + ret = table_init_iter(mt->tables[i], &subiters[i].iter, typ); if (ret < 0) goto out; } @@ -280,14 +280,14 @@ int merged_table_init_iter(struct reftable_merged_table *mt, mi->advance_index = -1; mi->suppress_deletions = mt->suppress_deletions; mi->subiters = subiters; - mi->subiters_len = mt->readers_len; + mi->subiters_len = mt->tables_len; iterator_from_merged_iter(it, mi); ret = 0; out: if (ret < 0) { - for (size_t i = 0; subiters && i < mt->readers_len; i++) { + for (size_t i = 0; subiters && i < mt->tables_len; i++) { reftable_iterator_destroy(&subiters[i].iter); reftable_record_release(&subiters[i].rec); } @@ -301,13 +301,13 @@ out: int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, struct reftable_iterator *it) { - return merged_table_init_iter(mt, it, BLOCK_TYPE_REF); + return merged_table_init_iter(mt, it, REFTABLE_BLOCK_TYPE_REF); } int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, struct reftable_iterator *it) { - return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); + return merged_table_init_iter(mt, it, REFTABLE_BLOCK_TYPE_LOG); } enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *mt) diff --git a/reftable/merged.h b/reftable/merged.h index 0b7d939e92..4317e5f5f6 100644 --- a/reftable/merged.h +++ b/reftable/merged.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef MERGED_H #define MERGED_H @@ -13,8 +13,8 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-basics.h" struct reftable_merged_table { - struct reftable_reader **readers; - size_t readers_len; + struct reftable_table **tables; + size_t tables_len; enum reftable_hash hash_id; /* If unset, produce deletions. This is useful for compaction. For the diff --git a/reftable/pq.c b/reftable/pq.c index 82394a972d..9a79f5c5ee 100644 --- a/reftable/pq.c +++ b/reftable/pq.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "pq.h" diff --git a/reftable/pq.h b/reftable/pq.h index ff39016445..42310670b0 100644 --- a/reftable/pq.h +++ b/reftable/pq.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef PQ_H #define PQ_H diff --git a/reftable/reader.h b/reftable/reader.h deleted file mode 100644 index bb72108a6f..0000000000 --- a/reftable/reader.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef READER_H -#define READER_H - -#include "block.h" -#include "record.h" -#include "reftable-iterator.h" -#include "reftable-reader.h" - -uint64_t block_source_size(struct reftable_block_source *source); - -ssize_t block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size); -void block_source_close(struct reftable_block_source *source); - -/* metadata for a block type */ -struct reftable_reader_offsets { - int is_present; - uint64_t offset; - uint64_t index_offset; -}; - -/* The state for reading a reftable file. */ -struct reftable_reader { - /* for convenience, associate a name with the instance. */ - char *name; - struct reftable_block_source source; - - /* Size of the file, excluding the footer. */ - uint64_t size; - - /* The hash function used for ref records. */ - enum reftable_hash hash_id; - - uint32_t block_size; - uint64_t min_update_index; - uint64_t max_update_index; - /* Length of the OID keys in the 'o' section */ - int object_id_len; - int version; - - struct reftable_reader_offsets ref_offsets; - struct reftable_reader_offsets obj_offsets; - struct reftable_reader_offsets log_offsets; - - uint64_t refcount; -}; - -const char *reader_name(struct reftable_reader *r); - -int reader_init_iter(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t typ); - -/* initialize a block reader to read from `r` */ -int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br, - uint64_t next_off, uint8_t want_typ); - -#endif diff --git a/reftable/record.c b/reftable/record.c index c0080024ed..fcd387ba5d 100644 --- a/reftable/record.c +++ b/reftable/record.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ /* record.c - methods for different types of records. */ @@ -69,10 +69,10 @@ int put_var_int(struct string_view *dest, uint64_t value) int reftable_is_block_type(uint8_t typ) { switch (typ) { - case BLOCK_TYPE_REF: - case BLOCK_TYPE_LOG: - case BLOCK_TYPE_OBJ: - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_INDEX: return 1; } return 0; @@ -459,7 +459,7 @@ static int reftable_ref_record_cmp_void(const void *_a, const void *_b) static struct reftable_record_vtable reftable_ref_record_vtable = { .key = &reftable_ref_record_key, - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .copy_from = &reftable_ref_record_copy_from, .val_type = &reftable_ref_record_val_type, .encode = &reftable_ref_record_encode, @@ -659,7 +659,7 @@ static int reftable_obj_record_cmp_void(const void *_a, const void *_b) static struct reftable_record_vtable reftable_obj_record_vtable = { .key = &reftable_obj_record_key, - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .copy_from = &reftable_obj_record_copy_from, .val_type = &reftable_obj_record_val_type, .encode = &reftable_obj_record_encode, @@ -1030,7 +1030,7 @@ static int reftable_log_record_is_deletion_void(const void *p) static struct reftable_record_vtable reftable_log_record_vtable = { .key = &reftable_log_record_key, - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .copy_from = &reftable_log_record_copy_from, .val_type = &reftable_log_record_val_type, .encode = &reftable_log_record_encode, @@ -1132,7 +1132,7 @@ static int reftable_index_record_cmp(const void *_a, const void *_b) static struct reftable_record_vtable reftable_index_record_vtable = { .key = &reftable_index_record_key, - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .copy_from = &reftable_index_record_copy_from, .val_type = &reftable_index_record_val_type, .encode = &reftable_index_record_encode, @@ -1275,13 +1275,13 @@ int reftable_log_record_is_deletion(const struct reftable_log_record *log) static void *reftable_record_data(struct reftable_record *rec) { switch (rec->type) { - case BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_REF: return &rec->u.ref; - case BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_LOG: return &rec->u.log; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_INDEX: return &rec->u.idx; - case BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_OBJ: return &rec->u.obj; } abort(); @@ -1291,13 +1291,13 @@ static struct reftable_record_vtable * reftable_record_vtable(struct reftable_record *rec) { switch (rec->type) { - case BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_REF: return &reftable_ref_record_vtable; - case BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_LOG: return &reftable_log_record_vtable; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_INDEX: return &reftable_index_record_vtable; - case BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_OBJ: return &reftable_obj_record_vtable; } abort(); @@ -1309,11 +1309,11 @@ int reftable_record_init(struct reftable_record *rec, uint8_t typ) rec->type = typ; switch (typ) { - case BLOCK_TYPE_REF: - case BLOCK_TYPE_LOG: - case BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_OBJ: return 0; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_INDEX: reftable_buf_init(&rec->u.idx.last_key); return 0; default: diff --git a/reftable/record.h b/reftable/record.h index 867810a932..7953f352a3 100644 --- a/reftable/record.h +++ b/reftable/record.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef RECORD_H #define RECORD_H diff --git a/reftable/reftable-basics.h b/reftable/reftable-basics.h index e0397ed583..6d73f19c85 100644 --- a/reftable/reftable-basics.h +++ b/reftable/reftable-basics.h @@ -4,13 +4,21 @@ * Use of this source code is governed by a BSD-style * license that can be found in the LICENSE file or at * https://developers.google.com/open-source/licenses/bsd -*/ + */ #ifndef REFTABLE_BASICS_H #define REFTABLE_BASICS_H #include <stddef.h> +/* A buffer that contains arbitrary byte slices. */ +struct reftable_buf { + size_t alloc; + size_t len; + char *buf; +}; +#define REFTABLE_BUF_INIT { 0 } + /* * Hash functions understood by the reftable library. Note that the values are * arbitrary and somewhat random such that we can easily detect cases where the diff --git a/reftable/reftable-block.h b/reftable/reftable-block.h new file mode 100644 index 0000000000..04c3b518c8 --- /dev/null +++ b/reftable/reftable-block.h @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_BLOCK_H +#define REFTABLE_BLOCK_H + +#include <stdint.h> + +#include "reftable-basics.h" +#include "reftable-blocksource.h" +#include "reftable-iterator.h" + +struct z_stream_s; + +/* + * A block part of a reftable. Contains records as well as some metadata + * describing them. + */ +struct reftable_block { + /* + * Offset of the block header; nonzero for the first block in a + * reftable. + */ + uint32_t header_off; + + /* The memory block. */ + struct reftable_block_data block_data; + uint32_t hash_size; + + /* Uncompressed data for log entries. */ + struct z_stream_s *zstream; + unsigned char *uncompressed_data; + size_t uncompressed_cap; + + /* + * Restart point data. Restart points are located after the block's + * record data. + */ + uint16_t restart_count; + uint32_t restart_off; + + /* + * Size of the data in the file. For log blocks, this is the compressed + * size. + */ + uint32_t full_block_size; + uint8_t block_type; +}; + +/* Initialize a reftable block from the given block source. */ +int reftable_block_init(struct reftable_block *b, + struct reftable_block_source *source, + uint32_t offset, uint32_t header_size, + uint32_t table_block_size, uint32_t hash_size); + +/* Release resources allocated by the block. */ +void reftable_block_release(struct reftable_block *b); + +/* Initialize a generic record iterator from the given block. */ +int reftable_block_init_iterator(const struct reftable_block *b, + struct reftable_iterator *it); + +/* Returns the block type (eg. 'r' for refs). */ +uint8_t reftable_block_type(const struct reftable_block *b); + +/* Decodes the first key in the block. */ +int reftable_block_first_key(const struct reftable_block *b, struct reftable_buf *key); + +#endif /* REFTABLE_BLOCK_H */ diff --git a/reftable/reftable-blocksource.h b/reftable/reftable-blocksource.h index 6b326aa5ea..f5ba867bd6 100644 --- a/reftable/reftable-blocksource.h +++ b/reftable/reftable-blocksource.h @@ -1,17 +1,18 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_BLOCKSOURCE_H #define REFTABLE_BLOCKSOURCE_H #include <stdint.h> -/* block_source is a generic wrapper for a seekable readable file. +/* + * Generic wrapper for a seekable readable file. */ struct reftable_block_source { struct reftable_block_source_vtable *ops; @@ -20,7 +21,7 @@ struct reftable_block_source { /* a contiguous segment of bytes. It keeps track of its generating block_source * so it can return itself into the pool. */ -struct reftable_block { +struct reftable_block_data { uint8_t *data; size_t len; struct reftable_block_source source; @@ -28,20 +29,20 @@ struct reftable_block { /* block_source_vtable are the operations that make up block_source */ struct reftable_block_source_vtable { - /* returns the size of a block source */ + /* Returns the size of a block source. */ uint64_t (*size)(void *source); /* * Reads a segment from the block source. It is an error to read beyond * the end of the block. */ - ssize_t (*read_block)(void *source, struct reftable_block *dest, - uint64_t off, uint32_t size); + ssize_t (*read_data)(void *source, struct reftable_block_data *dest, + uint64_t off, uint32_t size); - /* mark the block as read; may return the data back to malloc */ - void (*return_block)(void *source, struct reftable_block *blockp); + /* Mark the block as read; may release the data. */ + void (*release_data)(void *source, struct reftable_block_data *data); - /* release all resources associated with the block source */ + /* Release all resources associated with the block source. */ void (*close)(void *source); }; diff --git a/reftable/reftable-constants.h b/reftable/reftable-constants.h new file mode 100644 index 0000000000..4ae9ba4bac --- /dev/null +++ b/reftable/reftable-constants.h @@ -0,0 +1,18 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_CONSTANTS_H +#define REFTABLE_CONSTANTS_H + +#define REFTABLE_BLOCK_TYPE_LOG 'g' +#define REFTABLE_BLOCK_TYPE_INDEX 'i' +#define REFTABLE_BLOCK_TYPE_REF 'r' +#define REFTABLE_BLOCK_TYPE_OBJ 'o' +#define REFTABLE_BLOCK_TYPE_ANY 0 + +#endif /* REFTABLE_CONSTANTS_H */ diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h index a7e33d964d..d100e0df92 100644 --- a/reftable/reftable-error.h +++ b/reftable/reftable-error.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_ERROR_H #define REFTABLE_ERROR_H diff --git a/reftable/reftable-iterator.h b/reftable/reftable-iterator.h index e3bf688d53..af582028c2 100644 --- a/reftable/reftable-iterator.h +++ b/reftable/reftable-iterator.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_ITERATOR_H #define REFTABLE_ITERATOR_H diff --git a/reftable/reftable-merged.h b/reftable/reftable-merged.h index f2d01c3ef8..e5af846b32 100644 --- a/reftable/reftable-merged.h +++ b/reftable/reftable-merged.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_MERGED_H #define REFTABLE_MERGED_H @@ -26,14 +26,14 @@ https://developers.google.com/open-source/licenses/bsd /* A merged table is implements seeking/iterating over a stack of tables. */ struct reftable_merged_table; -struct reftable_reader; +struct reftable_table; /* - * reftable_merged_table_new creates a new merged table. The readers must be + * reftable_merged_table_new creates a new merged table. The tables must be * kept alive as long as the merged table is still in use. */ int reftable_merged_table_new(struct reftable_merged_table **dest, - struct reftable_reader **readers, size_t n, + struct reftable_table **tables, size_t n, enum reftable_hash hash_id); /* Initialize a merged table iterator for reading refs. */ diff --git a/reftable/reftable-reader.h b/reftable/reftable-reader.h deleted file mode 100644 index 0085fbb903..0000000000 --- a/reftable/reftable-reader.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright 2020 Google LLC - - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file or at - https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef REFTABLE_READER_H -#define REFTABLE_READER_H - -#include "reftable-iterator.h" -#include "reftable-blocksource.h" - -/* - * Reading single tables - * - * The follow routines are for reading single files. For an - * application-level interface, skip ahead to struct - * reftable_merged_table and struct reftable_stack. - */ - -/* The reader struct is a handle to an open reftable file. */ -struct reftable_reader; - -/* reftable_reader_new opens a reftable for reading. If successful, - * returns 0 code and sets pp. The name is used for creating a - * stack. Typically, it is the basename of the file. The block source - * `src` is owned by the reader, and is closed on calling - * reftable_reader_destroy(). On error, the block source `src` is - * closed as well. - */ -int reftable_reader_new(struct reftable_reader **pp, - struct reftable_block_source *src, const char *name); - -/* - * Manage the reference count of the reftable reader. A newly initialized - * reader starts with a refcount of 1 and will be deleted once the refcount has - * reached 0. - * - * This is required because readers may have longer lifetimes than the stack - * they belong to. The stack may for example be reloaded while the old tables - * are still being accessed by an iterator. - */ -void reftable_reader_incref(struct reftable_reader *reader); -void reftable_reader_decref(struct reftable_reader *reader); - -/* Initialize a reftable iterator for reading refs. */ -int reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it); - -/* Initialize a reftable iterator for reading logs. */ -int reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it); - -/* returns the hash ID used in this table. */ -enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r); - -/* return an iterator for the refs pointing to `oid`. */ -int reftable_reader_refs_for(struct reftable_reader *r, - struct reftable_iterator *it, uint8_t *oid); - -/* return the max_update_index for a table */ -uint64_t reftable_reader_max_update_index(struct reftable_reader *r); - -/* return the min_update_index for a table */ -uint64_t reftable_reader_min_update_index(struct reftable_reader *r); - -/* print blocks onto stdout for debugging. */ -int reftable_reader_print_blocks(const char *tablename); - -#endif diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h index 931e594744..385a74cc86 100644 --- a/reftable/reftable-record.h +++ b/reftable/reftable-record.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_RECORD_H #define REFTABLE_RECORD_H diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h index ae14270ea7..910ec6ef3a 100644 --- a/reftable/reftable-stack.h +++ b/reftable/reftable-stack.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_STACK_H #define REFTABLE_STACK_H diff --git a/reftable/reftable-table.h b/reftable/reftable-table.h new file mode 100644 index 0000000000..5f935d02e3 --- /dev/null +++ b/reftable/reftable-table.h @@ -0,0 +1,115 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_TABLE_H +#define REFTABLE_TABLE_H + +#include "reftable-iterator.h" +#include "reftable-block.h" +#include "reftable-blocksource.h" + +/* + * Reading single tables + * + * The follow routines are for reading single files. For an + * application-level interface, skip ahead to struct + * reftable_merged_table and struct reftable_stack. + */ + +/* Metadata for a block type. */ +struct reftable_table_offsets { + int is_present; + uint64_t offset; + uint64_t index_offset; +}; + +/* The table struct is a handle to an open reftable file. */ +struct reftable_table { + /* for convenience, associate a name with the instance. */ + char *name; + struct reftable_block_source source; + + /* Size of the file, excluding the footer. */ + uint64_t size; + + /* The hash function used for ref records. */ + enum reftable_hash hash_id; + + uint32_t block_size; + uint64_t min_update_index; + uint64_t max_update_index; + /* Length of the OID keys in the 'o' section */ + int object_id_len; + int version; + + struct reftable_table_offsets ref_offsets; + struct reftable_table_offsets obj_offsets; + struct reftable_table_offsets log_offsets; + + uint64_t refcount; +}; + +/* reftable_table_new opens a reftable for reading. If successful, + * returns 0 code and sets pp. The name is used for creating a + * stack. Typically, it is the basename of the file. The block source + * `src` is owned by the table, and is closed on calling + * reftable_table_destroy(). On error, the block source `src` is + * closed as well. + */ +int reftable_table_new(struct reftable_table **out, + struct reftable_block_source *src, const char *name); + +/* + * Manage the reference count of the reftable table. A newly initialized + * table starts with a refcount of 1 and will be deleted once the refcount has + * reached 0. + * + * This is required because tables may have longer lifetimes than the stack + * they belong to. The stack may for example be reloaded while the old tables + * are still being accessed by an iterator. + */ +void reftable_table_incref(struct reftable_table *table); +void reftable_table_decref(struct reftable_table *table); + +/* Initialize a reftable iterator for reading refs. */ +int reftable_table_init_ref_iterator(struct reftable_table *t, + struct reftable_iterator *it); + +/* Initialize a reftable iterator for reading logs. */ +int reftable_table_init_log_iterator(struct reftable_table *t, + struct reftable_iterator *it); + +/* returns the hash ID used in this table. */ +enum reftable_hash reftable_table_hash_id(struct reftable_table *t); + +/* return an iterator for the refs pointing to `oid`. */ +int reftable_table_refs_for(struct reftable_table *t, + struct reftable_iterator *it, uint8_t *oid); + +/* return the max_update_index for a table */ +uint64_t reftable_table_max_update_index(struct reftable_table *t); + +/* return the min_update_index for a table */ +uint64_t reftable_table_min_update_index(struct reftable_table *t); + +/* + * An iterator that iterates through the blocks contained in a given table. + */ +struct reftable_table_iterator { + void *iter_arg; +}; + +int reftable_table_iterator_init(struct reftable_table_iterator *it, + struct reftable_table *t); + +void reftable_table_iterator_release(struct reftable_table_iterator *it); + +int reftable_table_iterator_next(struct reftable_table_iterator *it, + const struct reftable_block **out); + +#endif diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 1befe3b07c..0fbeff17f4 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_WRITER_H #define REFTABLE_WRITER_H diff --git a/reftable/stack.c b/reftable/stack.c index 6dac015b47..4caf96aa1d 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -1,20 +1,20 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "stack.h" #include "system.h" #include "constants.h" #include "merged.h" -#include "reader.h" #include "reftable-error.h" #include "reftable-record.h" #include "reftable-merged.h" +#include "table.h" #include "writer.h" static int stack_try_add(struct reftable_stack *st, @@ -203,14 +203,14 @@ int reftable_stack_init_ref_iterator(struct reftable_stack *st, struct reftable_iterator *it) { return merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_REF); + it, REFTABLE_BLOCK_TYPE_REF); } int reftable_stack_init_log_iterator(struct reftable_stack *st, struct reftable_iterator *it) { return merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_LOG); + it, REFTABLE_BLOCK_TYPE_LOG); } struct reftable_merged_table * @@ -248,11 +248,11 @@ void reftable_stack_destroy(struct reftable_stack *st) REFTABLE_FREE_AND_NULL(names); } - if (st->readers) { + if (st->tables) { struct reftable_buf filename = REFTABLE_BUF_INIT; - for (size_t i = 0; i < st->readers_len; i++) { - const char *name = reader_name(st->readers[i]); + for (size_t i = 0; i < st->tables_len; i++) { + const char *name = reftable_table_name(st->tables[i]); int try_unlinking = 1; reftable_buf_reset(&filename); @@ -260,7 +260,7 @@ void reftable_stack_destroy(struct reftable_stack *st) if (stack_filename(&filename, st, name) < 0) try_unlinking = 0; } - reftable_reader_decref(st->readers[i]); + reftable_table_decref(st->tables[i]); if (try_unlinking && filename.len) { /* On Windows, can only unlink after closing. */ @@ -269,8 +269,8 @@ void reftable_stack_destroy(struct reftable_stack *st) } reftable_buf_release(&filename); - st->readers_len = 0; - REFTABLE_FREE_AND_NULL(st->readers); + st->tables_len = 0; + REFTABLE_FREE_AND_NULL(st->tables); } if (st->list_fd >= 0) { @@ -284,14 +284,14 @@ void reftable_stack_destroy(struct reftable_stack *st) free_names(names); } -static struct reftable_reader **stack_copy_readers(struct reftable_stack *st, - size_t cur_len) +static struct reftable_table **stack_copy_tables(struct reftable_stack *st, + size_t cur_len) { - struct reftable_reader **cur = reftable_calloc(cur_len, sizeof(*cur)); + struct reftable_table **cur = reftable_calloc(cur_len, sizeof(*cur)); if (!cur) return NULL; for (size_t i = 0; i < cur_len; i++) - cur[i] = st->readers[i]; + cur[i] = st->tables[i]; return cur; } @@ -299,19 +299,19 @@ static int reftable_stack_reload_once(struct reftable_stack *st, const char **names, int reuse_open) { - size_t cur_len = !st->merged ? 0 : st->merged->readers_len; - struct reftable_reader **cur = NULL; - struct reftable_reader **reused = NULL; - struct reftable_reader **new_readers = NULL; + size_t cur_len = !st->merged ? 0 : st->merged->tables_len; + struct reftable_table **cur = NULL; + struct reftable_table **reused = NULL; + struct reftable_table **new_tables = NULL; size_t reused_len = 0, reused_alloc = 0, names_len; - size_t new_readers_len = 0; + size_t new_tables_len = 0; struct reftable_merged_table *new_merged = NULL; struct reftable_buf table_path = REFTABLE_BUF_INIT; int err = 0; size_t i; if (cur_len) { - cur = stack_copy_readers(st, cur_len); + cur = stack_copy_tables(st, cur_len); if (!cur) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; @@ -321,28 +321,28 @@ static int reftable_stack_reload_once(struct reftable_stack *st, names_len = names_length(names); if (names_len) { - new_readers = reftable_calloc(names_len, sizeof(*new_readers)); - if (!new_readers) { + new_tables = reftable_calloc(names_len, sizeof(*new_tables)); + if (!new_tables) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } } while (*names) { - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; const char *name = *names++; /* this is linear; we assume compaction keeps the number of tables under control so this is not quadratic. */ for (i = 0; reuse_open && i < cur_len; i++) { if (cur[i] && 0 == strcmp(cur[i]->name, name)) { - rd = cur[i]; + table = cur[i]; cur[i] = NULL; /* * When reloading the stack fails, we end up - * releasing all new readers. This also - * includes the reused readers, even though + * releasing all new tables. This also + * includes the reused tables, even though * they are still in used by the old stack. We * thus need to keep them alive here, which we * do by bumping their refcount. @@ -354,13 +354,13 @@ static int reftable_stack_reload_once(struct reftable_stack *st, err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - reused[reused_len++] = rd; - reftable_reader_incref(rd); + reused[reused_len++] = table; + reftable_table_incref(table); break; } } - if (!rd) { + if (!table) { struct reftable_block_source src = { NULL }; err = stack_filename(&table_path, st, name); @@ -372,36 +372,36 @@ static int reftable_stack_reload_once(struct reftable_stack *st, if (err < 0) goto done; - err = reftable_reader_new(&rd, &src, name); + err = reftable_table_new(&table, &src, name); if (err < 0) goto done; } - new_readers[new_readers_len] = rd; - new_readers_len++; + new_tables[new_tables_len] = table; + new_tables_len++; } /* success! */ - err = reftable_merged_table_new(&new_merged, new_readers, - new_readers_len, st->opts.hash_id); + err = reftable_merged_table_new(&new_merged, new_tables, + new_tables_len, st->opts.hash_id); if (err < 0) goto done; /* - * Close the old, non-reused readers and proactively try to unlink + * Close the old, non-reused tables and proactively try to unlink * them. This is done for systems like Windows, where the underlying - * file of such an open reader wouldn't have been possible to be + * file of such an open table wouldn't have been possible to be * unlinked by the compacting process. */ for (i = 0; i < cur_len; i++) { if (cur[i]) { - const char *name = reader_name(cur[i]); + const char *name = reftable_table_name(cur[i]); err = stack_filename(&table_path, st, name); if (err < 0) goto done; - reftable_reader_decref(cur[i]); + reftable_table_decref(cur[i]); unlink(table_path.buf); } } @@ -412,25 +412,25 @@ static int reftable_stack_reload_once(struct reftable_stack *st, new_merged->suppress_deletions = 1; st->merged = new_merged; - if (st->readers) - reftable_free(st->readers); - st->readers = new_readers; - st->readers_len = new_readers_len; - new_readers = NULL; - new_readers_len = 0; + if (st->tables) + reftable_free(st->tables); + st->tables = new_tables; + st->tables_len = new_tables_len; + new_tables = NULL; + new_tables_len = 0; /* - * Decrement the refcount of reused readers again. This only needs to + * Decrement the refcount of reused tables again. This only needs to * happen on the successful case, because on the unsuccessful one we - * decrement their refcount via `new_readers`. + * decrement their refcount via `new_tables`. */ for (i = 0; i < reused_len; i++) - reftable_reader_decref(reused[i]); + reftable_table_decref(reused[i]); done: - for (i = 0; i < new_readers_len; i++) - reftable_reader_decref(new_readers[i]); - reftable_free(new_readers); + for (i = 0; i < new_tables_len; i++) + reftable_table_decref(new_tables[i]); + reftable_free(new_tables); reftable_free(reused); reftable_free(cur); reftable_buf_release(&table_path); @@ -615,10 +615,10 @@ static int stack_uptodate(struct reftable_stack *st) /* * It's fine for "tables.list" to not exist. In that * case, we have to refresh when the loaded stack has - * any readers. + * any tables. */ if (errno == ENOENT) - return !!st->readers_len; + return !!st->tables_len; return REFTABLE_IO_ERROR; } @@ -637,19 +637,19 @@ static int stack_uptodate(struct reftable_stack *st) if (err < 0) return err; - for (size_t i = 0; i < st->readers_len; i++) { + for (size_t i = 0; i < st->tables_len; i++) { if (!names[i]) { err = 1; goto done; } - if (strcmp(st->readers[i]->name, names[i])) { + if (strcmp(st->tables[i]->name, names[i])) { err = 1; goto done; } } - if (names[st->merged->readers_len]) { + if (names[st->merged->tables_len]) { err = 1; goto done; } @@ -792,8 +792,8 @@ int reftable_addition_commit(struct reftable_addition *add) if (add->new_tables_len == 0) goto done; - for (i = 0; i < add->stack->merged->readers_len; i++) { - if ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 || + for (i = 0; i < add->stack->merged->tables_len; i++) { + if ((err = reftable_buf_addstr(&table_list, add->stack->tables[i]->name)) < 0 || (err = reftable_buf_addstr(&table_list, "\n")) < 0) goto done; } @@ -1000,9 +1000,9 @@ done: uint64_t reftable_stack_next_update_index(struct reftable_stack *st) { - int sz = st->merged->readers_len; + int sz = st->merged->tables_len; if (sz > 0) - return reftable_reader_max_update_index(st->readers[sz - 1]) + + return reftable_table_max_update_index(st->tables[sz - 1]) + 1; return 1; } @@ -1021,8 +1021,8 @@ static int stack_compact_locked(struct reftable_stack *st, struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; int err = 0; - err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]), - reftable_reader_max_update_index(st->readers[last])); + err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]), + reftable_table_max_update_index(st->tables[last])); if (err < 0) goto done; @@ -1087,18 +1087,18 @@ static int stack_write_compact(struct reftable_stack *st, int err = 0; for (size_t i = first; i <= last; i++) - st->stats.bytes += st->readers[i]->size; - err = reftable_writer_set_limits(wr, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); + st->stats.bytes += st->tables[i]->size; + err = reftable_writer_set_limits(wr, st->tables[first]->min_update_index, + st->tables[last]->max_update_index); if (err < 0) goto done; - err = reftable_merged_table_new(&mt, st->readers + first, subtabs_len, + err = reftable_merged_table_new(&mt, st->tables + first, subtabs_len, st->opts.hash_id); if (err < 0) goto done; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); if (err < 0) goto done; @@ -1126,7 +1126,7 @@ static int stack_write_compact(struct reftable_stack *st, } reftable_iterator_destroy(&it); - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); if (err < 0) goto done; @@ -1250,7 +1250,7 @@ static int stack_compact_range(struct reftable_stack *st, table_locks[i] = REFTABLE_FLOCK_INIT; for (i = last + 1; i > first; i--) { - err = stack_filename(&table_name, st, reader_name(st->readers[i - 1])); + err = stack_filename(&table_name, st, reftable_table_name(st->tables[i - 1])); if (err < 0) goto done; @@ -1376,7 +1376,7 @@ static int stack_compact_range(struct reftable_stack *st, * compacted in the updated "tables.list" file. */ for (size_t i = 0; names[i]; i++) { - if (strcmp(names[i], st->readers[first]->name)) + if (strcmp(names[i], st->tables[first]->name)) continue; /* @@ -1386,8 +1386,8 @@ static int stack_compact_range(struct reftable_stack *st, * have compacted them. */ for (size_t j = 1; j < last - first + 1; j++) { - const char *old = first + j < st->merged->readers_len ? - st->readers[first + j]->name : NULL; + const char *old = first + j < st->merged->tables_len ? + st->tables[first + j]->name : NULL; const char *new = names[i + j]; /* @@ -1427,16 +1427,16 @@ static int stack_compact_range(struct reftable_stack *st, * `fd_read_lines()` uses a `NULL` sentinel to indicate that * the array is at its end. As we use `free_names()` to free * the array, we need to include this sentinel value here and - * thus have to allocate `readers_len + 1` many entries. + * thus have to allocate `tables_len + 1` many entries. */ - REFTABLE_CALLOC_ARRAY(names, st->merged->readers_len + 1); + REFTABLE_CALLOC_ARRAY(names, st->merged->tables_len + 1); if (!names) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - for (size_t i = 0; i < st->merged->readers_len; i++) { - names[i] = reftable_strdup(st->readers[i]->name); + for (size_t i = 0; i < st->merged->tables_len; i++) { + names[i] = reftable_strdup(st->tables[i]->name); if (!names[i]) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; @@ -1451,8 +1451,8 @@ static int stack_compact_range(struct reftable_stack *st, * it into place now. */ if (!is_empty_table) { - err = format_name(&new_table_name, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); + err = format_name(&new_table_name, st->tables[first]->min_update_index, + st->tables[last]->max_update_index); if (err < 0) goto done; @@ -1559,7 +1559,7 @@ done: int reftable_stack_compact_all(struct reftable_stack *st, struct reftable_log_expiry_config *config) { - size_t last = st->merged->readers_len ? st->merged->readers_len - 1 : 0; + size_t last = st->merged->tables_len ? st->merged->tables_len - 1 : 0; return stack_compact_range(st, 0, last, config, 0); } @@ -1650,12 +1650,12 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) int overhead = header_size(version) - 1; uint64_t *sizes; - REFTABLE_CALLOC_ARRAY(sizes, st->merged->readers_len); + REFTABLE_CALLOC_ARRAY(sizes, st->merged->tables_len); if (!sizes) return NULL; - for (size_t i = 0; i < st->merged->readers_len; i++) - sizes[i] = st->readers[i]->size - overhead; + for (size_t i = 0; i < st->merged->tables_len; i++) + sizes[i] = st->tables[i]->size - overhead; return sizes; } @@ -1665,14 +1665,14 @@ int reftable_stack_auto_compact(struct reftable_stack *st) struct segment seg; uint64_t *sizes; - if (st->merged->readers_len < 2) + if (st->merged->tables_len < 2) return 0; sizes = stack_table_sizes_for_compaction(st); if (!sizes) return REFTABLE_OUT_OF_MEMORY_ERROR; - seg = suggest_compaction_segment(sizes, st->merged->readers_len, + seg = suggest_compaction_segment(sizes, st->merged->tables_len, st->opts.auto_compaction_factor); reftable_free(sizes); @@ -1763,7 +1763,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max, int err = 0; uint64_t update_idx = 0; struct reftable_block_source src = { NULL }; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_buf table_path = REFTABLE_BUF_INIT; err = stack_filename(&table_path, st, name); @@ -1774,12 +1774,12 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max, if (err < 0) goto done; - err = reftable_reader_new(&rd, &src, name); + err = reftable_table_new(&table, &src, name); if (err < 0) goto done; - update_idx = reftable_reader_max_update_index(rd); - reftable_reader_decref(rd); + update_idx = reftable_table_max_update_index(table); + reftable_table_decref(table); if (update_idx <= max) { unlink(table_path.buf); @@ -1803,8 +1803,8 @@ static int reftable_stack_clean_locked(struct reftable_stack *st) if (!is_table_name(d->d_name)) continue; - for (size_t i = 0; !found && i < st->readers_len; i++) - found = !strcmp(reader_name(st->readers[i]), d->d_name); + for (size_t i = 0; !found && i < st->tables_len; i++) + found = !strcmp(reftable_table_name(st->tables[i]), d->d_name); if (found) continue; diff --git a/reftable/stack.h b/reftable/stack.h index 5b45cff4f7..bc28f2998a 100644 --- a/reftable/stack.h +++ b/reftable/stack.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef STACK_H #define STACK_H @@ -22,8 +22,8 @@ struct reftable_stack { struct reftable_write_options opts; - struct reftable_reader **readers; - size_t readers_len; + struct reftable_table **tables; + size_t tables_len; struct reftable_merged_table *merged; struct reftable_compaction_stats stats; }; diff --git a/reftable/system.h b/reftable/system.h index 072d9daea0..beb9d2431f 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef SYSTEM_H #define SYSTEM_H diff --git a/reftable/reader.c b/reftable/table.c index 172aff2c10..ee83127615 100644 --- a/reftable/reader.c +++ b/reftable/table.c @@ -1,86 +1,46 @@ /* -Copyright 2020 Google LLC + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "reader.h" +#include "table.h" #include "system.h" #include "block.h" +#include "blocksource.h" #include "constants.h" #include "iter.h" #include "record.h" #include "reftable-error.h" -uint64_t block_source_size(struct reftable_block_source *source) -{ - return source->ops->size(source->arg); -} - -ssize_t block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size) -{ - ssize_t result = source->ops->read_block(source->arg, dest, off, size); - dest->source = *source; - return result; -} - -void block_source_close(struct reftable_block_source *source) -{ - if (!source->ops) { - return; - } - - source->ops->close(source->arg); - source->ops = NULL; -} - -static struct reftable_reader_offsets * -reader_offsets_for(struct reftable_reader *r, uint8_t typ) +static struct reftable_table_offsets * +table_offsets_for(struct reftable_table *t, uint8_t typ) { switch (typ) { - case BLOCK_TYPE_REF: - return &r->ref_offsets; - case BLOCK_TYPE_LOG: - return &r->log_offsets; - case BLOCK_TYPE_OBJ: - return &r->obj_offsets; + case REFTABLE_BLOCK_TYPE_REF: + return &t->ref_offsets; + case REFTABLE_BLOCK_TYPE_LOG: + return &t->log_offsets; + case REFTABLE_BLOCK_TYPE_OBJ: + return &t->obj_offsets; } abort(); } -static int reader_get_block(struct reftable_reader *r, - struct reftable_block *dest, uint64_t off, - uint32_t sz) +enum reftable_hash reftable_table_hash_id(struct reftable_table *t) { - ssize_t bytes_read; - if (off >= r->size) - return 0; - if (off + sz > r->size) - sz = r->size - off; - - bytes_read = block_source_read_block(&r->source, dest, off, sz); - if (bytes_read < 0) - return (int)bytes_read; - - return 0; + return t->hash_id; } -enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r) +const char *reftable_table_name(struct reftable_table *t) { - return r->hash_id; + return t->name; } -const char *reader_name(struct reftable_reader *r) -{ - return r->name; -} - -static int parse_footer(struct reftable_reader *r, uint8_t *footer, +static int parse_footer(struct reftable_table *t, uint8_t *footer, uint8_t *header) { uint8_t *f = footer; @@ -95,29 +55,29 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, } f += 4; - if (memcmp(footer, header, header_size(r->version))) { + if (memcmp(footer, header, header_size(t->version))) { err = REFTABLE_FORMAT_ERROR; goto done; } f++; - r->block_size = reftable_get_be24(f); + t->block_size = reftable_get_be24(f); f += 3; - r->min_update_index = reftable_get_be64(f); + t->min_update_index = reftable_get_be64(f); f += 8; - r->max_update_index = reftable_get_be64(f); + t->max_update_index = reftable_get_be64(f); f += 8; - if (r->version == 1) { - r->hash_id = REFTABLE_HASH_SHA1; + if (t->version == 1) { + t->hash_id = REFTABLE_HASH_SHA1; } else { switch (reftable_get_be32(f)) { case REFTABLE_FORMAT_ID_SHA1: - r->hash_id = REFTABLE_HASH_SHA1; + t->hash_id = REFTABLE_HASH_SHA1; break; case REFTABLE_FORMAT_ID_SHA256: - r->hash_id = REFTABLE_HASH_SHA256; + t->hash_id = REFTABLE_HASH_SHA256; break; default: err = REFTABLE_FORMAT_ERROR; @@ -127,20 +87,20 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, f += 4; } - r->ref_offsets.index_offset = reftable_get_be64(f); + t->ref_offsets.index_offset = reftable_get_be64(f); f += 8; - r->obj_offsets.offset = reftable_get_be64(f); + t->obj_offsets.offset = reftable_get_be64(f); f += 8; - r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1); - r->obj_offsets.offset >>= 5; + t->object_id_len = t->obj_offsets.offset & ((1 << 5) - 1); + t->obj_offsets.offset >>= 5; - r->obj_offsets.index_offset = reftable_get_be64(f); + t->obj_offsets.index_offset = reftable_get_be64(f); f += 8; - r->log_offsets.offset = reftable_get_be64(f); + t->log_offsets.offset = reftable_get_be64(f); f += 8; - r->log_offsets.index_offset = reftable_get_be64(f); + t->log_offsets.index_offset = reftable_get_be64(f); f += 8; computed_crc = crc32(0, footer, f - footer); @@ -151,13 +111,13 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, goto done; } - first_block_typ = header[header_size(r->version)]; - r->ref_offsets.is_present = (first_block_typ == BLOCK_TYPE_REF); - r->ref_offsets.offset = 0; - r->log_offsets.is_present = (first_block_typ == BLOCK_TYPE_LOG || - r->log_offsets.offset > 0); - r->obj_offsets.is_present = r->obj_offsets.offset > 0; - if (r->obj_offsets.is_present && !r->object_id_len) { + first_block_typ = header[header_size(t->version)]; + t->ref_offsets.is_present = (first_block_typ == REFTABLE_BLOCK_TYPE_REF); + t->ref_offsets.offset = 0; + t->log_offsets.is_present = (first_block_typ == REFTABLE_BLOCK_TYPE_LOG || + t->log_offsets.offset > 0); + t->obj_offsets.is_present = t->obj_offsets.offset > 0; + if (t->obj_offsets.is_present && !t->object_id_len) { err = REFTABLE_FORMAT_ERROR; goto done; } @@ -168,20 +128,20 @@ done: } struct table_iter { - struct reftable_reader *r; + struct reftable_table *table; uint8_t typ; uint64_t block_off; - struct block_reader br; + struct reftable_block block; struct block_iter bi; int is_finished; }; -static int table_iter_init(struct table_iter *ti, struct reftable_reader *r) +static int table_iter_init(struct table_iter *ti, struct reftable_table *t) { struct block_iter bi = BLOCK_ITER_INIT; memset(ti, 0, sizeof(*ti)); - reftable_reader_incref(r); - ti->r = r; + reftable_table_incref(t); + ti->table = t; ti->bi = bi; return 0; } @@ -190,8 +150,8 @@ static int table_iter_next_in_block(struct table_iter *ti, struct reftable_record *rec) { int res = block_iter_next(&ti->bi, rec); - if (res == 0 && reftable_record_type(rec) == BLOCK_TYPE_REF) { - rec->u.ref.update_index += ti->r->min_update_index; + if (res == 0 && reftable_record_type(rec) == REFTABLE_BLOCK_TYPE_REF) { + rec->u.ref.update_index += ti->table->min_update_index; } return res; @@ -199,68 +159,32 @@ static int table_iter_next_in_block(struct table_iter *ti, static void table_iter_block_done(struct table_iter *ti) { - block_reader_release(&ti->br); + reftable_block_release(&ti->block); block_iter_reset(&ti->bi); } -static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off, - int version) -{ - int32_t result = 0; - - if (off == 0) { - data += header_size(version); - } - - *typ = data[0]; - if (reftable_is_block_type(*typ)) { - result = reftable_get_be24(data + 1); - } - return result; -} - -int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br, - uint64_t next_off, uint8_t want_typ) +int table_init_block(struct reftable_table *t, struct reftable_block *block, + uint64_t next_off, uint8_t want_typ) { - int32_t guess_block_size = r->block_size ? r->block_size : - DEFAULT_BLOCK_SIZE; - struct reftable_block block = { NULL }; - uint8_t block_typ = 0; - int err = 0; - uint32_t header_off = next_off ? 0 : header_size(r->version); - int32_t block_size = 0; + uint32_t header_off = next_off ? 0 : header_size(t->version); + int err; - if (next_off >= r->size) + if (next_off >= t->size) return 1; - err = reader_get_block(r, &block, next_off, guess_block_size); + err = reftable_block_init(block, &t->source, next_off, header_off, + t->block_size, hash_size(t->hash_id)); if (err < 0) goto done; - block_size = extract_block_size(block.data, &block_typ, next_off, - r->version); - if (block_size < 0) { - err = block_size; - goto done; - } - if (want_typ != BLOCK_TYPE_ANY && block_typ != want_typ) { + if (want_typ != REFTABLE_BLOCK_TYPE_ANY && block->block_type != want_typ) { err = 1; goto done; } - if (block_size > guess_block_size) { - reftable_block_done(&block); - err = reader_get_block(r, &block, next_off, block_size); - if (err < 0) { - goto done; - } - } - - err = block_reader_init(br, &block, header_off, r->block_size, - hash_size(r->hash_id)); done: - reftable_block_done(&block); - + if (err) + reftable_block_release(block); return err; } @@ -268,15 +192,15 @@ static void table_iter_close(struct table_iter *ti) { table_iter_block_done(ti); block_iter_close(&ti->bi); - reftable_reader_decref(ti->r); + reftable_table_decref(ti->table); } static int table_iter_next_block(struct table_iter *ti) { - uint64_t next_block_off = ti->block_off + ti->br.full_block_size; + uint64_t next_block_off = ti->block_off + ti->block.full_block_size; int err; - err = reader_init_block_reader(ti->r, &ti->br, next_block_off, ti->typ); + err = table_init_block(ti->table, &ti->block, next_block_off, ti->typ); if (err > 0) ti->is_finished = 1; if (err) @@ -284,7 +208,7 @@ static int table_iter_next_block(struct table_iter *ti) ti->block_off = next_block_off; ti->is_finished = 0; - block_iter_seek_start(&ti->bi, &ti->br); + block_iter_init(&ti->bi, &ti->block); return 0; } @@ -326,27 +250,27 @@ static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ) { int err; - err = reader_init_block_reader(ti->r, &ti->br, off, typ); + err = table_init_block(ti->table, &ti->block, off, typ); if (err != 0) return err; - ti->typ = block_reader_type(&ti->br); + ti->typ = reftable_block_type(&ti->block); ti->block_off = off; - block_iter_seek_start(&ti->bi, &ti->br); + block_iter_init(&ti->bi, &ti->block); ti->is_finished = 0; return 0; } static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index) { - struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ); + struct reftable_table_offsets *offs = table_offsets_for(ti->table, typ); uint64_t off = offs->offset; if (index) { off = offs->index_offset; if (off == 0) { return 1; } - typ = BLOCK_TYPE_INDEX; + typ = REFTABLE_BLOCK_TYPE_INDEX; } return table_iter_seek_to(ti, off, typ); @@ -396,10 +320,10 @@ static int table_iter_seek_linear(struct table_iter *ti, * 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)); - next.br.zstream = NULL; - next.br.uncompressed_data = NULL; - next.br.uncompressed_cap = 0; + memset(&next.block.block_data, 0, sizeof(next.block.block_data)); + next.block.zstream = NULL; + next.block.uncompressed_data = NULL; + next.block.uncompressed_cap = 0; err = table_iter_next_block(&next); if (err < 0) @@ -407,7 +331,7 @@ static int table_iter_seek_linear(struct table_iter *ti, if (err > 0) break; - err = block_reader_first_key(&next.br, &got_key); + err = reftable_block_first_key(&next.block, &got_key); if (err < 0) goto done; @@ -425,7 +349,8 @@ static int table_iter_seek_linear(struct table_iter *ti, * the wanted key inside of it. If the block does not contain our key * we know that the corresponding record does not exist. */ - err = block_iter_seek_key(&ti->bi, &ti->br, &want_key); + block_iter_init(&ti->bi, &ti->block); + err = block_iter_seek_key(&ti->bi, &want_key); if (err < 0) goto done; err = 0; @@ -441,10 +366,10 @@ 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 = REFTABLE_BUF_INIT } + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT } }; struct reftable_record index_result = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int err; @@ -493,7 +418,9 @@ static int table_iter_seek_indexed(struct table_iter *ti, if (err != 0) goto done; - err = block_iter_seek_key(&ti->bi, &ti->br, &want_index.u.idx.last_key); + block_iter_init(&ti->bi, &ti->block); + + err = block_iter_seek_key(&ti->bi, &want_index.u.idx.last_key); if (err < 0) goto done; @@ -502,7 +429,7 @@ static int table_iter_seek_indexed(struct table_iter *ti, break; } - if (ti->typ != BLOCK_TYPE_INDEX) { + if (ti->typ != REFTABLE_BLOCK_TYPE_INDEX) { err = REFTABLE_FORMAT_ERROR; goto done; } @@ -518,7 +445,7 @@ static int table_iter_seek(struct table_iter *ti, struct reftable_record *want) { uint8_t typ = reftable_record_type(want); - struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ); + struct reftable_table_offsets *offs = table_offsets_for(ti->table, typ); int err; err = table_iter_seek_start(ti, reftable_record_type(want), @@ -566,11 +493,11 @@ static void iterator_from_table_iter(struct reftable_iterator *it, it->ops = &table_iter_vtable; } -int reader_init_iter(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t typ) +int table_init_iter(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t typ) { - struct reftable_reader_offsets *offs = reader_offsets_for(r, typ); + struct reftable_table_offsets *offs = table_offsets_for(t, typ); if (offs->is_present) { struct table_iter *ti; @@ -578,7 +505,7 @@ int reader_init_iter(struct reftable_reader *r, if (!ti) return REFTABLE_OUT_OF_MEMORY_ERROR; - table_iter_init(ti, r); + table_iter_init(ti, t); iterator_from_table_iter(it, ti); } else { iterator_set_empty(it); @@ -587,31 +514,31 @@ int reader_init_iter(struct reftable_reader *r, return 0; } -int reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it) +int reftable_table_init_ref_iterator(struct reftable_table *t, + struct reftable_iterator *it) { - return reader_init_iter(r, it, BLOCK_TYPE_REF); + return table_init_iter(t, it, REFTABLE_BLOCK_TYPE_REF); } -int reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it) +int reftable_table_init_log_iterator(struct reftable_table *t, + struct reftable_iterator *it) { - return reader_init_iter(r, it, BLOCK_TYPE_LOG); + return table_init_iter(t, it, REFTABLE_BLOCK_TYPE_LOG); } -int reftable_reader_new(struct reftable_reader **out, - struct reftable_block_source *source, char const *name) +int reftable_table_new(struct reftable_table **out, + struct reftable_block_source *source, char const *name) { - struct reftable_block footer = { 0 }; - struct reftable_block header = { 0 }; - struct reftable_reader *r; + struct reftable_block_data footer = { 0 }; + struct reftable_block_data header = { 0 }; + struct reftable_table *t; uint64_t file_size = block_source_size(source); uint32_t read_size; ssize_t bytes_read; int err; - REFTABLE_CALLOC_ARRAY(r, 1); - if (!r) { + REFTABLE_CALLOC_ARRAY(t, 1); + if (!t) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } @@ -626,7 +553,7 @@ int reftable_reader_new(struct reftable_reader **out, goto done; } - bytes_read = block_source_read_block(source, &header, 0, read_size); + bytes_read = block_source_read_data(source, &header, 0, read_size); if (bytes_read < 0 || (size_t)bytes_read != read_size) { err = REFTABLE_IO_ERROR; goto done; @@ -636,84 +563,84 @@ int reftable_reader_new(struct reftable_reader **out, err = REFTABLE_FORMAT_ERROR; goto done; } - r->version = header.data[4]; - if (r->version != 1 && r->version != 2) { + t->version = header.data[4]; + if (t->version != 1 && t->version != 2) { err = REFTABLE_FORMAT_ERROR; goto done; } - r->size = file_size - footer_size(r->version); - r->source = *source; - r->name = reftable_strdup(name); - if (!r->name) { + t->size = file_size - footer_size(t->version); + t->source = *source; + t->name = reftable_strdup(name); + if (!t->name) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - r->hash_id = 0; - r->refcount = 1; + t->hash_id = 0; + t->refcount = 1; - bytes_read = block_source_read_block(source, &footer, r->size, - footer_size(r->version)); - if (bytes_read < 0 || (size_t)bytes_read != footer_size(r->version)) { + bytes_read = block_source_read_data(source, &footer, t->size, + footer_size(t->version)); + if (bytes_read < 0 || (size_t)bytes_read != footer_size(t->version)) { err = REFTABLE_IO_ERROR; goto done; } - err = parse_footer(r, footer.data, header.data); + err = parse_footer(t, footer.data, header.data); if (err) goto done; - *out = r; + *out = t; done: - reftable_block_done(&footer); - reftable_block_done(&header); + block_source_release_data(&footer); + block_source_release_data(&header); if (err) { - if (r) - reftable_free(r->name); - reftable_free(r); + if (t) + reftable_free(t->name); + reftable_free(t); block_source_close(source); } return err; } -void reftable_reader_incref(struct reftable_reader *r) +void reftable_table_incref(struct reftable_table *t) { - r->refcount++; + t->refcount++; } -void reftable_reader_decref(struct reftable_reader *r) +void reftable_table_decref(struct reftable_table *t) { - if (!r) + if (!t) return; - if (--r->refcount) + if (--t->refcount) return; - block_source_close(&r->source); - REFTABLE_FREE_AND_NULL(r->name); - reftable_free(r); + block_source_close(&t->source); + REFTABLE_FREE_AND_NULL(t->name); + reftable_free(t); } -static int reftable_reader_refs_for_indexed(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t *oid) +static int reftable_table_refs_for_indexed(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t *oid) { struct reftable_record want = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { .hash_prefix = oid, - .hash_prefix_len = r->object_id_len, + .hash_prefix_len = t->object_id_len, }, }; struct reftable_iterator oit = { NULL }; struct reftable_record got = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { 0 }, }; int err = 0; struct indexed_table_ref_iter *itr = NULL; /* Look through the reverse index. */ - err = reader_init_iter(r, &oit, BLOCK_TYPE_OBJ); + err = table_init_iter(t, &oit, REFTABLE_BLOCK_TYPE_OBJ); if (err < 0) goto done; @@ -727,14 +654,14 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r, goto done; if (err > 0 || memcmp(want.u.obj.hash_prefix, got.u.obj.hash_prefix, - r->object_id_len)) { + t->object_id_len)) { /* didn't find it; return empty iterator */ iterator_set_empty(it); err = 0; goto done; } - err = indexed_table_ref_iter_new(&itr, r, oid, hash_size(r->hash_id), + err = indexed_table_ref_iter_new(&itr, t, oid, hash_size(t->hash_id), got.u.obj.offsets, got.u.obj.offset_len); if (err < 0) @@ -748,14 +675,14 @@ done: return err; } -static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t *oid) +static int reftable_table_refs_for_unindexed(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t *oid) { struct table_iter *ti; struct filtering_ref_iterator *filter = NULL; struct filtering_ref_iterator empty = FILTERING_REF_ITERATOR_INIT; - uint32_t oid_len = hash_size(r->hash_id); + uint32_t oid_len = hash_size(t->hash_id); int err; REFTABLE_ALLOC_ARRAY(ti, 1); @@ -764,8 +691,8 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, goto out; } - table_iter_init(ti, r); - err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0); + table_iter_init(ti, t); + err = table_iter_seek_start(ti, REFTABLE_BLOCK_TYPE_REF, 0); if (err < 0) goto out; @@ -795,85 +722,67 @@ out: return err; } -int reftable_reader_refs_for(struct reftable_reader *r, - struct reftable_iterator *it, uint8_t *oid) +int reftable_table_refs_for(struct reftable_table *t, + struct reftable_iterator *it, uint8_t *oid) { - if (r->obj_offsets.is_present) - return reftable_reader_refs_for_indexed(r, it, oid); - return reftable_reader_refs_for_unindexed(r, it, oid); + if (t->obj_offsets.is_present) + return reftable_table_refs_for_indexed(t, it, oid); + return reftable_table_refs_for_unindexed(t, it, oid); } -uint64_t reftable_reader_max_update_index(struct reftable_reader *r) +uint64_t reftable_table_max_update_index(struct reftable_table *t) { - return r->max_update_index; + return t->max_update_index; } -uint64_t reftable_reader_min_update_index(struct reftable_reader *r) +uint64_t reftable_table_min_update_index(struct reftable_table *t) { - return r->min_update_index; + return t->min_update_index; } -int reftable_reader_print_blocks(const char *tablename) +int reftable_table_iterator_init(struct reftable_table_iterator *it, + struct reftable_table *t) { - struct { - const char *name; - int type; - } sections[] = { - { - .name = "ref", - .type = BLOCK_TYPE_REF, - }, - { - .name = "obj", - .type = BLOCK_TYPE_OBJ, - }, - { - .name = "log", - .type = BLOCK_TYPE_LOG, - }, - }; - struct reftable_block_source src = { 0 }; - struct reftable_reader *r = NULL; - struct table_iter ti = { 0 }; - size_t i; + struct table_iter *ti; int err; - err = reftable_block_source_from_file(&src, tablename); - if (err < 0) - goto done; + REFTABLE_ALLOC_ARRAY(ti, 1); + if (!ti) + return REFTABLE_OUT_OF_MEMORY_ERROR; - err = reftable_reader_new(&r, &src, tablename); + err = table_iter_init(ti, t); if (err < 0) - goto done; + goto out; - table_iter_init(&ti, r); + it->iter_arg = ti; + err = 0; - printf("header:\n"); - printf(" block_size: %d\n", r->block_size); +out: + if (err < 0) + reftable_free(ti); + return err; +} - for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) { - err = table_iter_seek_start(&ti, sections[i].type, 0); - if (err < 0) - goto done; - if (err > 0) - continue; +void reftable_table_iterator_release(struct reftable_table_iterator *it) +{ + if (!it->iter_arg) + return; + table_iter_close(it->iter_arg); + reftable_free(it->iter_arg); + it->iter_arg = NULL; +} - printf("%s:\n", sections[i].name); +int reftable_table_iterator_next(struct reftable_table_iterator *it, + const struct reftable_block **out) +{ + struct table_iter *ti = it->iter_arg; + int err; - while (1) { - printf(" - length: %u\n", ti.br.block_len); - printf(" restarts: %u\n", ti.br.restart_count); + err = table_iter_next_block(ti); + if (err) + return err; - err = table_iter_next_block(&ti); - if (err < 0) - goto done; - if (err > 0) - break; - } - } + *out = &ti->block; -done: - reftable_reader_decref(r); - table_iter_close(&ti); - return err; + return 0; } diff --git a/reftable/table.h b/reftable/table.h new file mode 100644 index 0000000000..c54703e621 --- /dev/null +++ b/reftable/table.h @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef TABLE_H +#define TABLE_H + +#include "block.h" +#include "record.h" +#include "reftable-iterator.h" +#include "reftable-table.h" + +const char *reftable_table_name(struct reftable_table *t); + +int table_init_iter(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t typ); + +/* + * Initialize a block by reading from the given table and offset. + */ +int table_init_block(struct reftable_table *t, struct reftable_block *block, + uint64_t next_off, uint8_t want_typ); + +#endif diff --git a/reftable/tree.c b/reftable/tree.c index f4dbe72090..a52f7c0c7d 100644 --- a/reftable/tree.c +++ b/reftable/tree.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" #include "tree.h" diff --git a/reftable/tree.h b/reftable/tree.h index 9604453b6d..2c9c465299 100644 --- a/reftable/tree.h +++ b/reftable/tree.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef TREE_H #define TREE_H diff --git a/reftable/writer.c b/reftable/writer.c index 075ea8661b..cb16f71be4 100644 --- a/reftable/writer.c +++ b/reftable/writer.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "writer.h" @@ -172,7 +172,7 @@ int reftable_writer_new(struct reftable_writer **out, wp->write_arg = writer_arg; wp->opts = opts; wp->flush = flush_func; - writer_reinit_block_writer(wp, BLOCK_TYPE_REF); + writer_reinit_block_writer(wp, REFTABLE_BLOCK_TYPE_REF); *out = wp; @@ -342,7 +342,7 @@ int reftable_writer_add_ref(struct reftable_writer *w, struct reftable_ref_record *ref) { struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u = { .ref = *ref }, @@ -406,13 +406,13 @@ static int reftable_writer_add_log_verbatim(struct reftable_writer *w, struct reftable_log_record *log) { struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u = { .log = *log, }, }; if (w->block_writer && - block_writer_type(w->block_writer) == BLOCK_TYPE_REF) { + block_writer_type(w->block_writer) == REFTABLE_BLOCK_TYPE_REF) { int err = writer_finish_public_section(w); if (err < 0) return err; @@ -532,7 +532,7 @@ static int writer_finish_section(struct reftable_writer *w) max_level++; index_start = w->next; - err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX); + err = writer_reinit_block_writer(w, REFTABLE_BLOCK_TYPE_INDEX); if (err < 0) return err; @@ -544,7 +544,7 @@ static int writer_finish_section(struct reftable_writer *w) w->index_cap = 0; for (i = 0; i < idx_len; i++) { struct reftable_record rec = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u = { .idx = idx[i], }, @@ -609,7 +609,7 @@ static void write_object_record(void *void_arg, void *key) struct write_record_arg *arg = void_arg; struct obj_index_tree_node *entry = key; struct reftable_record - rec = { .type = BLOCK_TYPE_OBJ, + rec = { .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { .hash_prefix = (uint8_t *)entry->hash.buf, .hash_prefix_len = arg->w->stats.object_id_len, @@ -639,7 +639,7 @@ static void write_object_record(void *void_arg, void *key) if (arg->err < 0) goto done; - arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ); + arg->err = writer_reinit_block_writer(arg->w, REFTABLE_BLOCK_TYPE_OBJ); if (arg->err < 0) goto done; @@ -684,7 +684,7 @@ static int writer_dump_object_index(struct reftable_writer *w) infix_walk(w->obj_index_tree, &update_common, &common); w->stats.object_id_len = common.max + 1; - err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ); + err = writer_reinit_block_writer(w, REFTABLE_BLOCK_TYPE_OBJ); if (err < 0) return err; @@ -708,7 +708,7 @@ static int writer_finish_public_section(struct reftable_writer *w) err = writer_finish_section(w); if (err < 0) return err; - if (typ == BLOCK_TYPE_REF && !w->opts.skip_index_objects && + if (typ == REFTABLE_BLOCK_TYPE_REF && !w->opts.skip_index_objects && w->stats.ref_stats.index_blocks > 0) { err = writer_dump_object_index(w); if (err < 0) @@ -813,7 +813,7 @@ static int writer_flush_nonempty_block(struct reftable_writer *w) * By default, all records except for log records are padded to the * block size. */ - if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG) + if (!w->opts.unpadded && typ != REFTABLE_BLOCK_TYPE_LOG) padding = w->opts.block_size - raw_bytes; bstats = writer_reftable_block_stats(w, typ); diff --git a/reftable/writer.h b/reftable/writer.h index 1f4788a430..9f53610b27 100644 --- a/reftable/writer.h +++ b/reftable/writer.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef WRITER_H #define WRITER_H diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index 3c72ed985b..b16c0722c8 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -2,10 +2,11 @@ #include "hash.h" #include "hex.h" #include "reftable/system.h" +#include "reftable/reftable-constants.h" #include "reftable/reftable-error.h" #include "reftable/reftable-merged.h" -#include "reftable/reftable-reader.h" #include "reftable/reftable-stack.h" +#include "reftable/reftable-table.h" #include "test-tool.h" static void print_help(void) @@ -20,6 +21,72 @@ static void print_help(void) "\n"); } +static int dump_blocks(const char *tablename) +{ + struct reftable_table_iterator ti = { 0 }; + struct reftable_block_source src = { 0 }; + struct reftable_table *table = NULL; + uint8_t section_type = 0; + int err; + + err = reftable_block_source_from_file(&src, tablename); + if (err < 0) + goto done; + + err = reftable_table_new(&table, &src, tablename); + if (err < 0) + goto done; + + err = reftable_table_iterator_init(&ti, table); + if (err < 0) + goto done; + + printf("header:\n"); + printf(" block_size: %d\n", table->block_size); + + while (1) { + const struct reftable_block *block; + + err = reftable_table_iterator_next(&ti, &block); + if (err < 0) + goto done; + if (err > 0) + break; + + if (block->block_type != section_type) { + const char *section; + switch (block->block_type) { + case REFTABLE_BLOCK_TYPE_LOG: + section = "log"; + break; + case REFTABLE_BLOCK_TYPE_REF: + section = "ref"; + break; + case REFTABLE_BLOCK_TYPE_OBJ: + section = "obj"; + break; + case REFTABLE_BLOCK_TYPE_INDEX: + section = "idx"; + break; + default: + err = -1; + goto done; + } + + section_type = block->block_type; + printf("%s:\n", section); + } + + printf(" - length: %u\n", block->restart_off); + printf(" restarts: %u\n", block->restart_count); + } + +done: + reftable_table_iterator_release(&ti); + reftable_table_decref(table); + return err; +} + static int dump_table(struct reftable_merged_table *mt) { struct reftable_iterator it = { NULL }; @@ -126,19 +193,19 @@ static int dump_reftable(const char *tablename) { struct reftable_block_source src = { 0 }; struct reftable_merged_table *mt = NULL; - struct reftable_reader *r = NULL; + struct reftable_table *table = NULL; int err; err = reftable_block_source_from_file(&src, tablename); if (err < 0) goto done; - err = reftable_reader_new(&r, &src, tablename); + err = reftable_table_new(&table, &src, tablename); if (err < 0) goto done; - err = reftable_merged_table_new(&mt, &r, 1, - reftable_reader_hash_id(r)); + err = reftable_merged_table_new(&mt, &table, 1, + reftable_table_hash_id(table)); if (err < 0) goto done; @@ -146,7 +213,7 @@ static int dump_reftable(const char *tablename) done: reftable_merged_table_free(mt); - reftable_reader_decref(r); + reftable_table_decref(table); return err; } @@ -184,7 +251,7 @@ int cmd__dump_reftable(int argc, const char **argv) arg = argv[1]; if (opt_dump_blocks) { - err = reftable_reader_print_blocks(arg); + err = dump_blocks(arg); } else if (opt_dump_table) { err = dump_reftable(arg); } else if (opt_dump_stack) { diff --git a/t/meson.build b/t/meson.build index bfb744e886..43c9750b88 100644 --- a/t/meson.build +++ b/t/meson.build @@ -58,10 +58,10 @@ unit_test_programs = [ 'unit-tests/t-reftable-block.c', 'unit-tests/t-reftable-merged.c', 'unit-tests/t-reftable-pq.c', - 'unit-tests/t-reftable-reader.c', 'unit-tests/t-reftable-readwrite.c', 'unit-tests/t-reftable-record.c', 'unit-tests/t-reftable-stack.c', + 'unit-tests/t-reftable-table.c', ] foreach unit_test_program : unit_test_programs diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh index 42aa1592f8..6447920c9b 100755 --- a/t/t0613-reftable-write-options.sh +++ b/t/t0613-reftable-write-options.sh @@ -93,6 +93,9 @@ test_expect_success 'many refs results in multiple blocks' ' restarts: 3 - length: 3289 restarts: 3 + idx: + - length: 103 + restarts: 1 EOF test-tool dump-reftable -b .git/reftable/*.ref >actual && test_cmp expect actual @@ -241,6 +244,9 @@ test_expect_success 'object index gets written by default with ref index' ' restarts: 1 - length: 80 restarts: 1 + idx: + - length: 55 + restarts: 2 obj: - length: 11 restarts: 1 @@ -277,6 +283,9 @@ test_expect_success 'object index can be disabled' ' restarts: 1 - length: 80 restarts: 1 + idx: + - length: 55 + restarts: 2 EOF test-tool dump-reftable -b .git/reftable/*.ref >actual && test_cmp expect actual diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 22040aeefa..7dbd93601c 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -19,24 +19,25 @@ static void t_ref_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -62,9 +63,10 @@ static void t_ref_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source ,&block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -77,10 +79,9 @@ static void t_ref_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -89,7 +90,7 @@ static void t_ref_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -97,12 +98,11 @@ static void t_ref_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -113,24 +113,25 @@ static void t_log_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 2048; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -151,9 +152,10 @@ static void t_log_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -166,11 +168,10 @@ static void t_log_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_buf_reset(&want); check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -179,7 +180,7 @@ static void t_log_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -187,12 +188,11 @@ static void t_log_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -203,24 +203,25 @@ static void t_obj_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -243,9 +244,10 @@ static void t_obj_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -258,10 +260,9 @@ static void t_obj_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -270,12 +271,11 @@ static void t_obj_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -286,25 +286,26 @@ static void t_index_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.last_key = REFTABLE_BUF_INIT, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -314,7 +315,7 @@ static void t_index_block_read_write(void) snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); reftable_buf_init(&recs[i].u.idx.last_key); - recs[i].type = BLOCK_TYPE_INDEX; + recs[i].type = REFTABLE_BLOCK_TYPE_INDEX; check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); recs[i].u.idx.offset = i; @@ -327,9 +328,10 @@ static void t_index_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -342,10 +344,9 @@ static void t_index_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -354,7 +355,7 @@ static void t_index_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -362,22 +363,99 @@ static void t_index_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } +static void t_block_iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct block_writer writer = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record expected_refs[20]; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_block block = { 0 }; + struct reftable_buf data; + int err; + + data.len = 1024; + REFTABLE_CALLOC_ARRAY(data.buf, data.len); + check(data.buf != NULL); + + err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) data.buf, data.len, + 0, hash_size(REFTABLE_HASH_SHA1)); + check(!err); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) { + expected_refs[i] = (struct reftable_record) { + .type = REFTABLE_BLOCK_TYPE_REF, + .u.ref = { + .value_type = REFTABLE_REF_VAL1, + .refname = xstrfmt("refs/heads/branch-%02"PRIuMAX, (uintmax_t)i), + }, + }; + memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); + + err = block_writer_add(&writer, &expected_refs[i]); + check_int(err, ==, 0); + } + + err = block_writer_finish(&writer); + check_int(err, >, 0); + + block_source_from_buf(&source, &data); + reftable_block_init(&block, &source, 0, 0, data.len, REFTABLE_HASH_SIZE_SHA1); + + err = reftable_block_init_iterator(&block, &it); + check_int(err, ==, 0); + + for (size_t i = 0; ; i++) { + err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) { + check_int(i, ==, ARRAY_SIZE(expected_refs)); + break; + } + check_int(err, ==, 0); + + check(reftable_ref_record_equal(&ref, &expected_refs[i].u.ref, + REFTABLE_HASH_SIZE_SHA1)); + } + + err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist"); + check_int(err, ==, 0); + err = reftable_iterator_next_ref(&it, &ref); + check_int(err, ==, 1); + + err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13"); + check_int(err, ==, 0); + err = reftable_iterator_next_ref(&it, &ref); + check_int(err, ==, 0); + check(reftable_ref_record_equal(&ref, &expected_refs[13].u.ref, + REFTABLE_HASH_SIZE_SHA1)); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) + reftable_free(expected_refs[i].u.ref.refname); + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_block_release(&block); + block_writer_release(&writer); + reftable_buf_release(&data); +} + int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { TEST(t_index_block_read_write(), "read-write operations on index blocks work"); TEST(t_log_block_read_write(), "read-write operations on log blocks work"); TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); + TEST(t_block_iterator(), "block iterator works"); return test_done(); } diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c index 60836f80d6..18c3251a56 100644 --- a/t/unit-tests/t-reftable-merged.c +++ b/t/unit-tests/t-reftable-merged.c @@ -11,7 +11,7 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable/blocksource.h" #include "reftable/constants.h" #include "reftable/merged.h" -#include "reftable/reader.h" +#include "reftable/table.h" #include "reftable/reftable-error.h" #include "reftable/reftable-merged.h" #include "reftable/reftable-writer.h" @@ -19,7 +19,7 @@ https://developers.google.com/open-source/licenses/bsd static struct reftable_merged_table * merged_table_from_records(struct reftable_ref_record **refs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -28,8 +28,8 @@ merged_table_from_records(struct reftable_ref_record **refs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + check(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); check(*source != NULL); @@ -37,21 +37,21 @@ merged_table_from_records(struct reftable_ref_record **refs, t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); check(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); check(!err); return mt; } -static void readers_destroy(struct reftable_reader **readers, const size_t n) +static void tables_destroy(struct reftable_table **tables, const size_t n) { for (size_t i = 0; i < n; i++) - reftable_reader_decref(readers[i]); - reftable_free(readers); + reftable_table_decref(tables[i]); + reftable_free(tables); } static void t_merged_single_record(void) @@ -77,14 +77,14 @@ static void t_merged_single_record(void) size_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_ref_record ref = { 0 }; struct reftable_iterator it = { 0 }; int err; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); check(!err); err = reftable_iterator_seek_ref(&it, "a"); check(!err); @@ -94,7 +94,7 @@ static void t_merged_single_record(void) check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); @@ -154,9 +154,9 @@ static void t_merged_refs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; int err; struct reftable_ref_record *out = NULL; @@ -164,7 +164,7 @@ static void t_merged_refs(void) size_t cap = 0; size_t i; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); check(!err); err = reftable_iterator_seek_ref(&it, "a"); check(!err); @@ -193,7 +193,7 @@ static void t_merged_refs(void) for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } @@ -238,13 +238,13 @@ static void t_merged_seek_multiple_times(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); for (size_t i = 0; i < 5; i++) { int err = reftable_iterator_seek_ref(&it, "c"); @@ -266,7 +266,7 @@ static void t_merged_seek_multiple_times(void) for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); @@ -313,14 +313,14 @@ static void t_merged_seek_multiple_times_without_draining(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; int err; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); err = reftable_iterator_seek_ref(&it, "b"); check(!err); @@ -338,7 +338,7 @@ static void t_merged_seek_multiple_times_without_draining(void) for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); @@ -348,7 +348,7 @@ static void t_merged_seek_multiple_times_without_draining(void) static struct reftable_merged_table * merged_table_from_log_records(struct reftable_log_record **logs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -358,8 +358,8 @@ merged_table_from_log_records(struct reftable_log_record **logs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + check(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); check(*source != NULL); @@ -367,12 +367,12 @@ merged_table_from_log_records(struct reftable_log_record **logs, t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); check(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); check(!err); return mt; } @@ -435,9 +435,9 @@ static void t_merged_logs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = merged_table_from_log_records( - logs, &bs, &readers, sizes, bufs, 3); + logs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; int err; struct reftable_log_record *out = NULL; @@ -445,7 +445,7 @@ static void t_merged_logs(void) size_t cap = 0; size_t i; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); check(!err); err = reftable_iterator_seek_log(&it, "a"); check(!err); @@ -469,7 +469,7 @@ static void t_merged_logs(void) check(reftable_log_record_equal(want[i], &out[i], REFTABLE_HASH_SIZE_SHA1)); - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); check(!err); err = reftable_iterator_seek_log_at(&it, "a", 2); check(!err); @@ -485,7 +485,7 @@ static void t_merged_logs(void) for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } @@ -502,7 +502,7 @@ static void t_default_write_opts(void) int err; struct reftable_block_source source = { 0 }; uint32_t hash_id; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_merged_table *merged = NULL; reftable_writer_set_limits(w, 1, 1); @@ -516,18 +516,18 @@ static void t_default_write_opts(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); - hash_id = reftable_reader_hash_id(rd); + hash_id = reftable_table_hash_id(table); check_int(hash_id, ==, REFTABLE_HASH_SHA1); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA256); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA256); check_int(err, ==, REFTABLE_FORMAT_ERROR); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA1); check(!err); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_merged_table_free(merged); reftable_buf_release(&buf); } diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c index c128fe8616..fb5a4eb187 100644 --- a/t/unit-tests/t-reftable-pq.c +++ b/t/unit-tests/t-reftable-pq.c @@ -34,7 +34,7 @@ static void t_pq_record(void) char *last = NULL; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF)); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i); } @@ -57,7 +57,7 @@ static void t_pq_record(void) merged_iter_pqueue_check(&pq); check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); if (last) check_int(strcmp(last, e.rec->u.ref.refname), <, 0); last = e.rec->u.ref.refname; @@ -76,7 +76,7 @@ static void t_pq_index(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF)); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -100,7 +100,7 @@ static void t_pq_index(void) merged_iter_pqueue_check(&pq); check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); check_int(e.index, ==, i); if (last) check_str(last, e.rec->u.ref.refname); @@ -117,7 +117,7 @@ static void t_merged_iter_pqueue_top(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF)); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c deleted file mode 100644 index 546df6005e..0000000000 --- a/t/unit-tests/t-reftable-reader.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "test-lib.h" -#include "lib-reftable.h" -#include "reftable/blocksource.h" -#include "reftable/reader.h" - -static int t_reader_seek_once(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -static int t_reader_reseek(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - - for (size_t i = 0; i < 5; i++) { - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - } - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_reader_seek_once(), "reader can seek once"); - TEST(t_reader_reseek(), "reader can reseek multiple times"); - return test_done(); -} diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c index c9626831da..4c49129439 100644 --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/t-reftable-readwrite.c @@ -12,9 +12,9 @@ https://developers.google.com/open-source/licenses/bsd #include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/blocksource.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/reftable-writer.h" +#include "reftable/table.h" #include "strbuf.h" static const int update_index = 5; @@ -23,22 +23,22 @@ static void t_buffer(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_block out = { 0 }; + struct reftable_block_data out = { 0 }; int n; uint8_t in[] = "hello"; check(!reftable_buf_add(&buf, in, sizeof(in))); block_source_from_buf(&source, &buf); check_int(block_source_size(&source), ==, 6); - n = block_source_read_block(&source, &out, 0, sizeof(in)); + n = block_source_read_data(&source, &out, 0, sizeof(in)); check_int(n, ==, sizeof(in)); check(!memcmp(in, out.data, n)); - reftable_block_done(&out); + block_source_release_data(&out); - n = block_source_read_block(&source, &out, 1, 2); + n = block_source_read_data(&source, &out, 1, 2); check_int(n, ==, 2); check(!memcmp(out.data, "el", 2)); - reftable_block_done(&out); + block_source_release_data(&out); block_source_close(&source); reftable_buf_release(&buf); } @@ -204,7 +204,7 @@ static void t_log_write_read(void) struct reftable_ref_record ref = { 0 }; struct reftable_log_record log = { 0 }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -254,10 +254,10 @@ static void t_log_write_read(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[N - 1]); @@ -273,7 +273,7 @@ static void t_log_write_read(void) reftable_iterator_destroy(&it); reftable_ref_record_release(&ref); - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, ""); check(!err); @@ -294,7 +294,7 @@ static void t_log_write_read(void) /* cleanup. */ reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_log_zlib_corruption(void) @@ -303,7 +303,7 @@ static void t_log_zlib_corruption(void) .block_size = 256, }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -345,10 +345,10 @@ static void t_log_zlib_corruption(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check(!err); - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, "refname"); check_int(err, ==, REFTABLE_ZLIB_ERROR); @@ -356,7 +356,7 @@ static void t_log_zlib_corruption(void) reftable_iterator_destroy(&it); /* cleanup. */ - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -367,7 +367,7 @@ static void t_table_read_write_sequential(void) int N = 50; struct reftable_iterator it = { 0 }; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err = 0; int j = 0; @@ -375,10 +375,10 @@ static void t_table_read_write_sequential(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -396,7 +396,7 @@ static void t_table_read_write_sequential(void) check_int(j, ==, N); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); free_names(names); } @@ -417,7 +417,7 @@ static void t_table_read_api(void) char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; int err; struct reftable_log_record log = { 0 }; @@ -427,10 +427,10 @@ static void t_table_read_api(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[0]); check(!err); @@ -441,7 +441,7 @@ static void t_table_read_api(void) reftable_buf_release(&buf); free_names(names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -450,7 +450,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; int err; int i = 0; @@ -463,18 +463,18 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - check_int(hash_id, ==, reftable_reader_hash_id(reader)); + check_int(hash_id, ==, reftable_table_hash_id(table)); if (!index) { - reader->ref_offsets.index_offset = 0; + table->ref_offsets.index_offset = 0; } else { - check_int(reader->ref_offsets.index_offset, >, 0); + check_int(table->ref_offsets.index_offset, >, 0); } for (i = 1; i < N; i++) { - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[i]); check(!err); @@ -491,7 +491,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) check(!reftable_buf_addstr(&pastLast, names[N - 1])); check(!reftable_buf_addstr(&pastLast, "/")); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, pastLast.buf); if (err == 0) { @@ -507,7 +507,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_table_read_write_seek_linear(void) @@ -535,7 +535,7 @@ static void t_table_refs_for(int indexed) .block_size = 256, }; struct reftable_ref_record ref = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -585,18 +585,18 @@ static void t_table_refs_for(int indexed) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); if (!indexed) - reader->obj_offsets.is_present = 0; + table->obj_offsets.is_present = 0; - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); reftable_iterator_destroy(&it); - err = reftable_reader_refs_for(reader, &it, want_hash); + err = reftable_table_refs_for(table, &it, want_hash); check(!err); for (j = 0; ; j++) { @@ -613,7 +613,7 @@ static void t_table_refs_for(int indexed) reftable_buf_release(&buf); free_names(want_names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_table_refs_for_no_index(void) @@ -632,7 +632,7 @@ static void t_write_empty_table(void) struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); struct reftable_block_source source = { 0 }; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; int err; @@ -647,10 +647,10 @@ static void t_write_empty_table(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); - err = reftable_reader_init_ref_iterator(rd, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -659,7 +659,7 @@ static void t_write_empty_table(void) check_int(err, >, 0); reftable_iterator_destroy(&it); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -803,7 +803,7 @@ static void t_write_multiple_indices(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; char buf[128]; int err, i; @@ -852,21 +852,21 @@ static void t_write_multiple_indices(void) check_int(stats->log_stats.index_offset, >, 0); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); /* * Seeking the log uses the log index now. In case there is any * confusion regarding indices we would notice here. */ - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, ""); check(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); } @@ -880,7 +880,7 @@ static void t_write_multi_level_index(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; int err; writer = t_reftable_strbuf_writer(&writer_buf, &opts); @@ -909,20 +909,20 @@ static void t_write_multi_level_index(void) check_int(stats->ref_stats.max_index_level, ==, 2); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); /* * Seeking the last ref should work as expected. */ - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, "refs/heads/199"); check(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); reftable_buf_release(&buf); } @@ -931,11 +931,11 @@ static void t_corrupt_table_empty(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check_int(err, ==, REFTABLE_FORMAT_ERROR); } @@ -944,12 +944,12 @@ static void t_corrupt_table(void) uint8_t zeros[1024] = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; check(!reftable_buf_add(&buf, zeros, sizeof(zeros))); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check_int(err, ==, REFTABLE_FORMAT_ERROR); reftable_buf_release(&buf); diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c index 5954966373..553a007664 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/t-reftable-record.c @@ -84,17 +84,17 @@ static void t_reftable_ref_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_VAL1, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_DELETION, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "HEAD", .u.ref.value_type = REFTABLE_REF_SYMREF, .u.ref.value.symref = (char *) "refs/heads/master", @@ -141,10 +141,10 @@ static void t_reftable_ref_record_roundtrip(void) for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) { struct reftable_record in = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.value_type = i, }; - struct reftable_record out = { .type = BLOCK_TYPE_REF }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_REF }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -198,17 +198,17 @@ static void t_reftable_log_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 42, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 22, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/main", .u.log.update_index = 22, }, @@ -297,7 +297,7 @@ static void t_reftable_log_record_roundtrip(void) check(!reftable_log_record_is_deletion(&in[2])); for (size_t i = 0; i < ARRAY_SIZE(in); i++) { - struct reftable_record rec = { .type = BLOCK_TYPE_LOG }; + struct reftable_record rec = { .type = REFTABLE_BLOCK_TYPE_LOG }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -306,7 +306,7 @@ static void t_reftable_log_record_roundtrip(void) }; /* populate out, to check for leaks. */ struct reftable_record out = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log = { .refname = xstrdup("old name"), .value_type = REFTABLE_LOG_UPDATE, @@ -384,21 +384,21 @@ static void t_reftable_obj_record_comparison(void) uint64_t offsets[] = { 0, 16, 32, 48, 64, 80, 96, 112}; struct reftable_record in[3] = { { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 8, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 5, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 5, }, @@ -450,13 +450,13 @@ static void t_reftable_obj_record_roundtrip(void) .len = sizeof(buffer), }; struct reftable_record in = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u = { .obj = recs[i], }, }; struct reftable_buf key = REFTABLE_BUF_INIT; - struct reftable_record out = { .type = BLOCK_TYPE_OBJ }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_OBJ }; int n, m; uint8_t extra; @@ -482,17 +482,17 @@ static void t_reftable_index_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 22, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, @@ -523,7 +523,7 @@ static void t_reftable_index_record_comparison(void) static void t_reftable_index_record_roundtrip(void) { struct reftable_record in = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .offset = 42, .last_key = REFTABLE_BUF_INIT, @@ -537,7 +537,7 @@ static void t_reftable_index_record_roundtrip(void) struct reftable_buf scratch = REFTABLE_BUF_INIT; struct reftable_buf key = REFTABLE_BUF_INIT; struct reftable_record out = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int n, m; diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c index c3f0059c34..2f49c97519 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/t-reftable-stack.c @@ -12,9 +12,9 @@ https://developers.google.com/open-source/licenses/bsd #include "lib-reftable.h" #include "dir.h" #include "reftable/merged.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/stack.h" +#include "reftable/table.h" #include "strbuf.h" #include "tempfile.h" #include <dirent.h> @@ -176,7 +176,7 @@ static void t_reftable_stack_add_one(void) err = reftable_stack_read_ref(st, ref.refname, &dest); check(!err); check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); - check_int(st->readers_len, >, 0); + check_int(st->tables_len, >, 0); #ifndef GIT_WINDOWS_NATIVE check(!reftable_buf_addstr(&scratch, dir)); @@ -189,7 +189,7 @@ static void t_reftable_stack_add_one(void) check(!reftable_buf_addstr(&scratch, dir)); check(!reftable_buf_addstr(&scratch, "/")); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&scratch, st->readers[0]->name)); + check(!reftable_buf_addstr(&scratch, st->tables[0]->name)); err = stat(scratch.buf, &stat_result); check(!err); check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); @@ -402,9 +402,9 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + check_int(st->merged->tables_len, ==, i + 1); else - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); } reftable_stack_destroy(st); @@ -430,7 +430,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) err = reftable_stack_add(st, write_test_ref, &ref); check(!err); - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); check_int(st->stats.attempts, ==, 0); check_int(st->stats.failures, ==, 0); @@ -441,14 +441,14 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) */ check(!reftable_buf_addstr(&table_path, dir)); check(!reftable_buf_addstr(&table_path, "/")); - check(!reftable_buf_addstr(&table_path, st->readers[0]->name)); + check(!reftable_buf_addstr(&table_path, st->tables[0]->name)); check(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, "", 0); ref.update_index = 2; err = reftable_stack_add(st, write_test_ref, &ref); check(!err); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); check_int(st->stats.attempts, ==, 1); check_int(st->stats.failures, ==, 1); @@ -592,7 +592,7 @@ static void t_reftable_stack_add(void) check(!reftable_buf_addstr(&path, dir)); check(!reftable_buf_addstr(&path, "/")); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&path, st->readers[0]->name)); + check(!reftable_buf_addstr(&path, st->tables[0]->name)); err = stat(path.buf, &stat_result); check(!err); check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); @@ -1026,7 +1026,7 @@ static void t_reftable_stack_auto_compaction(void) err = reftable_stack_auto_compact(st); check(!err); - check(i < 2 || st->merged->readers_len < 2 * fastlogN(i, 2)); + check(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2)); } check_int(reftable_stack_compaction_stats(st)->entries_written, <, @@ -1061,7 +1061,7 @@ static void t_reftable_stack_auto_compaction_factor(void) err = reftable_stack_add(st, &write_test_ref, &ref); check(!err); - check(i < 5 || st->merged->readers_len < 5 * fastlogN(i, 5)); + check(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5)); } reftable_stack_destroy(st); @@ -1082,7 +1082,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) check(!err); write_n_ref_tables(st, 5); - check_int(st->merged->readers_len, ==, 5); + check_int(st->merged->tables_len, ==, 5); /* * Given that all tables we have written should be roughly the same @@ -1091,7 +1091,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) */ check(!reftable_buf_addstr(&buf, dir)); check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[2]->name)); + check(!reftable_buf_addstr(&buf, st->tables[2]->name)); check(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); @@ -1104,7 +1104,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) err = reftable_stack_auto_compact(st); check(!err); check_int(st->stats.failures, ==, 0); - check_int(st->merged->readers_len, ==, 4); + check_int(st->merged->tables_len, ==, 4); reftable_stack_destroy(st); reftable_buf_release(&buf); @@ -1149,9 +1149,9 @@ static void t_reftable_stack_add_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + check_int(st->merged->tables_len, ==, i + 1); else - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); } reftable_stack_destroy(st); @@ -1172,12 +1172,12 @@ static void t_reftable_stack_compaction_with_locked_tables(void) check(!err); write_n_ref_tables(st, 3); - check_int(st->merged->readers_len, ==, 3); + check_int(st->merged->tables_len, ==, 3); /* Lock one of the tables that we're about to compact. */ check(!reftable_buf_addstr(&buf, dir)); check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[1]->name)); + check(!reftable_buf_addstr(&buf, st->tables[1]->name)); check(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); @@ -1188,7 +1188,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void) err = reftable_stack_compact_all(st, NULL); check_int(err, ==, REFTABLE_LOCK_ERROR); check_int(st->stats.failures, ==, 1); - check_int(st->merged->readers_len, ==, 3); + check_int(st->merged->tables_len, ==, 3); reftable_stack_destroy(st); reftable_buf_release(&buf); @@ -1222,10 +1222,10 @@ static void t_reftable_stack_compaction_concurrent(void) static void unclean_stack_close(struct reftable_stack *st) { /* break abstraction boundary to simulate unclean shutdown. */ - for (size_t i = 0; i < st->readers_len; i++) - reftable_reader_decref(st->readers[i]); - st->readers_len = 0; - REFTABLE_FREE_AND_NULL(st->readers); + for (size_t i = 0; i < st->tables_len; i++) + reftable_table_decref(st->tables[i]); + st->tables_len = 0; + REFTABLE_FREE_AND_NULL(st->tables); } static void t_reftable_stack_compaction_concurrent_clean(void) @@ -1275,7 +1275,7 @@ static void t_reftable_stack_read_across_reload(void) err = reftable_new_stack(&st1, dir, &opts); check(!err); write_n_ref_tables(st1, 2); - check_int(st1->merged->readers_len, ==, 2); + check_int(st1->merged->tables_len, ==, 2); reftable_stack_init_ref_iterator(st1, &it); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -1283,10 +1283,10 @@ static void t_reftable_stack_read_across_reload(void) /* Set up a second stack for the same directory and compact it. */ err = reftable_new_stack(&st2, dir, &opts); check(!err); - check_int(st2->merged->readers_len, ==, 2); + check_int(st2->merged->tables_len, ==, 2); err = reftable_stack_compact_all(st2, NULL); check(!err); - check_int(st2->merged->readers_len, ==, 1); + check_int(st2->merged->tables_len, ==, 1); /* * Verify that we can continue to use the old iterator even after we @@ -1294,7 +1294,7 @@ static void t_reftable_stack_read_across_reload(void) */ err = reftable_stack_reload(st1); check(!err); - check_int(st1->merged->readers_len, ==, 1); + check_int(st1->merged->tables_len, ==, 1); err = reftable_iterator_next_ref(&it, &rec); check(!err); check_str(rec.refname, "refs/heads/branch-0000"); @@ -1325,19 +1325,19 @@ static void t_reftable_stack_reload_with_missing_table(void) err = reftable_new_stack(&st, dir, &opts); check(!err); write_n_ref_tables(st, 2); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); reftable_stack_init_ref_iterator(st, &it); err = reftable_iterator_seek_ref(&it, ""); check(!err); /* * Update the tables.list file with some garbage data, while reusing - * our old readers. This should trigger a partial reload of the stack, - * where we try to reuse our old readers. + * our old tables. This should trigger a partial reload of the stack, + * where we try to reuse our old tables. */ - check(!reftable_buf_addstr(&content, st->readers[0]->name)); + check(!reftable_buf_addstr(&content, st->tables[0]->name)); check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, st->readers[1]->name)); + check(!reftable_buf_addstr(&content, st->tables[1]->name)); check(!reftable_buf_addstr(&content, "\n")); check(!reftable_buf_addstr(&content, "garbage\n")); check(!reftable_buf_addstr(&table_path, st->list_file)); @@ -1348,7 +1348,7 @@ static void t_reftable_stack_reload_with_missing_table(void) err = reftable_stack_reload(st); check_int(err, ==, -4); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); /* * Even though the reload has failed, we should be able to continue diff --git a/t/unit-tests/t-reftable-table.c b/t/unit-tests/t-reftable-table.c new file mode 100644 index 0000000000..7e1eb533d0 --- /dev/null +++ b/t/unit-tests/t-reftable-table.c @@ -0,0 +1,206 @@ +#include "test-lib.h" +#include "lib-reftable.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/iter.h" +#include "reftable/table.h" +#include "strbuf.h" + +static int t_table_seek_once(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + reftable_table_init_ref_iterator(table, &it); + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + return 0; +} + +static int t_table_reseek(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + reftable_table_init_ref_iterator(table, &it); + + for (size_t i = 0; i < 5; i++) { + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + } + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + return 0; +} + +static int t_table_block_iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct reftable_table_iterator it = { 0 }; + struct reftable_ref_record *records; + const struct reftable_block *block; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct { + uint8_t block_type; + uint16_t header_off; + uint16_t restart_count; + uint16_t record_count; + } expected_blocks[] = { + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .header_off = 24, + .restart_count = 10, + .record_count = 158, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 2, + .record_count = 24, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_INDEX, + .restart_count = 1, + .record_count = 4, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_OBJ, + .restart_count = 1, + .record_count = 1, + }, + }; + const size_t nrecords = 500; + int ret; + + REFTABLE_CALLOC_ARRAY(records, nrecords); + for (size_t i = 0; i < nrecords; i++) { + records[i].value_type = REFTABLE_REF_VAL1; + records[i].refname = xstrfmt("refs/heads/branch-%03"PRIuMAX, + (uintmax_t) i); + } + + t_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + ret = reftable_table_iterator_init(&it, table); + check(!ret); + + for (size_t i = 0; i < ARRAY_SIZE(expected_blocks); i++) { + struct reftable_iterator record_it = { 0 }; + struct reftable_record record = { + .type = expected_blocks[i].block_type, + }; + + ret = reftable_table_iterator_next(&it, &block); + check(!ret); + + check_int(block->block_type, ==, expected_blocks[i].block_type); + check_int(block->header_off, ==, expected_blocks[i].header_off); + check_int(block->restart_count, ==, expected_blocks[i].restart_count); + + ret = reftable_block_init_iterator(block, &record_it); + check(!ret); + + for (size_t j = 0; ; j++) { + ret = iterator_next(&record_it, &record); + if (ret > 0) { + check_int(j, ==, expected_blocks[i].record_count); + break; + } + check(!ret); + } + + reftable_iterator_destroy(&record_it); + reftable_record_release(&record); + } + + ret = reftable_table_iterator_next(&it, &block); + check_int(ret, ==, 1); + + for (size_t i = 0; i < nrecords; i++) + reftable_free(records[i].refname); + reftable_table_iterator_release(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + reftable_free(records); + return 0; +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_table_seek_once(), "table can seek once"); + TEST(t_table_reseek(), "table can reseek multiple times"); + TEST(t_table_block_iterator(), "table can iterate through blocks"); + return test_done(); +} |
