Skip to content

Commit 46bc0e7

Browse files
hanwengitster
authored andcommitted
reftable: read reftable files
This supports reading a single reftable file. The commit introduces an abstract iterator type, which captures the usecases both of reading individual refs, and iterating over a segment of the ref namespace. Signed-off-by: Han-Wen Nienhuys <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 17df8db commit 46bc0e7

File tree

6 files changed

+1231
-0
lines changed

6 files changed

+1231
-0
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,7 +2460,9 @@ REFTABLE_OBJS += reftable/basics.o
24602460
REFTABLE_OBJS += reftable/error.o
24612461
REFTABLE_OBJS += reftable/block.o
24622462
REFTABLE_OBJS += reftable/blocksource.o
2463+
REFTABLE_OBJS += reftable/iter.o
24632464
REFTABLE_OBJS += reftable/publicbasics.o
2465+
REFTABLE_OBJS += reftable/reader.o
24642466
REFTABLE_OBJS += reftable/record.o
24652467
REFTABLE_OBJS += reftable/refname.o
24662468
REFTABLE_OBJS += reftable/generic.o

reftable/iter.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
Copyright 2020 Google LLC
3+
4+
Use of this source code is governed by a BSD-style
5+
license that can be found in the LICENSE file or at
6+
https://developers.google.com/open-source/licenses/bsd
7+
*/
8+
9+
#include "iter.h"
10+
11+
#include "system.h"
12+
13+
#include "block.h"
14+
#include "generic.h"
15+
#include "constants.h"
16+
#include "reader.h"
17+
#include "reftable-error.h"
18+
19+
int iterator_is_null(struct reftable_iterator *it)
20+
{
21+
return !it->ops;
22+
}
23+
24+
static void filtering_ref_iterator_close(void *iter_arg)
25+
{
26+
struct filtering_ref_iterator *fri = iter_arg;
27+
strbuf_release(&fri->oid);
28+
reftable_iterator_destroy(&fri->it);
29+
}
30+
31+
static int filtering_ref_iterator_next(void *iter_arg,
32+
struct reftable_record *rec)
33+
{
34+
struct filtering_ref_iterator *fri = iter_arg;
35+
struct reftable_ref_record *ref = rec->data;
36+
int err = 0;
37+
while (1) {
38+
err = reftable_iterator_next_ref(&fri->it, ref);
39+
if (err != 0) {
40+
break;
41+
}
42+
43+
if (fri->double_check) {
44+
struct reftable_iterator it = { NULL };
45+
46+
err = reftable_table_seek_ref(&fri->tab, &it,
47+
ref->refname);
48+
if (err == 0) {
49+
err = reftable_iterator_next_ref(&it, ref);
50+
}
51+
52+
reftable_iterator_destroy(&it);
53+
54+
if (err < 0) {
55+
break;
56+
}
57+
58+
if (err > 0) {
59+
continue;
60+
}
61+
}
62+
63+
if (ref->value_type == REFTABLE_REF_VAL2 &&
64+
(!memcmp(fri->oid.buf, ref->value.val2.target_value,
65+
fri->oid.len) ||
66+
!memcmp(fri->oid.buf, ref->value.val2.value,
67+
fri->oid.len)))
68+
return 0;
69+
70+
if (ref->value_type == REFTABLE_REF_VAL1 &&
71+
!memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
72+
return 0;
73+
}
74+
}
75+
76+
reftable_ref_record_release(ref);
77+
return err;
78+
}
79+
80+
static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
81+
.next = &filtering_ref_iterator_next,
82+
.close = &filtering_ref_iterator_close,
83+
};
84+
85+
void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
86+
struct filtering_ref_iterator *fri)
87+
{
88+
assert(!it->ops);
89+
it->iter_arg = fri;
90+
it->ops = &filtering_ref_iterator_vtable;
91+
}
92+
93+
static void indexed_table_ref_iter_close(void *p)
94+
{
95+
struct indexed_table_ref_iter *it = p;
96+
block_iter_close(&it->cur);
97+
reftable_block_done(&it->block_reader.block);
98+
reftable_free(it->offsets);
99+
strbuf_release(&it->oid);
100+
}
101+
102+
static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
103+
{
104+
uint64_t off;
105+
int err = 0;
106+
if (it->offset_idx == it->offset_len) {
107+
it->is_finished = 1;
108+
return 1;
109+
}
110+
111+
reftable_block_done(&it->block_reader.block);
112+
113+
off = it->offsets[it->offset_idx++];
114+
err = reader_init_block_reader(it->r, &it->block_reader, off,
115+
BLOCK_TYPE_REF);
116+
if (err < 0) {
117+
return err;
118+
}
119+
if (err > 0) {
120+
/* indexed block does not exist. */
121+
return REFTABLE_FORMAT_ERROR;
122+
}
123+
block_reader_start(&it->block_reader, &it->cur);
124+
return 0;
125+
}
126+
127+
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
128+
{
129+
struct indexed_table_ref_iter *it = p;
130+
struct reftable_ref_record *ref = rec->data;
131+
132+
while (1) {
133+
int err = block_iter_next(&it->cur, rec);
134+
if (err < 0) {
135+
return err;
136+
}
137+
138+
if (err > 0) {
139+
err = indexed_table_ref_iter_next_block(it);
140+
if (err < 0) {
141+
return err;
142+
}
143+
144+
if (it->is_finished) {
145+
return 1;
146+
}
147+
continue;
148+
}
149+
/* BUG */
150+
if (!memcmp(it->oid.buf, ref->value.val2.target_value,
151+
it->oid.len) ||
152+
!memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
153+
return 0;
154+
}
155+
}
156+
}
157+
158+
int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
159+
struct reftable_reader *r, uint8_t *oid,
160+
int oid_len, uint64_t *offsets, int offset_len)
161+
{
162+
struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
163+
struct indexed_table_ref_iter *itr =
164+
reftable_calloc(sizeof(struct indexed_table_ref_iter));
165+
int err = 0;
166+
167+
*itr = empty;
168+
itr->r = r;
169+
strbuf_add(&itr->oid, oid, oid_len);
170+
171+
itr->offsets = offsets;
172+
itr->offset_len = offset_len;
173+
174+
err = indexed_table_ref_iter_next_block(itr);
175+
if (err < 0) {
176+
reftable_free(itr);
177+
} else {
178+
*dest = itr;
179+
}
180+
return err;
181+
}
182+
183+
static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
184+
.next = &indexed_table_ref_iter_next,
185+
.close = &indexed_table_ref_iter_close,
186+
};
187+
188+
void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
189+
struct indexed_table_ref_iter *itr)
190+
{
191+
assert(!it->ops);
192+
it->iter_arg = itr;
193+
it->ops = &indexed_table_ref_iter_vtable;
194+
}

