/* * __wt_txn_global_shutdown -- * Shut down the global transaction state. */ int __wt_txn_global_shutdown(WT_SESSION_IMPL *session) { bool txn_active; /* * We're shutting down. Make sure everything gets freed. * * It's possible that the eviction server is in the middle of a long * operation, with a transaction ID pinned. In that case, we will loop * here until the transaction ID is released, when the oldest * transaction ID will catch up with the current ID. */ for (;;) { WT_RET(__wt_txn_activity_check(session, &txn_active)); if (!txn_active) break; WT_STAT_CONN_INCR(session, txn_release_blocked); __wt_yield(); } #ifdef HAVE_TIMESTAMPS /* * Now that all transactions have completed, no timestamps should be * pinned. */ __wt_timestamp_set_inf(&S2C(session)->txn_global.pinned_timestamp); #endif return (0); }
/* * __wt_conn_compat_config -- * Configure compatibility version. */ int __wt_conn_compat_config(WT_SESSION_IMPL *session, const char **cfg) { WT_CONFIG_ITEM cval; WT_CONNECTION_IMPL *conn; uint16_t patch; bool txn_active; conn = S2C(session); WT_RET(__wt_config_gets(session, cfg, "compatibility.release", &cval)); if (cval.len == 0) { conn->compat_major = WIREDTIGER_VERSION_MAJOR; conn->compat_minor = WIREDTIGER_VERSION_MINOR; return (0); } /* * Accept either a major.minor release string or a major.minor.patch * release string. We ignore the patch value, but allow it in the * string. */ if (sscanf(cval.str, "%" SCNu16 ".%" SCNu16, &conn->compat_major, &conn->compat_minor) != 2 && sscanf(cval.str, "%" SCNu16 ".%" SCNu16 ".%" SCNu16, &conn->compat_major, &conn->compat_minor, &patch) != 3) WT_RET_MSG(session, EINVAL, "illegal compatibility release"); if (conn->compat_major > WIREDTIGER_VERSION_MAJOR) WT_RET_MSG(session, ENOTSUP, "unsupported major version"); if (conn->compat_major == WIREDTIGER_VERSION_MAJOR && conn->compat_minor > WIREDTIGER_VERSION_MINOR) WT_RET_MSG(session, ENOTSUP, "unsupported minor version"); /* * We're doing an upgrade or downgrade, check whether transactions are * active. */ WT_RET(__wt_txn_activity_check(session, &txn_active)); if (txn_active) WT_RET_MSG(session, ENOTSUP, "system must be quiescent for upgrade or downgrade"); return (0); }
/* * __wt_conn_compat_config -- * Configure compatibility version. */ int __wt_conn_compat_config( WT_SESSION_IMPL *session, const char **cfg, bool reconfig) { WT_CONFIG_ITEM cval; WT_CONNECTION_IMPL *conn; WT_DECL_RET; uint16_t max_major, max_minor, min_major, min_minor; uint16_t rel_major, rel_minor; char *value; bool txn_active; conn = S2C(session); value = NULL; max_major = WT_CONN_COMPAT_NONE; max_minor = WT_CONN_COMPAT_NONE; min_major = WT_CONN_COMPAT_NONE; min_minor = WT_CONN_COMPAT_NONE; WT_RET(__wt_config_gets(session, cfg, "compatibility.release", &cval)); if (cval.len == 0) { rel_major = WIREDTIGER_VERSION_MAJOR; rel_minor = WIREDTIGER_VERSION_MINOR; F_CLR(conn, WT_CONN_COMPATIBILITY); } else { WT_RET(__conn_compat_parse( session, &cval, &rel_major, &rel_minor)); /* * We're doing an upgrade or downgrade, check whether * transactions are active. */ WT_RET(__wt_txn_activity_check(session, &txn_active)); if (txn_active) WT_RET_MSG(session, ENOTSUP, "system must be quiescent" " for upgrade or downgrade"); F_SET(conn, WT_CONN_COMPATIBILITY); } /* * If we're a reconfigure and the user did not set any compatibility, * we're done. */ if (reconfig && !F_ISSET(conn, WT_CONN_COMPATIBILITY)) goto done; /* * The maximum and minimum required version for existing files * is only available on opening the connection, not reconfigure. */ WT_RET(__wt_config_gets(session, cfg, "compatibility.require_min", &cval)); if (cval.len != 0) WT_RET(__conn_compat_parse( session, &cval, &min_major, &min_minor)); WT_RET(__wt_config_gets(session, cfg, "compatibility.require_max", &cval)); if (cval.len != 0) WT_RET(__conn_compat_parse( session, &cval, &max_major, &max_minor)); /* * The maximum required must be greater than or equal to the * compatibility release we're using now. This is on an open and we're * checking the two against each other. We'll check against what was * saved on a restart later. */ if (!reconfig && max_major != WT_CONN_COMPAT_NONE && (max_major < rel_major || (max_major == rel_major && max_minor < rel_minor))) WT_RET_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be smaller than compatibility release %" PRIu16 ".%" PRIu16, max_major, max_minor, rel_major, rel_minor); /* * The minimum required must be less than or equal to the compatibility * release we're using now. This is on an open and we're checking the * two against each other. We'll check against what was saved on a * restart later. */ if (!reconfig && min_major != WT_CONN_COMPAT_NONE && (min_major > rel_major || (min_major == rel_major && min_minor > rel_minor))) WT_RET_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than compatibility release %" PRIu16 ".%" PRIu16, min_major, min_minor, rel_major, rel_minor); /* * On a reconfigure, check the new release version against any * required maximum version set on open. */ if (reconfig && conn->req_max_major != WT_CONN_COMPAT_NONE && (conn->req_max_major < rel_major || (conn->req_max_major == rel_major && conn->req_max_minor < rel_minor))) WT_RET_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be smaller than requested compatibility release %" PRIu16 ".%" PRIu16, conn->req_max_major, conn->req_max_minor, rel_major, rel_minor); /* * On a reconfigure, check the new release version against any * required minimum version set on open. */ if (reconfig && conn->req_min_major != WT_CONN_COMPAT_NONE && (conn->req_min_major > rel_major || (conn->req_min_major == rel_major && conn->req_min_minor > rel_minor))) WT_RET_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than requested compatibility release %" PRIu16 ".%" PRIu16, conn->req_min_major, conn->req_min_minor, rel_major, rel_minor); conn->compat_major = rel_major; conn->compat_minor = rel_minor; /* * Only rewrite the turtle file if this is a reconfig. On startup * it will get written as part of creating the connection. We do this * after checking the required minimum version so that we don't rewrite * the turtle file if there is an error. */ if (reconfig) WT_RET(__wt_metadata_turtle_rewrite(session)); /* * The required maximum and minimum cannot be set via reconfigure and * they are meaningless on a newly created database. We're done in * those cases. */ if (reconfig || conn->is_new || (min_major == WT_CONN_COMPAT_NONE && max_major == WT_CONN_COMPAT_NONE)) goto done; /* * Check the minimum required against any saved compatibility version * in the turtle file saved from an earlier run. */ rel_major = rel_minor = WT_CONN_COMPAT_NONE; if ((ret = __wt_metadata_search(session, WT_METADATA_COMPAT, &value)) == 0) { WT_ERR(__wt_config_getones(session, value, "major", &cval)); rel_major = (uint16_t)cval.val; WT_ERR(__wt_config_getones(session, value, "minor", &cval)); rel_minor = (uint16_t)cval.val; if (max_major != WT_CONN_COMPAT_NONE && (max_major < rel_major || (max_major == rel_major && max_minor < rel_minor))) WT_ERR_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be larger than saved release %" PRIu16 ".%" PRIu16, max_major, max_minor, rel_major, rel_minor); if (min_major != WT_CONN_COMPAT_NONE && (min_major > rel_major || (min_major == rel_major && min_minor > rel_minor))) WT_ERR_MSG(session, ENOTSUP, WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than saved release %" PRIu16 ".%" PRIu16, min_major, min_minor, rel_major, rel_minor); } else if (ret == WT_NOTFOUND) ret = 0; else WT_ERR(ret); done: conn->req_max_major = max_major; conn->req_max_minor = max_minor; conn->req_min_major = min_major; conn->req_min_minor = min_minor; err: __wt_free(session, value); return (ret); }