Esempio n. 1
0
    def test_hs_instantiated_modify(self):
        # Create a small table.
        uri = "table:test_hs06"
        create_params = 'key_format={},value_format=S'.format(self.key_format)
        self.session.create(uri, create_params)

        value1 = 'a' * 500
        value2 = 'b' * 500

        # Load 5Mb of data.
        self.conn.set_timestamp(
            'oldest_timestamp=' + timestamp_str(1) + ',stable_timestamp=' + timestamp_str(1))
        cursor = self.session.open_cursor(uri)
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value1
            self.session.commit_transaction('commit_timestamp=' + timestamp_str(2))

        # Apply three sets of modifies.
        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('B', 100, 1)]), 0)
            self.session.commit_transaction('commit_timestamp=' + timestamp_str(3))

        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('C', 200, 1)]), 0)
            self.session.commit_transaction('commit_timestamp=' + timestamp_str(4))

        # Since the stable timestamp is still at 1, there will be no birthmark record.
        # History store instantiation should choose this update since it is the most recent.
        # We want to check that it gets converted into a standard update as appropriate.
        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('D', 300, 1)]), 0)
            self.session.commit_transaction('commit_timestamp=' + timestamp_str(5))

        # Make a bunch of updates to another table to flush everything out of cache.
        uri2 = 'table:test_hs06_extra'
        self.session.create(uri2, create_params)
        cursor2 = self.session.open_cursor(uri2)
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor2[self.create_key(i)] = value2
            self.session.commit_transaction('commit_timestamp=' + timestamp_str(6))

        expected = list(value1)
        expected[100] = 'B'
        expected[200] = 'C'
        expected[300] = 'D'
        expected = str().join(expected)

        # Go back and read. We should get the initial value with the 3 modifies applied on top.
        self.session.begin_transaction('read_timestamp=' + timestamp_str(5))
        for i in range(1, 11):
            self.assertEqual(cursor[self.create_key(i)], expected)
        self.session.rollback_transaction()
Esempio n. 2
0
    def test_reverse_modifies_constructed_after_eviction(self):
        uri = "table:test_hs13"
        create_params = 'value_format=S,key_format={}'.format(self.key_format)
        value1 = 'a' * 10000
        value2 = 'b' * 10000
        value3 = 'e' * 10000

        self.session.create(uri, create_params)
        cursor = self.session.open_cursor(uri)
        session2 = self.setUpSessionOpen(self.conn)
        cursor2 = session2.open_cursor(uri)

        # Insert a full value.
        self.session.begin_transaction()
        cursor[1] = value1
        self.session.commit_transaction()

        # Insert a modify.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor.modify([wiredtiger.Modify('A', 0, 0)])
        self.session.commit_transaction()

        # Validate that we do see the correct value.
        session2.begin_transaction()
        cursor2.set_key(1)
        cursor2.search()
        self.assertEquals(cursor2.get_value(), 'A' + value1)
        session2.commit_transaction()

        # Reset the cursor.
        cursor2.reset()

        # Begin session2's transaction so it gets a snapshot prior to the full value being
        # inserted below.
        session2.begin_transaction()

        # Insert a second modify.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor.modify([wiredtiger.Modify('B', 1, 0)])
        self.session.commit_transaction()

        # Insert one more value.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor[1] = value2
        self.session.commit_transaction()

        # Insert a whole bunch of data into the table to force wiredtiger to evict data
        # from the previous table.
        self.session.begin_transaction()
        for i in range(2, 10000):
            cursor[i] = value3
        self.session.commit_transaction()

        # Try to find the value we saw earlier.
        cursor2.set_key(1)
        cursor2.search()
        self.assertEquals(cursor2.get_value(), 'A' + value1)
Esempio n. 3
0
    def test_reverse_modifies_constructed_after_eviction(self):
        uri = "table:test_hs13"
        create_params = 'value_format=S,key_format={}'.format(self.key_format)
        value1 = 'a' * 10000
        value2 = 'b' * 10000
        value3 = 'e' * 10000

        self.session.create(uri, create_params)
        cursor = self.session.open_cursor(uri)
        session2 = self.setUpSessionOpen(self.conn)
        cursor2 = session2.open_cursor(uri)

        # Insert a full value.
        self.session.begin_transaction()
        cursor[1] = value1
        self.session.commit_transaction()

        # Insert a modify.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor.modify([wiredtiger.Modify('A', 0, 0)])
        self.session.commit_transaction()

        # Validate that we do see the correct value.
        session2.begin_transaction()
        cursor2.set_key(1)
        cursor2.search()
        self.assertEquals(cursor2.get_value(),  'A' + value1)
        session2.commit_transaction()

        # Reset the cursor.
        cursor2.reset()

        # Begin session2's transaction so it gets a snapshot prior to the full value being
        # inserted below.
        session2.begin_transaction()

        # Insert a second modify.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor.modify([wiredtiger.Modify('B', 1, 0)])
        self.session.commit_transaction()

        # Insert one more value.
        self.session.begin_transaction()
        cursor.set_key(1)
        cursor[1] = value2
        self.session.commit_transaction()

        # Configure debug behavior on a cursor to evict the positioned page on cursor reset
        # and evict the page.
        evict_cursor = self.session.open_cursor(uri, None, "debug=(release_evict)")
        evict_cursor.set_key(1)
        self.assertEquals(evict_cursor.search(), 0)
        evict_cursor.reset()

        # Try to find the value we saw earlier.
        cursor2.set_key(1)
        cursor2.search()
        self.assertEquals(cursor2.get_value(), 'A' + value1)
