Esempio n. 1
0
    def test_timestamp_ts_then_nots(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        # Create the table with the key consistency checking turned on. That checking will verify
        # any individual key is always or never used with a timestamp. And if it is used with a
        # timestamp that the timestamps are in increasing order for that key.
        uri = 'table:ts'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format) +
            ',write_timestamp_usage=ordered')

        c = self.session.open_cursor(uri)
        key = ds.key(5)

        self.session.begin_transaction()
        c[key] = ds.value(11)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(20))

        self.session.begin_transaction()
        c[key] = ds.value(12)
        msg ='/configured to always use timestamps once they are first used/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), msg)
Esempio n. 2
0
    def test_alter(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        if self.init_always:
            start = 'always'
            switch = 'never'
        else:
            start = 'never'
            switch = 'always'

        # Open the object, configuring the initial timestamp usage.
        # Check it.
        # Switch the object to the opposite usage.
        # Check it.
        uri = 'table:ts'
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) + ',' +
            'write_timestamp_usage={}'.format(start) +
            ',assert=(write_timestamp=on)')
        self.check(ds, uri, self.init_always)
        self.session.alter(uri, 'write_timestamp_usage={}'.format(switch))
        self.check(ds, uri, not self.init_always)
Esempio n. 3
0
    def test_wtu_never(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        # Open the object, configuring write_timestamp usage.
        uri = 'table:ts'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format) +
            ',write_timestamp_usage=never')

        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        c[ds.key(7)] = ds.value(8)

        # Commit with a timestamp.
        if self.with_ts:
            # Check both an explicit timestamp set and a set at commit.
            commit_ts = 'commit_timestamp=' + self.timestamp_str(10)
            if not self.commit_ts:
                self.session.timestamp_transaction(commit_ts)
                commit_ts = ''

            msg = '/set when disallowed/'
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                lambda: self.session.commit_transaction(commit_ts), msg)

        # Commit without a timestamp.
        else:
            self.session.commit_transaction()
Esempio n. 4
0
    def test_log_ts(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        # Open the object, configuring write_timestamp usage.
        uri = 'table:ts'
        config = ',write_timestamp_usage='
        config += 'always' if self.always else 'never'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format) + config)

        c = self.session.open_cursor(uri)

        # Commit with a timestamp.
        self.session.begin_transaction()
        c[ds.key(1)] = ds.value(1)
        self.session.breakpoint()
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(10))

        # Commit without a timestamp.
        self.session.begin_transaction()
        c[ds.key(2)] = ds.value(2)
        self.session.commit_transaction()
Esempio n. 5
0
    def test_commit_larger_than_active_timestamp(self):
        if not wiredtiger.diagnostic_build():
            self.skipTest('requires a diagnostic build')

        uri = 'table:test_txn26'
        self.session.create(uri, 'key_format=S,value_format=S')
        cursor = self.session.open_cursor(uri)
        self.conn.set_timestamp(
            'oldest_timestamp=' + timestamp_str(1) + ',stable_timestamp=' + timestamp_str(1))

        value = 'a'

        # Start a session with timestamp 10
        session2 = self.conn.open_session(self.session_config)
        session2.begin_transaction('read_timestamp=' + timestamp_str(10))

        # Try to commit at timestamp 10
        self.session.begin_transaction()
        cursor[str(0)] = value
        with self.expectedStderrPattern("must be greater than the latest active read timestamp"):
            try:
                self.session.commit_transaction('commit_timestamp=' + timestamp_str(10))
            except wiredtiger.WiredTigerError as e:
                gotException = True
                self.pr('got expected exception: ' + str(e))
                self.assertTrue(str(e).find('nvalid argument') >= 0)
        self.assertTrue(gotException, msg = 'expected exception')
Esempio n. 6
0
    def test_timestamp_ts_order(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Create the table with the key consistency checking turned on. That checking will verify
        # any individual key is always or never used with a timestamp. And if it is used with a
        # timestamp that the timestamps are in increasing order for that key.
        uri = 'table:ts'
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) +
            ',write_timestamp_usage=ordered')

        c = self.session.open_cursor(uri)
        key1 = ds.key(6)
        key2 = ds.key(7)

        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(30))
        c[key1] = ds.value(14)
        c[key2] = ds.value(15)
        self.session.commit_transaction()
        self.assertEquals(c[key1], ds.value(14))
        self.assertEquals(c[key2], ds.value(15))

        self.session.begin_transaction()
        c[key1] = ds.value(16)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(31))
        c[key2] = ds.value(17)
        self.session.commit_transaction()
        self.assertEquals(c[key1], ds.value(16))
        self.assertEquals(c[key2], ds.value(17))

        self.session.begin_transaction()
        c[key1] = ds.value(18)
        c[key2] = ds.value(19)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(32))
        self.session.commit_transaction()
        self.assertEquals(c[key1], ds.value(18))
        self.assertEquals(c[key2], ds.value(19))

        self.session.begin_transaction()
        c[key1] = ds.value(20)
        c[key2] = ds.value(21)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(33))
        self.assertEquals(c[key1], ds.value(20))
        self.assertEquals(c[key2], ds.value(21))
