Skip to content

Commit 6eb8e1d

Browse files
hanwengitster
authored andcommitted
reftable: read reftable files
Signed-off-by: Han-Wen Nienhuys <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9a6ac5b commit 6eb8e1d

File tree

6 files changed

+1232
-0
lines changed

6 files changed

+1232
-0
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2349,7 +2349,10 @@ REFTABLE_OBJS += reftable/block.o
23492349
REFTABLE_OBJS += reftable/blocksource.o
23502350
REFTABLE_OBJS += reftable/publicbasics.o
23512351
REFTABLE_OBJS += reftable/compat.o
2352+
REFTABLE_OBJS += reftable/iter.o
2353+
REFTABLE_OBJS += reftable/reader.o
23522354
REFTABLE_OBJS += reftable/record.o
2355+
REFTABLE_OBJS += reftable/reftable.o
23532356
REFTABLE_OBJS += reftable/strbuf.o
23542357
REFTABLE_OBJS += reftable/tree.o
23552358
REFTABLE_OBJS += reftable/writer.o

reftable/iter.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
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 "constants.h"
15+
#include "reader.h"
16+
#include "reftable.h"
17+
18+
int iterator_is_null(struct reftable_iterator *it)
19+
{
20+
return it->ops == NULL;
21+
}
22+
23+
static int empty_iterator_next(void *arg, struct reftable_record *rec)
24+
{
25+
return 1;
26+
}
27+
28+
static void empty_iterator_close(void *arg)
29+
{
30+
}
31+
32+
struct reftable_iterator_vtable empty_vtable = {
33+
.next = &empty_iterator_next,
34+
.close = &empty_iterator_close,
35+
};
36+
37+
void iterator_set_empty(struct reftable_iterator *it)
38+
{
39+
assert(it->ops == NULL);
40+
it->iter_arg = NULL;
41+
it->ops = &empty_vtable;
42+
}
43+
44+
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
45+
{
46+
return it->ops->next(it->iter_arg, rec);
47+
}
48+
49+
void reftable_iterator_destroy(struct reftable_iterator *it)
50+
{
51+
if (it->ops == NULL) {
52+
return;
53+
}
54+
it->ops->close(it->iter_arg);
55+
it->ops = NULL;
56+
FREE_AND_NULL(it->iter_arg);
57+
}
58+
59+
int reftable_iterator_next_ref(struct reftable_iterator *it,
60+
struct reftable_ref_record *ref)
61+
{
62+
struct reftable_record rec = { 0 };
63+
reftable_record_from_ref(&rec, ref);
64+
return iterator_next(it, &rec);
65+
}
66+
67+
int reftable_iterator_next_log(struct reftable_iterator *it,
68+
struct reftable_log_record *log)
69+
{
70+
struct reftable_record rec = { 0 };
71+
reftable_record_from_log(&rec, log);
72+
return iterator_next(it, &rec);
73+
}
74+
75+
static void filtering_ref_iterator_close(void *iter_arg)
76+
{
77+
struct filtering_ref_iterator *fri =
78+
(struct filtering_ref_iterator *)iter_arg;
79+
strbuf_release(&fri->oid);
80+
reftable_iterator_destroy(&fri->it);
81+
}
82+
83+
static int filtering_ref_iterator_next(void *iter_arg,
84+
struct reftable_record *rec)
85+
{
86+
struct filtering_ref_iterator *fri =
87+
(struct filtering_ref_iterator *)iter_arg;
88+
struct reftable_ref_record *ref =
89+
(struct reftable_ref_record *)rec->data;
90+
int err = 0;
91+
while (1) {
92+
err = reftable_iterator_next_ref(&fri->it, ref);
93+
if (err != 0) {
94+
break;
95+
}
96+
97+
if (fri->double_check) {
98+
struct reftable_iterator it = { 0 };
99+
100+
err = reftable_table_seek_ref(&fri->tab, &it,
101+
ref->refname);
102+
if (err == 0) {
103+
err = reftable_iterator_next_ref(&it, ref);
104+
}
105+
106+
reftable_iterator_destroy(&it);
107+
108+
if (err < 0) {
109+
break;
110+
}
111+
112+
if (err > 0) {
113+
continue;
114+
}
115+
}
116+
117+
if ((ref->target_value != NULL &&
118+
!memcmp(fri->oid.buf, ref->target_value, fri->oid.len)) ||
119+
(ref->value != NULL &&
120+
!memcmp(fri->oid.buf, ref->value, fri->oid.len))) {
121+
return 0;
122+
}
123+
}
124+
125+
reftable_ref_record_clear(ref);
126+
return err;
127+
}
128+
129+
struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
130+
.next = &filtering_ref_iterator_next,
131+
.close = &filtering_ref_iterator_close,
132+
};
133+
134+
void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
135+
struct filtering_ref_iterator *fri)
136+
{
137+
assert(it->ops == NULL);
138+
it->iter_arg = fri;
139+
it->ops = &filtering_ref_iterator_vtable;
140+
}
141+
142+
static void indexed_table_ref_iter_close(void *p)
143+
{
144+
struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
145+
block_iter_close(&it->cur);
146+
reftable_block_done(&it->block_reader.block);
147+
strbuf_release(&it->oid);
148+
}
149+
150+
static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
151+
{
152+
uint64_t off;
153+
int err = 0;
154+
if (it->offset_idx == it->offset_len) {
155+
it->is_finished = 1;
156+
return 1;
157+
}
158+
159+
reftable_block_done(&it->block_reader.block);
160+
161+
off = it->offsets[it->offset_idx++];
162+
err = reader_init_block_reader(it->r, &it->block_reader, off,
163+
BLOCK_TYPE_REF);
164+
if (err < 0) {
165+
return err;
166+
}
167+
if (err > 0) {
168+
/* indexed block does not exist. */
169+
return REFTABLE_FORMAT_ERROR;
170+
}
171+
block_reader_start(&it->block_reader, &it->cur);
172+
return 0;
173+
}
174+
175+
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
176+
{
177+
struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
178+
struct reftable_ref_record *ref =
179+
(struct reftable_ref_record *)rec->data;
180+
181+
while (1) {
182+
int err = block_iter_next(&it->cur, rec);
183+
if (err < 0) {
184+
return err;
185+
}
186+
187+
if (err > 0) {
188+
err = indexed_table_ref_iter_next_block(it);
189+
if (err < 0) {
190+
return err;
191+
}
192+
193+
if (it->is_finished) {
194+
return 1;
195+
}
196+
continue;
197+
}
198+
199+
if (!memcmp(it->oid.buf, ref->target_value, it->oid.len) ||
200+
!memcmp(it->oid.buf, ref->value, it->oid.len)) {
201+
return 0;
202+
}
203+
}
204+
}
205+
206+
int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
207+
struct reftable_reader *r, uint8_t *oid,
208+
int oid_len, uint64_t *offsets, int offset_len)
209+
{
210+
struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
211+
struct indexed_table_ref_iter *itr =
212+
reftable_calloc(sizeof(struct indexed_table_ref_iter));
213+
int err = 0;
214+
215+
*itr = empty;
216+
itr->r = r;
217+
strbuf_add(&itr->oid, oid, oid_len);
218+
219+
itr->offsets = offsets;
220+
itr->offset_len = offset_len;
221+
222+
err = indexed_table_ref_iter_next_block(itr);
223+
if (err < 0) {
224+
reftable_free(itr);
225+
} else {
226+
*dest = itr;
227+
}
228+
return err;
229+
}
230+
231+
struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
232+
.next = &indexed_table_ref_iter_next,
233+
.close = &indexed_table_ref_iter_close,
234+
};
235+
236+
void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
237+
struct indexed_table_ref_iter *itr)
238+
{
239+
assert(it->ops == NULL);
240+
it->iter_arg = itr;
241+
it->ops = &indexed_table_ref_iter_vtable;
242+
}

