Git fork
at reftables-rust 302 lines 6.8 kB view raw
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 "blocksource.h" 15#include "constants.h" 16#include "reftable-error.h" 17#include "table.h" 18 19int iterator_seek(struct reftable_iterator *it, struct reftable_record *want) 20{ 21 return it->ops->seek(it->iter_arg, want); 22} 23 24int iterator_next(struct reftable_iterator *it, struct reftable_record *rec) 25{ 26 return it->ops->next(it->iter_arg, rec); 27} 28 29static int empty_iterator_seek(void *arg REFTABLE_UNUSED, struct reftable_record *want REFTABLE_UNUSED) 30{ 31 return 0; 32} 33 34static int empty_iterator_next(void *arg REFTABLE_UNUSED, struct reftable_record *rec REFTABLE_UNUSED) 35{ 36 return 1; 37} 38 39static void empty_iterator_close(void *arg REFTABLE_UNUSED) 40{ 41} 42 43static struct reftable_iterator_vtable empty_vtable = { 44 .seek = &empty_iterator_seek, 45 .next = &empty_iterator_next, 46 .close = &empty_iterator_close, 47}; 48 49void iterator_set_empty(struct reftable_iterator *it) 50{ 51 assert(!it->ops); 52 it->iter_arg = NULL; 53 it->ops = &empty_vtable; 54} 55 56static void filtering_ref_iterator_close(void *iter_arg) 57{ 58 struct filtering_ref_iterator *fri = iter_arg; 59 reftable_buf_release(&fri->oid); 60 reftable_iterator_destroy(&fri->it); 61} 62 63static int filtering_ref_iterator_seek(void *iter_arg, 64 struct reftable_record *want) 65{ 66 struct filtering_ref_iterator *fri = iter_arg; 67 return iterator_seek(&fri->it, want); 68} 69 70static int filtering_ref_iterator_next(void *iter_arg, 71 struct reftable_record *rec) 72{ 73 struct filtering_ref_iterator *fri = iter_arg; 74 struct reftable_ref_record *ref = &rec->u.ref; 75 int err = 0; 76 while (1) { 77 err = reftable_iterator_next_ref(&fri->it, ref); 78 if (err != 0) { 79 break; 80 } 81 82 if (ref->value_type == REFTABLE_REF_VAL2 && 83 (!memcmp(fri->oid.buf, ref->value.val2.target_value, 84 fri->oid.len) || 85 !memcmp(fri->oid.buf, ref->value.val2.value, 86 fri->oid.len))) 87 return 0; 88 89 if (ref->value_type == REFTABLE_REF_VAL1 && 90 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) { 91 return 0; 92 } 93 } 94 95 reftable_ref_record_release(ref); 96 return err; 97} 98 99static struct reftable_iterator_vtable filtering_ref_iterator_vtable = { 100 .seek = &filtering_ref_iterator_seek, 101 .next = &filtering_ref_iterator_next, 102 .close = &filtering_ref_iterator_close, 103}; 104 105void iterator_from_filtering_ref_iterator(struct reftable_iterator *it, 106 struct filtering_ref_iterator *fri) 107{ 108 assert(!it->ops); 109 it->iter_arg = fri; 110 it->ops = &filtering_ref_iterator_vtable; 111} 112 113static void indexed_table_ref_iter_close(void *p) 114{ 115 struct indexed_table_ref_iter *it = p; 116 block_iter_close(&it->cur); 117 block_source_release_data(&it->block.block_data); 118 reftable_free(it->offsets); 119 reftable_buf_release(&it->oid); 120} 121 122static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) 123{ 124 uint64_t off; 125 int err = 0; 126 if (it->offset_idx == it->offset_len) { 127 it->is_finished = 1; 128 return 1; 129 } 130 131 block_source_release_data(&it->block.block_data); 132 133 off = it->offsets[it->offset_idx++]; 134 err = table_init_block(it->table, &it->block, off, REFTABLE_BLOCK_TYPE_REF); 135 if (err < 0) { 136 return err; 137 } 138 if (err > 0) { 139 /* indexed block does not exist. */ 140 return REFTABLE_FORMAT_ERROR; 141 } 142 block_iter_init(&it->cur, &it->block); 143 return 0; 144} 145 146static int indexed_table_ref_iter_seek(void *p REFTABLE_UNUSED, 147 struct reftable_record *want REFTABLE_UNUSED) 148{ 149 return REFTABLE_API_ERROR; 150} 151 152static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec) 153{ 154 struct indexed_table_ref_iter *it = p; 155 struct reftable_ref_record *ref = &rec->u.ref; 156 157 while (1) { 158 int err = block_iter_next(&it->cur, rec); 159 if (err < 0) { 160 return err; 161 } 162 163 if (err > 0) { 164 err = indexed_table_ref_iter_next_block(it); 165 if (err < 0) { 166 return err; 167 } 168 169 if (it->is_finished) { 170 return 1; 171 } 172 continue; 173 } 174 /* BUG */ 175 if (!memcmp(it->oid.buf, ref->value.val2.target_value, 176 it->oid.len) || 177 !memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) { 178 return 0; 179 } 180 } 181} 182 183int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, 184 struct reftable_table *t, uint8_t *oid, 185 int oid_len, uint64_t *offsets, int offset_len) 186{ 187 struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT; 188 struct indexed_table_ref_iter *itr; 189 int err = 0; 190 191 itr = reftable_calloc(1, sizeof(*itr)); 192 if (!itr) { 193 err = REFTABLE_OUT_OF_MEMORY_ERROR; 194 goto out; 195 } 196 197 *itr = empty; 198 itr->table = t; 199 200 err = reftable_buf_add(&itr->oid, oid, oid_len); 201 if (err < 0) 202 goto out; 203 204 itr->offsets = offsets; 205 itr->offset_len = offset_len; 206 207 err = indexed_table_ref_iter_next_block(itr); 208 if (err < 0) 209 goto out; 210 211 *dest = itr; 212 err = 0; 213 214out: 215 if (err < 0) { 216 *dest = NULL; 217 reftable_free(itr); 218 } 219 return err; 220} 221 222static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = { 223 .seek = &indexed_table_ref_iter_seek, 224 .next = &indexed_table_ref_iter_next, 225 .close = &indexed_table_ref_iter_close, 226}; 227 228void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it, 229 struct indexed_table_ref_iter *itr) 230{ 231 assert(!it->ops); 232 it->iter_arg = itr; 233 it->ops = &indexed_table_ref_iter_vtable; 234} 235 236void reftable_iterator_destroy(struct reftable_iterator *it) 237{ 238 if (!it->ops) 239 return; 240 it->ops->close(it->iter_arg); 241 it->ops = NULL; 242 REFTABLE_FREE_AND_NULL(it->iter_arg); 243} 244 245int reftable_iterator_seek_ref(struct reftable_iterator *it, 246 const char *name) 247{ 248 struct reftable_record want = { 249 .type = REFTABLE_BLOCK_TYPE_REF, 250 .u.ref = { 251 .refname = (char *)name, 252 }, 253 }; 254 return it->ops->seek(it->iter_arg, &want); 255} 256 257int reftable_iterator_next_ref(struct reftable_iterator *it, 258 struct reftable_ref_record *ref) 259{ 260 struct reftable_record rec = { 261 .type = REFTABLE_BLOCK_TYPE_REF, 262 .u = { 263 .ref = *ref 264 }, 265 }; 266 int err = iterator_next(it, &rec); 267 *ref = rec.u.ref; 268 return err; 269} 270 271int reftable_iterator_seek_log_at(struct reftable_iterator *it, 272 const char *name, uint64_t update_index) 273{ 274 struct reftable_record want = { 275 .type = REFTABLE_BLOCK_TYPE_LOG, 276 .u.log = { 277 .refname = (char *)name, 278 .update_index = update_index, 279 }, 280 }; 281 return it->ops->seek(it->iter_arg, &want); 282} 283 284int reftable_iterator_seek_log(struct reftable_iterator *it, 285 const char *name) 286{ 287 return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0)); 288} 289 290int reftable_iterator_next_log(struct reftable_iterator *it, 291 struct reftable_log_record *log) 292{ 293 struct reftable_record rec = { 294 .type = REFTABLE_BLOCK_TYPE_LOG, 295 .u = { 296 .log = *log, 297 }, 298 }; 299 int err = iterator_next(it, &rec); 300 *log = rec.u.log; 301 return err; 302}