summaryrefslogtreecommitdiffstats
path: root/src/knot/journal/journal_metadata.h
blob: 246d89973e2799662115aa8cf3f24174f42de06c (plain)
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);