summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2022-01-11 16:22:33 +1100
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-11 05:52:02 +0000
commit938a73213e7f62d8547ed6c49f0efe6f338b0516 (patch)
tree4762d580d43f1778a30942bd321864a292d5bdfa
parent9e51dd0d383ed86b08540418dee372db6cfb5dfe (diff)
downloadmongo-938a73213e7f62d8547ed6c49f0efe6f338b0516.tar.gz
Import wiredtiger: c6ae92c1623d9e87e2b1aff8cfe9eab204717c08 from branch mongodb-5.2
ref: e5af17e911..c6ae92c162 for: 5.2.0-rc5 WT-7922 Handle missing WiredTiger version file
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_api.c52
-rw-r--r--src/third_party/wiredtiger/test/suite/test_config10.py72
-rwxr-xr-xsrc/third_party/wiredtiger/test/suite/test_txn19.py4
4 files changed, 117 insertions, 13 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 07f4920db37..c5e01bafed3 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger.git",
"branch": "mongodb-5.2",
- "commit": "e5af17e9111138938f8d3ac0e928321a35cae91b"
+ "commit": "c6ae92c1623d9e87e2b1aff8cfe9eab204717c08"
}
diff --git a/src/third_party/wiredtiger/src/conn/conn_api.c b/src/third_party/wiredtiger/src/conn/conn_api.c
index 75bdf8c6466..f36bbc8cb2d 100644
--- a/src/third_party/wiredtiger/src/conn/conn_api.c
+++ b/src/third_party/wiredtiger/src/conn/conn_api.c
@@ -1695,7 +1695,7 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
wt_off_t size;
size_t len;
char buf[256];
- bool bytelock, exist, is_create, match;
+ bool bytelock, empty, exist, is_create, is_salvage, match;
conn = S2C(session);
fh = NULL;
@@ -1817,9 +1817,33 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
WT_SINGLETHREAD_STRING));
}
+ /*
+ * We own the database home, figure out if we're creating it. There are a few files created when
+ * initializing the database home and we could crash in-between any of them, so there's no
+ * simple test. The last thing we do during initialization is rename a turtle file into place,
+ * and there's never a database home after that point without a turtle file. If the turtle file
+ * doesn't exist, it's a create.
+ */
+ WT_ERR(__wt_turtle_exists(session, &exist));
+ conn->is_new = exist ? 0 : 1;
+
+ /*
+ * Unless we are salvaging, if the turtle file exists then the WiredTiger file should exist as
+ * well.
+ */
+ WT_ERR(__wt_config_gets(session, cfg, "salvage", &cval));
+ is_salvage = cval.val != 0;
+ if (!is_salvage && !conn->is_new) {
+ WT_ERR(__wt_fs_exist(session, WT_WIREDTIGER, &exist));
+ if (!exist) {
+ F_SET(conn, WT_CONN_DATA_CORRUPTION);
+ WT_ERR_MSG(session, WT_TRY_SALVAGE, "WiredTiger version file cannot be found");
+ }
+ }
+
/* We own the lock file, optionally create the WiredTiger file. */
- ret = __wt_open(
- session, WT_WIREDTIGER, WT_FS_OPEN_FILE_TYPE_REGULAR, is_create ? WT_FS_OPEN_CREATE : 0, &fh);
+ ret = __wt_open(session, WT_WIREDTIGER, WT_FS_OPEN_FILE_TYPE_REGULAR,
+ is_create || is_salvage ? WT_FS_OPEN_CREATE : 0, &fh);
/*
* If we're read-only, check for handled errors. Even if able to open the WiredTiger file
@@ -1848,16 +1872,22 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
}
/*
- * We own the database home, figure out if we're creating it. There are a few files created when
- * initializing the database home and we could crash in-between any of them, so there's no
- * simple test. The last thing we do during initialization is rename a turtle file into place,
- * and there's never a database home after that point without a turtle file. If the turtle file
- * doesn't exist, it's a create.
+ * If WiredTiger file exists but is size zero when it is not supposed to be (the turtle file
+ * exists and we are not salvaging), write a message but don't fail.
*/
- WT_ERR(__wt_turtle_exists(session, &exist));
- conn->is_new = exist ? 0 : 1;
+ empty = false;
+ if (fh != NULL) {
+ WT_ERR(__wt_filesize(session, fh, &size));
+ empty = size == 0;
+ if (!is_salvage && !conn->is_new && empty)
+ WT_ERR(__wt_msg(session, "WiredTiger version file is empty"));
+ }
- if (conn->is_new) {
+ /*
+ * Populate the WiredTiger file if this is a new connection or if the WiredTiger file is empty
+ * and we are salvaging.
+ */
+ if (conn->is_new || (is_salvage && empty)) {
if (F_ISSET(conn, WT_CONN_READONLY))
WT_ERR_MSG(session, EINVAL,
"The database directory is empty or needs recovery, cannot continue with a read only "
diff --git a/src/third_party/wiredtiger/test/suite/test_config10.py b/src/third_party/wiredtiger/test/suite/test_config10.py
new file mode 100644
index 00000000000..6ae7860ffa3
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_config10.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-present MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_config10.py
+# Test valid behaviour when starting WiredTiger with missing or empty
+# WiredTiger version file.
+
+import wiredtiger, wttest
+from wiredtiger import stat
+import os
+
+class test_config10(wttest.WiredTigerTestCase):
+ uri = 'table:config10.'
+
+ def test_missing_version_file(self):
+ self.conn.close()
+ os.remove('WiredTiger')
+ # Ensure error occurs when WiredTiger file is missing.
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.setUpConnectionOpen('.'), '/WT_TRY_SALVAGE: database corruption detected/')
+
+ def test_empty_version_file(self):
+ self.conn.close()
+ # Ensure returns message when WiredTiger file is empty.
+ open('WiredTiger','w').close()
+ expectMessage = 'WiredTiger version file is empty'
+ with self.expectedStdoutPattern(expectMessage):
+ self.setUpConnectionOpen('.')
+
+ def test_missing_version_file_with_salvage(self):
+ self.conn.close()
+ os.remove('WiredTiger')
+ salvage_config = 'salvage=true'
+ self.conn = self.wiredtiger_open('.', salvage_config)
+ # Check salvage creates and populates file.
+ self.assertNotEqual(os.stat('WiredTiger').st_size, 0)
+
+ def test_empty_version_file_with_salvage(self):
+ self.conn.close()
+ open('WiredTiger','w').close()
+ salvage_config = 'salvage=true'
+ self.conn = self.wiredtiger_open('.', salvage_config)
+ # Check salvage populates file.
+ self.assertNotEqual(os.stat('WiredTiger').st_size, 0)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_txn19.py b/src/third_party/wiredtiger/test/suite/test_txn19.py
index d975dc43a7c..5585f38d3fe 100755
--- a/src/third_party/wiredtiger/test/suite/test_txn19.py
+++ b/src/third_party/wiredtiger/test/suite/test_txn19.py
@@ -401,7 +401,6 @@ class test_txn19_meta(wttest.WiredTigerTestCase, suite_subprocess):
openable = [
"removal:WiredTiger.basecfg",
"removal:WiredTiger.turtle",
- "removal:WiredTiger",
"truncate:WiredTiger",
"truncate:WiredTiger.basecfg",
"truncate-middle:WiredTiger",
@@ -509,6 +508,9 @@ class test_txn19_meta(wttest.WiredTigerTestCase, suite_subprocess):
self.reopen_conn(dir, self.conn_config)
self.captureout.checkAdditionalPattern(self,
'unexpected file WiredTiger.wt found, renamed to WiredTiger.wt.1')
+ elif self.filename == 'WiredTiger' and self.kind == 'truncate':
+ with self.expectedStdoutPattern("WiredTiger version file is empty"):
+ self.reopen_conn(dir, self.conn_config)
else:
self.reopen_conn(dir, self.conn_config)
self.close_conn()