Skip to content

Commit

Permalink
WT-6015 Check log and turtle versions early before modifying database. (
Browse files Browse the repository at this point in the history
  • Loading branch information
sueloverso committed Jun 3, 2020
1 parent 49bb02e commit 8c54c2f
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/btree/bt_import.c
Expand Up @@ -108,9 +108,9 @@ __wt_import(WT_SESSION_IMPL *session, const char *uri)
__wt_verbose(session, WT_VERB_CHECKPOINT, "import configuration: %s/%s", uri, fileconf);

/*
* The just inserted metadata was correct as of immediately before the before the final
* checkpoint, but it's not quite right. The block manager returned the corrected final
* checkpoint, put it all together.
* The just inserted metadata was correct as of immediately before the final checkpoint, but
* it's not quite right. The block manager returned the corrected final checkpoint, put it all
* together.
*
* Get the checkpoint information from the file's metadata as an array of WT_CKPT structures.
*
Expand Down
57 changes: 45 additions & 12 deletions src/conn/conn_api.c
Expand Up @@ -2265,6 +2265,37 @@ wiredtiger_dummy_session_init(WT_CONNECTION_IMPL *conn, WT_EVENT_HANDLER *event_
F_SET(session, WT_SESSION_NO_DATA_HANDLES);
}

/*
* __conn_version_verify --
* Verify the versions before modifying the database.
*/
static int
__conn_version_verify(WT_SESSION_IMPL *session)
{
WT_CONNECTION_IMPL *conn;
bool exist;

conn = S2C(session);

/* Always set the compatibility versions. */
__wt_logmgr_compat_version(session);
/*
* If we're salvaging, don't verify now.
*/
if (F_ISSET(conn, WT_CONN_SALVAGE))
return (0);

/* If we have a turtle file, validate versions. */
WT_RET(__wt_fs_exist(session, WT_METADATA_TURTLE, &exist));
if (exist)
WT_RET(__wt_turtle_validate_version(session));

if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_CONFIG_ENABLED))
WT_RET(__wt_log_compat_verify(session));

return (0);
}

/*
* wiredtiger_open --
* Main library entry point: open a new connection to a WiredTiger database.
Expand Down Expand Up @@ -2401,18 +2432,6 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler, const char *c
/* Make sure no other thread of control already owns this database. */
WT_ERR(__conn_single(session, cfg));

/*
* Set compatibility versions early so that any subsystem sees it. Call after we own the
* database so that we can know if the database is new or not. Compatibility testing needs to
* know if salvage has been set, so parse that early.
*/
WT_ERR(__wt_config_gets(session, cfg, "salvage", &cval));
if (cval.val) {
if (F_ISSET(conn, WT_CONN_READONLY))
WT_ERR_MSG(session, EINVAL, "Readonly configuration incompatible with salvage");
F_SET(conn, WT_CONN_SALVAGE);
}

WT_ERR(__wt_conn_compat_config(session, cfg, false));

/*
Expand Down Expand Up @@ -2606,6 +2625,13 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler, const char *c
WT_ERR(__wt_config_gets(session, cfg, "operation_timeout_ms", &cval));
conn->operation_timeout_us = (uint64_t)(cval.val * WT_THOUSAND);

WT_ERR(__wt_config_gets(session, cfg, "salvage", &cval));
if (cval.val) {
if (F_ISSET(conn, WT_CONN_READONLY))
WT_ERR_MSG(session, EINVAL, "Readonly configuration incompatible with salvage");
F_SET(conn, WT_CONN_SALVAGE);
}

WT_ERR(__wt_conn_statistics_config(session, cfg));
WT_ERR(__wt_lsm_manager_config(session, cfg));
WT_ERR(__wt_sweep_config(session, cfg));
Expand Down Expand Up @@ -2658,6 +2684,13 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler, const char *c
WT_ERR(
__wt_encryptor_config(session, &cval, &keyid, (WT_CONFIG_ARG *)enc_cfg, &conn->kencryptor));

/*
* We need to parse the logging configuration here to verify the compatibility settings because
* we may need the log path and encryption and compression settings.
*/
WT_ERR(__wt_logmgr_config(session, cfg, false));
WT_ERR(__conn_version_verify(session));