Esempio n. 4
0
    def test_modify_txn_api(self):
        ds = SimpleDataSet(self,
                           self.uri,
                           100,
                           key_format=self.keyfmt,
                           value_format=self.valuefmt)
        ds.populate()

        c = self.session.open_cursor(self.uri, None)
        c.set_key(ds.key(10))
        msg = '/not supported/'

        self.session.begin_transaction("isolation=read-uncommitted")
        mods = []
        mods.append(wiredtiger.Modify('-', 1, 1))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: c.modify(mods), msg)
        self.session.rollback_transaction()

        self.session.begin_transaction("isolation=read-committed")
        mods = []
        mods.append(wiredtiger.Modify('-', 1, 1))
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: c.modify(mods), msg)
        self.session.rollback_transaction()
Esempio n. 5
0
    def test_hs20(self):
        uri = 'table:test_hs20'
        # Set a very small maximum leaf value to trigger writing overflow values
        self.session.create(uri,
                            'key_format=S,value_format=S,leaf_value_max=10B')
        cursor = self.session.open_cursor(uri)
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(1) +
                                ',stable_timestamp=' + timestamp_str(1))

        value1 = 'a' * 500
        value2 = 'b' * 50

        # Insert a value that is larger than the maximum leaf value.
        for i in range(0, 10):
            self.session.begin_transaction()
            cursor[str(i)] = value1
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(2))

        # Do 2 modifies.
        for i in range(0, 10):
            self.session.begin_transaction()
            cursor.set_key(str(i))
            mods = [wiredtiger.Modify('B', 500, 1)]
            self.assertEqual(cursor.modify(mods), 0)
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(3))

        for i in range(0, 10):
            self.session.begin_transaction()
            cursor.set_key(str(i))
            mods = [wiredtiger.Modify('C', 501, 1)]
            self.assertEqual(cursor.modify(mods), 0)
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(4))

        # Insert more data to trigger eviction.
        for i in range(10, 100000):
            self.session.begin_transaction()
            cursor[str(i)] = value2
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(5))

        # Update the overflow values.
        for i in range(0, 10):
            self.session.begin_transaction()
            cursor[str(i)] = value2
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(5))

        # Do a checkpoint to move the overflow values to the history store but keep the current in memory disk image.
        self.session.checkpoint()

        # Search the first modifies.
        for i in range(0, 10):
            self.session.begin_transaction('read_timestamp=' +
                                           timestamp_str(3))
            self.assertEqual(cursor[str(i)], value1 + "B")
            self.session.rollback_transaction()
Esempio n. 6
0
    def test_hs20(self):
        uri = 'table:test_hs20'
        key_format = 'key_format=' + self.key_format

        # Set a very small maximum leaf value to trigger writing overflow values
        self.session.create(
            uri, '{},value_format=S,leaf_value_max=10B'.format(key_format))
        cursor = self.session.open_cursor(uri)
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(1) +
                                ',stable_timestamp=' + self.timestamp_str(1))

        value1 = 'a' * 500
        value2 = 'b' * 50

        # FIXME-WT-9063 revisit the use of self.retry() throughout this file.

        # Insert a value that is larger than the maximum leaf value.
        for i in range(0, 10):
            for retry in self.retry():
                with retry.transaction(commit_timestamp=2):
                    cursor[self.make_key(i)] = value1

        # Do 2 modifies.
        for i in range(0, 10):
            for retry in self.retry():
                with retry.transaction(commit_timestamp=3):
                    cursor.set_key(self.make_key(i))
                    mods = [wiredtiger.Modify('B', 500, 1)]
                    self.assertEqual(cursor.modify(mods), 0)

        for i in range(0, 10):
            for retry in self.retry():
                with retry.transaction(commit_timestamp=4):
                    cursor.set_key(self.make_key(i))
                    mods = [wiredtiger.Modify('C', 501, 1)]
                    self.assertEqual(cursor.modify(mods), 0)

        # Insert more data to trigger eviction.
        for i in range(10, 100000):
            for retry in self.retry():
                with retry.transaction(commit_timestamp=5):
                    cursor[self.make_key(i)] = value2

        # Update the overflow values.
        for i in range(0, 10):
            for retry in self.retry():
                with retry.transaction(commit_timestamp=5):
                    cursor[self.make_key(i)] = value2

        # Do a checkpoint to move the overflow values to the history store but keep the current in memory disk image.
        self.session.checkpoint()

        # Search the first modifies.
        for i in range(0, 10):
            for retry in self.retry():
                with retry.transaction(read_timestamp=3, rollback=True):
                    self.assertEqual(cursor[self.make_key(i)], value1 + "B")