Esempio n. 7
0
    def test_timestamp_inconsistent_update(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        # Create the table with the key consistency checking turned on. That checking will verify
        # any individual key is always or never used with a timestamp. And if it is used with a
        # timestamp that the timestamps are in increasing order for that key.
        uri = 'table:ts'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format) +
            ',write_timestamp_usage=ordered')

        c = self.session.open_cursor(uri)
        key = ds.key(1)

        # Insert an item at timestamp 2.
        self.session.begin_transaction()
        c[key] = ds.value(1)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(2))

        # Upate the data item at timestamp 1, which should fail.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(1))
        c[key] = ds.value(2)
        msg = '/updates a value with an older timestamp/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), msg)

        # Make sure we can successfully add a different key at timestamp 1.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(1))
        c[ds.key(2)] = ds.value(3)
        self.session.commit_transaction()
        
        # Insert key1 at timestamp 10 and key2 at 15. Then update both keys in one transaction at
        # timestamp 13, and we should get a complaint about usage.
        key1 = ds.key(3)
        key2 = ds.key(4)
        self.session.begin_transaction()
        c[key1] = ds.value(3)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(10))
        self.session.begin_transaction()
        c[key2] = ds.value(4)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(15))

        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(13))
        c[key1] = ds.value(5)
        c[key2] = ds.value(6)
        msg = '/updates a value with an older timestamp/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), msg)
Esempio n. 8
0
    def test_read_timestamp(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Open the object, configuring read timestamp usage.
        uri = 'table:ts'
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) +
            ',assert=(read_timestamp=' + self.read_ts + ')')

        c = self.session.open_cursor(uri)
        key = ds.key(10)
        value = ds.value(10)

        # Insert a data item at a timestamp (although it doesn't really matter).
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(10))
        c[key] = value
        self.session.timestamp_transaction()
        self.session.commit_transaction()

        # Try reading without a timestamp.
        self.session.begin_transaction()
        c.set_key(key)
        if self.read_ts != 'always':
            self.assertEquals(c.search(), 0)
            self.assertEqual(c.get_value(), value)
        else:
            msg = '/read timestamps required and none set/'
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                         lambda: c.search(), msg)

        self.session.rollback_transaction()

        # Try reading with a timestamp.
        self.session.begin_transaction()
        self.session.timestamp_transaction('read_timestamp=20')
        c.set_key(key)
        if self.read_ts != 'never':
            self.assertEquals(c.search(), 0)
            self.assertEqual(c.get_value(), value)
        else:
            msg = '/read timestamps disallowed/'
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                         lambda: c.search(), msg)
        self.session.rollback_transaction()
Esempio n. 9
0
    def test_in_memory_ts(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Open the object, configuring write_timestamp usage.
        uri = 'table:ts'
        config = ',' + self.obj_config
        config += ',write_timestamp_usage='
        config += 'ordered' if self.always else 'never'
        self.session.breakpoint()
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) + config)

        c = self.session.open_cursor(uri)

        # Commit with a timestamp.
        self.session.begin_transaction()
        c[ds.key(1)] = ds.value(1)
        if self.always == True or self.obj_ignore == True:
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(1))
        else:
            msg = '/unexpected timestamp usage/'
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.session.commit_transaction(
                    'commit_timestamp=' + self.timestamp_str(1)), msg)

        # Commit without a timestamp (but first with a timestamp if in ordered mode so we get
        # a failure).
        if self.always:
            self.session.begin_transaction()
            c[ds.key(2)] = ds.value(2)
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(2))
        self.session.begin_transaction()
        c[ds.key(2)] = ds.value(2)
        if self.always == False or self.obj_ignore == True:
            self.session.commit_transaction()
        else:
            msg = '/no timestamp provided/'
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.session.commit_transaction(), msg)
Esempio n. 10
0
    def test_bulk_load_row_order_nocheck(self):
        uri = self.type + self.name
        self.session.create(uri, 'key_format=S,value_format=S')
        cursor = self.session.open_cursor(uri, None, "bulk,skip_sort_check")
        cursor[key_populate(cursor, 10)] = value_populate(cursor, 10)
        cursor[key_populate(cursor, 1)] = value_populate(cursor, 1)

        if not wiredtiger.diagnostic_build():
            self.skipTest('requires a diagnostic build')

        # Close explicitly, there's going to be a fallure.
        msg = '/are incorrectly sorted/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.conn.close(), msg)
Esempio n. 11
0
    def test_bulk_load_row_order_nocheck(self):
        uri = self.type + self.name
        self.session.create(uri, 'key_format=S,value_format=S')
        cursor = self.session.open_cursor(uri, None, "bulk,skip_sort_check")
        cursor[key_populate(cursor, 10)] = value_populate(cursor, 10)
        cursor[key_populate(cursor, 1)] = value_populate(cursor, 1)

        if not wiredtiger.diagnostic_build():
            self.skipTest('requires a diagnostic build')

        # Close explicitly, there's going to be a fallure.
        msg = '/are incorrectly sorted/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.conn.close(), msg)
Esempio n. 12
0
    def test_alter(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Open the object, configuring "never" timestamp usage.
        # Check it.
        # Switch the object to "ordered" usage.
        # Check it.
        uri = 'table:ts'
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) +
            ',write_timestamp_usage=never')

        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        c[ds.key(10)] = ds.value(10)
        msg = '/set when disallowed by table configuration/'
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction('commit_timestamp=' + self.
                                                    timestamp_str(10)), msg)
        c.close()

        self.session.alter(uri, 'write_timestamp_usage=ordered')

        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        c[ds.key(10)] = ds.value(10)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(11))
        self.session.begin_transaction()
        c[ds.key(10)] = ds.value(10)
        msg = '/always use timestamps/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.session.commit_transaction(),
                                     msg)
