1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "knot/journal/journal_basic.h"
typedef struct {
uint32_t first_serial;
uint32_t serial_to;
uint32_t flushed_upto;
uint32_t merged_serial;
uint32_t changeset_count;
uint32_t flags; // a bitmap of flags, see enum below
bool _new_zone; // private: if there were no metadata at all previously
} journal_metadata_t;
enum journal_metadata_flags {
JOURNAL_LAST_FLUSHED_VALID = (1 << 0), // deprecated
JOURNAL_SERIAL_TO_VALID = (1 << 1),
JOURNAL_MERGED_SERIAL_VALID = (1 << 2),
};
typedef int (*journals_walk_cb_t)(const knot_dname_t *zone, void *ctx);
/*!
* \brief Update the computation of DB resources used by each zone.
*
* Because the amount of used space is bigger than sum of changesets' serialized_sizes,
* journal uses a complicated way to compute each zone's used space: there is a metadata
* showing always the previously-inserting zone. Before the next insert, it is computed
* how the total usage of the DB changed during the previous insert (or delete), and the
* usage increase (or decrease) is accounted on the bill of the previous inserter.
*
* \param txn Journal DB transaction.
* \param new_inserter Name of the zone that is going to insert now. Might be NULL if no insert nor delete will be done.
*/
void update_last_inserter(knot_lmdb_txn_t *txn, const knot_dname_t *new_inserter);
/* \brief Return the journal database usage by given zone. */
uint64_t journal_get_occupied(knot_lmdb_txn_t *txn, const knot_dname_t *zone);
/*!
* \brief Load the metadata from DB into structure.
*
* \param txn Journal DB transaction.
* \param zone Zone name.
* \param md Output: metadata structure.
*/
void journal_load_metadata(knot_lmdb_txn_t *txn, const knot_dname_t *zone, journal_metadata_t *md);
/*!
* \brief Store the metadata from structure into DB.
*
* \param txn Journal DB transaction.
* \param zone Zone name.
* \param md Metadata structure.
*/
void journal_store_metadata(knot_lmdb_txn_t *txn, const knot_dname_t *zone, const journal_metadata_t *md);
/*!
* \brief Update metadata according to what was deleted.
*
* \param md Metadata structure to be updated.
* \param deleted_upto Serial-to of the last deleted changeset.
* \param deleted_count Number of deleted changesets.
*/
void journal_metadata_after_delete(journal_metadata_t *md, uint32_t deleted_upto,
size_t deleted_count);
/*!
* \brief Update metadata according to what was merged.
*
* \param md Metadata structure to be updated.
* \param merged_zij True if it was a merge into zone-in-journal.
* \param merged_serial Serial-from of the merged changeset (ignored if 'merged_zij').
* \param merged_serial_to Serial-to of the merged changeset.
* \param original_serial_to Previous serial-to of the merged changeset before the merge.
*/
void journal_metadata_after_merge(journal_metadata_t *md, bool merged_zij, uint32_t merged_serial,
uint32_t merged_serial_to, uint32_t original_serial_to);
/*!
* \brief Update metadata according to what was inserted.
*
* \param md Metadata structure to be updated.
* \param serial Serial-from of the inserted changeset.
* \param serial_to Serial-to of the inserted changeset.
*/
void journal_metadata_after_insert(journal_metadata_t *md, uint32_t serial, uint32_t serial_to);
/*!
* \brief Update metadata according to inserted extra changeset.
*
* \param md Metadata structure to be updated.
* \param serial Serial-from of the inserted changeset.
* \param serial_to Serial-to of the inserted changeset.
*/
void journal_metadata_after_extra(journal_metadata_t *md, uint32_t serial, uint32_t serial_to);
/*!
* \brief Delete all zone records in a txn that will later write to the same zone.
*
* \note The difference against journal_del_zone(), which purges even metadata, incl "occupied".
* \note This preserves keeping track of space occupied/freed by this zone.
*/
void journal_del_zone_txn(knot_lmdb_txn_t *txn, const knot_dname_t *zone);
/*!
* \brief Completely delete all journal records belonging to this zone, including metadata.
*
* \param j Journal to be scraped.
* \param check_existence Don't operate if the journal seems not to exist.
*
* \return KNOT_E*
*/
int journal_scrape_with_md(zone_journal_t j, bool check_existence);
/*!
* \brief Copy all records related to this zone from one journal DB to another.
*
* \param from DB to copy from.
* \param to DB to copy to.
* \param zone Journal zone.
*
* \return KNOT_E*
*/
int journal_copy_with_md(knot_lmdb_db_t *from, knot_lmdb_db_t *to, const knot_dname_t *zone);
/*!
* \brief Update the metadata stored in journal DB after a zone flush.
*
* \param j Journal to be notified about flush.
*
* \return KNOT_E*
*/
int journal_set_flushed(zone_journal_t j);
/*!
* \brief Obtain information about the zone's journal from the DB (mostly metadata).
*
* \param j Zone journal.
* \param exists Output: bool if the zone exists in the journal.
* \param first_serial Optional output: serial-from of the first changeset in journal.
* \param has_zij Optional output: bool if there is zone-in-journal.
* \param serial_to Optional output: serial.to of the last changeset in journal.
* \param has_merged Optional output: bool if there is a special (non zone-in-journal) merged changeset.
* \param merged_serial Optional output: serial-from of the merged changeset.
* \param occupied Optional output: DB space occupied by this zones.
* \param occupied_total Optional output: DB space occupied in total by all zones.
*
* \return KNOT_E*
*/
int journal_info(zone_journal_t j, bool *exists, uint32_t *first_serial, bool *has_zij,
uint32_t *serial_to, bool *has_merged, uint32_t *merged_serial,
uint64_t *occupied, uint64_t *occupied_total);
/*! \brief Return true if this zone exists in journal DB. */
inline static bool journal_is_existing(zone_journal_t j) {
bool ex = false;
(void)journal_info(j, &ex, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
return ex;
}
/*!
* \brief Call a function for each zone being in the journal DB.
*
* \param db Journal database.
* \param cb Callback to be called for each zone-name found.
* \param ctx Arbitrary context to be passed to the callback.
*
* \return An error code from either journal operations or from the callback.
*/
int journals_walk(knot_lmdb_db_t *db, journals_walk_cb_t cb, void *ctx);
|