Esempio n. 7
0
    def test_modify_insert_to_hs(self):
        uri = "table:test_hs10"
        uri2 = "table:test_hs10_otherdata"
        create_params = 'value_format=S,key_format={}'.format(self.key_format)
        value1 = 'a' * 1000
        value2 = 'b' * 1000
        self.session.create(uri, create_params)
        session2 = self.setUpSessionOpen(self.conn)
        session2.create(uri2, create_params)
        cursor2 = session2.open_cursor(uri2)
        # Insert a full value.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(1))
        self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(1))
        cursor = self.session.open_cursor(uri)
        self.session.begin_transaction()
        cursor[1] = value1
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(2))

        # Insert 3 modifies in separate transactions.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('A', 1000, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(3))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('B', 1001, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(4))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('C', 1002, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(5))
        self.session.checkpoint()

        # Insert a whole bunch of data into the other table to force wiredtiger to evict data
        # from the previous table.
        for i in range(1, 10000):
            cursor2[i] = value2

        # Validate that we see the correct value at each of the timestamps.
        self.session.begin_transaction('read_timestamp=' + self.timestamp_str(3))
        cursor.set_key(1)
        cursor.search()
        self.assertEqual(cursor[1], value1 + 'A')
        self.session.commit_transaction()

        cursor2 = self.session.open_cursor(uri)
        self.session.begin_transaction('read_timestamp=' + self.timestamp_str(4))
        cursor2.set_key(1)
        cursor2.search()
        self.assertEqual(cursor2.get_value(), value1 + 'AB')
        self.session.commit_transaction()

        self.session.begin_transaction('read_timestamp=' + self.timestamp_str(5))
        self.assertEqual(cursor[1], value1 + 'ABC')
        self.session.commit_transaction()
Esempio n. 8
0
    def test_hs_multiple_modifies(self):
        # FLCS doesn't support modify, so just skip over this test.
        if self.value_format == '8t':
            return

        # Create a small table.
        uri = "table:test_hs06"
        create_params = 'key_format={},value_format={}'.format(
            self.key_format, self.value_format)
        self.session.create(uri, create_params)

        value1 = 'a' * 500
        value2 = 'b' * 500

        # Load 1Mb of data.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(1))
        cursor = self.session.open_cursor(uri)
        for i in range(1, self.nrows):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value1
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(2))

        # Apply three sets of modifies.
        # They specifically need to be in separate modify calls.
        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('B', 100, 1)]),
                             0)
            self.assertEqual(cursor.modify([wiredtiger.Modify('C', 200, 1)]),
                             0)
            self.assertEqual(cursor.modify([wiredtiger.Modify('D', 300, 1)]),
                             0)
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(3))

        expected = list(value1)
        expected[100] = 'B'
        expected[200] = 'C'
        expected[300] = 'D'
        expected = str().join(expected)

        # Write a newer value on top.
        for i in range(1, self.nrows):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value2
            self.session.commit_transaction('commit_timestamp=' +
                                            self.timestamp_str(4))

        # Go back and read. We should get the initial value with the 3 modifies applied on top.
        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(3))
        for i in range(1, 11):
            self.assertEqual(cursor[self.create_key(i)], expected)
        self.session.rollback_transaction()
Esempio n. 9
0
    def test_modify_abort(self):
        ds = SimpleDataSet(self,
                           self.uri,
                           20,
                           key_format=self.keyfmt,
                           value_format=self.valuefmt)
        ds.populate()

        # Start a transaction.
        self.session.begin_transaction("isolation=snapshot")

        # Insert a new record.
        c = self.session.open_cursor(self.uri, None)
        c.set_key(ds.key(30))
        c.set_value(ds.value(30))
        self.assertEquals(c.insert(), 0)

        # Test that we can successfully modify our own record.
        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)
        c.set_key(ds.key(30))
        mods = self.fix_mods(mods)
        self.assertEqual(c.modify(mods), 0)

        # Test that another transaction cannot modify our uncommitted record.
        xs = self.conn.open_session()
        xc = xs.open_cursor(self.uri, None)
        xs.begin_transaction("isolation=snapshot")
        xc.set_key(ds.key(30))
        xc.set_value(ds.value(30))
        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)
        mods = self.fix_mods(mods)
        xc.set_key(ds.key(30))
        self.assertEqual(xc.modify(mods), wiredtiger.WT_NOTFOUND)
        xs.rollback_transaction()

        # Rollback our transaction.
        self.session.rollback_transaction()

        # Test that we can't modify our aborted insert.
        self.session.begin_transaction("isolation=snapshot")
        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)
        mods = self.fix_mods(mods)
        c.set_key(ds.key(30))
        self.assertEqual(c.modify(mods), wiredtiger.WT_NOTFOUND)
        self.session.rollback_transaction()