Esempio n. 13
0
    def test_always_never(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Open the object, configuring write_timestamp usage.
        uri = 'table:ts'
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) +
            ',write_timestamp_usage=' + self.write_timestamp + ',' +
            ',assert=(write_timestamp=' + self.assert_ts + ')')

        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        c[ds.key(7)] = ds.value(8)

        # Commit with a timestamp.
        if self.with_ts:
            # Check both an explicit timestamp set and a set at commit.
            commit_ts = 'commit_timestamp=' + self.timestamp_str(10)
            if not self.commit_ts:
                self.session.timestamp_transaction(commit_ts)
                commit_ts = ''

            if self.assert_ts == 'off' or self.write_timestamp == 'always':
                self.session.commit_transaction(commit_ts)
            else:
                with self.expectedStderrPattern('set when disallowed'):
                    self.session.commit_transaction(commit_ts)

        # Commit without a timestamp.
        else:
            if self.assert_ts == 'off' or self.write_timestamp == 'never':
                self.session.commit_transaction()
            else:
                with self.expectedStderrPattern('timestamp required by table'):
                    self.session.commit_transaction()
Esempio n. 14
0
    def test_in_memory_ts(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Open the object, configuring write_timestamp usage.
        uri = 'table:ts'
        config = ',' + self.obj_config
        config += ',write_timestamp_usage='
        config += 'always' if self.always else 'never'
        config += ',assert=(write_timestamp=on)'
        self.session.breakpoint()
        self.session.create(
            uri, 'key_format={},value_format={}'.format(
                self.key_format, self.value_format) + config)

        c = self.session.open_cursor(uri)

        # Commit with a timestamp.
        self.session.begin_transaction()
        c[ds.key(1)] = ds.value(1)
        if self.always == True or self.obj_ignore == True:
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(1))
        else:
            with self.expectedStderrPattern('unexpected timestamp usage'):
                self.session.commit_transaction('commit_timestamp=' +
                                                self.timestamp_str(1))

        # Commit without a timestamp.
        self.session.begin_transaction()
        c[ds.key(2)] = ds.value(2)
        if self.always == False or self.obj_ignore == True:
            self.session.commit_transaction()
        else:
            with self.expectedStderrPattern('unexpected timestamp usage'):
                self.session.commit_transaction()
    def prepare_resolve(self, resolve):
        ds = self.dataset(self,
                          "table:rts30",
                          10,
                          key_format=self.keyfmt,
                          value_format=self.valfmt)
        ds.populate()

        # Pin oldest and stable timestamps to 1.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(1) +
                                ',stable_timestamp=' + self.timestamp_str(1))

        # Write some data and prepare it.
        cursor = self.session.open_cursor(ds.uri)
        self.session.begin_transaction()

        # Modify a row.
        cursor[ds.key(5)] = ds.value(20)

        # Prepare at timestamp 10.
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(10))

        # Roll back to stable should fail because there's an active transaction.
        msg = '/rollback_to_stable.*active/'
        if wiredtiger.diagnostic_build():
            with self.expectedStdoutPattern('transaction state dump'):
                self.assertRaisesWithMessage(
                    wiredtiger.WiredTigerError,
                    lambda: self.conn.rollback_to_stable(), msg)
        else:
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.conn.rollback_to_stable(), msg)

        # Set commit, durable timestamps to 20.
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(20) +
                                           ',durable_timestamp=' +
                                           self.timestamp_str(20))

        # Commit or abort the prepared transaction.
        resolve()
Esempio n. 16
0
    def test_bulk_load_row_order_nocheck(self):
        # Row-store offers an optional fast-past that skips the relatively
        # expensive key-order checks, used when the input is known to be
        # correct. Column-store comparisons are cheap, so it doesn't have
        # that fast-path support.
        if self.keyfmt != 'S':
            return

        uri = self.type + self.name
        self.session.create(
            uri, 'key_format=' + self.keyfmt + ',value_format=' + self.valfmt)
        cursor = self.session.open_cursor(uri, None, "bulk,skip_sort_check")
        cursor[simple_key(cursor, 10)] = simple_value(cursor, 10)
        cursor[simple_key(cursor, 1)] = simple_value(cursor, 1)

        if not wiredtiger.diagnostic_build():
            self.skipTest('requires a diagnostic build')

        # Close explicitly, there's going to be a failure.
        msg = '/are incorrectly sorted/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.conn.close(), msg)
