Coverage Report

Created: 2020-05-07 18:36

/proc/self/cwd/c/iter.c
Line
Count
Source (jump to first uncovered line)
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 "constants.h"
15
#include "reader.h"
16
#include "reftable.h"
17
18
bool iterator_is_null(struct reftable_iterator it)
19
670
{
20
670
  return it.ops == NULL;
21
670
}
22
23
static int empty_iterator_next(void *arg, struct record rec)
24
215
{
25
215
  return 1;
26
215
}
27
28
static void empty_iterator_close(void *arg)
29
215
{
30
215
}
31
32
struct reftable_iterator_vtable empty_vtable = {
33
  .next = &empty_iterator_next,
34
  .close = &empty_iterator_close,
35
};
36
37
void iterator_set_empty(struct reftable_iterator *it)
38
215
{
39
215
  assert(it->ops == NULL);
40
215
  it->iter_arg = NULL;
41
215
  it->ops = &empty_vtable;
42
215
}
43
44
int iterator_next(struct reftable_iterator it, struct record rec)
45
3.11k
{
46
3.11k
  return it.ops->next(it.iter_arg, rec);
47
3.11k
}
48
49
void reftable_iterator_destroy(struct reftable_iterator *it)
50
2.37k
{
51
2.37k
  if (it->ops == NULL) {
52
699
    return;
53
699
  }
54
1.67k
  it->ops->close(it->iter_arg);
55
1.67k
  it->ops = NULL;
56
1.67k
  FREE_AND_NULL(it->iter_arg);
57
1.67k
}
58
59
int reftable_iterator_next_ref(struct reftable_iterator it,
60
             struct reftable_ref_record *ref)
61
1.25k
{
62
1.25k
  struct record rec = { 0 };
63
1.25k
  record_from_ref(&rec, ref);
64
1.25k
  return iterator_next(it, rec);
65
1.25k
}
66
67
int reftable_iterator_next_log(struct reftable_iterator it,
68
             struct reftable_log_record *log)
69
187
{
70
187
  struct record rec = { 0 };
71
187
  record_from_log(&rec, log);
72
187
  return iterator_next(it, rec);
73
187
}
74
75
static void filtering_ref_iterator_close(void *iter_arg)
76
1
{
77
1
  struct filtering_ref_iterator *fri =
78
1
    (struct filtering_ref_iterator *)iter_arg;
79
1
  slice_clear(&fri->oid);
80
1
  reftable_iterator_destroy(&fri->it);
81
1
}
82
83
static int filtering_ref_iterator_next(void *iter_arg, struct record rec)
84
9
{
85
9
  struct filtering_ref_iterator *fri =
86
9
    (struct filtering_ref_iterator *)iter_arg;
87
9
  struct reftable_ref_record *ref =
88
9
    (struct reftable_ref_record *)rec.data;
89
9
  int err = 0;
90
51
  while (true) {
91
51
    err = reftable_iterator_next_ref(fri->it, ref);
92
51
    if (err != 0) {
93
1
      break;
94
1
    }
95
50
96
50
    if (fri->double_check) {
97
0
      struct reftable_iterator it = { 0 };
98
0
99
0
      err = reftable_table_seek_ref(fri->tab, &it,
100
0
                  ref->ref_name);
101
0
      if (err == 0) {
102
0
        err = reftable_iterator_next_ref(it, ref);
103
0
      }
104
0
105
0
      reftable_iterator_destroy(&it);
106
0
107
0
      if (err < 0) {
108
0
        break;
109
0
      }
110
0
111
0
      if (err > 0) {
112
0
        continue;
113
0
      }
114
50
    }
115
50
116
50
    if ((ref->target_value != NULL &&
117
50
         !memcmp(fri->oid.buf, ref->target_value, fri->oid.len)) ||
118
50
        (ref->value != NULL &&
119
46
         !memcmp(fri->oid.buf, ref->value, fri->oid.len))) {
120
8
      return 0;
121
8
    }
122
50
  }
123
9
124
9
  reftable_ref_record_clear(ref);
125
1
  return err;
126
9
}
127
128
struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
129
  .next = &filtering_ref_iterator_next,
