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 reftable_buf_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 reftable_buf_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 indexed_table_ref_iter_new(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
;
192 itr
= reftable_calloc(1, sizeof(*itr
));
194 err
= REFTABLE_OUT_OF_MEMORY_ERROR
;
201 err
= reftable_buf_add(&itr
->oid
, oid
, oid_len
);
205 itr
->offsets
= offsets
;
206 itr
->offset_len
= offset_len
;
208 err
= indexed_table_ref_iter_next_block(itr
);
223 static struct reftable_iterator_vtable indexed_table_ref_iter_vtable
= {
224 .seek
= &indexed_table_ref_iter_seek
,
225 .next
= &indexed_table_ref_iter_next
,
226 .close
= &indexed_table_ref_iter_close
,
229 void iterator_from_indexed_table_ref_iter(struct reftable_iterator
*it
,
230 struct indexed_table_ref_iter
*itr
)
234 it
->ops
= &indexed_table_ref_iter_vtable
;
237 void reftable_iterator_destroy(struct reftable_iterator
*it
)
241 it
->ops
->close(it
->iter_arg
);
243 REFTABLE_FREE_AND_NULL(it
->iter_arg
);
246 int reftable_iterator_seek_ref(struct reftable_iterator
*it
,
249 struct reftable_record want
= {
250 .type
= BLOCK_TYPE_REF
,
252 .refname
= (char *)name
,
255 return it
->ops
->seek(it
->iter_arg
, &want
);
258 int reftable_iterator_next_ref(struct reftable_iterator
*it
,
259 struct reftable_ref_record
*ref
)
261 struct reftable_record rec
= {
262 .type
= BLOCK_TYPE_REF
,
267 int err
= iterator_next(it
, &rec
);
272 int reftable_iterator_seek_log_at(struct reftable_iterator
*it
,
273 const char *name
, uint64_t update_index
)
275 struct reftable_record want
= {
276 .type
= BLOCK_TYPE_LOG
,
278 .refname
= (char *)name
,
279 .update_index
= update_index
,
282 return it
->ops
->seek(it
->iter_arg
, &want
);
285 int reftable_iterator_seek_log(struct reftable_iterator
*it
,
288 return reftable_iterator_seek_log_at(it
, name
, ~((uint64_t) 0));
291 int reftable_iterator_next_log(struct reftable_iterator
*it
,
292 struct reftable_log_record
*log
)
294 struct reftable_record rec
= {
295 .type
= BLOCK_TYPE_LOG
,
300 int err
= iterator_next(it
, &rec
);