Package voldemort.client.rebalance

Source Code of voldemort.client.rebalance.RebalanceRebootstrapConsistencyTest

/*
* 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.client.rebalance;

import static org.junit.Assert.fail;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import voldemort.ServerTestUtils;
import voldemort.client.ClientConfig;
import voldemort.client.RoutingTier;
import voldemort.client.SystemStoreClient;
import voldemort.client.SystemStoreClientFactory;
import voldemort.client.SystemStoreRepository;
import voldemort.client.protocol.admin.AdminClient;
import voldemort.client.scheduler.AsyncMetadataVersionManager;
import voldemort.cluster.Cluster;
import voldemort.cluster.Node;
import voldemort.common.service.SchedulerService;
import voldemort.routing.RoutingStrategyType;
import voldemort.serialization.SerializerDefinition;
import voldemort.server.VoldemortConfig;
import voldemort.server.VoldemortServer;
import voldemort.store.StoreDefinition;
import voldemort.store.StoreDefinitionBuilder;
import voldemort.store.bdb.BdbStorageConfiguration;
import voldemort.store.metadata.MetadataStore;
import voldemort.store.socket.SocketStoreFactory;
import voldemort.store.socket.clientrequest.ClientRequestExecutorPool;
import voldemort.store.system.SystemStoreConstants;
import voldemort.utils.SystemTime;
import voldemort.versioning.VectorClock;
import voldemort.versioning.Versioned;
import voldemort.xml.ClusterMapper;
import voldemort.xml.StoreDefinitionsMapper;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

/**
*
* We simulate the rebalance controller here by changing the cluster state and
* stores state
*
* On rebootstrap we want to ensure that the cluster and store defs are
* consistent from a client's perspective
*
*/
public class RebalanceRebootstrapConsistencyTest {

    private Cluster cluster;
    private List<VoldemortServer> servers;

    String[] bootStrapUrls = null;
    public static String socketUrl = "";
    protected final int CLIENT_ZONE_ID = 0;

    private SystemStoreClient<String, String> sysVersionStore;
    private SystemStoreRepository repository;
    private SchedulerService scheduler;
    private AsyncMetadataVersionManager asyncCheckMetadata;
    private boolean callbackDone = false;

    private StoreDefinition rwStoreDefWithReplication;
    private StoreDefinition rwStoreDefWithReplication2;

    protected static String testStoreNameRW = "test";

    private static final String CLUSTER_VERSION_KEY = "cluster.xml";
    int maxRetries = 0;

    private static final ClusterMapper clusterMapper = new ClusterMapper();
    private static final StoreDefinitionsMapper storeMapper = new StoreDefinitionsMapper();

    AdminClient adminClient;

    List<StoreDefinition> newstoredefs;
    Cluster newCluster;

