220
struct reftable_reader *r;
221
uint8_t typ;
222
uint64_t block_off;
223
+ struct block_reader br;
224
struct block_iter bi;
225
int is_finished;
226
};
228
.bi = BLOCK_ITER_INIT \
229
}
230
230
-static void table_iter_copy_from(struct table_iter *dest,
231
- struct table_iter *src)
232
-{
233
- dest->r = src->r;
234
- dest->typ = src->typ;
235
- dest->block_off = src->block_off;
236
- dest->is_finished = src->is_finished;
237
- block_iter_copy_from(&dest->bi, &src->bi);
238
-}
239
-
231
static int table_iter_next_in_block(struct table_iter *ti,
232
struct reftable_record *rec)
233
{
241
242
static void table_iter_block_done(struct table_iter *ti)
243
{
253
- if (!ti->bi.br) {
254
- return;
255
- }
256
- block_reader_release(ti->bi.br);
257
- FREE_AND_NULL(ti->bi.br);
258
-
259
- ti->bi.last_key.len = 0;
260
- ti->bi.next_off = 0;
244
+ block_reader_release(&ti->br);
245
+ block_iter_reset(&ti->bi);
246
}
247
248
static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
306
return err;
307
}
308
309
+static void table_iter_close(struct table_iter *ti)
310
+{
311
+ table_iter_block_done(ti);
312
+ block_iter_close(&ti->bi);
313
+}
314
+
315
static int table_iter_next_block(struct table_iter *dest,
316
struct table_iter *src)
317
{
327
- uint64_t next_block_off = src->block_off + src->bi.br->full_block_size;
328
- struct block_reader br = { 0 };
329
- int err = 0;
318
+ uint64_t next_block_off = src->block_off + src->br.full_block_size;
319
+ int err;
320
321
dest->r = src->r;
322
dest->typ = src->typ;
323
dest->block_off = next_block_off;
324
335
- err = reader_init_block_reader(src->r, &br, next_block_off, src->typ);
336
- if (err > 0) {
325
+ err = reader_init_block_reader(src->r, &dest->br, next_block_off, src->typ);
326
+ if (err > 0)
327
dest->is_finished = 1;
338
- return 1;
339
- }
340
- if (err != 0)
328
+ if (err) {
329
+ table_iter_block_done(dest);
330
return err;
342
- else {
343
- struct block_reader *brp =
344
- reftable_malloc(sizeof(struct block_reader));
345
- *brp = br;
346
-
347
- dest->is_finished = 0;
348
- block_iter_seek_start(&dest->bi, brp);
331
}
332
+
333
+ dest->is_finished = 0;
334
+ block_iter_seek_start(&dest->bi, &dest->br);
335
+
336
return 0;
337
}
338
363
* iterator is drained.
364
*/
365
err = table_iter_next_block(&next, ti);
380
- table_iter_block_done(ti);
366
if (err) {
367
ti->is_finished = 1;
368
return err;
369
}
370
386
- table_iter_copy_from(ti, &next);
387
- block_iter_close(&next.bi);
371
+ table_iter_close(ti);
372
+ *ti = next;
373
}
374
}
375
378
return table_iter_next(ti, rec);
379
}
380
396
-static void table_iter_close(void *p)
381
+static void table_iter_close_void(void *ti)
382
{
398
- struct table_iter *ti = p;
399
- table_iter_block_done(ti);
400
- block_iter_close(&ti->bi);
383
+ table_iter_close(ti);
384
}
385
386
static struct reftable_iterator_vtable table_iter_vtable = {
387
.next = &table_iter_next_void,
405
- .close = &table_iter_close,
388
+ .close = &table_iter_close_void,
389
};
390
391
static void iterator_from_table_iter(struct reftable_iterator *it,
400
struct table_iter *ti, uint64_t off,
401
uint8_t typ)
402
{
420
- struct block_reader br = { 0 };
421
- struct block_reader *brp = NULL;
403
+ int err;
404
423
- int err = reader_init_block_reader(r, &br, off, typ);
405
+ err = reader_init_block_reader(r, &ti->br, off, typ);
406
if (err != 0)
407
return err;
408
427
- brp = reftable_malloc(sizeof(struct block_reader));
428
- *brp = br;
409
ti->r = r;
430
- ti->typ = block_reader_type(brp);
410
+ ti->typ = block_reader_type(&ti->br);
411
ti->block_off = off;
432
- block_iter_seek_start(&ti->bi, brp);
412
+ block_iter_seek_start(&ti->bi, &ti->br);
413
return 0;
414
}
415
434
{
435
struct strbuf want_key = STRBUF_INIT;
436
struct strbuf got_key = STRBUF_INIT;
457
- struct table_iter next = TABLE_ITER_INIT;
437
struct reftable_record rec;
438
int err = -1;
439
440
reftable_record_init(&rec, reftable_record_type(want));
441
reftable_record_key(want, &want_key);
442
443
+ /*
444
+ * First we need to locate the block that must contain our record. To
445
+ * do so we scan through blocks linearly until we find the first block
446
+ * whose first key is bigger than our wanted key. Once we have found
447
+ * that block we know that the key must be contained in the preceding
448
+ * block.
449
+ *
450
+ * This algorithm is somewhat unfortunate because it means that we
451
+ * always have to seek one block too far and then back up. But as we
452
+ * can only decode the _first_ key of a block but not its _last_ key we
453
+ * have no other way to do this.
454
+ */
455
while (1) {
456
+ struct table_iter next = TABLE_ITER_INIT;
457
+
458
err = table_iter_next_block(&next, ti);
459
if (err < 0)
460
goto done;
468
-
469
- if (err > 0) {
461
+ if (err > 0)
462
break;
471
- }
463
473
- err = block_reader_first_key(next.bi.br, &got_key);
464
+ err = block_reader_first_key(&next.br, &got_key);
465
if (err < 0)
466
goto done;
467
471
}
472
473
table_iter_block_done(ti);
483
- table_iter_copy_from(ti, &next);
474
+ *ti = next;
475
}
476
486
- err = block_iter_seek_key(&ti->bi, ti->bi.br, &want_key);
477
+ /*
478
+ * We have located the block that must contain our record, so we seek
479
+ * the wanted key inside of it. If the block does not contain our key
480
+ * we know that the corresponding record does not exist.
481
+ */
482
+ err = block_iter_seek_key(&ti->bi, &ti->br, &want_key);
483
if (err < 0)
484
goto done;
485
err = 0;
486
487
done:
492
- block_iter_close(&next.bi);
488
reftable_record_release(&rec);
489
strbuf_release(&want_key);
490
strbuf_release(&got_key);
503
.u.idx = { .last_key = STRBUF_INIT },
504
};
505
struct table_iter index_iter = TABLE_ITER_INIT;
506
+ struct table_iter empty = TABLE_ITER_INIT;
507
struct table_iter next = TABLE_ITER_INIT;
508
int err = 0;
509
545
* not exist.
546
*/
547
err = table_iter_next(&index_iter, &index_result);
552
- table_iter_block_done(&index_iter);
548
if (err != 0)
549
goto done;
550
553
if (err != 0)
554
goto done;
555
561
- err = block_iter_seek_key(&next.bi, next.bi.br, &want_index.u.idx.last_key);
556
+ err = block_iter_seek_key(&next.bi, &next.br, &want_index.u.idx.last_key);
557
if (err < 0)
558
goto done;
559
567
break;
568
}
569
575
- table_iter_copy_from(&index_iter, &next);
570
+ table_iter_close(&index_iter);
571
+ index_iter = next;
572
+ next = empty;
573
}
574
575
if (err == 0) {
579
- struct table_iter empty = TABLE_ITER_INIT;
576
struct table_iter *malloced = reftable_calloc(1, sizeof(*malloced));
581
- *malloced = empty;
582
- table_iter_copy_from(malloced, &next);
577
+ *malloced = next;
578
+ next = empty;
579
iterator_from_table_iter(it, malloced);
580
}
581
+
582
done:
586
- block_iter_close(&next.bi);
583
+ table_iter_close(&next);
584
table_iter_close(&index_iter);
585
reftable_record_release(&want_index);
586
reftable_record_release(&index_result);