diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/txn/txn_ckpt.c')
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn_ckpt.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/src/third_party/wiredtiger/src/txn/txn_ckpt.c b/src/third_party/wiredtiger/src/txn/txn_ckpt.c index 5c61faee070..cba8357db23 100644 --- a/src/third_party/wiredtiger/src/txn/txn_ckpt.c +++ b/src/third_party/wiredtiger/src/txn/txn_ckpt.c @@ -1112,7 +1112,6 @@ static void __drop(WT_CKPT *ckptbase, const char *name, size_t len) { WT_CKPT *ckpt; - u_int max_ckpt_drop; /* * If we're dropping internal checkpoints, match to the '.' separating the checkpoint name from @@ -1121,20 +1120,9 @@ __drop(WT_CKPT *ckptbase, const char *name, size_t len) * it's one we want to drop. */ if (strncmp(WT_CHECKPOINT, name, len) == 0) { - /* - * Currently, hot backup cursors block checkpoint drop, which means releasing a hot backup - * cursor can result in immediately attempting to drop lots of checkpoints, which involves a - * fair amount of work while holding locks. Limit the number of standard checkpoints dropped - * per checkpoint. - */ - max_ckpt_drop = 0; WT_CKPT_FOREACH (ckptbase, ckpt) - if (WT_PREFIX_MATCH(ckpt->name, WT_CHECKPOINT)) { + if (WT_PREFIX_MATCH(ckpt->name, WT_CHECKPOINT)) F_SET(ckpt, WT_CKPT_DELETE); -#define WT_MAX_CHECKPOINT_DROP 4 - if (++max_ckpt_drop >= WT_MAX_CHECKPOINT_DROP) - break; - } } else WT_CKPT_FOREACH (ckptbase, ckpt) if (WT_STRING_MATCH(ckpt->name, name, len)) @@ -1214,30 +1202,44 @@ __checkpoint_lock_dirty_tree_int(WT_SESSION_IMPL *session, bool is_checkpoint, b { WT_CONNECTION_IMPL *conn; WT_DECL_RET; + u_int max_ckpt_drop; + bool is_wt_ckpt; WT_UNUSED(is_checkpoint); conn = S2C(session); - /* - * We can't delete checkpoints if a backup cursor is open. WiredTiger checkpoints are uniquely - * named and it's OK to have multiple of them in the system: clear the delete flag for them, and - * otherwise fail. Hold the lock until we're done (blocking hot backups from starting), we don't - * want to race with a future hot backup. - */ - if (conn->hot_backup) - WT_CKPT_FOREACH (ckptbase, ckpt) { - if (!F_ISSET(ckpt, WT_CKPT_DELETE)) - continue; - if (WT_PREFIX_MATCH(ckpt->name, WT_CHECKPOINT)) { + /* Check that it is OK to remove all the checkpoints marked for deletion. */ + max_ckpt_drop = 0; + WT_CKPT_FOREACH (ckptbase, ckpt) { + if (!F_ISSET(ckpt, WT_CKPT_DELETE)) + continue; + is_wt_ckpt = WT_PREFIX_MATCH(ckpt->name, WT_CHECKPOINT); + + /* + * If there is a hot backup, don't delete any WiredTiger checkpoint that could possibly have + * been created before the backup started. Fail if trying to delete any other named + * checkpoint. + */ + if (conn->hot_backup_start != 0 && ckpt->sec <= conn->hot_backup_start) { + if (is_wt_ckpt) { F_CLR(ckpt, WT_CKPT_DELETE); continue; } WT_RET_MSG(session, EBUSY, - "checkpoint %s blocked by hot backup: it would" - "delete an existing checkpoint, and checkpoints " - "cannot be deleted during a hot backup", + "checkpoint %s blocked by hot backup: it would " + "delete an existing named checkpoint, and such " + "checkpoints cannot be deleted during a hot backup", ckpt->name); } + /* + * Dropping checkpoints involves a fair amount of work while holding locks. Limit the number + * of WiredTiger checkpoints dropped per checkpoint. + */ + if (is_wt_ckpt) +#define WT_MAX_CHECKPOINT_DROP 4 + if (++max_ckpt_drop >= WT_MAX_CHECKPOINT_DROP) + F_CLR(ckpt, WT_CKPT_DELETE); + } /* * Mark old checkpoints that are being deleted and figure out which trees we can skip in this @@ -1257,6 +1259,8 @@ __checkpoint_lock_dirty_tree_int(WT_SESSION_IMPL *session, bool is_checkpoint, b WT_CKPT_FOREACH (ckptbase, ckpt) { if (!F_ISSET(ckpt, WT_CKPT_DELETE)) continue; + WT_ASSERT(session, !WT_PREFIX_MATCH(ckpt->name, WT_CHECKPOINT) || + conn->hot_backup_start == 0 || ckpt->sec > conn->hot_backup_start); /* * We can't delete checkpoints referenced by a cursor. WiredTiger checkpoints are * uniquely named and it's OK to have multiple in the system: clear the delete flag for |