Esempio n. 17
0
    def test_bulk_load_row_order_nocheck(self):
        # Row-store offers an optional fast-past that skips the relatively
        # expensive key-order checks, used when the input is known to be
        # correct. Column-store comparisons are cheap, so it doesn't have
        # that fast-path support.
        if self.keyfmt != 'S':
                return

        uri = self.type + self.name
        self.session.create(uri,
            'key_format=' + self.keyfmt + ',value_format=' + self.valfmt)
        cursor = self.session.open_cursor(uri, None, "bulk,skip_sort_check")
        cursor[simple_key(cursor, 10)] = simple_value(cursor, 10)
        cursor[simple_key(cursor, 1)] = simple_value(cursor, 1)

        if not wiredtiger.diagnostic_build():
            self.skipTest('requires a diagnostic build')

        # Close explicitly, there's going to be a fallure.
        msg = '/are incorrectly sorted/'
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.conn.close(), msg)
Esempio n. 18
0
    def test_timestamp_alter(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        cfg_on = 'write_timestamp_usage=ordered'
        cfg_off = 'write_timestamp_usage=none'

        # Create the table without the key consistency checking turned on.
        # Create a few items breaking the rules.
        # Then alter the setting and verify the inconsistent usage is detected.
        uri = 'file:assert06'
        self.session.create(
            uri,
            'key_format={},value_format={}'.format(self.key_format,
                                                   self.value_format))
        c = self.session.open_cursor(uri)

        # Insert a data item at timestamp 2.
        key = ds.key(1)
        self.session.begin_transaction()
        c[key] = ds.value(1)
        self.apply_timestamps(2, True)
        self.session.commit_transaction()

        # Modify the data item at timestamp 1, illegally moving the timestamp backward.
        self.session.begin_transaction()
        c[key] = ds.value(2)
        self.apply_timestamps(1, True)
        self.session.commit_transaction()

        # Insert a non-timestamped item.
        # Then illegally modify with a timestamp.
        # Then illegally modify without a timestamp.
        key = ds.key(2)
        self.session.begin_transaction()
        c[key] = ds.value(3)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(4)
        self.apply_timestamps(2, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(5)
        self.session.commit_transaction()

        # Now alter the setting and make sure we detect incorrect usage.
        # We must move the oldest timestamp forward in order to alter, otherwise alter closing the
        # file will fail with EBUSY.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(2))
        c.close()
        self.session.alter(uri, cfg_on)
        c = self.session.open_cursor(uri)

        # Update at timestamp 5, then detect not using a timestamp.
        key = ds.key(3)
        self.session.begin_transaction()
        c[key] = ds.value(6)
        self.apply_timestamps(5, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(6)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.session.commit_transaction(),
                                     self.msg_usage)

        # Detect using a timestamp on a non-timestamp key. We must first use a non-timestamped
        # operation on the key in order to violate the key consistency condition in the following
        # transaction.
        key = ds.key(4)
        self.session.begin_transaction()
        c[key] = ds.value(7)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(8)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(3))

        # Test to make sure that key consistency can be turned off after turning it on.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(4))
        c.close()
        self.session.alter(uri, cfg_off)
        c = self.session.open_cursor(uri)

        # Detection is off we can successfully change the same key with and without a timestamp.
        key = ds.key(5)
        self.session.begin_transaction()
        c[key] = ds.value(9)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(1)
        self.apply_timestamps(6, True)
        self.session.commit_transaction()
Esempio n. 19
0
    def test_timestamp_usage(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Create the table with the key consistency checking turned on. That checking will verify
        # any individual key is always or never used with a timestamp. And if it is used with a
        # timestamp that the timestamps are in increasing order for that key.
        uri = 'file:assert06'
        self.session.create(
            uri, 'key_format={},value_format={},'.format(
                self.key_format, self.value_format) +
            'write_timestamp_usage=ordered,assert=(write_timestamp=on)')
        c = self.session.open_cursor(uri)

        # Insert a data item at timestamp 2.
        self.session.begin_transaction()
        c[ds.key(1)] = ds.value(1)
        self.apply_timestamps(2, True)
        self.session.commit_transaction()

        # Make sure we can successfully add a different key at timestamp 1.
        self.session.begin_transaction()
        c[ds.key(2)] = ds.value(2)
        self.apply_timestamps(1, True)
        self.session.commit_transaction()

        # Insert key_ts3 at timestamp 10 and key_ts4 at 15, then modify both keys in one transaction
        # at timestamp 13, which should result in an error message.
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        c[ds.key(3)] = ds.value(3)
        self.apply_timestamps(10, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[ds.key(4)] = ds.value(4)
        self.apply_timestamps(15, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[ds.key(3)] = ds.value(5)
        c[ds.key(4)] = ds.value(6)
        self.apply_timestamps(13, False)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.session.commit_transaction(),
                                     '/unexpected timestamp usage/')
        self.assertEquals(c[ds.key(3)], ds.value(3))
        self.assertEquals(c[ds.key(4)], ds.value(4))

        # Modify a key previously used with timestamps without one. We should get the inconsistent
        # usage message.
        key = ds.key(5)
        self.session.begin_transaction()
        c[key] = ds.value(7)
        self.apply_timestamps(14, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(8)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: self.session.commit_transaction(),
                                     self.msg_usage)

        # Set the timestamp in the beginning, middle or end of the transaction.
        key = ds.key(6)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(16))
        c[key] = ds.value(9)
        self.session.commit_transaction()
        self.assertEquals(c[key], ds.value(9))

        key = ds.key(7)
        self.session.begin_transaction()
        c[key] = ds.value(10)
        c[key] = ds.value(11)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(17))
        c[key] = ds.value(12)
        c[key] = ds.value(13)
        self.session.commit_transaction()
        self.assertEquals(c[key], ds.value(13))

        key = ds.key(8)
        self.session.begin_transaction()
        c[key] = ds.value(14)
        self.apply_timestamps(18, True)
        self.session.commit_transaction()
        self.assertEquals(c[key], ds.value(14))

        # Confirm it is okay to set the durable timestamp on the commit call.
        key = ds.key(9)
        self.session.begin_transaction()
        c[key] = ds.value(15)
        c[key] = ds.value(16)
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(22))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(22))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           self.timestamp_str(22))
        self.session.commit_transaction()

        # Confirm that rolling back after preparing doesn't fire an assertion.
        key = ds.key(10)
        self.session.begin_transaction()
        c[key] = ds.value(17)
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(30))
        self.session.rollback_transaction()
