]> git.ipfire.org Git - thirdparty/git.git/blob - reftable/iter.c
93d04f735b852c8d1444623c24048017a956847a
[thirdparty/git.git] / reftable / iter.c
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 }