    @Before
    public void setUp() throws Exception {
        SocketStoreFactory socketStoreFactory = new ClientRequestExecutorPool(2,
                                                                              10000,
                                                                              100000,
                                                                              32 * 1024);

        int numServers = 2;

        rwStoreDefWithReplication = new StoreDefinitionBuilder().setName(testStoreNameRW)
                                                                .setType(BdbStorageConfiguration.TYPE_NAME)
                                                                .setKeySerializer(new SerializerDefinition("string"))
                                                                .setValueSerializer(new SerializerDefinition("string"))
                                                                .setRoutingPolicy(RoutingTier.CLIENT)
                                                                .setRoutingStrategyType(RoutingStrategyType.CONSISTENT_STRATEGY)
                                                                .setReplicationFactor(2)
                                                                .setPreferredReads(1)
                                                                .setRequiredReads(1)
                                                                .setPreferredWrites(1)
                                                                .setRequiredWrites(1)
                                                                .build();

        /*
         * Bug fix: The old code was trying to rename a store during rebalance !
         * God knows why Renaming it back to the original store name and
         * changing other preferences (required reads = 2)
         */
        rwStoreDefWithReplication2 = new StoreDefinitionBuilder().setName(testStoreNameRW)
                                                                 .setType(BdbStorageConfiguration.TYPE_NAME)
                                                                 .setKeySerializer(new SerializerDefinition("string"))
                                                                 .setValueSerializer(new SerializerDefinition("string"))
                                                                 .setRoutingPolicy(RoutingTier.CLIENT)
                                                                 .setRoutingStrategyType(RoutingStrategyType.CONSISTENT_STRATEGY)
                                                                 .setReplicationFactor(2)
                                                                 .setPreferredReads(2)
                                                                 .setRequiredReads(2)
                                                                 .setPreferredWrites(1)
                                                                 .setRequiredWrites(1)
                                                                 .build();

        List<StoreDefinition> storedefs = new ArrayList<StoreDefinition>();

        storedefs.add(rwStoreDefWithReplication);

        String storesXmlStr = new StoreDefinitionsMapper().writeStoreList(storedefs);

        // create a temp file
        File tempStoresXml = File.createTempFile("tempfile", ".tmp");

        BufferedWriter bw = new BufferedWriter(new FileWriter(tempStoresXml));
        bw.write(storesXmlStr);
        bw.close();

        VoldemortServer[] voldemortServers = new VoldemortServer[numServers];
        int partitionMap[][] = { { 0, 1 }, {} };
        cluster = ServerTestUtils.startVoldemortCluster(numServers,
                                                        voldemortServers,
                                                        partitionMap,
                                                        socketStoreFactory,
                                                        false,
                                                        null,
                                                        tempStoresXml.getAbsolutePath(),
                                                        new Properties());

        servers = Lists.newArrayList();
        for(int i = 0; i < numServers; ++i) {
            servers.add(voldemortServers[i]);
        }

        socketUrl = voldemortServers[0].getIdentityNode().getSocketUrl().toString();

        bootStrapUrls = new String[1];
        bootStrapUrls[0] = socketUrl;

        ClientConfig clientConfig = new ClientConfig();
        clientConfig.setBootstrapUrls(bootStrapUrls).setClientZoneId(this.CLIENT_ZONE_ID);
        SystemStoreClientFactory<String, String> systemStoreFactory = new SystemStoreClientFactory<String, String>(clientConfig);
        sysVersionStore = systemStoreFactory.createSystemStore(SystemStoreConstants.SystemStoreName.voldsys$_metadata_version_persistence.name());

        repository = new SystemStoreRepository(clientConfig);
        repository.addSystemStore(sysVersionStore,
                                  SystemStoreConstants.SystemStoreName.voldsys$_metadata_version_persistence.name());
        this.scheduler = new SchedulerService(2, SystemTime.INSTANCE, true);

        Callable<Void> rebootstrapCallback = new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                // callbackForClusterChange();
                checkConsistentMetadata();
                return null;
            }
        };

        // Starting the Version Metadata Manager
        this.asyncCheckMetadata = new AsyncMetadataVersionManager(this.repository,
                                                                  rebootstrapCallback,
                                                                  null);
        scheduler.schedule(asyncCheckMetadata.getClass().getName(),
                           asyncCheckMetadata,
                           new Date(),
                           500);

        // Wait until the Version Manager is active

        while(maxRetries < 3 && !asyncCheckMetadata.isActive) {
            Thread.sleep(500);
            maxRetries++;
        }

    }

    @After
    public void tearDown() {
        if(servers != null)
            for(VoldemortServer server: servers)
                server.stop();
    }

    /*
     * simulate rebalance behavior
     */
    public void rebalance() {
        assert servers != null && servers.size() > 1;

        VoldemortConfig config = servers.get(0).getVoldemortConfig();
        adminClient = AdminClient.createTempAdminClient(config, cluster, 4);
        List<Integer> partitionIds = ImmutableList.of(0, 1);
        int req = adminClient.storeMntOps.migratePartitions(0,
                                                            1,
                                                            testStoreNameRW,
                                                            partitionIds,
                                                            null,
                                                            null);
        adminClient.rpcOps.waitForCompletion(1, req, 5, TimeUnit.SECONDS);
        Versioned<Cluster> versionedCluster = adminClient.metadataMgmtOps.getRemoteCluster(0);

        Node node0 = versionedCluster.getValue().getNodeById(0);
        Node node1 = versionedCluster.getValue().getNodeById(1);
        Node newNode0 = new Node(node0.getId(),
                                 node0.getHost(),
                                 node0.getHttpPort(),
                                 node0.getSocketPort(),
                                 node0.getAdminPort(),
                                 ImmutableList.<Integer> of());
        Node newNode1 = new Node(node1.getId(),
                                 node1.getHost(),
                                 node1.getHttpPort(),
                                 node1.getSocketPort(),
                                 node1.getAdminPort(),
                                 ImmutableList.of(0, 1));
        adminClient.storeMntOps.deletePartitions(0, testStoreNameRW, ImmutableList.of(0, 1), null);

        newCluster = new Cluster(cluster.getName(),
                                 ImmutableList.of(newNode0, newNode1),
                                 Lists.newArrayList(cluster.getZones()));

        newstoredefs = new ArrayList<StoreDefinition>();

        newstoredefs.add(rwStoreDefWithReplication2);
        for(Node node: cluster.getNodes()) {
            VectorClock clock = (VectorClock) versionedCluster.getVersion();
            clock.incrementVersion(node.getId(), System.currentTimeMillis());

            adminClient.metadataMgmtOps.updateRemoteMetadata(node.getId(),
                                                             MetadataStore.STORES_KEY,
                                                             new Versioned<String>(storeMapper.writeStoreList(newstoredefs),
                                                                                   clock));

            adminClient.metadataMgmtOps.updateRemoteMetadata(node.getId(),
                                                             MetadataStore.CLUSTER_KEY,
                                                             new Versioned<String>(clusterMapper.writeCluster(newCluster),
                                                                                   clock));

        }

        adminClient.metadataMgmtOps.updateMetadataversion(CLUSTER_VERSION_KEY);

    }

    @Test
    public void testBasicAsyncBehaviour() {

        try {

            rebalance();
            maxRetries = 0;
            while(maxRetries < 3 && !callbackDone) {
                Thread.sleep(2000);
                maxRetries++;
            }

        } catch(Exception e) {
            e.printStackTrace();
            fail("Failed to start the Metadata Version Manager : " + e.getMessage());
        }
    }

    /*
     * In callback ensure metadata is consistent
     */
    private void checkConsistentMetadata() {

        Versioned<Cluster> versionedCluster = adminClient.metadataMgmtOps.getRemoteCluster(0);
        Versioned<List<StoreDefinition>> versionedStoreDefs = adminClient.metadataMgmtOps.getRemoteStoreDefList(0);

        if(versionedCluster.getValue().equals(newCluster)) {
            Assert.assertEquals(versionedStoreDefs.getValue().get(0), rwStoreDefWithReplication2);
        }
    }

}
TOP

Related Classes of voldemort.client.rebalance.RebalanceRebootstrapConsistencyTest

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.