Esempio n. 10
0
    def modify_load(self, ds, single):
        # For each test in the list:
        #       set the original value,
        #       apply modifications in order,
        #       confirm the final state
        row = 10
        c = self.session.open_cursor(self.uri, None)
        for i in self.list:
            c.set_key(ds.key(row))
            c.set_value(self.make_value(i['o']))
            self.assertEquals(c.update(), 0)
            c.reset()

            self.session.begin_transaction("isolation=snapshot")
            c.set_key(ds.key(row))
            mods = []
            for j in i['mods']:
                mod = wiredtiger.Modify(j[0], j[1], j[2])
                mods.append(mod)
            mods = self.fix_mods(mods)
            self.assertEquals(c.modify(mods), 0)
            self.session.commit_transaction()
            c.reset()

            c.set_key(ds.key(row))
            self.assertEquals(c.search(), 0)
            v = c.get_value()
            expect = self.make_value(i['f'])
            self.assertEquals(self.nulls_to_spaces(v), expect)

            if not single:
                row = row + 1
        c.close()
Esempio n. 11
0
    def test_apply_modifies_on_onpage_tombstone(self):
        self.session.create(self.uri, 'key_format=S,value_format=S')
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(1))
        cursor = self.session.open_cursor(self.uri)

        value = 'a' * 500
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor[str(i)] = value
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(2))

        # Apply tombstones for every key.
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor.set_key(str(i))
            cursor.remove()
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(3))

        self.session.checkpoint()

        # Now try to apply a modify on top of the tombstone at timestamp 3.
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor.set_key(str(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('B', 0, 100)]),
                             wiredtiger.WT_NOTFOUND)
            self.session.rollback_transaction()

        # Check that the tombstone is visible.
        for i in range(1, 10000):
            cursor.set_key(str(i))
            self.assertEqual(cursor.search(), wiredtiger.WT_NOTFOUND)
Esempio n. 12
0
    def large_modifies(self, uri, value, ds, location, nbytes, nrows, prepare, commit_ts):
        # Load a slight modification.
        session = self.session
        try:
            cursor = session.open_cursor(uri)
            session.begin_transaction()
            for i in range(1, nrows + 1):
                cursor.set_key(i)
                mods = [wiredtiger.Modify(value, location, nbytes)]
                self.assertEqual(cursor.modify(mods), 0)

            if commit_ts == 0:
                session.commit_transaction()
            elif prepare:
                session.prepare_transaction('prepare_timestamp=' + self.timestamp_str(commit_ts-1))
                session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(commit_ts))
                session.timestamp_transaction('durable_timestamp=' + self.timestamp_str(commit_ts+1))
                session.commit_transaction()
            else:
                session.commit_transaction('commit_timestamp=' + self.timestamp_str(commit_ts))
            cursor.close()
        except WiredTigerError as e:
            rollback_str = wiredtiger_strerror(WT_ROLLBACK)
            if rollback_str in str(e):
                session.rollback_transaction()
            raise(e)
Esempio n. 13
0
    def modify_load(self, ds, single):
        # For each test in the list:
        #       set the original value,
        #       apply modifications in order,
        #       confirm the final state
        row = 10
        c = self.session.open_cursor(self.uri, None)
        for i in self.list:
            c.set_key(ds.key(row))
            c.set_value(i['o'])
            self.assertEquals(c.update(), 0)
            c.reset()

            c.set_key(ds.key(row))
            mods = []
            for j in i['mods']:
                mod = wiredtiger.Modify(j[0], j[1], j[2])
                mods.append(mod)
            self.assertEquals(c.modify(mods), 0)
            c.reset()

            c.set_key(ds.key(row))
            self.assertEquals(c.search(), 0)
            v = c.get_value()
            self.assertEquals(v.replace("\x00", " "), i['f'])

            if not single:
                row = row + 1
        c.close()
Esempio n. 14
0
    def large_modifies(self, uri, value, ds, location, nbytes, nrows, prepare,
                       commit_ts):
        # Load a slight modification.
        session = self.session
        cursor = session.open_cursor(uri)
        session.begin_transaction()
        for i in range(1, nrows + 1):
            cursor.set_key(i)
            mods = [wiredtiger.Modify(value, location, nbytes)]
            self.assertEqual(cursor.modify(mods), 0)

        if commit_ts == 0:
            session.commit_transaction()
        elif prepare:
            session.prepare_transaction('prepare_timestamp=' +
                                        timestamp_str(commit_ts - 1))
            session.timestamp_transaction('commit_timestamp=' +
                                          timestamp_str(commit_ts))
            session.timestamp_transaction('durable_timestamp=' +
                                          timestamp_str(commit_ts + 1))
            session.commit_transaction()
        else:
            session.commit_transaction('commit_timestamp=' +
                                       timestamp_str(commit_ts))
        cursor.close()