Esempio n. 20
0
    def test_timestamp_api(self):
        format = 'key_format={},value_format={}'.format(
            self.key_format, self.value_format)
        self.session.create(self.uri, format)
        c = self.session.open_cursor(self.uri)

        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(20))
        self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(30))

        # It is illegal to set the prepare timestamp older than the stable
        # timestamp.
        self.session.begin_transaction()
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            prepare_transaction('prepare_timestamp=' + self.timestamp_str(10)),
            "/not newer than the stable timestamp/")
        self.session.rollback_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # stable timestamp is valid with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(20))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(25))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           self.timestamp_str(35))
        self.session.commit_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # *oldest* timestamp is also accepted with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(10))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(15))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           self.timestamp_str(35))
        self.session.commit_transaction()
        '''
        Commented out for now: the system panics if we fail after preparing a transaction.

        # Check setting a prepared transaction timestamps earlier than the
        # stable timestamp is invalid even with roundup_timestamps, if the
        # durable timestamp is less than the stable timestamp.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' + self.timestamp_str(20))
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(25))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.timestamp_transaction(
            'durable_timestamp=' + self.timestamp_str(25)),
            "/is less than the stable timestamp/")
        self.session.rollback_transaction()
        '''

        # Check the cases with an active reader.
        # Start a new reader to have an active read timestamp.
        s_reader = self.conn.open_session()
        s_reader.begin_transaction('read_timestamp=' + self.timestamp_str(40))

        # It is illegal to set the prepare timestamp as earlier than an active
        # read timestamp even with roundup_timestamps settings.  This is only
        # checked in diagnostic builds.
        if wiredtiger.diagnostic_build():
            self.session.begin_transaction(
                'roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                    'prepare_timestamp=' + self.timestamp_str(10)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

            # It is illegal to set the prepare timestamp the same as an active read
            # timestamp even with roundup_timestamps settings.
            self.session.begin_transaction(
                'roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                    'prepare_timestamp=' + self.timestamp_str(40)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()
        '''
        Commented out for now: the system panics if we fail after preparing a transaction.

        # It is illegal to set a commit timestamp less than the prepare
        # timestamp of a transaction.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction('prepare_timestamp=' + self.timestamp_str(45))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(
            'commit_timestamp=' + self.timestamp_str(30)),
            "/less than the prepare timestamp/")
        '''
        '''
        Commented out for now: the system panics if we fail after preparing a transaction.

        # It is legal to set a commit timestamp older than prepare timestamp of
        # a transaction with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        c[1] = 1
        self.session.prepare_transaction(
            'prepare_timestamp=' + self.timestamp_str(45))
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(30))
        #self.session.timestamp_transaction('durable_timestamp=' + self.timestamp_str(30))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.timestamp_transaction(
            'durable_timestamp=' + self.timestamp_str(30)),
            "/is less than the commit timestamp/")
        self.session.rollback_transaction()
        '''

        s_reader.commit_transaction()
Esempio n. 21
0
    def test_ordered(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(self,
                           'file:notused',
                           10,
                           key_format=self.key_format,
                           value_format=self.value_format)

        # Create the table without the key consistency checking turned on.
        # Create a few items breaking the rules. Then alter the setting and
        # verify the inconsistent usage is detected.
        uri = 'table:ts'
        self.session.create(
            uri,
            'key_format={},value_format={}'.format(self.key_format,
                                                   self.value_format))

        c = self.session.open_cursor(uri)
        key = ds.key(10)

        # Insert a data item at timestamp 2.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(2))
        c[key] = ds.value(10)
        self.session.commit_transaction()

        # Update the data item at timestamp 1.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(1))
        c[key] = ds.value(11)
        self.session.commit_transaction()

        key = ds.key(12)

        # Insert a non-timestamped item, then update with a timestamp and then without a timestamp.
        self.session.begin_transaction()
        c[key] = ds.value(12)
        self.session.commit_transaction()

        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(2))
        c[key] = ds.value(13)
        self.session.commit_transaction()

        self.session.begin_transaction()
        c[key] = ds.value(14)
        self.session.commit_transaction()

        # Now alter the setting and make sure we detect incorrect usage. We must move the oldest
        # timestamp forward in order to alter, otherwise alter will fail with EBUSY.
        c.close()
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(10))
        config = 'assert=(write_timestamp=on)'
        self.session.alter(uri, 'write_timestamp_usage=ordered,' + config)

        c = self.session.open_cursor(uri)
        key = ds.key(15)

        # Detect decreasing timestamp.
        self.session.begin_transaction()
        c[key] = ds.value(15)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(15))

        msg = 'with an older timestamp'
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(14))
        c[key] = ds.value(16)
        with self.expectedStderrPattern(msg):
            self.session.commit_transaction()

        # Detect not using a timestamp.
        msg = 'use timestamps once they are first used'
        self.session.begin_transaction()
        c[key] = ds.value(17)
        with self.expectedStderrPattern(msg):
            self.session.commit_transaction()

        # Now alter the setting again and detection is off.
        c.close()
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(20))
        self.session.alter(uri, 'assert=(write_timestamp=off)')
        c = self.session.open_cursor(uri)
        key = ds.key(18)

        # Detection is off we can successfully change the same key with then without a timestamp.
        self.session.begin_transaction()
        c[key] = ds.value(18)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(21))

        self.session.begin_transaction()
        c[key] = ds.value(19)
        self.session.commit_transaction()
        c.close()
