Files
mongo/test/suite/test_checkpoint01.py
Keith Bostic 5b509b7220 Update copyright notices for 2014.
Move lang/java and lang/python into the public domain.
2014-01-07 10:30:12 -05:00

421 lines
18 KiB
Python

#!/usr/bin/env python
#
# 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.
import wiredtiger, wttest
from helper import key_populate, complex_populate_lsm, simple_populate
# test_checkpoint01.py
# Checkpoint tests
# General checkpoint test: create an object containing sets of data associated
# with a set of checkpoints, then confirm the checkpoint's values are correct,
# including after other checkpoints are dropped.
class test_checkpoint(wttest.WiredTigerTestCase):
scenarios = [
('file', dict(uri='file:checkpoint',fmt='S')),
('table', dict(uri='table:checkpoint',fmt='S'))
]
# Each checkpoint has a key range and a "is dropped" flag.
checkpoints = {
"checkpoint-1": ((100, 200), 0),
"checkpoint-2": ((200, 220), 0),
"checkpoint-3": ((300, 320), 0),
"checkpoint-4": ((400, 420), 0),
"checkpoint-5": ((500, 520), 0),
"checkpoint-6": ((100, 620), 0),
"checkpoint-7": ((200, 250), 0),
"checkpoint-8": ((300, 820), 0),
"checkpoint-9": ((400, 920), 0)
}
# Add a set of records for a checkpoint.
def add_records(self, name):
cursor = self.session.open_cursor(self.uri, None, "overwrite")
start, stop = self.checkpoints[name][0]
for i in range(start, stop+1):
cursor.set_key("%010d KEY------" % i)
cursor.set_value("%010d VALUE "% i + name)
self.assertEqual(cursor.insert(), 0)
cursor.close()
self.checkpoints[name] = (self.checkpoints[name][0], 1)
# For each checkpoint entry, add/overwrite the specified records, then
# checkpoint the object, and verify it (which verifies all underlying
# checkpoints individually).
def build_file_with_checkpoints(self):
for checkpoint_name, entry in self.checkpoints.iteritems():
self.add_records(checkpoint_name)
self.session.checkpoint("name=" + checkpoint_name)
# Create a dictionary of sorted records a checkpoint should include.
def list_expected(self, name):
records = {}
for checkpoint_name, entry in self.checkpoints.iteritems():
start, stop = entry[0]
for i in range(start, stop+1):
records['%010d KEY------' % i] =\
'%010d VALUE ' % i + checkpoint_name
if name == checkpoint_name:
break
return records
# Create a dictionary of sorted records a checkpoint does include.
def list_checkpoint(self, name):
records = {}
cursor = self.session.open_cursor(self.uri, None, 'checkpoint=' + name)
while cursor.next() == 0:
records[cursor.get_key()] = cursor.get_value()
cursor.close()
return records
# For each existing checkpoint entry, verify it contains the records it
# should, and no other checkpoints exist.
def check(self):
# Physically verify the file, including the individual checkpoints.
self.session.verify(self.uri, None)
for checkpoint_name, entry in self.checkpoints.iteritems():
if entry[1] == 0:
self.assertRaises(wiredtiger.WiredTigerError,
lambda: self.session.open_cursor(
self.uri, None, "checkpoint=" + checkpoint_name))
else:
list_expected = self.list_expected(checkpoint_name)
list_checkpoint = self.list_checkpoint(checkpoint_name)
self.assertEqual(list_expected, list_checkpoint)
# Main checkpoint test driver.
def test_checkpoint(self):
# Build a file with a set of checkpoints, and confirm they all have
# the correct key/value pairs.
self.session.create(self.uri,
"key_format=" + self.fmt +\
",value_format=S,allocation_size=512,leaf_page_max=512")
self.build_file_with_checkpoints()
self.check()
# Drop a set of checkpoints sequentially, and each time confirm the
# contents of remaining checkpoints, and that dropped checkpoints
# don't appear.
for i in [1,3,7,9]:
checkpoint_name = 'checkpoint-' + str(i)
self.session.checkpoint('drop=(' + checkpoint_name + ')')
self.checkpoints[checkpoint_name] =\
(self.checkpoints[checkpoint_name][0], 0)
self.check()
# Drop remaining checkpoints, all subsequent checkpoint opens should
# fail.
self.session.checkpoint("drop=(from=all)")
for checkpoint_name, entry in self.checkpoints.iteritems():
self.checkpoints[checkpoint_name] =\
(self.checkpoints[checkpoint_name][0], 0)
self.check()
# Check some specific cursor checkpoint combinations.
class test_checkpoint_cursor(wttest.WiredTigerTestCase):
scenarios = [
('file', dict(uri='file:checkpoint',fmt='S')),
('table', dict(uri='table:checkpoint',fmt='S'))
]
# Check that you cannot open a checkpoint that doesn't exist.
def test_checkpoint_dne(self):
simple_populate(self, self.uri, 'key_format=' + self.fmt, 100)
self.assertRaises(wiredtiger.WiredTigerError,
lambda: self.session.open_cursor(
self.uri, None, "checkpoint=checkpoint-1"))
self.assertRaises(wiredtiger.WiredTigerError,
lambda: self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint"))
# Check that you can open checkpoints more than once.
def test_checkpoint_multiple_open(self):
simple_populate(self, self.uri, 'key_format=' + self.fmt, 100)
self.session.checkpoint("name=checkpoint-1")
c1 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-1")
c2 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-1")
c3 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-1")
c4 = self.session.open_cursor(self.uri, None, None)
c4.close, c3.close, c2.close, c1.close
self.session.checkpoint("name=checkpoint-2")
c1 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-1")
c2 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-2")
c3 = self.session.open_cursor(self.uri, None, "checkpoint=checkpoint-2")
c4 = self.session.open_cursor(self.uri, None, None)
c4.close, c3.close, c2.close, c1.close
# Check that you cannot drop a checkpoint if it's in use.
def test_checkpoint_inuse(self):
simple_populate(self, self.uri, 'key_format=' + self.fmt, 100)
self.session.checkpoint("name=checkpoint-1")
self.session.checkpoint("name=checkpoint-2")
self.session.checkpoint("name=checkpoint-3")
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=checkpoint-2")
# Check creating an identically named checkpoint fails. */
# Check dropping the specific checkpoint fails.
# Check dropping all checkpoints fails.
msg = '/checkpoints cannot be dropped/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.checkpoint("name=checkpoint-2"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.checkpoint("drop=(checkpoint-2)"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.checkpoint("drop=(from=all)"), msg)
# Check dropping other checkpoints succeeds (which also tests that you
# can create new checkpoints while other checkpoints are in-use).
self.session.checkpoint("drop=(checkpoint-1,checkpoint-3)")
# Close the cursor and repeat the failing commands, they should now
# succeed.
cursor.close()
self.session.checkpoint("name=checkpoint-2")
self.session.checkpoint("drop=(checkpoint-2)")
self.session.checkpoint("drop=(from=all)")
# Check that you can checkpoint targets.
class test_checkpoint_target(wttest.WiredTigerTestCase):
scenarios = [
('file', dict(uri='file:checkpoint',fmt='S')),
('table', dict(uri='table:checkpoint',fmt='S'))
]
def update(self, uri, value):
cursor = self.session.open_cursor(uri, None, "overwrite")
cursor.set_key(key_populate(cursor, 10))
cursor.set_value(value)
cursor.insert()
cursor.close()
def check(self, uri, value):
cursor = self.session.open_cursor(uri, None, "checkpoint=checkpoint-1")
self.assertEquals(cursor[key_populate(cursor, 10)], value)
cursor.close()
def test_checkpoint_target(self):
# Create 3 objects, change one record to an easily recognizable string.
uri = self.uri + '1'
simple_populate(self, uri, 'key_format=' + self.fmt, 100)
self.update(uri, 'ORIGINAL')
uri = self.uri + '2'
simple_populate(self, uri, 'key_format=' + self.fmt, 100)
self.update(uri, 'ORIGINAL')
uri = self.uri + '3'
simple_populate(self, uri, 'key_format=' + self.fmt, 100)
self.update(uri, 'ORIGINAL')
# Checkpoint all three objects.
self.session.checkpoint("name=checkpoint-1")
# Update all 3 objects, then checkpoint two of the objects with the
# same checkpoint name.
self.update(self.uri + '1', 'UPDATE')
self.update(self.uri + '2', 'UPDATE')
self.update(self.uri + '3', 'UPDATE')
target = 'target=("' + self.uri + '1"' + ',"' + self.uri + '2")'
self.session.checkpoint("name=checkpoint-1," + target)
# Confirm the checkpoint has the old value in objects that weren't
# checkpointed, and the new value in objects that were checkpointed.
self.check(self.uri + '1', 'UPDATE')
self.check(self.uri + '2', 'UPDATE')
self.check(self.uri + '3', 'ORIGINAL')
# Check that you can't write checkpoint cursors.
class test_checkpoint_cursor_update(wttest.WiredTigerTestCase):
scenarios = [
('file-r', dict(uri='file:checkpoint',fmt='r')),
('file-S', dict(uri='file:checkpoint',fmt='S')),
('table-r', dict(uri='table:checkpoint',fmt='r')),
('table-S', dict(uri='table:checkpoint',fmt='S'))
]
def test_checkpoint_cursor_update(self):
simple_populate(self, self.uri, 'key_format=' + self.fmt, 100)
self.session.checkpoint("name=ckpt")
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
cursor.set_key(key_populate(cursor, 10))
cursor.set_value("XXX")
self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.insert())
self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.remove())
self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.update())
cursor.close()
# Check that WiredTigerCheckpoint works as a checkpoint specifier.
class test_checkpoint_last(wttest.WiredTigerTestCase):
scenarios = [
('file', dict(uri='file:checkpoint',fmt='S')),
('table', dict(uri='table:checkpoint',fmt='S'))
]
def test_checkpoint_last(self):
# Create an object, change one record to an easily recognizable string,
# then checkpoint it and open a cursor, confirming we see the correct
# value. Repeat this action, we want to be sure the engine gets the
# latest checkpoint information each time.
uri = self.uri
simple_populate(self, uri, 'key_format=' + self.fmt, 100)
for value in ('FIRST', 'SECOND', 'THIRD', 'FOURTH', 'FIFTH'):
# Update the object.
cursor = self.session.open_cursor(uri, None, "overwrite")
cursor.set_key(key_populate(cursor, 10))
cursor.set_value(value)
cursor.insert()
cursor.close()
# Checkpoint the object.
self.session.checkpoint()
# Verify the "last" checkpoint sees the correct value.
cursor = self.session.open_cursor(
uri, None, "checkpoint=WiredTigerCheckpoint")
self.assertEquals(cursor[key_populate(cursor, 10)], value)
# Don't close the checkpoint cursor, we want it to remain open until
# the test completes.
# Check we can't use the reserved name as an application checkpoint name.
class test_checkpoint_last_name(wttest.WiredTigerTestCase):
def test_checkpoint_last_name(self):
simple_populate(self, "file:checkpoint", 'key_format=S', 100)
msg = '/the checkpoint name.*is reserved/'
for conf in (
'name=WiredTigerCheckpoint',
'name=WiredTigerCheckpoint.',
'name=WiredTigerCheckpointX',
'drop=(from=WiredTigerCheckpoint)',
'drop=(from=WiredTigerCheckpoint.)',
'drop=(from=WiredTigerCheckpointX)',
'drop=(to=WiredTigerCheckpoint)',
'drop=(to=WiredTigerCheckpoint.)',
'drop=(to=WiredTigerCheckpointX)'):
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.checkpoint(conf), msg)
# Check we can't name checkpoints that include LSM tables.
class test_checkpoint_lsm_name(wttest.WiredTigerTestCase):
def test_checkpoint_lsm_name(self):
complex_populate_lsm(self,
"table:checkpoint", 'type=lsm,key_format=S', 1000)
msg = '/object does not support named checkpoints/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.checkpoint("name=ckpt"), msg)
class test_checkpoint_empty(wttest.WiredTigerTestCase):
scenarios = [
('file', dict(uri='file:checkpoint')),
('table', dict(uri='table:checkpoint')),
]
# Create an empty file, do one of 4 cases of checkpoint, then verify the
# checkpoints exist. The reason for the 4 cases is we must create all
# checkpoints an application can explicitly reference using a cursor, and
# I want to test when other types of checkpoints are created before the
# checkpoint we really need.
# Case 1: a named checkpoint
def test_checkpoint_empty_one(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint('name=ckpt')
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
# Case 2: an internal checkpoint
def test_checkpoint_empty_two(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint()
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
# Case 3: a named checkpoint, then an internal checkpoint
def test_checkpoint_empty_three(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint('name=ckpt')
self.session.checkpoint()
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
# Case 4: an internal checkpoint, then a named checkpoint
def test_checkpoint_empty_four(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint()
self.session.checkpoint('name=ckpt')
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
# Check that we can create an empty checkpoint, change the underlying
# object, checkpoint again, and still see the original empty tree, for
# both named and unnamed checkpoints.
def test_checkpoint_empty_five(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint('name=ckpt')
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
self.assertEquals(cursor.next(), wiredtiger.WT_NOTFOUND)
cursor.close()
cursor = self.session.open_cursor(self.uri, None)
cursor.set_key("key")
cursor.set_value("value")
cursor.insert()
self.session.checkpoint()
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
self.assertEquals(cursor.next(), wiredtiger.WT_NOTFOUND)
def test_checkpoint_empty_six(self):
self.session.create(self.uri, "key_format=S,value_format=S")
self.session.checkpoint()
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
self.assertEquals(cursor.next(), wiredtiger.WT_NOTFOUND)
cursor.close()
cursor = self.session.open_cursor(self.uri, None)
cursor.set_key("key")
cursor.set_value("value")
cursor.insert()
self.session.checkpoint('name=ckpt')
cursor = self.session.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
self.assertEquals(cursor.next(), wiredtiger.WT_NOTFOUND)
if __name__ == '__main__':
wttest.run()