Esempio n. 15
0
    def test_modify_many(self):
        ds = SimpleDataSet(self,
                           self.uri,
                           20,
                           key_format=self.keyfmt,
                           value_format=self.valuefmt)
        ds.populate()

        c = self.session.open_cursor(self.uri, None)
        self.session.begin_transaction("isolation=snapshot")
        c.set_key(ds.key(10))
        orig = self.make_value('abcdefghijklmnopqrstuvwxyz')
        c.set_value(orig)
        self.assertEquals(c.update(), 0)
        for i in range(0, 50000):
            new = self.make_value("".join([random.choice(string.digits) \
                for i in range(5)]))
            orig = orig[:10] + new + orig[15:]
            mods = []
            mod = wiredtiger.Modify(new, 10, 5)
            mods.append(mod)
            mods = self.fix_mods(mods)
            self.assertEquals(c.modify(mods), 0)
        self.session.commit_transaction()

        c.set_key(ds.key(10))
        self.assertEquals(c.search(), 0)
        self.assertEquals(c.get_value(), orig)
Esempio n. 16
0
 def large_modifies(self, uri, value, ds, location, nbytes, nrows, commit_ts):
     # Load a slight modification.
     session = self.session
     cursor = session.open_cursor(uri)
     session.begin_transaction()
     for i in range(0, nrows):
         cursor.set_key(i)
         mods = [wiredtiger.Modify(value, location, nbytes)]
         self.assertEqual(cursor.modify(mods), 0)
     session.commit_transaction('commit_timestamp=' + self.timestamp_str(commit_ts))
     cursor.close()
 def fix_mods(self, mods):
     if bytes != str and self.valuefmt == 'u':
         # In Python3, bytes and strings are independent types, and
         # the WiredTiger API needs bytes when the format calls for bytes.
         newmods = []
         for mod in mods:
             # We need to check because we may converted some of the Modify
             # records already.
             if type(mod.data) == str:
                 newmods.append(wiredtiger.Modify(
                     self.make_value(mod.data), mod.offset, mod.size))
             else:
                 newmods.append(mod)
         mods = newmods
     return mods
Esempio n. 18
0
    def test_modify_delete(self):
        self.session.create(self.uri, 'key_format=S,value_format=u')
        cursor = self.session.open_cursor(self.uri, None, None)
        cursor['ABC'] = 'ABCDEFGH'
        cursor.set_key('ABC')
        cursor.remove()

        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)

        cursor.set_key('ABC')
        #self.assertEqual(cursor.modify(mods), wiredtiger.WT_NOTFOUND)
        self.assertRaises(wiredtiger.WiredTigerError,
                          lambda: cursor.modify(mods))
Esempio n. 19
0
    def test_modify_delete(self):
        ds = SimpleDataSet(self,
            self.uri, 20, key_format=self.keyfmt, value_format=self.valuefmt)
        ds.populate()

        c = self.session.open_cursor(self.uri, None)
        c.set_key(ds.key(10))
        self.assertEquals(c.remove(), 0)

        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)

        c.set_key(ds.key(10))
        self.assertEqual(c.modify(mods), wiredtiger.WT_NOTFOUND)
Esempio n. 20
0
    def large_modifies(self, session, uri, offset, ds, nrows, timestamp=False):
        # Modify a large number of records, we'll hang if the history store table
        # isn't doing its thing.
        cursor = session.open_cursor(uri)
        for i in range(1, 10000):
            if timestamp == True:
                session.begin_transaction()
            cursor.set_key(ds.key(nrows + i))
            mods = []
            mod = wiredtiger.Modify('A', offset, 1)
            mods.append(mod)

            self.assertEqual(cursor.modify(mods), 0)
            if timestamp == True:
                session.commit_transaction('commit_timestamp=' + timestamp_str(i + 1))
        cursor.close()
    def test_modify_delete(self):
        ds = SimpleDataSet(self,
            self.uri, 20, key_format=self.keyfmt, value_format=self.valuefmt)
        ds.populate()

        c = self.session.open_cursor(self.uri, None)
        c.set_key(ds.key(10))
        self.assertEquals(c.remove(), 0)

        self.session.begin_transaction("isolation=snapshot")
        mods = []
        mod = wiredtiger.Modify('ABCD', 3, 3)
        mods.append(mod)
        mods = self.fix_mods(mods)

        c.set_key(ds.key(10))
        self.assertEqual(c.modify(mods), wiredtiger.WT_NOTFOUND)
        self.session.commit_transaction()
Esempio n. 22
0
    def large_modifies(self, session, uri, offset, ds, nrows, timestamp=False):
        cursor = session.open_cursor(uri)
        for i in range(1, nrows):
            # Unlike inserts and updates, modify operations do not implicitly start/commit a transaction.
            # Hence, we begin/commit transaction manually.
            session.begin_transaction()
            cursor.set_key(ds.key(i))
            mods = []
            mod = wiredtiger.Modify('A', offset, 1)
            mods.append(mod)
            self.assertEqual(cursor.modify(mods), 0)

            if timestamp == True:
                session.commit_transaction('commit_timestamp=' +
                                           self.timestamp_str(i + 1))
            else:
                session.commit_transaction()
        cursor.close()