Esempio n. 22
0
    def test_timestamp_api(self):
        self.session.create(self.uri, 'key_format=i,value_format=i')
        c = self.session.open_cursor(self.uri)

        # It is illegal to set the prepare timestamp older than the oldest
        # timestamp.
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(20))
        self.conn.set_timestamp('stable_timestamp=' + timestamp_str(30))
        self.session.begin_transaction()
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.prepare_transaction(
            'prepare_timestamp=' + timestamp_str(10)),
            "/older than the oldest timestamp/")
        self.session.rollback_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # oldest timestamp is valid with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' + timestamp_str(10))
        self.session.timestamp_transaction('commit_timestamp=' + timestamp_str(15))
        self.session.timestamp_transaction('durable_timestamp=' + timestamp_str(35))
        self.session.commit_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # oldest timestamp is invalid, if durable timestamp is less than the
        # stable timestamp.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' + timestamp_str(10))
        self.session.timestamp_transaction('commit_timestamp=' + timestamp_str(15))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.timestamp_transaction(
            'durable_timestamp=' + timestamp_str(25)),
            "/is less than the stable timestamp/")
        self.session.rollback_transaction()

        # Check the cases with an active reader.
        # Start a new reader to have an active read timestamp.
        s_reader = self.conn.open_session()
        s_reader.begin_transaction('read_timestamp=' + timestamp_str(40))

        # It is illegal to set the prepare timestamp as earlier than an active
        # read timestamp even with roundup_timestamps settings.  This is only
        # checked in diagnostic builds.
        if wiredtiger.diagnostic_build():
            self.session.begin_transaction('roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                'prepare_timestamp=' + timestamp_str(10)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

            # It is illegal to set the prepare timestamp the same as an active read
            # timestamp even with roundup_timestamps settings.
            self.session.begin_transaction('roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                'prepare_timestamp=' + timestamp_str(40)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

        # It is illegal to set a commit timestamp less than the prepare
        # timestamp of a transaction.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction(
            'prepare_timestamp=' + timestamp_str(45))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(
            'commit_timestamp=' + timestamp_str(30)),
            "/less than the prepare timestamp/")

        # It is legal to set a commit timestamp older than prepare timestamp of
        # a transaction with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        c[1] = 1
        self.session.prepare_transaction(
            'prepare_timestamp=' + timestamp_str(45))
        self.session.timestamp_transaction('commit_timestamp=' + timestamp_str(30))
        #self.session.timestamp_transaction('durable_timestamp=' + timestamp_str(30))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.timestamp_transaction(
            'durable_timestamp=' + timestamp_str(30)),
            "/is less than the commit timestamp/")
        self.session.rollback_transaction()

        s_reader.commit_transaction()
Esempio n. 23
0
    def test_timestamp_api(self):
        format = 'key_format={},value_format={}'.format(
            self.key_format, self.value_format)
        self.session.create(self.uri, format)
        c = self.session.open_cursor(self.uri)

        # It is illegal to set a prepare timestamp older than the stable timestamp.
        self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(2))
        self.session.begin_transaction()
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            prepare_transaction('prepare_timestamp=' + self.timestamp_str(1)),
            "/not newer than the stable timestamp/")
        self.session.rollback_transaction()

        # It is also illegal to set a prepare timestamp the same as the stable timestamp.
        self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(2))
        self.session.begin_transaction()
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            prepare_transaction('prepare_timestamp=' + self.timestamp_str(2)),
            "/not newer than the stable timestamp/")
        self.session.rollback_transaction()

        # Check setting the prepare timestamp immediately after the stable timestamp is valid.
        self.session.begin_transaction()
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(3))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(3))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           self.timestamp_str(3))
        self.session.commit_transaction()

        # In a single transaction it is illegal to set a commit timestamp
        # before invoking prepare for this transaction.
        # Note: Values are not important, setting commit timestamp before
        # prepare itself is illegal.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(3))
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            prepare_transaction('prepare_timestamp=' + self.timestamp_str(2)),
            "/should not have been set before/")
        self.session.rollback_transaction()

        # This is also true even if the prepare timestamp was set first.
        self.session.begin_transaction()
        self.session.timestamp_transaction('prepare_timestamp=' +
                                           self.timestamp_str(3))
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            timestamp_transaction('commit_timestamp=' + self.timestamp_str(3)),
            "/commit timestamp must not be set/")
        self.session.rollback_transaction()

        # It is illegal to set a prepare timestamp same as or earlier than an
        # active read timestamp.
        # Start a new reader to have an active read timestamp.
        if wiredtiger.diagnostic_build():
            s_reader = self.conn.open_session()
            s_reader.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(4))
            self.session.begin_transaction()
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                    'prepare_timestamp=' + self.timestamp_str(4)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

            # Check setting the prepare timestamp as later than active read
            # timestamp is valid.
            self.session.begin_transaction()
            c[1] = 1
            self.session.prepare_transaction('prepare_timestamp=' +
                                             self.timestamp_str(5))
            # Resolve the reader transaction started earlier.
            s_reader.rollback_transaction()
            self.session.rollback_transaction()
        '''
        Commented out for now: the system panics if we fail after preparing a transaction.

        # It is illegal to set a commit timestamp older than prepare timestamp of a transaction.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction('prepare_timestamp=' + self.timestamp_str(5))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(
            'commit_timestamp=' + self.timestamp_str(4)),
            "/less than the prepare timestamp/")
        '''

        # It is legal to set a commit timestamp as same as prepare
        # timestamp.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction('prepare_timestamp=' +
                                         self.timestamp_str(5))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(5))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           self.timestamp_str(5))
        self.session.commit_transaction()
