Package voldemort.utils

Source Code of voldemort.utils.ConsistencyFixTest

/*
* Copyright 2013 LinkedIn, Inc
*
* 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.
*/

package voldemort.utils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

import voldemort.ServerTestUtils;
import voldemort.TestUtils;
import voldemort.cluster.Cluster;
import voldemort.cluster.Node;
import voldemort.server.VoldemortServer;
import voldemort.store.socket.SocketStoreFactory;
import voldemort.store.socket.clientrequest.ClientRequestExecutorPool;
import voldemort.utils.ConsistencyFix.BadKey;
import voldemort.utils.ConsistencyFix.BadKeyOrphanReader;
import voldemort.utils.ConsistencyFix.BadKeyReader;
import voldemort.utils.ConsistencyFix.BadKeyStatus;
import voldemort.utils.ConsistencyFix.BadKeyWriter;
import voldemort.utils.ConsistencyFix.Stats;
import voldemort.versioning.VectorClock;

public class ConsistencyFixTest {

    final static String STORE_NAME = "consistency-fix";
    final static String STORES_XML = "test/common/voldemort/config/consistency-stores.xml";

    /**
     *
     * @return bootstrap url
     */
    public static String setUpCluster() {
        // setup four nodes with one store and one partition
        final SocketStoreFactory socketStoreFactory = new ClientRequestExecutorPool(2,
                                                                                    10000,
                                                                                    100000,
                                                                                    32 * 1024);
        VoldemortServer[] servers = new VoldemortServer[4];
        int partitionMap[][] = { { 0 }, { 1 }, { 2 }, { 3 } };
        try {
            Cluster cluster = ServerTestUtils.startVoldemortCluster(4,
                                                                    servers,
                                                                    partitionMap,
                                                                    socketStoreFactory,
                                                                    true,
                                                                    null,
                                                                    STORES_XML,
                                                                    new Properties());
            Node node = cluster.getNodeById(0);
            return "tcp://" + node.getHost() + ":" + node.getSocketPort();
        } catch(IOException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }

        return null;
    }

