reftable: generic interface to tables
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Han-Wen Nienhuys committed
Oct 7, 2021 at 20:25 UTC
17df8dbeba18c8c36f14c58815a03091ba61f895
6 files changed
+405
Makefile
+3
@@ -2462,6 +2462,9 @@ REFTABLE_OBJS += reftable/block.o
2462
REFTABLE_OBJS += reftable/blocksource.o
2463
REFTABLE_OBJS += reftable/publicbasics.o
2464
REFTABLE_OBJS += reftable/record.o
2465
+REFTABLE_OBJS += reftable/refname.o
2466
+REFTABLE_OBJS += reftable/generic.o
2467
+REFTABLE_OBJS += reftable/stack.o
2468
REFTABLE_OBJS += reftable/tree.o
2469
REFTABLE_OBJS += reftable/writer.o
2470
reftable/generic.c
new
+169
@@ -0,0 +1,169 @@
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 "basics.h"
10
+#include "record.h"
11
+#include "generic.h"
12
+#include "reftable-iterator.h"
13
+#include "reftable-generic.h"
14
+
15
+int reftable_table_seek_ref(struct reftable_table *tab,
16
+ struct reftable_iterator *it, const char *name)
17
+{
18
+ struct reftable_ref_record ref = {
19
+ .refname = (char *)name,
20
+ };
21
+ struct reftable_record rec = { NULL };
22
+ reftable_record_from_ref(&rec, &ref);
23
+ return tab->ops->seek_record(tab->table_arg, it, &rec);
24
+}
25
+
26
+int reftable_table_seek_log(struct reftable_table *tab,
27
+ struct reftable_iterator *it, const char *name)
28
+{
29
+ struct reftable_log_record log = {
30
+ .refname = (char *)name,
31
+ .update_index = ~((uint64_t)0),
32
+ };
33
+ struct reftable_record rec = { NULL };
34
+ reftable_record_from_log(&rec, &log);
35
+ return tab->ops->seek_record(tab->table_arg, it, &rec);
36
+}
37
+
38
+int reftable_table_read_ref(struct reftable_table *tab, const char *name,
39
+ struct reftable_ref_record *ref)
40
+{
41
+ struct reftable_iterator it = { NULL };
42
+ int err = reftable_table_seek_ref(tab, &it, name);
43
+ if (err)
44
+ goto done;
45
+
46
+ err = reftable_iterator_next_ref(&it, ref);
47
+ if (err)
48
+ goto done;
49
+
50
+ if (strcmp(ref->refname, name) ||
51
+ reftable_ref_record_is_deletion(ref)) {
52
+ reftable_ref_record_release(ref);
53
+ err = 1;
54
+ goto done;
55
+ }
56
+
57
+done:
58
+ reftable_iterator_destroy(&it);
59
+ return err;
60
+}
61
+
62
+int reftable_table_print(struct reftable_table *tab) {
63
+ struct reftable_iterator it = { NULL };
64
+ struct reftable_ref_record ref = { NULL };
65
+ struct reftable_log_record log = { NULL };
66
+ uint32_t hash_id = reftable_table_hash_id(tab);
67
+ int err = reftable_table_seek_ref(tab, &it, "");
68
+ if (err < 0) {
69
+ return err;
70
+ }
71
+
72
+ while (1) {
73
+ err = reftable_iterator_next_ref(&it, &ref);
74
+ if (err > 0) {
75
+ break;
76
+ }
77
+ if (err < 0) {
78
+ return err;
79
+ }
80
+ reftable_ref_record_print(&ref, hash_id);
81
+ }
82
+ reftable_iterator_destroy(&it);
83
+ reftable_ref_record_release(&ref);
84
+
85
+ err = reftable_table_seek_log(tab, &it, "");
86
+ if (err < 0) {
87
+ return err;
88
+ }
89
+ while (1) {
90
+ err = reftable_iterator_next_log(&it, &log);
91
+ if (err > 0) {
92
+ break;
93
+ }
94
+ if (err < 0) {
95
+ return err;
96
+ }
97
+ reftable_log_record_print(&log, hash_id);
98
+ }
99
+ reftable_iterator_destroy(&it);
100
+ reftable_log_record_release(&log);
101
+ return 0;
102
+}
103
+
104
+uint64_t reftable_table_max_update_index(struct reftable_table *tab)
105
+{
106
+ return tab->ops->max_update_index(tab->table_arg);
107
+}
108
+
109
+uint64_t reftable_table_min_update_index(struct reftable_table *tab)
110
+{
111
+ return tab->ops->min_update_index(tab->table_arg);
112
+}
113
+
114
+uint32_t reftable_table_hash_id(struct reftable_table *tab)
115
+{
116
+ return tab->ops->hash_id(tab->table_arg);
117
+}
118
+
119
+void reftable_iterator_destroy(struct reftable_iterator *it)
120
+{
121
+ if (!it->ops) {
122
+ return;
123
+ }
124
+ it->ops->close(it->iter_arg);
125
+ it->ops = NULL;
126
+ FREE_AND_NULL(it->iter_arg);
127
+}
128
+
129
+int reftable_iterator_next_ref(struct reftable_iterator *it,
130
+ struct reftable_ref_record *ref)
131
+{
132
+ struct reftable_record rec = { NULL };
133
+ reftable_record_from_ref(&rec, ref);
134
+ return iterator_next(it, &rec);
135
+}
136
+
137
+int reftable_iterator_next_log(struct reftable_iterator *it,
138
+ struct reftable_log_record *log)
139
+{
140
+ struct reftable_record rec = { NULL };
141
+ reftable_record_from_log(&rec, log);
142
+ return iterator_next(it, &rec);
143
+}
144
+
145
+int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
146
+{
147
+ return it->ops->next(it->iter_arg, rec);
148
+}
149
+
150
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
151
+{
152
+ return 1;
153
+}
154
+
155
+static void empty_iterator_close(void *arg)
156
+{
157
+}
158
+
159
+static struct reftable_iterator_vtable empty_vtable = {
160
+ .next = &empty_iterator_next,
161
+ .close = &empty_iterator_close,
162
+};
163
+
164
+void iterator_set_empty(struct reftable_iterator *it)
165
+{
166
+ assert(!it->ops);
167
+ it->iter_arg = NULL;
168
+ it->ops = &empty_vtable;
169
+}
reftable/generic.h
new
+32
@@ -0,0 +1,32 @@
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
+#ifndef GENERIC_H
10
+#define GENERIC_H
11
+
12
+#include "record.h"
13
+#include "reftable-generic.h"
14
+
15
+/* generic interface to reftables */
16
+struct reftable_table_vtable {
17
+ int (*seek_record)(void *tab, struct reftable_iterator *it,
18
+ struct reftable_record *);
19
+ uint32_t (*hash_id)(void *tab);
20
+ uint64_t (*min_update_index)(void *tab);
21
+ uint64_t (*max_update_index)(void *tab);
22
+};
23
+
24
+struct reftable_iterator_vtable {
25
+ int (*next)(void *iter_arg, struct reftable_record *rec);
26
+ void (*close)(void *iter_arg);
27
+};
28
+
29
+void iterator_set_empty(struct reftable_iterator *it);
30
+int iterator_next(struct reftable_iterator *it, struct reftable_record *rec);
31
+
32
+#endif
reftable/reftable-generic.h
new
+47
@@ -0,0 +1,47 @@
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
+#ifndef REFTABLE_GENERIC_H
10
+#define REFTABLE_GENERIC_H
11
+
12
+#include "reftable-iterator.h"
13
+
14
+struct reftable_table_vtable;
15
+
16
+/*
17
+ * Provides a unified API for reading tables, either merged tables, or single
18
+ * readers. */
19
+struct reftable_table {
20
+ struct reftable_table_vtable *ops;
21
+ void *table_arg;
22
+};
23
+
24
+int reftable_table_seek_log(struct reftable_table *tab,
25
+ struct reftable_iterator *it, const char *name);
26
+
27
+int reftable_table_seek_ref(struct reftable_table *tab,
28
+ struct reftable_iterator *it, const char *name);
29
+
30
+/* returns the hash ID from a generic reftable_table */
31
+uint32_t reftable_table_hash_id(struct reftable_table *tab);
32
+
33
+/* returns the max update_index covered by this table. */
34
+uint64_t reftable_table_max_update_index(struct reftable_table *tab);
35
+
36
+/* returns the min update_index covered by this table. */
37
+uint64_t reftable_table_min_update_index(struct reftable_table *tab);
38
+
39
+/* convenience function to read a single ref. Returns < 0 for error, 0
40
+ for success, and 1 if ref not found. */
41
+int reftable_table_read_ref(struct reftable_table *tab, const char *name,
42
+ struct reftable_ref_record *ref);
43
+
44
+/* dump table contents onto stdout for debugging */
45
+int reftable_table_print(struct reftable_table *tab);
46
+
47
+#endif
reftable/reftable-iterator.h
new
+39
@@ -0,0 +1,39 @@
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
+#ifndef REFTABLE_ITERATOR_H
10
+#define REFTABLE_ITERATOR_H
11
+
12
+#include "reftable-record.h"
13
+
14
+struct reftable_iterator_vtable;
15
+
16
+/* iterator is the generic interface for walking over data stored in a
17
+ * reftable.
18
+ */
19
+struct reftable_iterator {
20
+ struct reftable_iterator_vtable *ops;
21
+ void *iter_arg;
22
+};
23
+
24
+/* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0:
25
+ * end of iteration.
26
+ */
27
+int reftable_iterator_next_ref(struct reftable_iterator *it,
28
+ struct reftable_ref_record *ref);
29
+
30
+/* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0:
31
+ * end of iteration.
32
+ */
33
+int reftable_iterator_next_log(struct reftable_iterator *it,
34
+ struct reftable_log_record *log);
35
+
36
+/* releases resources associated with an iterator. */
37
+void reftable_iterator_destroy(struct reftable_iterator *it);
38
+
39
+#endif
reftable/reftable.c
new
+115
@@ -0,0 +1,115 @@
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 "basics.h"
10
+#include "record.h"
11
+#include "generic.h"
12
+#include "reftable-iterator.h"
13
+#include "reftable-generic.h"
14
+
15
+int reftable_table_seek_ref(struct reftable_table *tab,
16
+ struct reftable_iterator *it, const char *name)
17
+{
18
+ struct reftable_ref_record ref = {
19
+ .refname = (char *)name,
20
+ };
21
+ struct reftable_record rec = { NULL };
22
+ reftable_record_from_ref(&rec, &ref);
23
+ return tab->ops->seek_record(tab->table_arg, it, &rec);
24
+}
25
+
26
+int reftable_table_read_ref(struct reftable_table *tab, const char *name,
27
+ struct reftable_ref_record *ref)
28
+{
29
+ struct reftable_iterator it = { NULL };
30
+ int err = reftable_table_seek_ref(tab, &it, name);
31
+ if (err)
32
+ goto done;
33
+
34
+ err = reftable_iterator_next_ref(&it, ref);
35
+ if (err)
36
+ goto done;
37
+
38
+ if (strcmp(ref->refname, name) ||
39
+ reftable_ref_record_is_deletion(ref)) {
40
+ reftable_ref_record_release(ref);
41
+ err = 1;
42
+ goto done;
43
+ }
44
+
45
+done:
46
+ reftable_iterator_destroy(&it);
47
+ return err;
48
+}
49
+
50
+uint64_t reftable_table_max_update_index(struct reftable_table *tab)
51
+{
52
+ return tab->ops->max_update_index(tab->table_arg);
53
+}
54
+
55
+uint64_t reftable_table_min_update_index(struct reftable_table *tab)
56
+{
57
+ return tab->ops->min_update_index(tab->table_arg);
58
+}
59
+
60
+uint32_t reftable_table_hash_id(struct reftable_table *tab)
61
+{
62
+ return tab->ops->hash_id(tab->table_arg);
63
+}
64
+
65
+void reftable_iterator_destroy(struct reftable_iterator *it)
66
+{
67
+ if (!it->ops) {
68
+ return;
69
+ }
70
+ it->ops->close(it->iter_arg);
71
+ it->ops = NULL;
72
+ FREE_AND_NULL(it->iter_arg);
73
+}
74
+
75
+int reftable_iterator_next_ref(struct reftable_iterator *it,
76
+ struct reftable_ref_record *ref)
77
+{
78
+ struct reftable_record rec = { NULL };
79
+ reftable_record_from_ref(&rec, ref);
80
+ return iterator_next(it, &rec);
81
+}
82
+
83
+int reftable_iterator_next_log(struct reftable_iterator *it,
84
+ struct reftable_log_record *log)
85
+{
86
+ struct reftable_record rec = { NULL };
87
+ reftable_record_from_log(&rec, log);
88
+ return iterator_next(it, &rec);
89
+}
90
+
91
+int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
92
+{
93
+ return it->ops->next(it->iter_arg, rec);
94
+}
95
+
96
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
97
+{
98
+ return 1;
99
+}
100
+
101
+static void empty_iterator_close(void *arg)
102
+{
103
+}
104
+
105
+static struct reftable_iterator_vtable empty_vtable = {
106
+ .next = &empty_iterator_next,
107
+ .close = &empty_iterator_close,
108
+};
109
+
110
+void iterator_set_empty(struct reftable_iterator *it)
111
+{
112
+ assert(!it->ops);
113
+ it->iter_arg = NULL;
114
+ it->ops = &empty_vtable;
115
+}