reftable/iter.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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 "block.h"
13+
#include "record.h"
14+
#include "strbuf.h"
15+
16+
struct reftable_iterator_vtable {
17+
int (*next)(void *iter_arg, struct reftable_record *rec);
18+
void (*close)(void *iter_arg);
19+
};
20+
21+
void iterator_set_empty(struct reftable_iterator *it);
22+
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec);
23+
24+
/* Returns true for a zeroed out iterator, such as the one returned from
25+
iterator_destroy. */
26+
int iterator_is_null(struct reftable_iterator *it);
27+
28+
/* iterator that produces only ref records that point to `oid` */
29+
struct filtering_ref_iterator {
30+
int double_check;
31+
struct reftable_table tab;
32+
struct strbuf oid;
33+
struct reftable_iterator it;
34+
};
35+
#define FILTERING_REF_ITERATOR_INIT \
36+
{ \
37+
.oid = STRBUF_INIT \
38+
}
39+
40+
void iterator_from_filtering_ref_iterator(struct reftable_iterator *,
41+
struct filtering_ref_iterator *);
42+
43+
/* iterator that produces only ref records that point to `oid`,
44+
but using the object index.
45+
*/
46+
struct indexed_table_ref_iter {
47+
struct reftable_reader *r;
48+
struct strbuf oid;
49+
50+
/* mutable */
51+
uint64_t *offsets;
52+
53+
/* Points to the next offset to read. */
54+
int offset_idx;
55+
int offset_len;
56+
struct block_reader block_reader;
57+
struct block_iter cur;
58+
int is_finished;
59+
};
60+
61+
#define INDEXED_TABLE_REF_ITER_INIT \
62+
{ \
63+
.cur = { .last_key = STRBUF_INIT }, .oid = STRBUF_INIT, \
64+
}
65+
66+
void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
67+
struct indexed_table_ref_iter *itr);
68+
int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
69+
struct reftable_reader *r, uint8_t *oid,
70+
int oid_len, uint64_t *offsets, int offset_len);
71+
72+
#endif

0 commit comments

Comments
 (0)