2 Copyright 2020 Google LLC
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
14 #include "constants.h"
16 #include "reftable-error.h"
18 int iterator_seek(struct reftable_iterator
*it
, struct reftable_record
*want
)
20 return it
->ops
->seek(it
->iter_arg
, want
);
23 int iterator_next(struct reftable_iterator
*it
, struct reftable_record
*rec
)
25 return it
->ops
->next(it
->iter_arg
, rec
);
28 static int empty_iterator_seek(void *arg UNUSED
, struct reftable_record
*want UNUSED
)
33 static int empty_iterator_next(void *arg UNUSED
, struct reftable_record
*rec UNUSED
)
38 static void empty_iterator_close(void *arg UNUSED
)
42 static struct reftable_iterator_vtable empty_vtable
= {
43 .seek
= &empty_iterator_seek
,
44 .next
= &empty_iterator_next
,
45 .close
= &empty_iterator_close
,
48 void iterator_set_empty(struct reftable_iterator
*it
)
52 it
->ops
= &empty_vtable
;
55 static void filtering_ref_iterator_close(void *iter_arg
)
57 struct filtering_ref_iterator
*fri
= iter_arg
;
58 strbuf_release(&fri
->oid
);
59 reftable_iterator_destroy(&fri
->it
);
62 static int filtering_ref_iterator_seek(void *iter_arg
,
63 struct reftable_record
*want
)
65 struct filtering_ref_iterator
*fri
= iter_arg
;
66 return iterator_seek(&fri
->it
, want
);
69 static int filtering_ref_iterator_next(void *iter_arg
,
70 struct reftable_record
*rec
)
72 struct filtering_ref_iterator
*fri
= iter_arg
;
73 struct reftable_ref_record
*ref
= &rec
->u
.ref
;
76 err
= reftable_iterator_next_ref(&fri
->it
, ref
);
81 if (ref
->value_type
== REFTABLE_REF_VAL2
&&
82 (!memcmp(fri
->oid
.buf
, ref
->value
.val2
.target_value
,
84 !memcmp(fri
->oid
.buf
, ref
->value
.val2
.value
,
88 if (ref
->value_type
== REFTABLE_REF_VAL1
&&
89 !memcmp(fri
->oid
.buf
, ref
->value
.val1
, fri
->oid
.len
)) {
94 reftable_ref_record_release(ref
);
98 static struct reftable_iterator_vtable filtering_ref_iterator_vtable
= {
99 .seek
= &filtering_ref_iterator_seek
,
100 .next
= &filtering_ref_iterator_next
,
101 .close
= &filtering_ref_iterator_close
,
104 void iterator_from_filtering_ref_iterator(struct reftable_iterator
*it
,
105 struct filtering_ref_iterator
*fri
)
109 it
->ops
= &filtering_ref_iterator_vtable
;
112 static void indexed_table_ref_iter_close(void *p
)
114 struct indexed_table_ref_iter
*it
= p
;
115 block_iter_close(&it
->cur
);
116 reftable_block_done(&it
->block_reader
.block
);
117 reftable_free(it
->offsets
);
118 strbuf_release(&it
->oid
);
121 static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter
*it
)
125 if (it
->offset_idx
== it
->offset_len
) {
130 reftable_block_done(&it
->block_reader
.block
);
132 off
= it
->offsets
[it
->offset_idx
++];
133 err
= reader_init_block_reader(it
->r
, &it
->block_reader
, off
,
139 /* indexed block does not exist. */
140 return REFTABLE_FORMAT_ERROR
;
142 block_iter_seek_start(&it
->cur
, &it
->block_reader
);
146 static int indexed_table_ref_iter_seek(void *p UNUSED
,
147 struct reftable_record
*want UNUSED
)
149 BUG("seeking indexed table is not supported");
153 static int indexed_table_ref_iter_next(void *p
, struct reftable_record
*rec
)
155 struct indexed_table_ref_iter
*it
= p
;
156 struct reftable_ref_record
*ref
= &rec
->u
.ref
;
159 int err
= block_iter_next(&it
->cur
, rec
);
165 err
= indexed_table_ref_iter_next_block(it
);
170 if (it
->is_finished
) {
176 if (!memcmp(it
->oid
.buf
, ref
->value
.val2
.target_value
,
178 !memcmp(it
->oid
.buf
, ref
->value
.val2
.value
, it
->oid
.len
)) {
184 int new_indexed_table_ref_iter(struct indexed_table_ref_iter
**dest
,
185 struct reftable_reader
*r
, uint8_t *oid
,
186 int oid_len
, uint64_t *offsets
, int offset_len
)
188 struct indexed_table_ref_iter empty
= INDEXED_TABLE_REF_ITER_INIT
;
189 struct indexed_table_ref_iter
*itr
= reftable_calloc(1, sizeof(*itr
));
194 strbuf_add(&itr
->oid
, oid
, oid_len
);
196 itr
->offsets
= offsets
;
197 itr
->offset_len
= offset_len
;
199 err
= indexed_table_ref_iter_next_block(itr
);
208 static struct reftable_iterator_vtable indexed_table_ref_iter_vtable
= {
209 .seek
= &indexed_table_ref_iter_seek
,
210 .next
= &indexed_table_ref_iter_next
,
211 .close
= &indexed_table_ref_iter_close
,
214 void iterator_from_indexed_table_ref_iter(struct reftable_iterator
*it
,
215 struct indexed_table_ref_iter
*itr
)
219 it
->ops
= &indexed_table_ref_iter_vtable
;
222 void reftable_iterator_destroy(struct reftable_iterator
*it
)
226 it
->ops
->close(it
->iter_arg
);
228 FREE_AND_NULL(it
->iter_arg
);
231 int reftable_iterator_seek_ref(struct reftable_iterator
*it
,
234 struct reftable_record want
= {
235 .type
= BLOCK_TYPE_REF
,
237 .refname
= (char *)name
,
240 return it
->ops
->seek(it
->iter_arg
, &want
);
243 int reftable_iterator_next_ref(struct reftable_iterator
*it
,
244 struct reftable_ref_record
*ref
)
246 struct reftable_record rec
= {
247 .type
= BLOCK_TYPE_REF
,
252 int err
= iterator_next(it
, &rec
);
257 int reftable_iterator_seek_log_at(struct reftable_iterator
*it
,
258 const char *name
, uint64_t update_index
)
260 struct reftable_record want
= {
261 .type
= BLOCK_TYPE_LOG
,
263 .refname
= (char *)name
,
264 .update_index
= update_index
,
267 return it
->ops
->seek(it
->iter_arg
, &want
);
270 int reftable_iterator_seek_log(struct reftable_iterator
*it
,
273 return reftable_iterator_seek_log_at(it
, name
, ~((uint64_t) 0));
276 int reftable_iterator_next_log(struct reftable_iterator
*it
,
277 struct reftable_log_record
*log
)
279 struct reftable_record rec
= {
280 .type
= BLOCK_TYPE_LOG
,
285 int err
= iterator_next(it
, &rec
);