Package com.taobao.metamorphosis.server.transaction.store

Source Code of com.taobao.metamorphosis.server.transaction.store.JournalTransactionStoreUnitTest

/*
* (C) 2007-2012 Alibaba Group Holding Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Authors:
*   wuhua <wq163@163.com> , boyan <killme2008@gmail.com>
*/
package com.taobao.metamorphosis.server.transaction.store;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.io.FileUtils;
import org.junit.Test;

import com.taobao.metamorphosis.Message;
import com.taobao.metamorphosis.consumer.MessageIterator;
import com.taobao.metamorphosis.exception.InvalidMessageException;
import com.taobao.metamorphosis.network.PutCommand;
import com.taobao.metamorphosis.server.store.FileMessageSet;
import com.taobao.metamorphosis.server.store.MessageStore;
import com.taobao.metamorphosis.server.transaction.BaseTransactionUnitTest;
import com.taobao.metamorphosis.server.transaction.TransactionRecoveryListener;
import com.taobao.metamorphosis.server.transaction.store.JournalTransactionStore.Tx;
import com.taobao.metamorphosis.server.utils.XIDGenerator;
import com.taobao.metamorphosis.transaction.LocalTransactionId;
import com.taobao.metamorphosis.transaction.XATransactionId;
import com.taobao.metamorphosis.utils.test.ConcurrentTestCase;
import com.taobao.metamorphosis.utils.test.ConcurrentTestTask;


public class JournalTransactionStoreUnitTest extends BaseTransactionUnitTest {