130
  .close = &filtering_ref_iterator_close,
131
};
132
133
void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
134
            struct filtering_ref_iterator *fri)
135
1
{
136
1
  assert(it->ops == NULL);
137
1
  it->iter_arg = fri;
138
1
  it->ops = &filtering_ref_iterator_vtable;
139
1
}
140
141
static void indexed_table_ref_iter_close(void *p)
142
1
{
143
1
  struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
144
1
  block_iter_close(&it->cur);
145
1
  reftable_block_done(&it->block_reader.block);
146
1
  slice_clear(&it->oid);
147
1
}
148
149
static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
150
5
{
151
5
  if (it->offset_idx == it->offset_len) {
152
1
    it->finished = true;
153
1
    return 1;
154
1
  }
155
4
156
4
  reftable_block_done(&it->block_reader.block);
157
4
158
4
  {
159
4
    uint64_t off = it->offsets[it->offset_idx++];
160
4
    int err = reader_init_block_reader(it->r, &it->block_reader,
161
4
               off, BLOCK_TYPE_REF);
162
4
    if (err < 0) {
163
0
      return err;
164
0
    }
165
4
    if (err > 0) {
166
0
      /* indexed block does not exist. */
167
0
      return REFTABLE_FORMAT_ERROR;
168
0
    }
169
4
  }
170
4
  block_reader_start(&it->block_reader, &it->cur);
171
4
  return 0;
172
4
}
173
174
static int indexed_table_ref_iter_next(void *p, struct record rec)
175
9
{
176
9
  struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
177
9
  struct reftable_ref_record *ref =
178
9
    (struct reftable_ref_record *)rec.data;
179
9
180
16
  while (true) {
181
16
    int err = block_iter_next(&it->cur, rec);
182
16
    if (err < 0) {
183
0
      return err;
184
0
    }
185
16
186
16
    if (err > 0) {
187
4
      err = indexed_table_ref_iter_next_block(it);
188
4
      if (err < 0) {
189
0
        return err;
190
0
      }
191
4
192
4
      if (it->finished) {
193
1
        return 1;
194
1
      }
195
3
      continue;
196
3
    }
197
12
198
12
    if (!memcmp(it->oid.buf, ref->target_value, it->oid.len) ||
199
12
        !memcmp(it->oid.buf, ref->value, it->oid.len)) {
200
8
      return 0;
201
8
    }
202
12
  }
203
9
}
204
205
int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
206
             struct reftable_reader *r, byte *oid,
207
             int oid_len, uint64_t *offsets, int offset_len)
208
1
{
209
1
  struct indexed_table_ref_iter *itr =
210
1
    reftable_calloc(sizeof(struct indexed_table_ref_iter));
211
1
  int err = 0;
212
1
213
1
  itr->r = r;
214
1
  slice_resize(&itr->oid, oid_len);
215
1
  memcpy(itr->oid.buf, oid, oid_len);
216
1
217
1
  itr->offsets = offsets;
218
1
  itr->offset_len = offset_len;
219
1
220
1
  err = indexed_table_ref_iter_next_block(itr);
221
1
  if (err < 0) {
222
0
    reftable_free(itr);
223
1
  } else {
224
1
    *dest = itr;
225
1
  }
226
1
  return err;
227
1
}
228
229
struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
230
  .next = &indexed_table_ref_iter_next,
231
  .close = &indexed_table_ref_iter_close,
232
};
233
234
void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
235
            struct indexed_table_ref_iter *itr)
236
1
{
237
1
  assert(it->ops == NULL);
238
1
  it->iter_arg = itr;
239
1
  it->ops = &indexed_table_ref_iter_vtable;
240
1
}