1#!/usr/bin/env python 2# 3# Public Domain 2014-2018 MongoDB, Inc. 4# Public Domain 2008-2014 WiredTiger, Inc. 5# 6# This is free and unencumbered software released into the public domain. 7# 8# Anyone is free to copy, modify, publish, use, compile, sell, or 9# distribute this software, either in source code form or as a compiled 10# binary, for any purpose, commercial or non-commercial, and by any 11# means. 12# 13# In jurisdictions that recognize copyright laws, the author or authors 14# of this software dedicate any and all copyright interest in the 15# software to the public domain. We make this dedication for the benefit 16# of the public at large and to the detriment of our heirs and 17# successors. We intend this dedication to be an overt act of 18# relinquishment in perpetuity of all present and future rights to this 19# software under copyright law. 20# 21# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27# OTHER DEALINGS IN THE SOFTWARE. 28# 29# test_txn14.py 30# Transactions: commits and rollbacks 31# 32 33import fnmatch, os, shutil, time 34from suite_subprocess import suite_subprocess 35from wtscenario import make_scenarios 36import wttest 37 38class test_txn14(wttest.WiredTigerTestCase, suite_subprocess): 39 t1 = 'table:test_txn14_1' 40 create_params = 'key_format=i,value_format=i' 41 entries = 10000 42 extra_entries = 5 43 conn_config = 'log=(archive=false,enabled,file_max=100K)' 44 45 sync_list = [ 46 ('write', dict(sync='off')), 47 ('sync', dict(sync='on')), 48 ('bg', dict(sync='background')), 49 ] 50 scenarios = make_scenarios(sync_list) 51 52 def simulate_crash_restart(self, olddir, newdir): 53 ''' Simulate a crash from olddir and restart in newdir. ''' 54 # with the connection still open, copy files to new directory 55 shutil.rmtree(newdir, ignore_errors=True) 56 os.mkdir(newdir) 57 for fname in os.listdir(olddir): 58 fullname = os.path.join(olddir, fname) 59 # Skip lock file on Windows since it is locked 60 if os.path.isfile(fullname) and \ 61 "WiredTiger.lock" not in fullname and \ 62 "Tmplog" not in fullname and \ 63 "Preplog" not in fullname: 64 shutil.copy(fullname, newdir) 65 # 66 # close the original connection and open to new directory 67 # NOTE: This really cannot test the difference between the 68 # write-no-sync (off) version of log_flush and the sync 69 # version since we're not crashing the system itself. 70 # 71 self.close_conn() 72 self.conn = self.setUpConnectionOpen(newdir) 73 self.session = self.setUpSessionOpen(self.conn) 74 75 def test_log_flush(self): 76 # Here's the strategy: 77 # - Create a table. 78 # - Insert data into table. 79 # - Call log_flush. 80 # - Simulate a crash and restart 81 # - Make recovery run. 82 # - Confirm flushed data is in the table. 83 # 84 self.session.create(self.t1, self.create_params) 85 c = self.session.open_cursor(self.t1, None, None) 86 for i in range(self.entries): 87 c[i] = i + 1 88 cfgarg='sync=%s' % self.sync 89 self.pr('cfgarg ' + cfgarg) 90 self.session.log_flush(cfgarg) 91 for i in range(self.extra_entries): 92 c[i+self.entries] = i + self.entries + 1 93 c.close() 94 self.session.log_flush(cfgarg) 95 if self.sync == 'background': 96 # If doing a background flush, wait 30 seconds. I have seen an 97 # individual log file's fsync take more than a second on some 98 # systems, and we've seen timeouts at 10 seconds on systems 99 # with slow I/O. So give it time to flush perhaps a few files. 100 self.session.transaction_sync('timeout_ms=30000') 101 self.simulate_crash_restart(".", "RESTART") 102 c = self.session.open_cursor(self.t1, None, None) 103 i = 0 104 for key, value in c: 105 self.assertEqual(i, key) 106 self.assertEqual(i+1, value) 107 i += 1 108 all = self.entries + self.extra_entries 109 self.assertEqual(i, all) 110 c.close() 111 112if __name__ == '__main__': 113 wttest.run() 114