/*
* Configuration completed; optionally write a base configuration file.
*/
Expand Down
31 changes: 16 additions & 15 deletions src/conn/conn_log.c
Expand Up @@ -190,11 +190,11 @@ __logmgr_version(WT_SESSION_IMPL *session, bool reconfig)
}

/*
* __logmgr_config --
* __wt_logmgr_config --
* Parse and setup the logging server options.
*/
static int
__logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp, bool reconfig)
int
__wt_logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool reconfig)
{
WT_CONFIG_ITEM cval;
WT_CONNECTION_IMPL *conn;
Expand Down Expand Up @@ -245,7 +245,10 @@ __logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp, bool rec
"log=(enabled=true)");
}

*runp = enabled;
if (enabled)
FLD_SET(conn->log_flags, WT_CONN_LOG_CONFIG_ENABLED);
else
FLD_CLR(conn->log_flags, WT_CONN_LOG_CONFIG_ENABLED);

/*
* Setup a log path and compression even if logging is disabled in case we are going to print a
Expand All @@ -258,12 +261,13 @@ __logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp, bool rec
WT_RET(__wt_config_gets_none(session, cfg, "log.compressor", &cval));
WT_RET(__wt_compressor_config(session, &cval, &conn->log_compressor));

conn->log_path = NULL;
WT_RET(__wt_config_gets(session, cfg, "log.path", &cval));
WT_RET(__wt_strndup(session, cval.str, cval.len, &conn->log_path));
}

/* We are done if logging isn't enabled. */
if (!*runp)
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_CONFIG_ENABLED))
return (0);

WT_RET(__wt_config_gets(session, cfg, "log.archive", &cval));
Expand Down Expand Up @@ -336,9 +340,7 @@ __logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp, bool rec
int
__wt_logmgr_reconfig(WT_SESSION_IMPL *session, const char **cfg)
{
bool dummy;

WT_RET(__logmgr_config(session, cfg, &dummy, true));
WT_RET(__wt_logmgr_config(session, cfg, true));
return (__logmgr_version(session, true));
}

Expand Down Expand Up @@ -967,19 +969,18 @@ __log_server(void *arg)
* Initialize the log subsystem (before running recovery).
*/
int
__wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
__wt_logmgr_create(WT_SESSION_IMPL *session)
{
WT_CONNECTION_IMPL *conn;
WT_LOG *log;
bool run;

conn = S2C(session);

/* Handle configuration. */
WT_RET(__logmgr_config(session, cfg, &run, false));

/* If logging is not configured, we're done. */
if (!run)
/*
* Logging configuration is parsed early on for compatibility checking. It is separated from
* turning on the subsystem. We only need to proceed here if logging is enabled.
*/
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_CONFIG_ENABLED))
return (0);

FLD_SET(conn->log_flags, WT_CONN_LOG_ENABLED);
Expand Down
2 changes: 1 addition & 1 deletion src/conn/conn_open.c
Expand Up @@ -205,7 +205,7 @@ __wt_connection_workers(WT_SESSION_IMPL *session, const char *cfg[])
* can know if statistics are enabled or not.
*/
WT_RET(__wt_statlog_create(session, cfg));
WT_RET(__wt_logmgr_create(session, cfg));
WT_RET(__wt_logmgr_create(session));

/*
* Run recovery. NOTE: This call will start (and stop) eviction if recovery is required.
Expand Down
9 changes: 0 additions & 9 deletions src/conn/conn_reconfig.c
Expand Up @@ -200,15 +200,6 @@ __wt_conn_compat_config(WT_SESSION_IMPL *session, const char **cfg, bool reconfi
conn->req_max_minor = max_minor;
conn->req_min_major = min_major;
conn->req_min_minor = min_minor;
/*
* Set up the log manager versions in the connection and verify any logs. We do this at the end
* here, but very early in the startup process so that if we're starting from a backup and there
* are compatibility errors, we inform the user but leave the directory unchanged.
*/
__wt_logmgr_compat_version(session);
if (!reconfig && !F_ISSET(conn, WT_CONN_SALVAGE))
WT_ERR(__wt_log_compat_verify(session));

err:
__wt_free(session, value);

