Git fork

reftable/block: rename `block_reader` to `reftable_block`

The `block_reader` structure is used to access parsed data of a reftable
block. The structure is currently treated as an internal implementation
detail and not exposed via our public interfaces. The functionality
provided by the structure is useful to external users of the reftable
library though, for example when implementing consistency checks that
need to scan through the blocks manually.

Rename the structure to `reftable_block` now that the name has been made
available in the preceding commit. This name is in line with the naming
schema used for other data structures like `reftable_table` in that it
describes the underlying entity that it provides access to.

The new data structure isn't yet exposed via the public interface, which
is left for a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
12a9aa8c 2b3362c1

+172 -166
+71 -71
reftable/block.c
··· 222 return block_source_read_data(source, dest, off, sz); 223 } 224 225 - int block_reader_init(struct block_reader *br, 226 - struct reftable_block_source *source, 227 - uint32_t offset, uint32_t header_size, 228 - uint32_t table_block_size, uint32_t hash_size) 229 { 230 uint32_t guess_block_size = table_block_size ? 231 table_block_size : DEFAULT_BLOCK_SIZE; ··· 236 uint8_t block_type; 237 int err; 238 239 - err = read_block(source, &br->block_data, offset, guess_block_size); 240 if (err < 0) 241 goto done; 242 243 - block_type = br->block_data.data[header_size]; 244 if (!reftable_is_block_type(block_type)) { 245 err = REFTABLE_FORMAT_ERROR; 246 goto done; 247 } 248 249 - block_size = reftable_get_be24(br->block_data.data + header_size + 1); 250 if (block_size > guess_block_size) { 251 - err = read_block(source, &br->block_data, offset, block_size); 252 if (err < 0) 253 goto done; 254 } ··· 256 if (block_type == BLOCK_TYPE_LOG) { 257 uint32_t block_header_skip = 4 + header_size; 258 uLong dst_len = block_size - block_header_skip; 259 - uLong src_len = br->block_data.len - block_header_skip; 260 261 /* Log blocks specify the *uncompressed* size in their header. */ 262 - REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, block_size, 263 - br->uncompressed_cap); 264 - if (!br->uncompressed_data) { 265 err = REFTABLE_OUT_OF_MEMORY_ERROR; 266 goto done; 267 } 268 269 /* Copy over the block header verbatim. It's not compressed. */ 270 - memcpy(br->uncompressed_data, br->block_data.data, block_header_skip); 271 272 - if (!br->zstream) { 273 - REFTABLE_CALLOC_ARRAY(br->zstream, 1); 274 - if (!br->zstream) { 275 err = REFTABLE_OUT_OF_MEMORY_ERROR; 276 goto done; 277 } 278 279 - err = inflateInit(br->zstream); 280 } else { 281 - err = inflateReset(br->zstream); 282 } 283 if (err != Z_OK) { 284 err = REFTABLE_ZLIB_ERROR; 285 goto done; 286 } 287 288 - br->zstream->next_in = br->block_data.data + block_header_skip; 289 - br->zstream->avail_in = src_len; 290 - br->zstream->next_out = br->uncompressed_data + block_header_skip; 291 - br->zstream->avail_out = dst_len; 292 293 /* 294 * We know both input as well as output size, and we know that ··· 297 * here to instruct zlib to inflate the data in one go, which 298 * is more efficient than using `Z_NO_FLUSH`. 299 */ 300 - err = inflate(br->zstream, Z_FINISH); 301 if (err != Z_STREAM_END) { 302 err = REFTABLE_ZLIB_ERROR; 303 goto done; 304 } 305 err = 0; 306 307 - if (br->zstream->total_out + block_header_skip != block_size) { 308 err = REFTABLE_FORMAT_ERROR; 309 goto done; 310 } 311 312 /* We're done with the input data. */ 313 - block_source_release_data(&br->block_data); 314 - br->block_data.data = br->uncompressed_data; 315 - br->block_data.len = block_size; 316 - full_block_size = src_len + block_header_skip - br->zstream->avail_in; 317 } else if (full_block_size == 0) { 318 full_block_size = block_size; 319 - } else if (block_size < full_block_size && block_size < br->block_data.len && 320 - br->block_data.data[block_size] != 0) { 321 /* If the block is smaller than the full block size, it is 322 padded (data followed by '\0') or the next block is 323 unaligned. */ 324 full_block_size = block_size; 325 } 326 327 - restart_count = reftable_get_be16(br->block_data.data + block_size - 2); 328 restart_off = block_size - 2 - 3 * restart_count; 329 330 - br->block_type = block_type; 331 - br->hash_size = hash_size; 332 - br->restart_off = restart_off; 333 - br->full_block_size = full_block_size; 334 - br->header_off = header_size; 335 - br->restart_count = restart_count; 336 337 err = 0; 338 339 done: 340 if (err < 0) 341 - block_reader_release(br); 342 return err; 343 } 344 345 - void block_reader_release(struct block_reader *br) 346 { 347 - inflateEnd(br->zstream); 348 - reftable_free(br->zstream); 349 - reftable_free(br->uncompressed_data); 350 - block_source_release_data(&br->block_data); 351 - memset(br, 0, sizeof(*br)); 352 } 353 354 - uint8_t block_reader_type(const struct block_reader *r) 355 { 356 - return r->block_data.data[r->header_off]; 357 } 358 359 - int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key) 360 { 361 - int off = br->header_off + 4, n; 362 struct string_view in = { 363 - .buf = br->block_data.data + off, 364 - .len = br->restart_off - off, 365 }; 366 uint8_t extra = 0; 367 ··· 376 return 0; 377 } 378 379 - static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx) 380 { 381 - return reftable_get_be24(br->block_data.data + br->restart_off + 3 * idx); 382 } 383 384 - void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) 385 { 386 - it->block = br->block_data.data; 387 - it->block_len = br->restart_off; 388 - it->hash_size = br->hash_size; 389 reftable_buf_reset(&it->last_key); 390 - it->next_off = br->header_off + 4; 391 } 392 393 struct restart_needle_less_args { 394 int error; 395 struct reftable_buf needle; 396 - const struct block_reader *reader; 397 }; 398 399 static int restart_needle_less(size_t idx, void *_args) 400 { 401 struct restart_needle_less_args *args = _args; 402 - uint32_t off = block_reader_restart_offset(args->reader, idx); 403 struct string_view in = { 404 - .buf = args->reader->block_data.data + off, 405 - .len = args->reader->restart_off - off, 406 }; 407 uint64_t prefix_len, suffix_len; 408 uint8_t extra; ··· 477 reftable_buf_release(&it->scratch); 478 } 479 480 - int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, 481 struct reftable_buf *want) 482 { 483 struct restart_needle_less_args args = { 484 .needle = *want, 485 - .reader = br, 486 }; 487 struct reftable_record rec; 488 int err = 0; ··· 500 * restart point. While that works alright, we would end up scanning 501 * too many record. 502 */ 503 - i = binsearch(br->restart_count, &restart_needle_less, &args); 504 if (args.error) { 505 err = REFTABLE_FORMAT_ERROR; 506 goto done; ··· 525 * starting from the preceding restart point. 526 */ 527 if (i > 0) 528 - it->next_off = block_reader_restart_offset(br, i - 1); 529 else 530 - it->next_off = br->header_off + 4; 531 - it->block = br->block_data.data; 532 - it->block_len = br->restart_off; 533 - it->hash_size = br->hash_size; 534 535 - err = reftable_record_init(&rec, block_reader_type(br)); 536 if (err < 0) 537 goto done; 538 539 /* 540 * We're looking for the last entry less than the wanted key so that 541 * the next call to `block_reader_next()` would yield the wanted 542 - * record. We thus don't want to position our reader at the sought 543 * after record, but one before. To do so, we have to go one entry too 544 * far and then back up. 545 */
··· 222 return block_source_read_data(source, dest, off, sz); 223 } 224 225 + int reftable_block_init(struct reftable_block *block, 226 + struct reftable_block_source *source, 227 + uint32_t offset, uint32_t header_size, 228 + uint32_t table_block_size, uint32_t hash_size) 229 { 230 uint32_t guess_block_size = table_block_size ? 231 table_block_size : DEFAULT_BLOCK_SIZE; ··· 236 uint8_t block_type; 237 int err; 238 239 + err = read_block(source, &block->block_data, offset, guess_block_size); 240 if (err < 0) 241 goto done; 242 243 + block_type = block->block_data.data[header_size]; 244 if (!reftable_is_block_type(block_type)) { 245 err = REFTABLE_FORMAT_ERROR; 246 goto done; 247 } 248 249 + block_size = reftable_get_be24(block->block_data.data + header_size + 1); 250 if (block_size > guess_block_size) { 251 + err = read_block(source, &block->block_data, offset, block_size); 252 if (err < 0) 253 goto done; 254 } ··· 256 if (block_type == BLOCK_TYPE_LOG) { 257 uint32_t block_header_skip = 4 + header_size; 258 uLong dst_len = block_size - block_header_skip; 259 + uLong src_len = block->block_data.len - block_header_skip; 260 261 /* Log blocks specify the *uncompressed* size in their header. */ 262 + REFTABLE_ALLOC_GROW_OR_NULL(block->uncompressed_data, block_size, 263 + block->uncompressed_cap); 264 + if (!block->uncompressed_data) { 265 err = REFTABLE_OUT_OF_MEMORY_ERROR; 266 goto done; 267 } 268 269 /* Copy over the block header verbatim. It's not compressed. */ 270 + memcpy(block->uncompressed_data, block->block_data.data, block_header_skip); 271 272 + if (!block->zstream) { 273 + REFTABLE_CALLOC_ARRAY(block->zstream, 1); 274 + if (!block->zstream) { 275 err = REFTABLE_OUT_OF_MEMORY_ERROR; 276 goto done; 277 } 278 279 + err = inflateInit(block->zstream); 280 } else { 281 + err = inflateReset(block->zstream); 282 } 283 if (err != Z_OK) { 284 err = REFTABLE_ZLIB_ERROR; 285 goto done; 286 } 287 288 + block->zstream->next_in = block->block_data.data + block_header_skip; 289 + block->zstream->avail_in = src_len; 290 + block->zstream->next_out = block->uncompressed_data + block_header_skip; 291 + block->zstream->avail_out = dst_len; 292 293 /* 294 * We know both input as well as output size, and we know that ··· 297 * here to instruct zlib to inflate the data in one go, which 298 * is more efficient than using `Z_NO_FLUSH`. 299 */ 300 + err = inflate(block->zstream, Z_FINISH); 301 if (err != Z_STREAM_END) { 302 err = REFTABLE_ZLIB_ERROR; 303 goto done; 304 } 305 err = 0; 306 307 + if (block->zstream->total_out + block_header_skip != block_size) { 308 err = REFTABLE_FORMAT_ERROR; 309 goto done; 310 } 311 312 /* We're done with the input data. */ 313 + block_source_release_data(&block->block_data); 314 + block->block_data.data = block->uncompressed_data; 315 + block->block_data.len = block_size; 316 + full_block_size = src_len + block_header_skip - block->zstream->avail_in; 317 } else if (full_block_size == 0) { 318 full_block_size = block_size; 319 + } else if (block_size < full_block_size && block_size < block->block_data.len && 320 + block->block_data.data[block_size] != 0) { 321 /* If the block is smaller than the full block size, it is 322 padded (data followed by '\0') or the next block is 323 unaligned. */ 324 full_block_size = block_size; 325 } 326 327 + restart_count = reftable_get_be16(block->block_data.data + block_size - 2); 328 restart_off = block_size - 2 - 3 * restart_count; 329 330 + block->block_type = block_type; 331 + block->hash_size = hash_size; 332 + block->restart_off = restart_off; 333 + block->full_block_size = full_block_size; 334 + block->header_off = header_size; 335 + block->restart_count = restart_count; 336 337 err = 0; 338 339 done: 340 if (err < 0) 341 + reftable_block_release(block); 342 return err; 343 } 344 345 + void reftable_block_release(struct reftable_block *block) 346 { 347 + inflateEnd(block->zstream); 348 + reftable_free(block->zstream); 349 + reftable_free(block->uncompressed_data); 350 + block_source_release_data(&block->block_data); 351 + memset(block, 0, sizeof(*block)); 352 } 353 354 + uint8_t reftable_block_type(const struct reftable_block *b) 355 { 356 + return b->block_data.data[b->header_off]; 357 } 358 359 + int reftable_block_first_key(const struct reftable_block *block, struct reftable_buf *key) 360 { 361 + int off = block->header_off + 4, n; 362 struct string_view in = { 363 + .buf = block->block_data.data + off, 364 + .len = block->restart_off - off, 365 }; 366 uint8_t extra = 0; 367 ··· 376 return 0; 377 } 378 379 + static uint32_t block_restart_offset(const struct reftable_block *b, size_t idx) 380 { 381 + return reftable_get_be24(b->block_data.data + b->restart_off + 3 * idx); 382 } 383 384 + void block_iter_seek_start(struct block_iter *it, const struct reftable_block *b) 385 { 386 + it->block = b->block_data.data; 387 + it->block_len = b->restart_off; 388 + it->hash_size = b->hash_size; 389 reftable_buf_reset(&it->last_key); 390 + it->next_off = b->header_off + 4; 391 } 392 393 struct restart_needle_less_args { 394 int error; 395 struct reftable_buf needle; 396 + const struct reftable_block *block; 397 }; 398 399 static int restart_needle_less(size_t idx, void *_args) 400 { 401 struct restart_needle_less_args *args = _args; 402 + uint32_t off = block_restart_offset(args->block, idx); 403 struct string_view in = { 404 + .buf = args->block->block_data.data + off, 405 + .len = args->block->restart_off - off, 406 }; 407 uint64_t prefix_len, suffix_len; 408 uint8_t extra; ··· 477 reftable_buf_release(&it->scratch); 478 } 479 480 + int block_iter_seek_key(struct block_iter *it, const struct reftable_block *block, 481 struct reftable_buf *want) 482 { 483 struct restart_needle_less_args args = { 484 .needle = *want, 485 + .block = block, 486 }; 487 struct reftable_record rec; 488 int err = 0; ··· 500 * restart point. While that works alright, we would end up scanning 501 * too many record. 502 */ 503 + i = binsearch(block->restart_count, &restart_needle_less, &args); 504 if (args.error) { 505 err = REFTABLE_FORMAT_ERROR; 506 goto done; ··· 525 * starting from the preceding restart point. 526 */ 527 if (i > 0) 528 + it->next_off = block_restart_offset(block, i - 1); 529 else 530 + it->next_off = block->header_off + 4; 531 + it->block = block->block_data.data; 532 + it->block_len = block->restart_off; 533 + it->hash_size = block->hash_size; 534 535 + err = reftable_record_init(&rec, reftable_block_type(block)); 536 if (err < 0) 537 goto done; 538 539 /* 540 * We're looking for the last entry less than the wanted key so that 541 * the next call to `block_reader_next()` would yield the wanted 542 + * record. We thus don't want to position our iterator at the sought 543 * after record, but one before. To do so, we have to go one entry too 544 * far and then back up. 545 */
+17 -12
reftable/block.h
··· 64 65 struct z_stream; 66 67 - /* Read a block. */ 68 - struct block_reader { 69 /* offset of the block header; nonzero for the first block in a 70 * reftable. */ 71 uint32_t header_off; ··· 92 uint8_t block_type; 93 }; 94 95 - /* initializes a block reader. */ 96 - int block_reader_init(struct block_reader *br, 97 - struct reftable_block_source *source, 98 - uint32_t offset, uint32_t header_size, 99 - uint32_t table_block_size, uint32_t hash_size); 100 101 - void block_reader_release(struct block_reader *br); 102 103 /* Returns the block type (eg. 'r' for refs) */ 104 - uint8_t block_reader_type(const struct block_reader *r); 105 106 /* Decodes the first key in the block */ 107 - int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key); 108 109 /* Iterate over entries in a block */ 110 struct block_iter { ··· 125 } 126 127 /* Position `it` at start of the block */ 128 - void block_iter_seek_start(struct block_iter *it, const struct block_reader *br); 129 130 /* Position `it` to the `want` key in the block */ 131 - int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, 132 struct reftable_buf *want); 133 134 /* return < 0 for error, 0 for OK, > 0 for EOF. */
··· 64 65 struct z_stream; 66 67 + /* 68 + * A block part of a reftable. Contains records as well as some metadata 69 + * describing them. 70 + */ 71 + struct reftable_block { 72 /* offset of the block header; nonzero for the first block in a 73 * reftable. */ 74 uint32_t header_off; ··· 95 uint8_t block_type; 96 }; 97 98 + /* 99 + * Initialize a reftable block from the given block source. 100 + */ 101 + int reftable_block_init(struct reftable_block *b, 102 + struct reftable_block_source *source, 103 + uint32_t offset, uint32_t header_size, 104 + uint32_t table_block_size, uint32_t hash_size); 105 106 + void reftable_block_release(struct reftable_block *b); 107 108 /* Returns the block type (eg. 'r' for refs) */ 109 + uint8_t reftable_block_type(const struct reftable_block *b); 110 111 /* Decodes the first key in the block */ 112 + int reftable_block_first_key(const struct reftable_block *b, struct reftable_buf *key); 113 114 /* Iterate over entries in a block */ 115 struct block_iter { ··· 130 } 131 132 /* Position `it` at start of the block */ 133 + void block_iter_seek_start(struct block_iter *it, const struct reftable_block *block); 134 135 /* Position `it` to the `want` key in the block */ 136 + int block_iter_seek_key(struct block_iter *it, const struct reftable_block *block, 137 struct reftable_buf *want); 138 139 /* return < 0 for error, 0 for OK, > 0 for EOF. */
+4 -5
reftable/iter.c
··· 114 { 115 struct indexed_table_ref_iter *it = p; 116 block_iter_close(&it->cur); 117 - block_source_release_data(&it->block_reader.block_data); 118 reftable_free(it->offsets); 119 reftable_buf_release(&it->oid); 120 } ··· 128 return 1; 129 } 130 131 - block_source_release_data(&it->block_reader.block_data); 132 133 off = it->offsets[it->offset_idx++]; 134 - err = table_init_block_reader(it->table, &it->block_reader, off, 135 - BLOCK_TYPE_REF); 136 if (err < 0) { 137 return err; 138 } ··· 140 /* indexed block does not exist. */ 141 return REFTABLE_FORMAT_ERROR; 142 } 143 - block_iter_seek_start(&it->cur, &it->block_reader); 144 return 0; 145 } 146
··· 114 { 115 struct indexed_table_ref_iter *it = p; 116 block_iter_close(&it->cur); 117 + block_source_release_data(&it->block.block_data); 118 reftable_free(it->offsets); 119 reftable_buf_release(&it->oid); 120 } ··· 128 return 1; 129 } 130 131 + block_source_release_data(&it->block.block_data); 132 133 off = it->offsets[it->offset_idx++]; 134 + err = table_init_block(it->table, &it->block, off, BLOCK_TYPE_REF); 135 if (err < 0) { 136 return err; 137 } ··· 139 /* indexed block does not exist. */ 140 return REFTABLE_FORMAT_ERROR; 141 } 142 + block_iter_seek_start(&it->cur, &it->block); 143 return 0; 144 } 145
+1 -1
reftable/iter.h
··· 68 /* Points to the next offset to read. */ 69 int offset_idx; 70 int offset_len; 71 - struct block_reader block_reader; 72 struct block_iter cur; 73 int is_finished; 74 };
··· 68 /* Points to the next offset to read. */ 69 int offset_idx; 70 int offset_len; 71 + struct reftable_block block; 72 struct block_iter cur; 73 int is_finished; 74 };
+23 -23
reftable/table.c
··· 131 struct reftable_table *table; 132 uint8_t typ; 133 uint64_t block_off; 134 - struct block_reader br; 135 struct block_iter bi; 136 int is_finished; 137 }; ··· 159 160 static void table_iter_block_done(struct table_iter *ti) 161 { 162 - block_reader_release(&ti->br); 163 block_iter_reset(&ti->bi); 164 } 165 166 - int table_init_block_reader(struct reftable_table *t, struct block_reader *br, 167 - uint64_t next_off, uint8_t want_typ) 168 { 169 uint32_t header_off = next_off ? 0 : header_size(t->version); 170 int err; ··· 172 if (next_off >= t->size) 173 return 1; 174 175 - err = block_reader_init(br, &t->source, next_off, header_off, 176 - t->block_size, hash_size(t->hash_id)); 177 if (err < 0) 178 goto done; 179 180 - if (want_typ != BLOCK_TYPE_ANY && br->block_type != want_typ) { 181 err = 1; 182 goto done; 183 } 184 185 done: 186 if (err) 187 - block_reader_release(br); 188 return err; 189 } 190 ··· 197 198 static int table_iter_next_block(struct table_iter *ti) 199 { 200 - uint64_t next_block_off = ti->block_off + ti->br.full_block_size; 201 int err; 202 203 - err = table_init_block_reader(ti->table, &ti->br, next_block_off, ti->typ); 204 if (err > 0) 205 ti->is_finished = 1; 206 if (err) ··· 208 209 ti->block_off = next_block_off; 210 ti->is_finished = 0; 211 - block_iter_seek_start(&ti->bi, &ti->br); 212 213 return 0; 214 } ··· 250 { 251 int err; 252 253 - err = table_init_block_reader(ti->table, &ti->br, off, typ); 254 if (err != 0) 255 return err; 256 257 - ti->typ = block_reader_type(&ti->br); 258 ti->block_off = off; 259 - block_iter_seek_start(&ti->bi, &ti->br); 260 ti->is_finished = 0; 261 return 0; 262 } ··· 320 * as we have more than three blocks we would have an index, so 321 * we would not do a linear search there anymore. 322 */ 323 - memset(&next.br.block_data, 0, sizeof(next.br.block_data)); 324 - next.br.zstream = NULL; 325 - next.br.uncompressed_data = NULL; 326 - next.br.uncompressed_cap = 0; 327 328 err = table_iter_next_block(&next); 329 if (err < 0) ··· 331 if (err > 0) 332 break; 333 334 - err = block_reader_first_key(&next.br, &got_key); 335 if (err < 0) 336 goto done; 337 ··· 349 * the wanted key inside of it. If the block does not contain our key 350 * we know that the corresponding record does not exist. 351 */ 352 - err = block_iter_seek_key(&ti->bi, &ti->br, &want_key); 353 if (err < 0) 354 goto done; 355 err = 0; ··· 417 if (err != 0) 418 goto done; 419 420 - err = block_iter_seek_key(&ti->bi, &ti->br, &want_index.u.idx.last_key); 421 if (err < 0) 422 goto done; 423 ··· 785 printf("%s:\n", sections[i].name); 786 787 while (1) { 788 - printf(" - length: %u\n", ti.br.restart_off); 789 - printf(" restarts: %u\n", ti.br.restart_count); 790 791 err = table_iter_next_block(&ti); 792 if (err < 0)
··· 131 struct reftable_table *table; 132 uint8_t typ; 133 uint64_t block_off; 134 + struct reftable_block block; 135 struct block_iter bi; 136 int is_finished; 137 }; ··· 159 160 static void table_iter_block_done(struct table_iter *ti) 161 { 162 + reftable_block_release(&ti->block); 163 block_iter_reset(&ti->bi); 164 } 165 166 + int table_init_block(struct reftable_table *t, struct reftable_block *block, 167 + uint64_t next_off, uint8_t want_typ) 168 { 169 uint32_t header_off = next_off ? 0 : header_size(t->version); 170 int err; ··· 172 if (next_off >= t->size) 173 return 1; 174 175 + err = reftable_block_init(block, &t->source, next_off, header_off, 176 + t->block_size, hash_size(t->hash_id)); 177 if (err < 0) 178 goto done; 179 180 + if (want_typ != BLOCK_TYPE_ANY && block->block_type != want_typ) { 181 err = 1; 182 goto done; 183 } 184 185 done: 186 if (err) 187 + reftable_block_release(block); 188 return err; 189 } 190 ··· 197 198 static int table_iter_next_block(struct table_iter *ti) 199 { 200 + uint64_t next_block_off = ti->block_off + ti->block.full_block_size; 201 int err; 202 203 + err = table_init_block(ti->table, &ti->block, next_block_off, ti->typ); 204 if (err > 0) 205 ti->is_finished = 1; 206 if (err) ··· 208 209 ti->block_off = next_block_off; 210 ti->is_finished = 0; 211 + block_iter_seek_start(&ti->bi, &ti->block); 212 213 return 0; 214 } ··· 250 { 251 int err; 252 253 + err = table_init_block(ti->table, &ti->block, off, typ); 254 if (err != 0) 255 return err; 256 257 + ti->typ = reftable_block_type(&ti->block); 258 ti->block_off = off; 259 + block_iter_seek_start(&ti->bi, &ti->block); 260 ti->is_finished = 0; 261 return 0; 262 } ··· 320 * as we have more than three blocks we would have an index, so 321 * we would not do a linear search there anymore. 322 */ 323 + memset(&next.block.block_data, 0, sizeof(next.block.block_data)); 324 + next.block.zstream = NULL; 325 + next.block.uncompressed_data = NULL; 326 + next.block.uncompressed_cap = 0; 327 328 err = table_iter_next_block(&next); 329 if (err < 0) ··· 331 if (err > 0) 332 break; 333 334 + err = reftable_block_first_key(&next.block, &got_key); 335 if (err < 0) 336 goto done; 337 ··· 349 * the wanted key inside of it. If the block does not contain our key 350 * we know that the corresponding record does not exist. 351 */ 352 + err = block_iter_seek_key(&ti->bi, &ti->block, &want_key); 353 if (err < 0) 354 goto done; 355 err = 0; ··· 417 if (err != 0) 418 goto done; 419 420 + err = block_iter_seek_key(&ti->bi, &ti->block, &want_index.u.idx.last_key); 421 if (err < 0) 422 goto done; 423 ··· 785 printf("%s:\n", sections[i].name); 786 787 while (1) { 788 + printf(" - length: %u\n", ti.block.restart_off); 789 + printf(" restarts: %u\n", ti.block.restart_count); 790 791 err = table_iter_next_block(&ti); 792 if (err < 0)
+5 -3
reftable/table.h
··· 53 struct reftable_iterator *it, 54 uint8_t typ); 55 56 - /* initialize a block reader to read from `t` */ 57 - int table_init_block_reader(struct reftable_table *t, struct block_reader *br, 58 - uint64_t next_off, uint8_t want_typ); 59 60 #endif
··· 53 struct reftable_iterator *it, 54 uint8_t typ); 55 56 + /* 57 + * Initialize a block by reading from the given table and offset. 58 + */ 59 + int table_init_block(struct reftable_table *t, struct reftable_block *block, 60 + uint64_t next_off, uint8_t want_typ); 61 62 #endif
+51 -51
t/unit-tests/t-reftable-block.c
··· 28 }; 29 size_t i = 0; 30 int ret; 31 - struct block_reader br = { 0 }; 32 struct block_iter it = BLOCK_ITER_INIT; 33 struct reftable_buf want = REFTABLE_BUF_INIT; 34 - struct reftable_buf block = REFTABLE_BUF_INIT; 35 36 - REFTABLE_CALLOC_ARRAY(block.buf, block_size); 37 - check(block.buf != NULL); 38 - block.len = block_size; 39 40 - ret = block_writer_init(&bw, BLOCK_TYPE_REF, (uint8_t *) block.buf, block_size, 41 header_off, hash_size(REFTABLE_HASH_SHA1)); 42 check(!ret); 43 ··· 63 64 block_writer_release(&bw); 65 66 - block_source_from_buf(&source ,&block); 67 - block_reader_init(&br, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 68 69 - block_iter_seek_start(&it, &br); 70 71 for (i = 0; ; i++) { 72 ret = block_iter_next(&it, &rec); ··· 82 block_iter_reset(&it); 83 reftable_record_key(&recs[i], &want); 84 85 - ret = block_iter_seek_key(&it, &br, &want); 86 check_int(ret, ==, 0); 87 88 ret = block_iter_next(&it, &rec); ··· 91 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 92 93 want.len--; 94 - ret = block_iter_seek_key(&it, &br, &want); 95 check_int(ret, ==, 0); 96 97 ret = block_iter_next(&it, &rec); ··· 99 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 100 } 101 102 - block_reader_release(&br); 103 block_iter_close(&it); 104 reftable_record_release(&rec); 105 reftable_buf_release(&want); 106 - reftable_buf_release(&block); 107 for (i = 0; i < N; i++) 108 reftable_record_release(&recs[i]); 109 } ··· 123 }; 124 size_t i = 0; 125 int ret; 126 - struct block_reader br = { 0 }; 127 struct block_iter it = BLOCK_ITER_INIT; 128 struct reftable_buf want = REFTABLE_BUF_INIT; 129 - struct reftable_buf block = REFTABLE_BUF_INIT; 130 131 - REFTABLE_CALLOC_ARRAY(block.buf, block_size); 132 - check(block.buf != NULL); 133 - block.len = block_size; 134 135 - ret = block_writer_init(&bw, BLOCK_TYPE_LOG, (uint8_t *) block.buf, block_size, 136 header_off, hash_size(REFTABLE_HASH_SHA1)); 137 check(!ret); 138 ··· 153 154 block_writer_release(&bw); 155 156 - block_source_from_buf(&source, &block); 157 - block_reader_init(&br, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 158 159 - block_iter_seek_start(&it, &br); 160 161 for (i = 0; ; i++) { 162 ret = block_iter_next(&it, &rec); ··· 173 reftable_buf_reset(&want); 174 check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); 175 176 - ret = block_iter_seek_key(&it, &br, &want); 177 check_int(ret, ==, 0); 178 179 ret = block_iter_next(&it, &rec); ··· 182 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 183 184 want.len--; 185 - ret = block_iter_seek_key(&it, &br, &want); 186 check_int(ret, ==, 0); 187 188 ret = block_iter_next(&it, &rec); ··· 190 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 191 } 192 193 - block_reader_release(&br); 194 block_iter_close(&it); 195 reftable_record_release(&rec); 196 reftable_buf_release(&want); 197 - reftable_buf_release(&block); 198 for (i = 0; i < N; i++) 199 reftable_record_release(&recs[i]); 200 } ··· 214 }; 215 size_t i = 0; 216 int ret; 217 - struct block_reader br = { 0 }; 218 struct block_iter it = BLOCK_ITER_INIT; 219 struct reftable_buf want = REFTABLE_BUF_INIT; 220 - struct reftable_buf block = REFTABLE_BUF_INIT; 221 222 - REFTABLE_CALLOC_ARRAY(block.buf, block_size); 223 - check(block.buf != NULL); 224 - block.len = block_size; 225 226 - ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, (uint8_t *) block.buf, block_size, 227 header_off, hash_size(REFTABLE_HASH_SHA1)); 228 check(!ret); 229 ··· 246 247 block_writer_release(&bw); 248 249 - block_source_from_buf(&source, &block); 250 - block_reader_init(&br, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 251 252 - block_iter_seek_start(&it, &br); 253 254 for (i = 0; ; i++) { 255 ret = block_iter_next(&it, &rec); ··· 265 block_iter_reset(&it); 266 reftable_record_key(&recs[i], &want); 267 268 - ret = block_iter_seek_key(&it, &br, &want); 269 check_int(ret, ==, 0); 270 271 ret = block_iter_next(&it, &rec); ··· 274 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 275 } 276 277 - block_reader_release(&br); 278 block_iter_close(&it); 279 reftable_record_release(&rec); 280 reftable_buf_release(&want); 281 - reftable_buf_release(&block); 282 for (i = 0; i < N; i++) 283 reftable_record_release(&recs[i]); 284 } ··· 299 }; 300 size_t i = 0; 301 int ret; 302 - struct block_reader br = { 0 }; 303 struct block_iter it = BLOCK_ITER_INIT; 304 struct reftable_buf want = REFTABLE_BUF_INIT; 305 - struct reftable_buf block = REFTABLE_BUF_INIT; 306 307 - REFTABLE_CALLOC_ARRAY(block.buf, block_size); 308 - check(block.buf != NULL); 309 - block.len = block_size; 310 311 - ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, (uint8_t *) block.buf, block_size, 312 header_off, hash_size(REFTABLE_HASH_SHA1)); 313 check(!ret); 314 ··· 331 332 block_writer_release(&bw); 333 334 - block_source_from_buf(&source, &block); 335 - block_reader_init(&br, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 336 337 - block_iter_seek_start(&it, &br); 338 339 for (i = 0; ; i++) { 340 ret = block_iter_next(&it, &rec); ··· 350 block_iter_reset(&it); 351 reftable_record_key(&recs[i], &want); 352 353 - ret = block_iter_seek_key(&it, &br, &want); 354 check_int(ret, ==, 0); 355 356 ret = block_iter_next(&it, &rec); ··· 359 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 360 361 want.len--; 362 - ret = block_iter_seek_key(&it, &br, &want); 363 check_int(ret, ==, 0); 364 365 ret = block_iter_next(&it, &rec); ··· 367 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 368 } 369 370 - block_reader_release(&br); 371 block_iter_close(&it); 372 reftable_record_release(&rec); 373 reftable_buf_release(&want); 374 - reftable_buf_release(&block); 375 for (i = 0; i < N; i++) 376 reftable_record_release(&recs[i]); 377 }
··· 28 }; 29 size_t i = 0; 30 int ret; 31 + struct reftable_block block = { 0 }; 32 struct block_iter it = BLOCK_ITER_INIT; 33 struct reftable_buf want = REFTABLE_BUF_INIT; 34 + struct reftable_buf block_data = REFTABLE_BUF_INIT; 35 36 + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 37 + check(block_data.buf != NULL); 38 + block_data.len = block_size; 39 40 + ret = block_writer_init(&bw, BLOCK_TYPE_REF, (uint8_t *) block_data.buf, block_size, 41 header_off, hash_size(REFTABLE_HASH_SHA1)); 42 check(!ret); 43 ··· 63 64 block_writer_release(&bw); 65 66 + block_source_from_buf(&source ,&block_data); 67 + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 68 69 + block_iter_seek_start(&it, &block); 70 71 for (i = 0; ; i++) { 72 ret = block_iter_next(&it, &rec); ··· 82 block_iter_reset(&it); 83 reftable_record_key(&recs[i], &want); 84 85 + ret = block_iter_seek_key(&it, &block, &want); 86 check_int(ret, ==, 0); 87 88 ret = block_iter_next(&it, &rec); ··· 91 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 92 93 want.len--; 94 + ret = block_iter_seek_key(&it, &block, &want); 95 check_int(ret, ==, 0); 96 97 ret = block_iter_next(&it, &rec); ··· 99 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 100 } 101 102 + reftable_block_release(&block); 103 block_iter_close(&it); 104 reftable_record_release(&rec); 105 reftable_buf_release(&want); 106 + reftable_buf_release(&block_data); 107 for (i = 0; i < N; i++) 108 reftable_record_release(&recs[i]); 109 } ··· 123 }; 124 size_t i = 0; 125 int ret; 126 + struct reftable_block block = { 0 }; 127 struct block_iter it = BLOCK_ITER_INIT; 128 struct reftable_buf want = REFTABLE_BUF_INIT; 129 + struct reftable_buf block_data = REFTABLE_BUF_INIT; 130 131 + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 132 + check(block_data.buf != NULL); 133 + block_data.len = block_size; 134 135 + ret = block_writer_init(&bw, BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, 136 header_off, hash_size(REFTABLE_HASH_SHA1)); 137 check(!ret); 138 ··· 153 154 block_writer_release(&bw); 155 156 + block_source_from_buf(&source, &block_data); 157 + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 158 159 + block_iter_seek_start(&it, &block); 160 161 for (i = 0; ; i++) { 162 ret = block_iter_next(&it, &rec); ··· 173 reftable_buf_reset(&want); 174 check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); 175 176 + ret = block_iter_seek_key(&it, &block, &want); 177 check_int(ret, ==, 0); 178 179 ret = block_iter_next(&it, &rec); ··· 182 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 183 184 want.len--; 185 + ret = block_iter_seek_key(&it, &block, &want); 186 check_int(ret, ==, 0); 187 188 ret = block_iter_next(&it, &rec); ··· 190 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 191 } 192 193 + reftable_block_release(&block); 194 block_iter_close(&it); 195 reftable_record_release(&rec); 196 reftable_buf_release(&want); 197 + reftable_buf_release(&block_data); 198 for (i = 0; i < N; i++) 199 reftable_record_release(&recs[i]); 200 } ··· 214 }; 215 size_t i = 0; 216 int ret; 217 + struct reftable_block block = { 0 }; 218 struct block_iter it = BLOCK_ITER_INIT; 219 struct reftable_buf want = REFTABLE_BUF_INIT; 220 + struct reftable_buf block_data = REFTABLE_BUF_INIT; 221 222 + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 223 + check(block_data.buf != NULL); 224 + block_data.len = block_size; 225 226 + ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, 227 header_off, hash_size(REFTABLE_HASH_SHA1)); 228 check(!ret); 229 ··· 246 247 block_writer_release(&bw); 248 249 + block_source_from_buf(&source, &block_data); 250 + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 251 252 + block_iter_seek_start(&it, &block); 253 254 for (i = 0; ; i++) { 255 ret = block_iter_next(&it, &rec); ··· 265 block_iter_reset(&it); 266 reftable_record_key(&recs[i], &want); 267 268 + ret = block_iter_seek_key(&it, &block, &want); 269 check_int(ret, ==, 0); 270 271 ret = block_iter_next(&it, &rec); ··· 274 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 275 } 276 277 + reftable_block_release(&block); 278 block_iter_close(&it); 279 reftable_record_release(&rec); 280 reftable_buf_release(&want); 281 + reftable_buf_release(&block_data); 282 for (i = 0; i < N; i++) 283 reftable_record_release(&recs[i]); 284 } ··· 299 }; 300 size_t i = 0; 301 int ret; 302 + struct reftable_block block = { 0 }; 303 struct block_iter it = BLOCK_ITER_INIT; 304 struct reftable_buf want = REFTABLE_BUF_INIT; 305 + struct reftable_buf block_data = REFTABLE_BUF_INIT; 306 307 + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 308 + check(block_data.buf != NULL); 309 + block_data.len = block_size; 310 311 + ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, 312 header_off, hash_size(REFTABLE_HASH_SHA1)); 313 check(!ret); 314 ··· 331 332 block_writer_release(&bw); 333 334 + block_source_from_buf(&source, &block_data); 335 + reftable_block_init(&block, &source, 0, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 336 337 + block_iter_seek_start(&it, &block); 338 339 for (i = 0; ; i++) { 340 ret = block_iter_next(&it, &rec); ··· 350 block_iter_reset(&it); 351 reftable_record_key(&recs[i], &want); 352 353 + ret = block_iter_seek_key(&it, &block, &want); 354 check_int(ret, ==, 0); 355 356 ret = block_iter_next(&it, &rec); ··· 359 check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 360 361 want.len--; 362 + ret = block_iter_seek_key(&it, &block, &want); 363 check_int(ret, ==, 0); 364 365 ret = block_iter_next(&it, &rec); ··· 367 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 368 } 369 370 + reftable_block_release(&block); 371 block_iter_close(&it); 372 reftable_record_release(&rec); 373 reftable_buf_release(&want); 374 + reftable_buf_release(&block_data); 375 for (i = 0; i < N; i++) 376 reftable_record_release(&recs[i]); 377 }