assert(ctx != NULL);
ctx->backup_journal = MATCH_AND_FILTER(args, CTL_FILTER_PURGE_JOURNAL);
ctx->backup_zonefile = !MATCH_AND_FILTER(args, CTL_FILTER_PURGE_ZONEFILE);
- if (args->server->backup_ctx != NULL) {
- log_warning("backup already in progress");
- zone_backup_deinit(ctx);
- return KNOT_EPROGRESS;
- }
- args->server->backup_ctx = ctx;
- ctx->server_self_ptr = &args->server->backup_ctx;
+ zone_backups_add(&args->server->backup_ctxs, ctx);
return ret;
}
+static zone_backup_ctx_t *latest_backup_ctx(ctl_args_t *args)
+{
+ // no need to mutex in this case
+ return (zone_backup_ctx_t *)TAIL(args->server->backup_ctxs.ctxs);
+}
+
static void deinit_backup(ctl_args_t *args)
{
- zone_backup_ctx_t *ctx = args->server->backup_ctx;
- zone_backup_deinit(ctx);
+ zone_backup_deinit(latest_backup_ctx(args));
}
static int zone_backup_cmd(zone_t *zone, ctl_args_t *args)
{
- zone_backup_ctx_t *ctx = args->server->backup_ctx;
- assert(zone->backup_ctx == NULL);
+ zone_backup_ctx_t *ctx = latest_backup_ctx(args);
+ if (zone->backup_ctx != NULL) {
+ log_zone_warning(zone->name, "zone backup already in progress, skipping zone");
+ return KNOT_EOK;
+ }
zone->backup_ctx = ctx;
pthread_mutex_lock(&ctx->readers_mutex);
ctx->readers++;
/* Global catalog zones backup. */
if (args->data[KNOT_CTL_IDX_ZONE] == NULL) {
- zone_backup_ctx_t *ctx = args->server->backup_ctx;
+ zone_backup_ctx_t *ctx = latest_backup_ctx(args);
ctx->backup_global = true;
ret = global_backup(ctx, &args->server->catalog, NULL);
if (ret != KNOT_EOK) {
return ret;
}
+ zone_backups_init(&server->backup_ctxs);
+
char *catalog_dir = conf_db(conf(), C_CATALOG_DB);
conf_val_t catalog_size = conf_db_param(conf(), C_CATALOG_DB_MAX_SIZE, NULL);
catalog_init(&server->catalog, catalog_dir, conf_int(&catalog_size));
return;
}
- if (server->backup_ctx != NULL) {
- log_warning("backup in progress, terminating, will be incomplete");
- server->backup_ctx->readers = 1; // ensure complete deinit
- zone_backup_deinit(server->backup_ctx);
- }
+ zone_backups_deinit(&server->backup_ctxs);
/* Save zone timers. */
if (server->zone_db != NULL) {
catalog_update_t catalog_upd;
/*! \brief Context of pending zones' backup. */
- zone_backup_ctx_t *backup_ctx;
+ zone_backup_ctxs_t backup_ctxs;
} server_t;
/*!
ctx->restore_mode = restore_mode;
ctx->backup_global = false;
ctx->readers = 1;
- ctx->server_self_ptr = NULL;
ctx->backup_dir = (char *)(ctx + 1);
memcpy(ctx->backup_dir, backup_dir, backup_dir_len);
BACKUP_LOCKFILE(ctx, lockfile);
unlink(lockfile);
- if (ctx->server_self_ptr != NULL) {
- *ctx->server_self_ptr = NULL;
- }
+ zone_backups_rem(ctx);
free(ctx);
}
}
+void zone_backups_init(zone_backup_ctxs_t *ctxs)
+{
+ init_list(&ctxs->ctxs);
+ pthread_mutex_init(&ctxs->mutex, NULL);
+}
+
+void zone_backups_deinit(zone_backup_ctxs_t *ctxs)
+{
+ zone_backup_ctx_t *ctx, *nxt;
+ WALK_LIST_DELSAFE(ctx, nxt, ctxs->ctxs) {
+ log_warning("backup in progress, terminating, will be incomplete");
+ ctx->readers = 1; // ensure full deinit
+ zone_backup_deinit(ctx);
+ }
+ pthread_mutex_destroy(&ctxs->mutex);
+}
+
+void zone_backups_add(zone_backup_ctxs_t *ctxs, zone_backup_ctx_t *ctx)
+{
+ pthread_mutex_lock(&ctxs->mutex);
+ add_tail(&ctxs->ctxs, (node_t *)ctx);
+ pthread_mutex_unlock(&ctxs->mutex);
+}
+
+static zone_backup_ctxs_t *get_ctxs_trick(zone_backup_ctx_t *ctx)
+{
+ node_t *n = (node_t *)ctx;
+ while (n->prev != NULL) {
+ n = n->prev;
+ }
+ return (zone_backup_ctxs_t *)n;
+}
+
+void zone_backups_rem(zone_backup_ctx_t *ctx)
+{
+ zone_backup_ctxs_t *ctxs = get_ctxs_trick(ctx);
+ pthread_mutex_lock(&ctxs->mutex);
+ rem_node((node_t *)ctx);
+ pthread_mutex_unlock(&ctxs->mutex);
+}
+
static char *dir_file(const char *dir_name, const char *file_name)
{
const char *basename = strrchr(file_name, '/');
#include "knot/zone/zone.h"
typedef struct zone_backup_ctx {
+ node_t n; // ability to be put into list_t
bool restore_mode; // if true, this is not a backup, but restore
bool backup_journal; // if true, also backup journal
bool backup_zonefile; // if true, also backup zone contents to a zonefile (default on)
knot_lmdb_db_t bck_journal; // backup journal DB
knot_lmdb_db_t bck_catalog; // backup catalog DB
int lock_file; // lock file preventing simultaneous backups to same directory
- struct zone_backup_ctx **server_self_ptr; // pointer on pointer on this structure itself in server_t
} zone_backup_ctx_t;
+typedef struct {
+ list_t ctxs;
+ pthread_mutex_t mutex;
+} zone_backup_ctxs_t;
+
int zone_backup_init(bool restore_mode, const char *backup_dir,
size_t kasp_db_size, size_t timer_db_size, size_t journal_db_size,
size_t catalog_db_size, zone_backup_ctx_t **out_ctx);
int global_backup(zone_backup_ctx_t *ctx, catalog_t *catalog,
const knot_dname_t *zone_only);
+
+void zone_backups_init(zone_backup_ctxs_t *ctxs);
+void zone_backups_deinit(zone_backup_ctxs_t *ctxs);
+void zone_backups_add(zone_backup_ctxs_t *ctxs, zone_backup_ctx_t *ctx);
+void zone_backups_rem(zone_backup_ctx_t *ctx);