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
|
/* Copyright (C) 2022 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/conf/conf.h"
#include "knot/journal/knot_lmdb.h"
#include "knot/updates/changesets.h"
#include "libknot/dname.h"
typedef struct {
knot_lmdb_db_t *db;
const knot_dname_t *zone;
void *conf; // needed only for journal write operations
} zone_journal_t;
#define JOURNAL_CHUNK_MAX (70 * 1024) // must be at least 64k + 6B
#define JOURNAL_CHUNK_THRESH (15 * 1024)
#define JOURNAL_HEADER_SIZE (32)
/*! \brief Convert journal_mode to LMDB environment flags. */
inline static unsigned journal_env_flags(int journal_mode, bool readonly)
{
return (journal_mode == JOURNAL_MODE_ASYNC ? (MDB_WRITEMAP | MDB_MAPASYNC) : 0) |
(readonly ? MDB_RDONLY : 0);
}
/*!
* \brief Create a database key prefix to search for a changeset.
*
* \param zone_in_journal True if searching for zone-in-journal special changeset.
* \param serial Serial-from of the changeset to be searched for. Ignored if 'zone_in_journal'.
* \param zone Name of the zone.
*
* \return DB key. 'mv_data' shall be freed later. 'mv_data' is NULL on failure.
*/
MDB_val journal_changeset_id_to_key(bool zone_in_journal, uint32_t serial, const knot_dname_t *zone);
/*!
* \brief Create a database key for changeset chunk.
*
* \param apex Zone apex owner name.
* \param ch_from Serial "from" of the stored changeset.
* \param zij Zone-in-journal is stored.
* \param chunk_id Ordinal number of this changeset's chunk.
*
* \return DB key. 'mv_data' shall be freed later. 'mv_data' is NULL on failure.
*/
MDB_val journal_make_chunk_key(const knot_dname_t *apex, uint32_t ch_from, bool zij, uint32_t chunk_id);
/*!
* \brief Return a key prefix to operate with all zone-related records.
*/
MDB_val journal_zone_prefix(const knot_dname_t *zone);
/*!
* \brief Delete all zone-related records from journal with open read-write txn.
*/
void journal_del_zone(knot_lmdb_txn_t *txn, const knot_dname_t *zone);
/*!
* \brief Initialise chunk header.
*
* \param chunk Pointer to the changeset chunk. It must be at least JOURNAL_HEADER_SIZE, perhaps more.
* \param ch Serial-to of the changeset being serialized.
*/
void journal_make_header(void *chunk, uint32_t ch_serial_to);
/*!
* \brief Obtain serial-to of the serialized changeset.
*
* \param chunk Any chunk of a serialized changeset.
*
* \return The changeset's serial-to.
*/
uint32_t journal_next_serial(const MDB_val *chunk);
/*!
* \brief Obtain serial-to of a changeset stored in journal.
*
* \param txn Journal DB transaction.
* \param zij True if changeset in question is zone-in-journal.
* \param serial Serial-from of the changeset in question.
* \param zone Zone name.
* \param serial_to Output: serial-to of the changeset in question.
*
* \return True if the changeset exists in the journal.
*/
bool journal_serial_to(knot_lmdb_txn_t *txn, bool zij, uint32_t serial,
const knot_dname_t *zone, uint32_t *serial_to);
/*! \brief Return true if the changeset in question exists in the journal. */
inline static bool journal_contains(knot_lmdb_txn_t *txn, bool zone, uint32_t serial, const knot_dname_t *zone_name)
{
return journal_serial_to(txn, zone, serial, zone_name, NULL);
}
/*! \brief Return true if the journal may be flushed according to conf. */
bool journal_allow_flush(zone_journal_t j);
/*! \brief Return configured maximal per-zone usage of journal DB. */
size_t journal_conf_max_usage(zone_journal_t j);
/*! \brief Return configured maximal depth of journal. */
size_t journal_conf_max_changesets(zone_journal_t j);
|