    @Test
    public void testAddAddRollBackCloseRecover() throws Exception {
        final LocalTransactionId xid = new LocalTransactionId("test", 1);
        final MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2), null);

        final Tx tx = this.transactionStore.getInflyTx(xid);
        assertNotNull(tx);
        final PutCommand[] commands = tx.getRequests();
        assertNotNull(commands);
        assertEquals(2, commands.length);
        store.flush();
        // ��û��д��
        assertEquals(0, store.getSizeInBytes());

        // rollback
        this.transactionStore.rollback(xid);
        assertNull(this.transactionStore.getInflyTx(xid));
        store.flush();
        // �ع�����Ȼû��д��
        assertEquals(0, store.getSizeInBytes());

        this.tearDown();
        this.init(this.path);
        assertTrue(this.journalStore.getCurrDataFile().getLength() > 0);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertEquals(0, this.messageStoreManager.getOrCreateMessageStore("topic1", 2).getSizeInBytes());

    }


    @Test
    public void testAddAddCloseRecover() throws Exception {
        final LocalTransactionId xid1 = new LocalTransactionId("test", 1);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid1, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid1, 0, 2), null);

        final LocalTransactionId xid2 = new LocalTransactionId("test", 2);
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid2, 0, 1), null);

        this.tearDown();
        this.init(this.path);
        assertTrue(this.journalStore.getCurrDataFile().getLength() > 0);

        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        // ȷ����Ϣû��д��
        assertEquals(0, store.getSizeInBytes());

        // ȷ��TX������
        final Tx tx1 = this.transactionStore.getInflyTx(xid1);
        assertNotNull(tx1);
        PutCommand[] commands = tx1.getRequests();
        assertNotNull(commands);
        assertEquals(2, commands.length);

        final Tx tx2 = this.transactionStore.getInflyTx(xid2);
        assertNotNull(tx2);
        commands = tx2.getRequests();
        assertNotNull(commands);
        assertEquals(1, commands.length);

        // recover�󣬶��ع���
        this.transactionStore.recover(null);
        assertNull(this.transactionStore.getInflyTx(xid1));
        assertNull(this.transactionStore.getInflyTx(xid2));
        // ȷ����Ϣ����û��д��
        assertEquals(0, store.getSizeInBytes());
    }


    @Test
    public void testAddAddCommitCloseRecover() throws Exception {
        final LocalTransactionId xid = new LocalTransactionId("test", 1);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2), null);

        final Tx tx = this.transactionStore.getInflyTx(xid);
        assertNotNull(tx);
        final PutCommand[] commands = tx.getRequests();
        assertNotNull(commands);
        assertEquals(2, commands.length);
        store.flush();
        // ��û��д��
        assertEquals(0, store.getSizeInBytes());

        // rollback
        this.transactionStore.commit(xid, false);
        assertNull(this.transactionStore.getInflyTx(xid));
        store.flush();
        // д����Ϣ
        assertTrue(store.getSizeInBytes() > 0);

        this.tearDown();
        this.init(this.path);
        assertTrue(this.journalStore.getCurrDataFile().getLength() > 0);
        assertNull(this.transactionStore.getInflyTx(xid));

        // ���´�store
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.assertMessages(store);
    }


    private void assertMessages(final MessageStore store) throws IOException, InvalidMessageException {
        final FileMessageSet msgSet = (FileMessageSet) store.slice(0, 1024);
        final ByteBuffer buf = ByteBuffer.allocate((int) msgSet.getSizeInBytes());
        msgSet.read(buf, 0);
        final MessageIterator it = new MessageIterator("topic1", buf.array());
        int count = 0;
        while (it.hasNext()) {
            final Message msg = it.next();
            assertTrue(new String(msg.getData()).startsWith("msg"));
            count++;
        }
        assertEquals(2, count);
    }


    @Test
    public void testBeginCommitCloseRecover() throws Exception {
        final LocalTransactionId xid = new LocalTransactionId("test", 1);
        this.transactionStore.commit(xid, false);
        assertNull(this.transactionStore.getInflyTx(xid));
        this.tearDown();
        this.init(this.path);
        assertNull(this.transactionStore.getInflyTx(xid));
    }


    @Test
    public void testAddAddPrepareCommitCloseRecover() throws Exception {
        final XATransactionId xid = XIDGenerator.createXID(99);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2), null);
        assertNotNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));
        // prepare
        this.transactionStore.prepare(xid);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNotNull(this.transactionStore.getPreparedTx(xid));
        store.flush();
        // ȷ�ϻ�δд��
        assertEquals(0, store.getSizeInBytes());

        // commit
        this.transactionStore.commit(xid, true);
        store.flush();
        assertTrue(store.getSizeInBytes() > 0);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));

        // close and reopen
        this.tearDown();
        this.init(this.path);
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        assertTrue(store.getSizeInBytes() > 0);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));
        this.assertMessages(store);

    }


    @Test
    public void testAddAddPrepareRollbackCloseRecover() throws Exception {
        final XATransactionId xid = XIDGenerator.createXID(99);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2), null);
        assertNotNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));
        // prepare
        this.transactionStore.prepare(xid);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNotNull(this.transactionStore.getPreparedTx(xid));
        store.flush();
        // ȷ�ϻ�δд��
        assertEquals(0, store.getSizeInBytes());

        // rollback
        this.transactionStore.rollback(xid);
        store.flush();
        assertEquals(0, store.getSizeInBytes());
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));

        // close and reopen
        this.tearDown();
        this.init(this.path);
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        assertEquals(0, store.getSizeInBytes());
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNull(this.transactionStore.getPreparedTx(xid));

    }


    @Test
    public void testAddAddPrepareCloseRecover() throws Exception {
        final XATransactionId xid = XIDGenerator.createXID(99);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        final PutCommand cmd1 = new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1);
        this.transactionStore.addMessage(store, 1, cmd1, null);
        final PutCommand cmd2 = new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2);
        this.transactionStore.addMessage(store, 1, cmd2, null);

        // prepare
        this.transactionStore.prepare(xid);
        assertNull(this.transactionStore.getInflyTx(xid));
        assertNotNull(this.transactionStore.getPreparedTx(xid));
        store.flush();
        // ȷ�ϻ�δд��
        assertEquals(0, store.getSizeInBytes());

        // close and reopen
        this.tearDown();
        this.init(this.path);
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        assertEquals(0, store.getSizeInBytes());
        assertNull(this.transactionStore.getInflyTx(xid));
        // ��Ȼ����prepare״̬
        assertNotNull(this.transactionStore.getPreparedTx(xid));
        // ȷ�ϲ�������
        final Tx tx = this.transactionStore.getPreparedTx(xid);
        assertNotNull(tx);
        final PutCommand[] commands = tx.getRequests();
        assertNotNull(commands);
        assertEquals(2, commands.length);
        for (final PutCommand cmd : commands) {
            assertTrue(cmd.equals(cmd1) || cmd.equals(cmd2));
        }

        // recover
        this.transactionStore.recover(new TransactionRecoveryListener() {

            @Override
            public void recover(final XATransactionId id, final PutCommand[] addedMessages) {
                assertEquals(xid, id);
                assertArrayEquals(commands, addedMessages);

            }
        });
    }


    @Test
    public void testCheckpoint() throws Exception {
        // ����1
        final LocalTransactionId xid1 = new LocalTransactionId("session1", 1);
        final MessageStore store1 = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store1, 1, new PutCommand("topic1", 2, ("msg" + 2).getBytes(), xid1, 0, 1),
            null);

        // ����2
        final LocalTransactionId xid2 = new LocalTransactionId("session2", 1);
        final MessageStore store2 = this.messageStoreManager.getOrCreateMessageStore("topic1", 3);
        this.transactionStore.addMessage(store2, 1, new PutCommand("topic1", 3, ("msg" + 3).getBytes(), xid2, 0, 1),
            null);

        // ����3���Ѿ��ύ
        final LocalTransactionId xid3 = new LocalTransactionId("session3", 1);
        final MessageStore store3 = this.messageStoreManager.getOrCreateMessageStore("topic1", 0);
        this.transactionStore.addMessage(store3, 1, new PutCommand("topic1", 0, ("msg" + 0).getBytes(), xid3, 0, 1),
            null);
        this.transactionStore.commit(xid3, false);

        // ����checkpoint��Ӧ��Ϊ����1
        final JournalLocation location = this.transactionStore.checkpoint();
        final Tx tx = this.transactionStore.getInflyTx(xid1);
        assertEquals(location, tx.getLocation());
    }


    @Test
    public void concurrentTest() throws Exception {
        final Random rand = new Random();
        final AtomicInteger gen = new AtomicInteger();
        final ConcurrentTestCase testCase = new ConcurrentTestCase(100, 1000, new ConcurrentTestTask() {

            @Override
            public void run(final int index, final int times) throws Exception {
                final int id = gen.incrementAndGet();
                final LocalTransactionId xid = new LocalTransactionId("test", id);
                for (int j = 0; j < rand.nextInt(3) + 1; j++) {
                    final int partition = rand.nextInt(10);
                    final MessageStore store =
                            JournalTransactionStoreUnitTest.this.messageStoreManager.getOrCreateMessageStore("topic1",
                                partition % 10);
                    JournalTransactionStoreUnitTest.this.transactionStore.addMessage(store, 1, new PutCommand("topic1",
                        partition, ("msg" + id).getBytes(), xid, 0, 1), null);
                }
                if (id % 100 == 0) {
                    JournalTransactionStoreUnitTest.this.journalStore.checkpoint();
                }
                // commit
                JournalTransactionStoreUnitTest.this.transactionStore.commit(xid, false);

            }
        });

        testCase.start();

        System.out.println("����ʱ�䣺" + testCase.getDurationInMillis() + "ms");

        for (int i = 0; i < 10; i++) {
            final MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", i);
            assertTrue(store.getSizeInBytes() > 0);
        }
        assertEquals(0, this.transactionStore.getActiveTransactionCount());

        // �رմ�
        this.tearDown();
        final long start = System.currentTimeMillis();
        this.init(this.path);
        System.out.println("�ָ�����ʱ��:" + (System.currentTimeMillis() - start) + "ms");
        for (int i = 0; i < 10; i++) {
            final MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", i);
            assertTrue(store.getSizeInBytes() > 0);
        }
        assertEquals(0, this.transactionStore.getActiveTransactionCount());
    }


    @Test
    public void testAddManyRollJournal() throws Exception {
        final Random rand = new Random();
        this.tearDown();
        final int oldSize = JournalStore.MAX_FILE_SIZE;
        JournalStore.MAX_FILE_SIZE = 512;
        try {
            this.init(this.path);
            for (int i = 0; i < 10000; i++) {
                final LocalTransactionId xid = new LocalTransactionId("test", i);
                // �漴��Ӽ�����Ϣ
                for (int j = 0; j < rand.nextInt(3) + 1; j++) {
                    final int partition = rand.nextInt(10);
                    final MessageStore store =
                            this.messageStoreManager.getOrCreateMessageStore("topic1", partition % 10);
                    this.transactionStore.addMessage(store, 1,
                        new PutCommand("topic1", partition, ("msg" + i).getBytes(), xid, 0, 1), null);
                }
                // commit
                this.transactionStore.commit(xid, false);

            }
            // ȷ���ļ�roll��
            assertTrue(this.journalStore.getCurrDataFile().getNumber() > 1);
            assertEquals(1, this.journalStore.getDataFiles().size());
        }
        finally {
            JournalStore.MAX_FILE_SIZE = oldSize;
        }

    }


    @Test
    public void testAddManyCheckpointRecover() throws Exception {
        final Random rand = new Random();
        for (int i = 0; i < 10000; i++) {
            final LocalTransactionId xid = new LocalTransactionId("test", i);

            // �漴��Ӽ�����Ϣ
            for (int j = 0; j < rand.nextInt(3) + 1; j++) {
                final int partition = rand.nextInt(10);
                final MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", partition % 10);
                this.transactionStore.addMessage(store, 1, new PutCommand("topic1", partition, ("msg" + i).getBytes(),
                    xid, 0, 1), null);
            }
            if (i % 100 == 0) {
                this.journalStore.checkpoint();
            }
            // commit
            this.transactionStore.commit(xid, false);
            if (i % 77 == 0) {
                this.journalStore.checkpoint();
            }
        }

        // �رմ�
        this.tearDown();
        final long start = System.currentTimeMillis();
        this.init(this.path);
        System.out.println("�ָ�����ʱ��:" + (System.currentTimeMillis() - start));
        for (int i = 0; i < 10; i++) {
            final MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", i);
            assertTrue(store.getSizeInBytes() > 0);
        }
        assertEquals(0, this.transactionStore.getActiveTransactionCount());
    }


    @Test
    public void testAddAddCommit_CloseReplayAppend_CloseRecover() throws Exception {
        final LocalTransactionId xid = new LocalTransactionId("test", 1);
        MessageStore store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg1".getBytes(), xid, 0, 1), null);
        this.transactionStore.addMessage(store, 1, new PutCommand("topic1", 2, "msg2".getBytes(), xid, 0, 2), null);
        assertNotNull(this.transactionStore.getInflyTx(xid));

        // commit
        this.transactionStore.commit(xid, false);
        store.flush();
        final long sizeInBytes = store.getSizeInBytes();
        assertTrue(sizeInBytes > 0);
        this.assertMessages(store);

        this.tearDown();
        // delete data
        System.out.println("ɾ��Ŀ¼:" + this.path + File.separator + store.getDescription());
        FileUtils.deleteDirectory(new File(this.path + File.separator + store.getDescription()));
        this.init(this.path);

        // Ӧ���طŲ���������,ȷ��������ȷ
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        store.flush();
        assertTrue(store.getSizeInBytes() > 0);
        assertEquals(sizeInBytes, store.getSizeInBytes());
        this.assertMessages(store);
        assertNull(this.transactionStore.getInflyTx(xid));

        // �ٴιرմ򿪣�״̬��ȷ
        this.tearDown();
        this.init(this.path);
        store = this.messageStoreManager.getOrCreateMessageStore("topic1", 2);
        assertTrue(store.getSizeInBytes() > 0);
        assertEquals(sizeInBytes, store.getSizeInBytes());
        this.assertMessages(store);
        assertNull(this.transactionStore.getInflyTx(xid));

    }
}
TOP

Related Classes of com.taobao.metamorphosis.server.transaction.store.JournalTransactionStoreUnitTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.