Esempio n. 23
0
    def test_insert_hs_full_update(self):
        uri = 'table:test_hs28'
        self.session.create(
            uri, 'key_format={},value_format=S'.format(self.key_format))

        value1 = "a"
        value2 = "b"

        cursor = self.session.open_cursor(uri)
        # Insert a full value
        self.session.begin_transaction()
        cursor[1] = value1
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(2))

        # Do a modify update
        self.session.begin_transaction()
        cursor.set_key(1)
        mods = [wiredtiger.Modify('A', 0, 1)]
        self.assertEqual(cursor.modify(mods), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(5))

        # Commit a transaction with multiple updates on the same key
        self.session.begin_transaction()
        cursor[1] = value1
        cursor[1] = value2
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(10))

        # Move the updates to the history store
        self.session.checkpoint()

        stat_cursor = self.session.open_cursor('statistics:', None, None)
        hs_full_update = stat_cursor[
            wiredtiger.stat.conn.cache_hs_insert_full_update][2]
        hs_reverse_modify = stat_cursor[
            wiredtiger.stat.conn.cache_hs_insert_reverse_modify][2]
        stat_cursor.close()

        self.assertEqual(hs_full_update, 2)
        self.assertEqual(hs_reverse_modify, 0)
Esempio n. 24
0
    def test_modify_many(self):
        ds = SimpleDataSet(self,
            self.uri, 20, key_format=self.keyfmt, value_format=self.valuefmt)
        ds.populate()

        c = self.session.open_cursor(self.uri, None)
        c.set_key(ds.key(10))
        orig = 'abcdefghijklmnopqrstuvwxyz'
        c.set_value(orig)
        self.assertEquals(c.update(), 0)
        for i in range(0, 50000):
            new = "".join([random.choice(string.digits) for i in xrange(5)])
            orig = orig[:10] + new + orig[15:]
            mods = []
            mod = wiredtiger.Modify(new, 10, 5)
            mods.append(mod)
            self.assertEquals(c.modify(mods), 0)

        c.set_key(ds.key(10))
        self.assertEquals(c.search(), 0)
        self.assertEquals(c.get_value(), orig)
Esempio n. 25
0
    def test_flcs(self):
        uri = "table:test_flcs04"
        nrows = 10
        ds = SimpleDataSet(self,
                           uri,
                           nrows,
                           key_format='r',
                           value_format='6t',
                           config='leaf_page_max=4096')
        ds.populate()

        cursor = self.session.open_cursor(uri)
        self.session.begin_transaction()

        cursor.set_key(5)
        mods = [wiredtiger.Modify('Q', 100, 1)]
        self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
                                     lambda: cursor.modify(mods),
                                     "/WT_CURSOR.modify only supported for/")

        self.session.rollback_transaction()
        cursor.close()
Esempio n. 26
0
    def large_modifies(self, uri, value, ds, location, nbytes, nrows, prepare,
                       commit_ts):
        # Load a slight modification.
        session = self.session
        try:
            cursor = session.open_cursor(uri)
            session.begin_transaction()
            for i in range(1, nrows + 1):
                cursor.set_key(i)
                # FLCS doesn't support modify (for obvious reasons) so just update.
                # Use the first character of the passed-in value.
                if self.value_format == '8t':
                    cursor.set_value(bytes(value, encoding='utf-8')[0])
                    self.assertEqual(cursor.update(), 0)
                else:
                    mods = [wiredtiger.Modify(value, location, nbytes)]
                    self.assertEqual(cursor.modify(mods), 0)

            if commit_ts == 0:
                session.commit_transaction()
            elif prepare:
                session.prepare_transaction('prepare_timestamp=' +
                                            self.timestamp_str(commit_ts - 1))
                session.timestamp_transaction('commit_timestamp=' +
                                              self.timestamp_str(commit_ts))
                session.timestamp_transaction('durable_timestamp=' +
                                              self.timestamp_str(commit_ts +
                                                                 1))
                session.commit_transaction()
            else:
                session.commit_transaction('commit_timestamp=' +
                                           self.timestamp_str(commit_ts))
            cursor.close()
        except WiredTigerError as e:
            rollback_str = wiredtiger_strerror(WT_ROLLBACK)
            if rollback_str in str(e):
                session.rollback_transaction()
            raise (e)