Esempio n. 24
0
    def test_timestamp_range(self):
        if not wiredtiger.timestamp_build() or not wiredtiger.diagnostic_build(
        ):
            self.skipTest('requires a timestamp and diagnostic build')

        base = 'timestamp10'
        uri = 'file:' + base
        # Create a data item at a timestamp
        self.session.create(uri, 'key_format=S,value_format=S')

        # Insert a data item at timestamp 2
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(2))
        c['key'] = 'value2'
        self.session.commit_transaction()
        c.close()

        # Modify the data item at timestamp 1
        #
        # The docs say:
        # The commits to a particular data item must be performed in timestamp
        # order. Again, this is only checked in diagnostic builds and if
        # applications violate this rule, data consistency can be violated.
        #
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(1))
        c['key'] = 'value1'
        msg = 'on new update is older than'
        with self.expectedStdoutPattern(msg):
            self.session.commit_transaction()
        c.close()

        # Make sure we can successfully add a different key at timestamp 1.
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(1))
        c['key1'] = 'value1'
        self.session.commit_transaction()
        c.close()

        #
        # Insert key2 at timestamp 10 and key3 at 15.
        # Then modify both keys in one transaction at timestamp 14.
        # Modifying the one from 15 should report a warning message, but
        # the update will be applied.
        #
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(10))
        c['key2'] = 'value10'
        self.session.commit_transaction()
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(15))
        c['key3'] = 'value15'
        self.session.commit_transaction()

        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(14))
        c['key2'] = 'value14'
        c['key3'] = 'value14'
        with self.expectedStdoutPattern(msg):
            self.session.commit_transaction()
        c.close()

        c = self.session.open_cursor(uri)
        self.assertEquals(c['key2'], 'value14')
        self.assertEquals(c['key3'], 'value14')
        c.close()

        #
        # Separately, we should be able to update key2 at timestamp 16.
        #
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(16))
        c['key2'] = 'value16'
        self.session.commit_transaction()

        # Updating key3 inserted at timestamp 13 will report a warning.
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(13))
        c['key3'] = 'value13'
        with self.expectedStdoutPattern(msg):
            self.session.commit_transaction()
        c.close()

        # Test that updating again with an invalid timestamp reports a warning.
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(12))
        c['key3'] = 'value12'
        with self.expectedStdoutPattern(msg):
            self.session.commit_transaction()
        c.close()

        c = self.session.open_cursor(uri)
        self.assertEquals(c['key3'], 'value12')
        c.close()

        # Now try a later timestamp.
        c = self.session.open_cursor(uri)
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(17))
        c['key3'] = 'value17'
        self.session.commit_transaction()
        c.close()
Esempio n. 25
0
    def test_timestamp_api(self):
        self.session.create(self.uri, 'key_format=i,value_format=i')
        c = self.session.open_cursor(self.uri)

        # It is illegal to set the prepare timestamp older than the oldest
        # timestamp.
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(20))
        self.conn.set_timestamp('stable_timestamp=' + timestamp_str(30))
        self.session.begin_transaction()
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            prepare_transaction('prepare_timestamp=' + timestamp_str(10)),
            "/older than the oldest timestamp/")
        self.session.rollback_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # oldest timestamp is valid with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' +
                                         timestamp_str(10))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(15))
        self.session.timestamp_transaction('durable_timestamp=' +
                                           timestamp_str(35))
        self.session.commit_transaction()

        # Check setting a prepared transaction timestamps earlier than the
        # oldest timestamp is invalid, if durable timestamp is less than the
        # stable timestamp.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        self.session.prepare_transaction('prepare_timestamp=' +
                                         timestamp_str(10))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(15))
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            timestamp_transaction('durable_timestamp=' + timestamp_str(25)),
            "/is less than the stable timestamp/")
        self.session.rollback_transaction()

        # Check the cases with an active reader.
        # Start a new reader to have an active read timestamp.
        s_reader = self.conn.open_session()
        s_reader.begin_transaction('read_timestamp=' + timestamp_str(40))

        # It is illegal to set the prepare timestamp as earlier than an active
        # read timestamp even with roundup_timestamps settings.  This is only
        # checked in diagnostic builds.
        if wiredtiger.diagnostic_build():
            self.session.begin_transaction(
                'roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError, lambda: self.session.
                prepare_transaction('prepare_timestamp=' + timestamp_str(10)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

            # It is illegal to set the prepare timestamp the same as an active read
            # timestamp even with roundup_timestamps settings.
            self.session.begin_transaction(
                'roundup_timestamps=(prepared=true)')
            self.assertRaisesWithMessage(
                wiredtiger.WiredTigerError, lambda: self.session.
                prepare_transaction('prepare_timestamp=' + timestamp_str(40)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

        # It is illegal to set a commit timestamp less than the prepare
        # timestamp of a transaction.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction('prepare_timestamp=' +
                                         timestamp_str(45))
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            commit_transaction('commit_timestamp=' + timestamp_str(30)),
            "/less than the prepare timestamp/")

        # It is legal to set a commit timestamp older than prepare timestamp of
        # a transaction with roundup_timestamps settings.
        self.session.begin_transaction('roundup_timestamps=(prepared=true)')
        c[1] = 1
        self.session.prepare_transaction('prepare_timestamp=' +
                                         timestamp_str(45))
        self.session.timestamp_transaction('commit_timestamp=' +
                                           timestamp_str(30))
        #self.session.timestamp_transaction('durable_timestamp=' + timestamp_str(30))
        self.assertRaisesWithMessage(
            wiredtiger.WiredTigerError, lambda: self.session.
            timestamp_transaction('durable_timestamp=' + timestamp_str(30)),
            "/is less than the commit timestamp/")
        self.session.rollback_transaction()

        s_reader.commit_transaction()
Esempio n. 26
0
    def test_timestamp_api(self):
        self.session.create(self.uri, 'key_format=i,value_format=i')
        c = self.session.open_cursor(self.uri)

        # It is illegal to set a prepare timestamp older than oldest timestamp.
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(2))
        self.session.begin_transaction()
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.prepare_transaction(
            'prepare_timestamp=' + timestamp_str(1)),
            "/older than the oldest timestamp/")
        self.session.commit_transaction('commit_timestamp=' + timestamp_str(3))

        # Check setting the prepare timestamp same as oldest timestamp is valid.
        self.session.begin_transaction()
        self.session.prepare_transaction('prepare_timestamp=' + timestamp_str(2))
        self.session.timestamp_transaction('commit_timestamp=' + timestamp_str(3))
        self.session.timestamp_transaction('durable_timestamp=' + timestamp_str(3))
        self.session.commit_transaction()

        # In a single transaction it is illegal to set a commit timestamp
        # before invoking prepare for this transaction.
        # Note: Values are not important, setting commit timestamp before
        # prepare itself is illegal.
        self.session.begin_transaction()
        self.session.timestamp_transaction(
            'commit_timestamp=' + timestamp_str(3))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.prepare_transaction(
            'prepare_timestamp=' + timestamp_str(2)),
            "/should not have been set before/")
        self.session.commit_transaction('commit_timestamp=' + timestamp_str(3))

        # It is illegal to set a prepare timestamp same as or earlier than an
        # active read timestamp.
        # Start a new reader to have an active read timestamp.
        if wiredtiger.diagnostic_build():
            s_reader = self.conn.open_session()
            s_reader.begin_transaction('read_timestamp=' + timestamp_str(4))
            self.session.begin_transaction()
            self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                lambda: self.session.prepare_transaction(
                'prepare_timestamp=' + timestamp_str(4)),
                "/must be greater than the latest active read timestamp/")
            self.session.rollback_transaction()

            # Check setting the prepare timestamp as later than active read
            # timestamp is valid.
            self.session.begin_transaction()
            c[1] = 1
            self.session.prepare_transaction(
                    'prepare_timestamp=' + timestamp_str(5))
            # Resolve the reader transaction started earlier.
            s_reader.rollback_transaction()
            self.session.rollback_transaction()

        # It is illegal to set a commit timestamp older than prepare
        # timestamp of a transaction.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction(
                'prepare_timestamp=' + timestamp_str(5))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(
            'commit_timestamp=' + timestamp_str(4)),
            "/less than the prepare timestamp/")

        # It is legal to set a commit timestamp as same as prepare
        # timestamp.
        self.session.begin_transaction()
        c[1] = 1
        self.session.prepare_transaction(
                'prepare_timestamp=' + timestamp_str(5))
        self.session.timestamp_transaction('commit_timestamp=' + timestamp_str(5))
        self.session.timestamp_transaction('durable_timestamp=' + timestamp_str(5))
        self.session.commit_transaction()
