journal.h 6.48 KB
Newer Older
1
/*  Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

    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 <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <pthread.h>

21
#include "libknot/db/db.h"
22 23 24
#include "contrib/ucw/lists.h"
#include "knot/updates/changesets.h"
#include "knot/journal/serialization.h"
25
#include "knot/zone/serial.h"
26

27 28
/*! \brief Minimum journal size. */
#define JOURNAL_MIN_FSLIMIT	(1 * 1024 * 1024)
29

30 31 32 33 34
typedef enum {
	JOURNAL_MODE_ROBUST = 0, // Robust journal DB disk synchronization.
	JOURNAL_MODE_ASYNC  = 1, // Asynchronous journal DB disk synchronization.
} journal_mode_t;

35 36 37 38 39
typedef struct {
	knot_db_t *db;
	const knot_db_api_t *db_api;
	char *path;
	size_t fslimit;
40
	journal_mode_t mode;
41 42 43 44 45 46 47 48
	pthread_mutex_t db_mutex; // please delete this once you move DB opening from journal_open to db_init
} journal_db_t;

typedef struct {
	journal_db_t *db;
	knot_dname_t *zone;
} journal_t;

49 50 51
typedef enum {
	JOURNAL_CHECK_SILENT = 0, // No logging, just curious for return value.
	JOURNAL_CHECK_WARN   = 1, // Log journal inconsistencies.
52 53
	JOURNAL_CHECK_INFO   = 2, // Log journal state.
	JOURNAL_CHECK_STDERR = 3, // Log everything and redirect to stderr.
54
} journal_check_level_t;
55 56 57 58 59 60 61

/*!
 * \brief Initialize shared journal DB file. The DB will be open on first use.
 *
 * \param db             Database to be initialized. Must be (*db == NULL) before!
 * \param lmdb_dir_path  Path to the directory with DB
 * \param lmdb_fslimit   Maximum size of DB data file
62
 * \param mode           Journal DB synchronization mode.
63 64 65
 *
 * \return KNOT_E*
 */
66 67
int journal_db_init(journal_db_t **db, const char *lmdb_dir_path, size_t lmdb_fslimit,
                    journal_mode_t mode);
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

/*!
 * \brief Close shared journal DB file.
 *
 * \param db DB to close.
 */
void journal_db_close(journal_db_t **db);

/*!
 * \brief List the zones contained in journal DB.
 *
 * \param db[in]      Shared journal DB
 * \param zones[out]  List of strings (char *) of zone names
 *
 * \return KNOT_EOK    ok
 * \retval KNOT_ENOMEM no zones found
 * \retval KNOT_EMALF  different # of zones found than expected
 * \retval KNOT_E*     other error
 */
int journal_db_list_zones(journal_db_t **db, list_t *zones);
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

/*!
 * \brief Allocate a new journal structure.
 *
 * \retval new journal instance if successful.
 * \retval NULL on error.
 */
journal_t *journal_new(void);

/*!
 * \brief Free a journal structure.
 *
 * \param journal  A journal structure to free.
 */
void journal_free(journal_t **journal);

/*!
 * \brief Open journal.
 *
 * \param j          Journal struct to use.
 * \param db         Shared journal database
 * \param zone_name  Name of the zone this journal belongs to.
 *
 * \retval KNOT_EOK on success.
 * \return < KNOT_EOK on other errors.
 */
int journal_open(journal_t *j, journal_db_t **db, const knot_dname_t *zone_name);

/*!
 * \brief Close journal.
 *
 * \param journal  Journal to close.
 */
void journal_close(journal_t *journal);

/*!
124
 * \brief Load changesets from journal since "from" serial.
125 126 127 128 129 130 131 132 133 134 135
 *
 * \param journal  Journal to load from.
 * \param dst      Store changesets here.
 * \param from     Start serial.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_ENOENT when the lookup of the first entry fails.
 * \return < KNOT_EOK on other error.
 */
int journal_load_changesets(journal_t *journal, list_t *dst, uint32_t from);

136 137 138 139 140 141 142 143 144 145 146 147
/*!
 * \brief Load changesets from journal, starting with bootstrap changeset.
 *
 * \param journal  Journal to load from.
 * \param dst      Store changesets here, starting with bootstrap changeset.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_ENOENT when there is no bootstrap changeset.
 * \return < KNOT_EOK on other error.
 */
int journal_load_bootstrap(journal_t *j, list_t *dst);

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
/*!
 * \brief Store changesets in journal.
 *
 * \param journal  Journal to store in.
 * \param src      Changesets to store.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EBUSY when full, asking zone to flush itself to zonefile
 *                    to allow cleaning up history and freeing up space
 * \retval KNOT_ESPACE when full and not able to free up any space
 * \return < KNOT_EOK on other errors.
 */
int journal_store_changesets(journal_t *journal, list_t *src);

/*!
 * \brief Store changesets in journal.
 *
 * \param journal  Journal to store in.
 * \param change   Changeset to store.
 *
 * \retval (same as for journal_store_changesets())
 */
int journal_store_changeset(journal_t *journal, changeset_t *change);

172 173 174 175 176 177 178 179 180 181
/*!
 * \brief Open the journal database.
 *
 * This is an "almost static" function, which is mostly called by other journal
 * methods like journal_open() and journal_exists(). However it can be called
 * separately just for more precise error resolution.
 *
 * \param db Journal to be opened.
 * \return KNOT_E*
 */
182
int journal_open_db(journal_db_t **db);
183

184 185 186
/*!
 * \brief Check if this (zone's) journal is present in shared journal DB.
 *
187 188
 * \param db         Shared journal DB
 * \param zone_name  Name of the zone of the journal in question
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
 *
 * \return true or false
 */
bool journal_exists(journal_db_t **db, knot_dname_t *zone_name);

/*! \brief Tell the journal that zone has been flushed.
 *
 * \param journal  Journal to flush.
 *
 * \return KNOT_E*
 */
int journal_flush(journal_t *journal);

/*! \brief Remove completely this (zone's) journal from shared journal DB.
 *
 * This must be called with opened journal.
 *
 * \param j Journal to be deleted
 *
 * \return KNOT_E*
 */
210
int journal_scrape(journal_t *j);
211 212 213

/*! \brief Obtain public information from journal metadata
 */
214
void journal_metadata_info(journal_t *j, bool *is_empty, kserial_t *merged_serial,
215 216
                           kserial_t *first_serial, kserial_t *last_flushed, kserial_t *serial_to,
                           uint64_t *occupied);
217 218 219

/*! \brief Check the journal consistency, errors to stderr.
 *
220 221
 * \param journal     Journal to check.
 * \param warn_level  Journal check level.
222 223 224
 *
 * \return KNOT_E*
 */
225
int journal_check(journal_t *j, journal_check_level_t warn_level);
226 227

/*! @} */