reftable/iter.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
Copyright 2020 Google LLC
3+
4+
Use of this source code is governed by a BSD-style
5+
license that can be found in the LICENSE file or at
6+
https://developers.google.com/open-source/licenses/bsd
7+
*/
8+
9+
#ifndef ITER_H
10+
#define ITER_H
11+
12+
#include "system.h"
13+
#include "block.h"
14+
#include "record.h"
15+
16+
#include "reftable-iterator.h"
17+
#include "reftable-generic.h"
18+
19+
/* Returns true for a zeroed out iterator, such as the one returned from
20+
* iterator_destroy. */
21+
int iterator_is_null(struct reftable_iterator *it);
22+
23+
/* iterator that produces only ref records that point to `oid` */
24+
struct filtering_ref_iterator {
25+
int double_check;
26+
struct reftable_table tab;
27+
struct strbuf oid;
28+
struct reftable_iterator it;
29+
};
30+
#define FILTERING_REF_ITERATOR_INIT \
31+
{ \
32+
.oid = STRBUF_INIT \
33+
}
34+
35+
void iterator_from_filtering_ref_iterator(struct reftable_iterator *,
36+
struct filtering_ref_iterator *);
37+
38+
/* iterator that produces only ref records that point to `oid`,
39+
* but using the object index.
40+
*/
41+
struct indexed_table_ref_iter {
42+
struct reftable_reader *r;
43+
struct strbuf oid;
44+
45+
/* mutable */
46+
uint64_t *offsets;
47+
48+
/* Points to the next offset to read. */
49+
int offset_idx;
50+
int offset_len;
51+
struct block_reader block_reader;
52+
struct block_iter cur;
53+
int is_finished;
54+
};
55+
56+
#define INDEXED_TABLE_REF_ITER_INIT \
57+
{ \
58+
.cur = { .last_key = STRBUF_INIT }, .oid = STRBUF_INIT, \
59+
}
60+
61+
void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
62+
struct indexed_table_ref_iter *itr);
63+
64+
/* Takes ownership of `offsets` */
65+
int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
66+
struct reftable_reader *r, uint8_t *oid,
67+
int oid_len, uint64_t *offsets, int offset_len);
68+
69+
#endif

0 commit comments

Comments
 (0)