Package voldemort.store.metadata

Source Code of voldemort.store.metadata.MetadataStoreTest

/*
* Copyright 2008-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.store.metadata;

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

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import voldemort.ServerTestUtils;
import voldemort.VoldemortException;
import voldemort.client.rebalance.RebalanceTaskInfo;
import voldemort.cluster.Cluster;
import voldemort.server.rebalance.RebalancerState;
import voldemort.store.metadata.MetadataStore.VoldemortState;
import voldemort.tools.admin.AvroAddStoreTest;
import voldemort.utils.ByteArray;
import voldemort.utils.ByteUtils;
import voldemort.versioning.ObsoleteVersionException;
import voldemort.versioning.VectorClock;
import voldemort.versioning.Versioned;
import voldemort.xml.ClusterMapper;
import voldemort.xml.StoreDefinitionsMapper;

import com.google.common.collect.Maps;

public class MetadataStoreTest {
    private Logger logger = Logger.getLogger(MetadataStore.class);

    public static String storesXmlWithBackwardIncompatibleSchema = "<stores>\n" + AvroAddStoreTest.storeXmlWithBackwardIncompatibleSchema + "</stores>";

    public static String storesXmlWithBackwardCompatibleSchema = "<stores>\n" + AvroAddStoreTest.storeXmlWithBackwardCompatibleSchema + "</stores>";

    private static int TEST_RUNS = 100;

    private MetadataStore metadataStore;
    private List<String> TEST_KEYS = Arrays.asList(MetadataStore.CLUSTER_KEY,
                                                   MetadataStore.STORES_KEY,
                                                   MetadataStore.REBALANCING_STEAL_INFO,
                                                   MetadataStore.SERVER_STATE_KEY,
                                                   MetadataStore.REBALANCING_SOURCE_CLUSTER_XML);

    @Before
    public void setUp() throws Exception {
        metadataStore = ServerTestUtils.createMetadataStore(ServerTestUtils.getLocalCluster(1),
                                                            ServerTestUtils.getStoreDefs(1));
    }

    public ByteArray getValidKey() {
        int i = (int) (Math.random() * TEST_KEYS.size());
        String key = TEST_KEYS.get(i);
        return new ByteArray(ByteUtils.getBytes(key, "UTF-8"));
    }

    public byte[] getValidValue(ByteArray key) {
        String keyString = ByteUtils.getString(key.get(), "UTF-8");
        if(MetadataStore.CLUSTER_KEY.equals(keyString)
           || MetadataStore.REBALANCING_SOURCE_CLUSTER_XML.equals(keyString)) {
            return ByteUtils.getBytes(new ClusterMapper().writeCluster(ServerTestUtils.getLocalCluster(1)),
                                      "UTF-8");
        } else if(MetadataStore.STORES_KEY.equals(keyString)) {
            return ByteUtils.getBytes(new StoreDefinitionsMapper().writeStoreList(ServerTestUtils.getStoreDefs(1)),
                                      "UTF-8");

        } else if(MetadataStore.SERVER_STATE_KEY.equals(keyString)) {
            int i = (int) (Math.random() * VoldemortState.values().length);
            return ByteUtils.getBytes(VoldemortState.values()[i].toString(), "UTF-8");
        } else if(MetadataStore.REBALANCING_STEAL_INFO.equals(keyString)) {
            int size = (int) (Math.random() * 10) + 1;
            List<Integer> partition = new ArrayList<Integer>();
            for(int i = 0; i < size; i++) {
                partition.add((int) Math.random() * 10);
            }

            List<Integer> partitionIds = partition;

            HashMap<String, List<Integer>> storeToReplicaToPartitionList = Maps.newHashMap();
            storeToReplicaToPartitionList.put("test", partitionIds);

            return ByteUtils.getBytes(new RebalancerState(Arrays.asList(new RebalanceTaskInfo(0,
                                                                                              (int) Math.random() * 5,
                                                                                              storeToReplicaToPartitionList,
                                                                                              ServerTestUtils.getLocalCluster(1)))).toJsonString(),
                                      "UTF-8");
        }

        throw new RuntimeException("Unhandled key:" + keyString + " passed");
    }

    @Test
    public void testSimpleGetAndPut() {
        for(int i = 0; i <= TEST_RUNS; i++) {
            ByteArray key = getValidKey();
            VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion();
            Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key),
                                                            clock.incremented(0, 1));

            metadataStore.put(key, value, null);
            checkValues(value, metadataStore.get(key, null), key);
        }
    }

    @Test
    public void testRepeatedPuts() {
        for(int i = 0; i <= TEST_RUNS; i++) {
            for(int j = 0; j <= 5; j++) {
                ByteArray key = getValidKey();

                VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion();
                Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key),
                                                                clock.incremented(0, 1));

                metadataStore.put(key, value, null);
                checkValues(value, metadataStore.get(key, null), key);
            }
        }
    }

    @Test
    public void testObsoletePut() {
        for(int i = 0; i <= TEST_RUNS; i++) {
            ByteArray key = getValidKey();
            VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion();
            Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key),
                                                            clock.incremented(0, 1));

            try {
                metadataStore.put(key, value, null);
                assertTrue(true);
                metadataStore.put(key, value, null);
                fail();
            } catch(ObsoleteVersionException e) {
                // expected ObsoleteVersionException
            }
        }
    }

    @Test
    public void testSynchronousPut() {
        for(int i = 0; i <= TEST_RUNS; i++) {
            ByteArray key = getValidKey();
            VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion();

            Versioned<byte[]> value1 = new Versioned<byte[]>(getValidValue(key),
                                                             clock.incremented(1, 1));
            Versioned<byte[]> value2 = new Versioned<byte[]>(getValidValue(key),
                                                             clock.incremented(2, 1));

            metadataStore.put(key, value1, null);
            metadataStore.put(key, value2, null);

            assertEquals("Only one metadata value should return", 1, metadataStore.get(key, null)
                                                                                  .size());
            checkValues(value2, metadataStore.get(key, null), key);
        }
    }

    @Test
    public void testCleanAllStates() {
        // put state entries.
        incrementVersionAndPut(metadataStore,
                               MetadataStore.SERVER_STATE_KEY,
                               MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER);

        assertEquals("Values should match.",
                     metadataStore.getServerStateUnlocked(),
                     VoldemortState.REBALANCING_MASTER_SERVER);

        // do clean
        metadataStore.cleanAllRebalancingState();

        // check all values revert back to default.
        assertEquals("Values should match.",
                     metadataStore.getServerStateUnlocked(),
                     VoldemortState.NORMAL_SERVER);
    }

    @Test
    public void testRebalacingSourceClusterXmlKey() {
        metadataStore.cleanAllRebalancingState();

        assertTrue("Should be null", null == metadataStore.getRebalancingSourceCluster());

        Cluster dummyCluster = ServerTestUtils.getLocalCluster(2);
        metadataStore.put(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML, dummyCluster);
        assertEquals("Should be equal", dummyCluster, metadataStore.getRebalancingSourceCluster());

        metadataStore.put(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML, (Object) null);
        assertTrue("Should be null", null == metadataStore.getRebalancingSourceCluster());

        List<Versioned<byte[]>> sourceClusterVersions = metadataStore.get(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML,
                                                                          null);
        assertTrue("Just one version expected", 1 == sourceClusterVersions.size());
        assertEquals("Empty string should map to null",
                     "",
                     new String(sourceClusterVersions.get(0).getValue()));

    }

    /**
     * Test update stores.xml with incompatible avro versions. Should reject and throw exceptions
     */
    @Test
    public void testUpdateStoresXmlWithIncompatibleAvroSchema() {
        try{
            logger.info("Now inserting stores with non backward compatible schema. Should see exception");
            metadataStore.put(MetadataStore.STORES_KEY, new StoreDefinitionsMapper().readStoreList(new StringReader(storesXmlWithBackwardIncompatibleSchema)));
            Assert.fail("Did not throw exception");
        } catch(VoldemortException e) {

        }
        logger.info("Now inserting stores with backward compatible schema. Should not see exception");
        metadataStore.put(MetadataStore.STORES_KEY, new StoreDefinitionsMapper().readStoreList(new StringReader(storesXmlWithBackwardCompatibleSchema)));
    }

    private void checkValues(Versioned<byte[]> value, List<Versioned<byte[]>> list, ByteArray key) {
        assertEquals("should return exactly one value ", 1, list.size());

        assertEquals("should return the last saved version", value.getVersion(), list.get(0)
                                                                                     .getVersion());
        assertEquals("should return the last saved value (key:"
                     + ByteUtils.getString(key.get(), "UTF-8") + ")",
                     new String(value.getValue()),
                     new String(list.get(0).getValue()));
    }

    /**
     * helper function to auto update version and put()
     *
     * @param key
     * @param value
     */
    private void incrementVersionAndPut(MetadataStore metadataStore, String keyString, Object value) {
        ByteArray key = new ByteArray(ByteUtils.getBytes(keyString, "UTF-8"));
        VectorClock current = (VectorClock) metadataStore.getVersions(key).get(0);

        metadataStore.put(keyString,
                          new Versioned<Object>(value,
                                                current.incremented(0, System.currentTimeMillis())));
    }
}
TOP

Related Classes of voldemort.store.metadata.MetadataStoreTest

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.