Esempio n. 27
0
    def test_alter_inconsistent_update(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        # Create the table without the key consistency checking turned on.
        # Create a few items breaking the rules. Then alter the setting and
        # verify the inconsistent usage is detected.
        uri = 'table:ts'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format))

        c = self.session.open_cursor(uri)
        key = ds.key(10)

        # Insert a data item at timestamp 2.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(2))
        c[key] = ds.value(10)
        self.session.commit_transaction()

        # Update the data item at timestamp 1.
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(1))
        c[key] = ds.value(11)
        self.session.commit_transaction()

        key = ds.key(12)

        # Insert a non-timestamped item, then update with a timestamp and then without a timestamp.
        self.session.begin_transaction()
        c[key] = ds.value(12)
        self.session.commit_transaction()

        self.session.begin_transaction()
        c[key] = ds.value(13)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(2))

        self.session.begin_transaction()
        c[key] = ds.value(14)
        self.session.commit_transaction()

        # Now alter the setting and make sure we detect incorrect usage. We must move the oldest
        # timestamp forward in order to alter, otherwise alter will fail with EBUSY.
        c.close()
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(10))
        self.session.alter(uri, 'write_timestamp_usage=ordered')

        c = self.session.open_cursor(uri)
        key = ds.key(15)

        # Detect decreasing timestamp.
        self.session.begin_transaction()
        c[key] = ds.value(15)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(15))

        msg = '/with an older timestamp/'
        self.session.begin_transaction()
        self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(14))
        c[key] = ds.value(16)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), msg)

        # Detect not using a timestamp.
        msg = '/use timestamps once they are first used/'
        self.session.begin_transaction()
        c[key] = ds.value(17)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), msg)
Esempio n. 28
0
    def test_timestamp_alter(self):
        if wiredtiger.diagnostic_build():
            self.skipTest('requires a non-diagnostic build')

        # Create an object that's never written, it's just used to generate valid k/v pairs.
        ds = SimpleDataSet(
            self, 'file:notused', 10, key_format=self.key_format, value_format=self.value_format)

        cfg_on = 'write_timestamp_usage=ordered'
        cfg_off = 'write_timestamp_usage=none'

        # Create a few items with and without timestamps.
        # Then alter the setting and verify the inconsistent usage is detected.
        uri = 'file:assert06'
        self.session.create(uri,
            'key_format={},value_format={}'.format(self.key_format, self.value_format))
        c = self.session.open_cursor(uri)

        # Insert a data item at timestamp 2.
        key = ds.key(1)
        self.session.begin_transaction()
        c[key] = ds.value(1)
        self.apply_timestamps(2, True)
        self.session.commit_transaction()

        # Modify the data item without a timestamp.
        self.session.begin_transaction('no_timestamp=true')
        c[key] = ds.value(2)
        self.session.commit_transaction()

        # Insert an item without a timestamp.
        # Then modify with a timestamp.
        # Then modify without a timestamp.
        key = ds.key(2)
        self.session.begin_transaction('no_timestamp=true')
        c[key] = ds.value(3)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(4)
        self.apply_timestamps(2, True)
        self.session.commit_transaction()
        self.session.begin_transaction('no_timestamp=true')
        c[key] = ds.value(5)
        self.session.commit_transaction()

        # Now alter the setting and make sure we detect incorrect usage.
        # We must move the oldest timestamp forward in order to alter, otherwise alter closing the
        # file will fail with EBUSY.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(2))
        c.close()
        self.session.alter(uri, cfg_on)
        c = self.session.open_cursor(uri)

        # Update at timestamp 5, then detect not using a timestamp.
        key = ds.key(3)
        self.session.begin_transaction()
        c[key] = ds.value(6)
        self.apply_timestamps(5, True)
        self.session.commit_transaction()
        self.session.begin_transaction()
        c[key] = ds.value(6)
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
            lambda: self.session.commit_transaction(), self.msg_usage)