Esempio n. 27
0
    def large_modifies(self, session, uri, offset, ds, nrows, timestamp=False):
        cursor = session.open_cursor(uri)
        for i in range(1, nrows):
            # Unlike inserts and updates, modify operations do not implicitly start/commit a transaction.
            # Hence, we begin/commit transaction manually.
            session.begin_transaction()
            cursor.set_key(ds.key(i))

            # FLCS doesn't allow modify (it doesn't make sense) so just update to 'j' then 'k'.
            if self.value_format == '8t':
                cursor.set_value(106 + offset)
                self.assertEqual(cursor.update(), 0)
            else:
                mods = []
                mod = wiredtiger.Modify('A', offset, 1)
                mods.append(mod)
                self.assertEqual(cursor.modify(mods), 0)

            if timestamp == True:
                session.commit_transaction('commit_timestamp=' +
                                           self.timestamp_str(i + 1))
            else:
                session.commit_transaction()
        cursor.close()
Esempio n. 28
0
    def test_modify_insert_to_hs(self):
        uri = "table:test_hs08"
        create_params = 'value_format=S,key_format={}'.format(self.key_format)
        value1 = 'a' * 1000
        self.session.create(uri, create_params)

        # Insert a full value.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(1))
        cursor = self.session.open_cursor(uri)
        self.session.begin_transaction()
        cursor[1] = value1
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(2))

        # Insert 3 modifies in separate transactions.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('A', 1000, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(3))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('B', 1001, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(4))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('C', 1002, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(5))

        # Call checkpoint.
        self.session.checkpoint('use_timestamp=true')

        # Validate that we did write at least once to the history store.
        hs_writes = self.get_stat(stat.conn.cache_write_hs)
        squashed_write = self.get_stat(stat.conn.cache_hs_write_squash)
        self.assertGreaterEqual(hs_writes, 1)
        self.assertEqual(squashed_write, 0)

        # Validate that we see the correct value at each of the timestamps.
        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(3))
        self.assertEqual(cursor[1], value1 + 'A')
        self.session.commit_transaction()

        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(4))
        self.assertEqual(cursor[1], value1 + 'AB')
        self.session.commit_transaction()

        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(5))
        self.assertEqual(cursor[1], value1 + 'ABC')
        self.session.commit_transaction()

        # Insert another two modifies. When we call checkpoint the first modify
        # will get written to the data store as a full value and the second will
        # be written to the data store as a reverse delta.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('D', 1000, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(7))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('E', 1001, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(8))

        # Call checkpoint again.
        self.session.checkpoint('use_timestamp=true')

        # Validate that we wrote to the history store again.
        hs_writes = self.get_stat(stat.conn.cache_write_hs)
        squashed_write = self.get_stat(stat.conn.cache_hs_write_squash)
        self.assertGreaterEqual(hs_writes, 2)
        self.assertEqual(squashed_write, 0)

        # Validate that we see the expected value on the modifies, this
        # scenario tests the logic that will retrieve a full value for
        # a modify previously inserted into the history store.
        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(7))
        self.assertEqual(cursor[1], value1 + 'DBC')
        self.session.commit_transaction()

        self.session.begin_transaction('read_timestamp=' +
                                       self.timestamp_str(8))
        self.assertEqual(cursor[1], value1 + 'DEC')
        self.session.commit_transaction()

        # Insert multiple modifies in the same transaction the first two should be squashed.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('F', 1002, 1)]), 0)
        self.assertEqual(cursor.modify([wiredtiger.Modify('G', 1003, 1)]), 0)
        self.assertEqual(cursor.modify([wiredtiger.Modify('H', 1004, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(9))

        # Call checkpoint again.
        self.session.checkpoint('use_timestamp=true')

        # Validate that we squashed two modifies. Note we can't count the exact number
        # we squashed, just that we did squash.
        hs_writes = self.get_stat(stat.conn.cache_write_hs)
        squashed_write = self.get_stat(stat.conn.cache_hs_write_squash)
        self.assertGreaterEqual(hs_writes, 3)
        self.assertEqual(squashed_write, 1)

        # Insert multiple modifies in two different transactions so we should squash two.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('F', 1002, 1)]), 0)
        self.assertEqual(cursor.modify([wiredtiger.Modify('G', 1003, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(10))

        self.session.begin_transaction()
        cursor.set_key(1)
        self.assertEqual(cursor.modify([wiredtiger.Modify('F', 1002, 1)]), 0)
        self.assertEqual(cursor.modify([wiredtiger.Modify('G', 1003, 1)]), 0)
        self.session.commit_transaction('commit_timestamp=' +
                                        self.timestamp_str(11))

        # Call checkpoint again.
        self.session.checkpoint('use_timestamp=true')

        # Validate that we squashed two modifies. We also squashed a modify that was previously
        # squashed hence the number actually goes up by three.
        hs_writes = self.get_stat(stat.conn.cache_write_hs)
        squashed_write = self.get_stat(stat.conn.cache_hs_write_squash)
        self.assertGreaterEqual(hs_writes, 4)
        self.assertEqual(squashed_write, 4)

        # Insert multiple modifies in different transactions with different timestamps on each
        # modify to guarantee we squash zero modifies.
        self.session.begin_transaction()
        cursor.set_key(1)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(12))
        self.assertEqual(cursor.modify([wiredtiger.Modify('F', 1002, 1)]), 0)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(13))
        self.assertEqual(cursor.modify([wiredtiger.Modify('G', 1003, 1)]), 0)
        self.session.commit_transaction()

        self.session.begin_transaction()
        cursor.set_key(1)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(14))
        self.assertEqual(cursor.modify([wiredtiger.Modify('F', 1002, 1)]), 0)
        self.session.timestamp_transaction('commit_timestamp=' +
                                           self.timestamp_str(15))
        self.assertEqual(cursor.modify([wiredtiger.Modify('G', 1003, 1)]), 0)
        self.session.commit_transaction()

        # Call checkpoint again.
        self.session.checkpoint('use_timestamp=true')

        # Validate that we squashed zero modifies.
        hs_writes = self.get_stat(stat.conn.cache_write_hs)
        squashed_write = self.get_stat(stat.conn.cache_hs_write_squash)
        self.assertGreaterEqual(hs_writes, 5)
        self.assertEqual(squashed_write, 5)
Esempio n. 29
0
    def test_hs15(self):
        uri = 'table:test_hs15'
        self.session.create(
            uri, 'key_format={},value_format=S'.format(self.key_format))
        cursor = self.session.open_cursor(uri)

        value1 = 'a' * 500
        value2 = 'b' * 500
        value3 = 'c' * 500

        # Insert an update without timestamp
        self.session.begin_transaction()
        cursor[self.create_key(1)] = value1
        self.session.commit_transaction()

        # Insert a bunch of other contents to trigger eviction
        for i in range(2, 1000):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value2
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(3))

        # Do a modify and an update with timestamps
        self.session.begin_transaction()
        cursor.set_key(self.create_key(1))
        mods = [wiredtiger.Modify('B', 100, 1)]
        self.assertEqual(cursor.modify(mods), 0)
        self.session.commit_transaction('commit_timestamp=' + timestamp_str(1))

        self.session.begin_transaction()
        cursor[self.create_key(1)] = value2
        self.session.commit_transaction('commit_timestamp=' + timestamp_str(2))

        # Make the modify with timestamp and the update without timestamp obsolete
        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(1))

        # Do a checkpoint
        self.session.checkpoint()

        self.session.begin_transaction()
        cursor[self.create_key(1)] = value3
        self.session.commit_transaction('commit_timestamp=' + timestamp_str(3))

        # Insert a bunch of other contents to trigger eviction
        for i in range(2, 1000):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value3
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(3))

        expected = list(value1)
        expected[100] = 'B'
        expected = str().join(expected)
        self.session.begin_transaction('read_timestamp=' + timestamp_str(1))
        self.assertEqual(cursor[self.create_key(1)], expected)
        self.session.rollback_transaction()

        self.session.begin_transaction('read_timestamp=' + timestamp_str(2))
        self.assertEqual(cursor[self.create_key(1)], value2)
        self.session.rollback_transaction()

        self.session.begin_transaction('read_timestamp=' + timestamp_str(3))
        self.assertEqual(cursor[self.create_key(1)], value3)
        self.session.rollback_transaction()
