#!/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_sweep01.py # Test lots of tables, number of open files and sweeping. Run both # with and without checkpoints. # import fnmatch, os, shutil, run, time from suite_subprocess import suite_subprocess from wtscenario import make_scenarios from wiredtiger import stat import wttest class test_sweep01(wttest.WiredTigerTestCase, suite_subprocess): tablebase = 'test_sweep01' uri = 'table:' + tablebase numfiles = 30 numkv = 1000 conn_config = 'file_manager=(close_handle_minimum=0,' + \ 'close_idle_time=3,close_scan_interval=1),' + \ 'statistics=(fast),operation_tracking=(enabled=false),' types = [ ('row', dict(tabletype='row', create_params = 'key_format=i,value_format=i')), ('var', dict(tabletype='var', create_params = 'key_format=r,value_format=i')), ('fix', dict(tabletype='fix', create_params = 'key_format=r,value_format=8t')), ] scenarios = make_scenarios(types) def test_ops(self): # # Set up numfiles with numkv entries. We just want some data in there # we don't care what it is. # for f in range(self.numfiles): uri = '%s.%d' % (self.uri, f) # print "Creating %s with config '%s'" % (uri, self.create_params) self.session.create(uri, self.create_params) c = self.session.open_cursor(uri, None) for k in range(self.numkv): c[k+1] = 1 c.close() if f % 20 == 0: time.sleep(1) stat_cursor = self.session.open_cursor('statistics:', None, None) close1 = stat_cursor[stat.conn.dh_sweep_close][2] remove1 = stat_cursor[stat.conn.dh_sweep_remove][2] sweep1 = stat_cursor[stat.conn.dh_sweeps][2] sclose1 = stat_cursor[stat.conn.dh_session_handles][2] ssweep1 = stat_cursor[stat.conn.dh_session_sweeps][2] tod1 = stat_cursor[stat.conn.dh_sweep_tod][2] ref1 = stat_cursor[stat.conn.dh_sweep_ref][2] nfile1 = stat_cursor[stat.conn.file_open][2] stat_cursor.close() # # We've configured checkpoints to run every 5 seconds, sweep server to # run every 2 seconds and idle time to be 6 seconds. It should take # about 8 seconds for a handle to be closed. Sleep for double to be # safe. # uri = '%s.test' % self.uri self.session.create(uri, self.create_params) # # Keep inserting data to keep at least one handle active and give # checkpoint something to do. Make sure checkpoint doesn't adjust # the time of death for inactive handles. # # Note that we do checkpoints inline because that has the side effect # of sweeping the session cache, which will allow handles to be # removed. # c = self.session.open_cursor(uri, None) k = 0 sleep = 0 max = 60 final_nfile = 4 while sleep < max: self.session.checkpoint() k = k+1 c[k] = 1 sleep += 0.5 time.sleep(0.5) # Give slow machines time to process files. stat_cursor = self.session.open_cursor('statistics:', None, None) this_nfile = stat_cursor[stat.conn.file_open][2] removed = stat_cursor[stat.conn.dh_sweep_remove][2] stat_cursor.close() self.pr("==== loop " + str(sleep)) self.pr("this_nfile " + str(this_nfile)) self.pr("removed " + str(removed)) # On slow machines there can be a lag where files get closed but # the sweep server cannot yet remove the handles. So wait for the # removed statistic to indicate forward progress too. if this_nfile == final_nfile and removed != remove1: break c.close() self.pr("Sweep loop took " + str(sleep)) stat_cursor = self.session.open_cursor('statistics:', None, None) close2 = stat_cursor[stat.conn.dh_sweep_close][2] remove2 = stat_cursor[stat.conn.dh_sweep_remove][2] sweep2 = stat_cursor[stat.conn.dh_sweeps][2] sclose2 = stat_cursor[stat.conn.dh_session_handles][2] ssweep2 = stat_cursor[stat.conn.dh_session_sweeps][2] nfile2 = stat_cursor[stat.conn.file_open][2] tod2 = stat_cursor[stat.conn.dh_sweep_tod][2] ref2 = stat_cursor[stat.conn.dh_sweep_ref][2] stat_cursor.close() # print "checkpoint: " + str(self.ckpt) # print "nfile1: " + str(nfile1) + " nfile2: " + str(nfile2) # print "close1: " + str(close1) + " close2: " + str(close2) # print "sweep1: " + str(sweep1) + " sweep2: " + str(sweep2) # print "ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2) # print "sclose1: " + str(sclose1) + " sclose2: " + str(sclose2) # print "tod1: " + str(tod1) + " tod2: " + str(tod2) # print "ref1: " + str(ref1) + " ref2: " + str(ref2) # # The files are all closed. Check that sweep did its work even # in the presence of recent checkpoints. # if (close1 >= close2): print("XX: close1: " + str(close1) + " close2: " + str(close2)) print("remove1: " + str(remove1) + " remove2: " + str(remove2)) print("sweep1: " + str(sweep1) + " sweep2: " + str(sweep2)) print("sclose1: " + str(sclose1) + " sclose2: " + str(sclose2)) print("ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2)) print("tod1: " + str(tod1) + " tod2: " + str(tod2)) print("ref1: " + str(ref1) + " ref2: " + str(ref2)) print("nfile1: " + str(nfile1) + " nfile2: " + str(nfile2)) self.assertEqual(close1 < close2, True) if (remove1 >= remove2): print("close1: " + str(close1) + " close2: " + str(close2)) print("XX: remove1: " + str(remove1) + " remove2: " + str(remove2)) print("sweep1: " + str(sweep1) + " sweep2: " + str(sweep2)) print("sclose1: " + str(sclose1) + " sclose2: " + str(sclose2)) print("ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2)) print("tod1: " + str(tod1) + " tod2: " + str(tod2)) print("ref1: " + str(ref1) + " ref2: " + str(ref2)) print("nfile1: " + str(nfile1) + " nfile2: " + str(nfile2)) self.assertEqual(remove1 < remove2, True) if (sweep1 >= sweep2): print("close1: " + str(close1) + " close2: " + str(close2)) print("remove1: " + str(remove1) + " remove2: " + str(remove2)) print("XX: sweep1: " + str(sweep1) + " sweep2: " + str(sweep2)) print("sclose1: " + str(sclose1) + " sclose2: " + str(sclose2)) print("ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2)) print("tod1: " + str(tod1) + " tod2: " + str(tod2)) print("ref1: " + str(ref1) + " ref2: " + str(ref2)) self.assertEqual(sweep1 < sweep2, True) if (nfile2 >= nfile1): print("close1: " + str(close1) + " close2: " + str(close2)) print("remove1: " + str(remove1) + " remove2: " + str(remove2)) print("sweep1: " + str(sweep1) + " sweep2: " + str(sweep2)) print("sclose1: " + str(sclose1) + " sclose2: " + str(sclose2)) print("ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2)) print("tod1: " + str(tod1) + " tod2: " + str(tod2)) print("ref1: " + str(ref1) + " ref2: " + str(ref2)) print("XX: nfile1: " + str(nfile1) + " nfile2: " + str(nfile2)) self.assertEqual(nfile2 < nfile1, True) # The only files that should be left are the metadata, the history store # file, the lock file, and the active file. if (nfile2 != final_nfile): print("close1: " + str(close1) + " close2: " + str(close2)) print("remove1: " + str(remove1) + " remove2: " + str(remove2)) print("sweep1: " + str(sweep1) + " sweep2: " + str(sweep2)) print("sclose1: " + str(sclose1) + " sclose2: " + str(sclose2)) print("ssweep1: " + str(ssweep1) + " ssweep2: " + str(ssweep2)) print("tod1: " + str(tod1) + " tod2: " + str(tod2)) print("ref1: " + str(ref1) + " ref2: " + str(ref2)) print("XX2: nfile1: " + str(nfile1) + " nfile2: " + str(nfile2)) self.assertEqual(nfile2 == final_nfile, True) if __name__ == '__main__': wttest.run()