summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsueloverso <sue@mongodb.com>2015-09-22 14:18:49 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2015-09-28 16:44:43 +1000
commitcd8ae463f0830e56ec66de73de78ca81041615b2 (patch)
tree6b0a5cc4ca11e6b0833546dcabd77d0f2746b0c2
parentbbc2d3efc8bc8e8581df632a8970ff2a4497b161 (diff)
downloadmongo-cd8ae463f0830e56ec66de73de78ca81041615b2.tar.gz
WT-2039 Add error check and unit test for log records over 4Gb.
Merge pull request #2207 from wiredtiger/large-records (cherry picked from commit 75a46556bbca11630c045d46a51282a7defad209)
-rw-r--r--src/log/log.c9
-rw-r--r--src/txn/txn.c1
-rw-r--r--test/suite/test_txn13.py95
3 files changed, 103 insertions, 2 deletions
diff --git a/src/log/log.c b/src/log/log.c
index 567200ffa0b..9b1da4b0b35 100644
--- a/src/log/log.c
+++ b/src/log/log.c
@@ -1760,9 +1760,16 @@ __log_write_internal(WT_SESSION_IMPL *session, WT_ITEM *record, WT_LSN *lsnp,
conn = S2C(session);
log = conn->log;
- free_slot = locked = 0;
+ if (record->size > UINT32_MAX) {
+ __wt_errx(session, "Log record size of %" WT_SIZET_FMT
+ " exceeds the maximum supported size of %" PRIu32,
+ record->size, UINT32_MAX);
+ return (EFBIG);
+ }
WT_INIT_LSN(&lsn);
+ free_slot = locked = 0;
myslot.slot = NULL;
+
/*
* Assume the WT_ITEM the caller passed is a WT_LOG_RECORD, which has a
* header at the beginning for us to fill in.
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 3529d1c6d66..52e840f89d8 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -419,7 +419,6 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
*/
__wt_txn_release_snapshot(session);
ret = __wt_txn_log_commit(session, cfg);
- WT_ASSERT(session, ret == 0);
}
/*
diff --git a/test/suite/test_txn13.py b/test/suite/test_txn13.py
new file mode 100644
index 00000000000..7d22cb4b96b
--- /dev/null
+++ b/test/suite/test_txn13.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2015 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_txn13.py
+# Test very large log records. Even with a small log file we should be
+# able to write them. Expect an error over 4Gb.
+#
+
+#import fnmatch, os, shutil, run, time
+from suite_subprocess import suite_subprocess
+from wiredtiger import wiredtiger_open
+from wtscenario import check_scenarios
+import wiredtiger, wttest
+
+class test_txn13(wttest.WiredTigerTestCase, suite_subprocess):
+ logmax = "100K"
+ tablename = 'test_txn13'
+ uri = 'table:' + tablename
+ nops = 1024
+ create_params = 'key_format=i,value_format=S'
+
+ scenarios = check_scenarios([
+ ('1gb', dict(expect_err=False, valuesize=1048576)),
+ ('2gb', dict(expect_err=False, valuesize=2097152)),
+ ('4gb', dict(expect_err=True, valuesize=4194304))
+ ])
+
+ # Overrides WiredTigerTestCase
+ def setUpConnectionOpen(self, dir):
+ self.home = dir
+ conn_params = \
+ 'log=(archive=false,enabled,file_max=%s)' % self.logmax + \
+ ',create,cache_size=8G,error_prefix="%s: ",' % self.shortid()
+ # print "Creating conn at '%s' with config '%s'" % (dir, conn_params)
+ try:
+ conn = wiredtiger_open(dir, conn_params)
+ except wiredtiger.WiredTigerError as e:
+ print "Failed conn at '%s' with config '%s'" % (dir, conn_params)
+ self.pr(`conn`)
+ return conn
+
+ def test_large_values(self):
+ # print "Creating %s with config '%s'" % (self.uri, self.create_params)
+ # print "Running with %d" % (self.valuesize)
+ self.session.create(self.uri, self.create_params)
+ c = self.session.open_cursor(self.uri, None)
+
+ # We want to test very large values. Generate 'nops' records within
+ # a single transaction.
+ valuepfx = self.valuesize * 'X'
+
+ gotException = False
+ self.session.begin_transaction()
+ for k in range(self.nops):
+ value = valuepfx + str(k)
+ c[k] = value
+
+ if self.expect_err:
+ # EFBIG is expected: File too large
+ msg = '/exceeds the maximum/'
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda:self.session.commit_transaction(), msg)
+ gotException = True
+ else:
+ self.session.commit_transaction()
+
+ self.assertTrue(gotException == self.expect_err)
+
+if __name__ == '__main__':
+ wttest.run()