Esempio n. 30
0
    def test_hs_rec_modify(self):
        # Create a small table.
        uri = "table:test_hs06"
        create_params = 'key_format={},value_format=S'.format(self.key_format)
        self.session.create(uri, create_params)

        value1 = 'a' * 500
        value2 = 'b' * 500

        self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(1) +
                                ',stable_timestamp=' + timestamp_str(1))
        cursor = self.session.open_cursor(uri)

        # Base update.
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value1
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(2))

        # Apply three sets of modifies.
        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('B', 100, 1)]),
                             0)
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(3))

        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('C', 200, 1)]),
                             0)
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(4))

        # This is the one we want to be selected by the checkpoint.
        for i in range(1, 11):
            self.session.begin_transaction()
            cursor.set_key(self.create_key(i))
            self.assertEqual(cursor.modify([wiredtiger.Modify('D', 300, 1)]),
                             0)
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(5))

        # Apply another update and evict the pages with the modifies out of cache.
        for i in range(1, 10000):
            self.session.begin_transaction()
            cursor[self.create_key(i)] = value2
            self.session.commit_transaction('commit_timestamp=' +
                                            timestamp_str(6))

        # Checkpoint such that the modifies will be selected. When we grab it from the history
        # store, we'll need to unflatten it before using it for reconciliation.
        self.conn.set_timestamp('stable_timestamp=' + timestamp_str(5))
        self.session.checkpoint()

        expected = list(value1)
        expected[100] = 'B'
        expected[200] = 'C'
        expected[300] = 'D'
        expected = str().join(expected)

        # Check that the correct value is visible after checkpoint.
        self.session.begin_transaction('read_timestamp=' + timestamp_str(5))
        for i in range(1, 11):
            self.assertEqual(cursor[self.create_key(i)], expected)
        self.session.rollback_transaction()