The eleventh batch
[alt-git.git] / reftable / iter.c
blob86e801ca9fbc6bc9a830f041979621ffb03dd3aa
1 /*
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
7 */
9 #include "iter.h"
11 #include "system.h"
13 #include "block.h"
14 #include "constants.h"
15 #include "reader.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)
30 return 0;
33 static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
35 return 1;
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)
50 assert(!it->ops);
51 it->iter_arg = NULL;
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;
74 int err = 0;
75 while (1) {
76 err = reftable_iterator_next_ref(&fri->it, ref);
77 if (err != 0) {
78 break;
81 if (ref->value_type == REFTABLE_REF_VAL2 &&
82 (!memcmp(fri->oid.buf, ref->value.val2.target_value,
83 fri->oid.len) ||
84 !memcmp(fri->oid.buf, ref->value.val2.value,
85 fri->oid.len)))
86 return 0;
88 if (ref->value_type == REFTABLE_REF_VAL1 &&
89 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
90 return 0;
94 reftable_ref_record_release(ref);
95 return err;
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)
107 assert(!it->ops);
108 it->iter_arg = 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)
123 uint64_t off;
124 int err = 0;
125 if (it->offset_idx == it->offset_len) {
126 it->is_finished = 1;
127 return 1;
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,
134 BLOCK_TYPE_REF);
135 if (err < 0) {
136 return err;
138 if (err > 0) {
139 /* indexed block does not exist. */
140 return REFTABLE_FORMAT_ERROR;
142 block_iter_seek_start(&it->cur, &it->block_reader);
143 return 0;
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");
150 return -1;
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;
158 while (1) {
159 int err = block_iter_next(&it->cur, rec);
160 if (err < 0) {
161 return err;
164 if (err > 0) {
165 err = indexed_table_ref_iter_next_block(it);
166 if (err < 0) {
167 return err;
170 if (it->is_finished) {
171 return 1;
173 continue;
175 /* BUG */
176 if (!memcmp(it->oid.buf, ref->value.val2.target_value,
177 it->oid.len) ||
178 !memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
179 return 0;
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;
190 int err = 0;
192 itr = reftable_calloc(1, sizeof(*itr));
193 if (!itr) {
194 err = REFTABLE_OUT_OF_MEMORY_ERROR;
195 goto out;
198 *itr = empty;
199 itr->r = r;
201 err = reftable_buf_add(&itr->oid, oid, oid_len);
202 if (err < 0)
203 goto out;
205 itr->offsets = offsets;
206 itr->offset_len = offset_len;
208 err = indexed_table_ref_iter_next_block(itr);
209 if (err < 0)
210 goto out;
212 *dest = itr;
213 err = 0;
215 out:
216 if (err < 0) {
217 *dest = NULL;
218 reftable_free(itr);
220 return err;
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)
232 assert(!it->ops);
233 it->iter_arg = itr;
234 it->ops = &indexed_table_ref_iter_vtable;
237 void reftable_iterator_destroy(struct reftable_iterator *it)
239 if (!it->ops)
240 return;
241 it->ops->close(it->iter_arg);
242 it->ops = NULL;
243 REFTABLE_FREE_AND_NULL(it->iter_arg);
246 int reftable_iterator_seek_ref(struct reftable_iterator *it,
247 const char *name)
249 struct reftable_record want = {
250 .type = BLOCK_TYPE_REF,
251 .u.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,
263 .u = {
264 .ref = *ref
267 int err = iterator_next(it, &rec);
268 *ref = rec.u.ref;
269 return err;
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,
277 .u.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,
286 const char *name)
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,
296 .u = {
297 .log = *log,
300 int err = iterator_next(it, &rec);
301 *log = rec.u.log;
302 return err;