    public void badKeyReaderWriteBadKeys(String fileName, boolean addWhiteSpace) {
        // Write file of "bad keys" with messy white space
        try {
            BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName));
            if(addWhiteSpace)
                fileWriter.write("\n\n\t\t\n\n\t\n");
            for(int i = 0; i < 1000; ++i) {
                byte[] keyb = TestUtils.randomBytes(10);
                fileWriter.write(ByteUtils.toHexString(keyb) + "\n");
                if(addWhiteSpace) {

                    if(i % 5 == 0) {
                        fileWriter.write("\n\n\t\t\n\n\t\n");
                    }
                    if(i % 7 == 0) {
                        fileWriter.write("\t");
                    }
                }
            }
            if(addWhiteSpace)
                fileWriter.write("\n\n\t\t\n\n\t\n");
            fileWriter.close();
        } catch(IOException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }
    }

    public void badKeyReaderWriteOrphanKeys(String fileName, boolean addWhiteSpace) {
        // Write file of "orphans" with some white space between entries.
        /*-
         * Example entry:
        6473333333646464,2
        00,version(1:1, 2:1) ts:1357257858674
        00,version(1:1, 3:1) ts:1357257858684
         */
        try {
            BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName));
            if(addWhiteSpace)
                fileWriter.write("\n\n\t\t\n\n\t\n");
            for(int i = 0; i < 1000; ++i) {
                int numValues = (i % 3) + 1;
                byte[] keyb = TestUtils.randomBytes(10);
                String keyLine = ByteUtils.toHexString(keyb) + "," + numValues;
                System.out.println("keyLine: " + keyLine);
                fileWriter.write(keyLine + "\n");
                for(int j = 0; j < numValues; j++) {
                    int valLength = (j + 10) * (j + 1);
                    String value = ByteUtils.toHexString(TestUtils.randomBytes(valLength));
                    VectorClock vectorClock = TestUtils.getClock(j);
                    String valueLine = value + "," + vectorClock.toString();
                    System.out.println("valueLine: " + valueLine);
                    fileWriter.write(valueLine + "\n");
                }
                if(addWhiteSpace) {
                    if(i % 5 == 0) {
                        fileWriter.write("\n\n\t\t\n\n\t\n");
                    }
                }
            }
            if(addWhiteSpace)
                fileWriter.write("\n\n\t\t\n\n\t\n");
            fileWriter.close();
        } catch(IOException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }
    }

    /**
     *
     * @param orphan true for testing orphan, false for testing normal...
     */
    public void badKeyReaderHelper(boolean orphan) {
        String tmpDir = TestUtils.createTempDir().getAbsolutePath();
        String fileName = tmpDir + "BadKeyFile";
        if(orphan) {
            badKeyReaderWriteOrphanKeys(fileName, true);
        } else {
            badKeyReaderWriteBadKeys(fileName, true);
        }

        // Get cluster bootstrap url
        String url = setUpCluster();

        // Construct ConsistencyFix with parseOnly true
        ConsistencyFix consistencyFix = new ConsistencyFix(url, STORE_NAME, 100, 100, false, true);

        // Do set up for BadKeyReader akin to consistencyFix.execute...
        int parallelism = 1;
        BlockingQueue<Runnable> blockingQ = new ArrayBlockingQueue<Runnable>(parallelism);
        RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
        ExecutorService consistencyFixWorkers = new ThreadPoolExecutor(parallelism,
                                                                       parallelism,
                                                                       0L,
                                                                       TimeUnit.MILLISECONDS,
                                                                       blockingQ,
                                                                       rejectedExecutionHandler);
        BlockingQueue<BadKeyStatus> badKeyQOut = new ArrayBlockingQueue<BadKeyStatus>(10000);

        ExecutorService badKeyReaderService = Executors.newSingleThreadExecutor();
        CountDownLatch allBadKeysReadLatch = new CountDownLatch(1);

        // Submit file of bad keys to (appropriate) BadKeyReader
        BadKeyReader bkr = null;
        if(orphan) {
            bkr = new BadKeyOrphanReader(allBadKeysReadLatch,
                                         fileName,
                                         consistencyFix,
                                         consistencyFixWorkers,
                                         badKeyQOut);
        } else {
            bkr = new BadKeyReader(allBadKeysReadLatch,
                                   fileName,
                                   consistencyFix,
                                   consistencyFixWorkers,
                                   badKeyQOut);
        }
        badKeyReaderService.submit(bkr);

        // Wait for file to be processed.
        try {
            allBadKeysReadLatch.await();

            badKeyReaderService.shutdown();
            consistencyFixWorkers.shutdown();
        } catch(InterruptedException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }
        consistencyFix.close();

        // Make sure everything worked as expected.
        assertFalse(bkr.hasException());
        assertEquals(0, badKeyQOut.size());
    }

    @Test
    public void testBadKeyReader() {
        badKeyReaderHelper(false);
    }

    @Test
    public void testBadKeyOrphanReader() {
        badKeyReaderHelper(true);
    }

    @Test
    public void testBadKeyResult() {
        BadKey badKey = new BadKey("0101", "0101\n");
        ConsistencyFix.BadKeyStatus bkr1 = new BadKeyStatus(badKey, ConsistencyFix.Status.SUCCESS);
        assertFalse(bkr1.isPoison());
        assertEquals(bkr1.getBadKey().getKeyInHexFormat(), "0101");
        assertEquals(bkr1.getBadKey().getReaderInput(), "0101\n");
        assertEquals(bkr1.getStatus(), ConsistencyFix.Status.SUCCESS);

        ConsistencyFix.BadKeyStatus bkr2 = new BadKeyStatus();
        assertTrue(bkr2.isPoison());
        assertEquals(bkr2.getBadKey(), null);
        assertEquals(bkr2.getStatus(), null);
    }

    @Test
    public void testBadKeyWriter() {
        String tmpDir = TestUtils.createTempDir().getAbsolutePath();
        String fileName = tmpDir + "BadKeyFile";

        // Set up bad key writer
        BlockingQueue<BadKeyStatus> bq = new ArrayBlockingQueue<BadKeyStatus>(5);
        ExecutorService badKeyWriterService = Executors.newSingleThreadExecutor();

        BadKeyWriter badKeyWriter = new BadKeyWriter(fileName, bq);
        badKeyWriterService.submit(badKeyWriter);

        // Enqueue stuff for bad key writer to write
        try {
            for(int i = 0; i < 100; ++i) {
                BadKey badKey = new BadKey(Integer.toHexString(i), Integer.toHexString(i) + "\n");

                bq.put(new BadKeyStatus(badKey, ConsistencyFix.Status.REPAIR_EXCEPTION));
            }
            // Poison bad key writer
            bq.put(new BadKeyStatus());
        } catch(InterruptedException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }

        // wait for bad key writer to shutdown
        badKeyWriterService.shutdown();
        try {
            badKeyWriterService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch(InterruptedException e) {
            e.printStackTrace();
            fail("Unexpected exception");
        }

        assertFalse(badKeyWriter.hasException());

        // Read output file & verify.
        try {
            BufferedReader fileReader = new BufferedReader(new FileReader(fileName));

            int i = 0;
            for(String keyLine = fileReader.readLine(); keyLine != null; keyLine = fileReader.readLine()) {
                assertEquals(keyLine, Integer.toHexString(i));
                i++;
            }
        } catch(FileNotFoundException fnfe) {
            fnfe.printStackTrace();
            fail("Unexpected exception");
        } catch(IOException ioe) {
            ioe.printStackTrace();
            fail("Unexpected exception");
        }
    }

    @Test
    public void testConsistencyFixSetupTeardown() {
        String url = setUpCluster();

        ConsistencyFix consistencyFix = new ConsistencyFix(url, STORE_NAME, 100, 100, false, false);

        consistencyFix.close();
    }

    @Test
    public void testStats() throws InterruptedException {
        ConsistencyFix.Stats stats = new Stats(1000);

        long lastTimeMs = stats.lastTimeMs;
        TimeUnit.MILLISECONDS.sleep(2);
        for(int i = 0; i < 1001; ++i) {
            stats.incrementFixCount();
        }
        assertTrue(stats.fixCount == 1001);
        assertTrue(stats.startTimeMs < stats.lastTimeMs);
        assertTrue(lastTimeMs < System.currentTimeMillis());

    }

    @Test
    public void testStatus() {
        ConsistencyFix.Status status = ConsistencyFix.Status.SUCCESS;
        assertEquals(status.toString(), "success");
    }
}
TOP

Related Classes of voldemort.utils.ConsistencyFixTest

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.