Expand Down
21 changes: 11 additions & 10 deletions src/include/connection.h
Expand Up @@ -354,16 +354,17 @@ struct __wt_connection_impl {

/* AUTOMATIC FLAG VALUE GENERATION START */
#define WT_CONN_LOG_ARCHIVE 0x001u /* Archive is enabled */
#define WT_CONN_LOG_DEBUG_MODE 0x002u /* Debug-mode logging enabled */
#define WT_CONN_LOG_DOWNGRADED 0x004u /* Running older version */
#define WT_CONN_LOG_ENABLED 0x008u /* Logging is enabled */
#define WT_CONN_LOG_EXISTED 0x010u /* Log files found */
#define WT_CONN_LOG_FORCE_DOWNGRADE 0x020u /* Force downgrade */
#define WT_CONN_LOG_RECOVER_DIRTY 0x040u /* Recovering unclean */
#define WT_CONN_LOG_RECOVER_DONE 0x080u /* Recovery completed */
#define WT_CONN_LOG_RECOVER_ERR 0x100u /* Error if recovery required */
#define WT_CONN_LOG_RECOVER_FAILED 0x200u /* Recovery failed */
#define WT_CONN_LOG_ZERO_FILL 0x400u /* Manually zero files */
#define WT_CONN_LOG_CONFIG_ENABLED 0x002u /* Logging is configured */
#define WT_CONN_LOG_DEBUG_MODE 0x004u /* Debug-mode logging enabled */
#define WT_CONN_LOG_DOWNGRADED 0x008u /* Running older version */
#define WT_CONN_LOG_ENABLED 0x010u /* Logging is enabled */
#define WT_CONN_LOG_EXISTED 0x020u /* Log files found */
#define WT_CONN_LOG_FORCE_DOWNGRADE 0x040u /* Force downgrade */
#define WT_CONN_LOG_RECOVER_DIRTY 0x080u /* Recovering unclean */
#define WT_CONN_LOG_RECOVER_DONE 0x100u /* Recovery completed */
#define WT_CONN_LOG_RECOVER_ERR 0x200u /* Error if recovery required */
#define WT_CONN_LOG_RECOVER_FAILED 0x400u /* Recovery failed */
#define WT_CONN_LOG_ZERO_FILL 0x800u /* Manually zero files */
/* AUTOMATIC FLAG VALUE GENERATION STOP */
uint32_t log_flags; /* Global logging configuration */
WT_CONDVAR *log_cond; /* Log server wait mutex */
Expand Down
6 changes: 5 additions & 1 deletion src/include/extern.h
Expand Up @@ -854,7 +854,9 @@ extern int __wt_log_vprintf(WT_SESSION_IMPL *session, const char *fmt, va_list a
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_write(WT_SESSION_IMPL *session, WT_ITEM *record, WT_LSN *lsnp, uint32_t flags)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
extern int __wt_logmgr_config(WT_SESSION_IMPL *session, const char **cfg, bool reconfig)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_logmgr_create(WT_SESSION_IMPL *session)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_logmgr_destroy(WT_SESSION_IMPL *session)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
Expand Down Expand Up @@ -1446,6 +1448,8 @@ extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **va
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_turtle_validate_version(WT_SESSION_IMPL *session)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_txn_activity_drain(WT_SESSION_IMPL *session)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[], bool waiting)
Expand Down
8 changes: 4 additions & 4 deletions src/meta/meta_turtle.c
Expand Up @@ -145,12 +145,12 @@ __metadata_load_bulk(WT_SESSION_IMPL *session)
}

/*
* __turtle_validate_version --
* __wt_turtle_validate_version --
* Retrieve version numbers from the turtle file and validate them against our WiredTiger
* version.
*/
static int
__turtle_validate_version(WT_SESSION_IMPL *session)
int
__wt_turtle_validate_version(WT_SESSION_IMPL *session)
{
WT_DECL_RET;
uint32_t major, minor;
Expand Down Expand Up @@ -293,7 +293,7 @@ __wt_turtle_init(WT_SESSION_IMPL *session)
WT_RET(__wt_remove_if_exists(session, WT_METADATA_TURTLE, false));
load = true;
} else if (validate_turtle)
WT_RET(__turtle_validate_version(session));
WT_RET(__wt_turtle_validate_version(session));
} else
load = true;
if (load) {
Expand Down

0 comments on commit 8c54c2f

Please sign in to comment.