Package voldemort.store.system

Source Code of voldemort.store.system.AsyncMetadataVersionManagerTest$StoresVersionCallback

/*
* Copyright 2012-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.system;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import voldemort.ClusterTestUtils;
import voldemort.ServerTestUtils;
import voldemort.TestUtils;
import voldemort.client.ClientConfig;
import voldemort.client.SystemStoreClient;
import voldemort.client.SystemStoreClientFactory;
import voldemort.client.SystemStoreRepository;
import voldemort.client.scheduler.AsyncMetadataVersionManager;
import voldemort.cluster.Cluster;
import voldemort.common.service.SchedulerService;
import voldemort.server.VoldemortConfig;
import voldemort.server.VoldemortServer;
import voldemort.store.StoreDefinition;
import voldemort.store.socket.SocketStoreFactory;
import voldemort.store.socket.clientrequest.ClientRequestExecutorPool;
import voldemort.utils.MetadataVersionStoreUtils;
import voldemort.utils.SystemTime;

/**
* Test class to verify the AsyncMetadataVersionManager
*
* @author csoman
*
*/
@RunWith(Parameterized.class)
public class AsyncMetadataVersionManagerTest {

    private static String storesXmlfile = "test/common/voldemort/config/stores.xml";
    String[] bootStrapUrls = null;
    private SocketStoreFactory socketStoreFactory = new ClientRequestExecutorPool(2,
                                                                                  10000,
                                                                                  100000,
                                                                                  32 * 1024);

    private VoldemortServer[] servers;
    private Cluster cluster;
    public static String socketUrl = "";
    protected int clientZoneId;
    private long newVersion = 0;

    private SystemStoreClient<String, String> sysVersionStore;
    private SystemStoreRepository repository;
    private SchedulerService scheduler;
    private AsyncMetadataVersionManager asyncCheckMetadata;
    private boolean callbackDone = false;
    private long updatedClusterVersion;
    private long updatedStoreVersion;
    private List<StoreDefinition> storeDefs;

    // Multi store version tracking test
    List<AsyncMetadataVersionManager> asyncVersionManagers = new ArrayList<AsyncMetadataVersionManager>();
    long[] updatedVersions = new long[3];
    boolean[] callbacksDone = new boolean[3];

    public AsyncMetadataVersionManagerTest(Cluster cluster,
                                           List<StoreDefinition> storeDefs,
                                           int clientZoneId) {
        this.cluster = cluster;
        this.storeDefs = storeDefs;
        this.clientZoneId = clientZoneId;
    }

    @Parameterized.Parameters
    public static Collection<Object[]> configs() {
        return Arrays.asList(new Object[][] {
                { ClusterTestUtils.getZ1Z3Z5ClusterWithNonContiguousNodeIds(),
                        ClusterTestUtils.getZ1Z3Z5StoreDefsBDB(), 3 },
                { ClusterTestUtils.getZZZCluster(), ClusterTestUtils.getZZZ322StoreDefs("bdb"), 0 } });
    }

    @Before
    public void setUp() throws Exception {
        servers = new VoldemortServer[cluster.getNodeIds().size()];
        int i = 0;
        for(Integer nodeId: cluster.getNodeIds()) {
            VoldemortConfig config = ServerTestUtils.createServerConfigWithDefs(true,
                                                                                nodeId,
                                                                                TestUtils.createTempDir()
                                                                                         .getAbsolutePath(),
                                                                                cluster,
                                                                                storeDefs,
                                                                                new Properties());
            VoldemortServer server = ServerTestUtils.startVoldemortServer(socketStoreFactory,
                                                                          config);
            servers[i++] = server;
        }

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

        bootStrapUrls = new String[1];
        bootStrapUrls[0] = socketUrl;
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.setBootstrapUrls(bootStrapUrls).setClientZoneId(clientZoneId);
        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);
    }

    @After
    public void tearDown() throws Exception {
        for(VoldemortServer server: servers) {
            ServerTestUtils.stopVoldemortServer(server);
        }
    }

    /*
     * Validates that the AsyncMetadataVersionManager correctly identifies the
     * version update. This is done by initializing the base metadata version
     * (for cluster.xml), starting the AsyncMetadataVersionManager and then
     * updating the version to a new value. For the test to succeed the callback
     * has to be invoked correctly by the asynchronous manager.
     */
    @Test(timeout = 60000)
    public void testBasicAsyncBehaviour() {
        String storeVersionKey = "cluster.xml";
        try {
            Callable<Void> rebootstrapCallback = new Callable<Void>() {

                public Void call() throws Exception {
                    callbackForClusterChange();
                    return null;
                }
            };

            // Write a base version of 100
            Properties versionProps = MetadataVersionStoreUtils.getProperties(this.sysVersionStore);
            versionProps.setProperty(storeVersionKey, Long.toString(100));
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            // Giving enough time to complete the above put.
            Thread.sleep(500);

            // 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(!asyncCheckMetadata.isActive) {
                Thread.sleep(500);
            }

            // Updating the version metadata here for the Version Metadata
            // Manager to detect
            this.newVersion = 101;
            System.err.println("Incrementing the version for : " + storeVersionKey);
            versionProps.setProperty(storeVersionKey, Long.toString(this.newVersion));
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            while(!callbackDone) {
                Thread.sleep(2000);
            }

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

    /*
     * Validates that the AsyncMetadataVersionManager correctly identifies the
     * store specific version update. This is done by initializing the base
     * metadata version (for a particular store), starting the
     * AsyncMetadataVersionManager and then updating the version to a new value.
     * For the test to succeed the callback has to be invoked correctly by the
     * asynchronous manager.
     */
    @Test(timeout = 60000)
    public void testStoreDefinitionChangeTracker() {
        String storeVersionKey = "users";
        Callable<Void> rebootstrapCallback = new Callable<Void>() {

            public Void call() throws Exception {
                callbackForStoreChange();
                return null;
            }
        };

        try {
            // Write a base version of 100
            Properties versionProps = MetadataVersionStoreUtils.getProperties(this.sysVersionStore);
            versionProps.setProperty(storeVersionKey, Long.toString(100));
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            // Giving enough time to complete the above put.
            Thread.sleep(500);

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

            // Wait until the Version Manager is active
            while(!asyncCheckMetadata.isActive) {
                Thread.sleep(500);
            }

            // Updating the version metadata here for the Version Metadata
            // Manager to detect
            this.newVersion = 101;
            System.err.println("Incrementing the version for : " + storeVersionKey);
            versionProps.setProperty(storeVersionKey, Long.toString(this.newVersion));
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            while(!callbackDone) {
                Thread.sleep(2000);
            }

            assertEquals(false, (this.updatedStoreVersion == 0));
            assertEquals(this.updatedStoreVersion, this.newVersion);
        } catch(Exception e) {
            e.printStackTrace();
            fail("Failed to start the Metadata Version Manager : " + e.getMessage());
        }
    }

    /*
     * Validates that the AsyncMetadataVersionManager correctly identifies the
     * store specific version update in the presence of multiple stores. This is
     * done by initializing the base metadata version (for a particular store),
     * starting the AsyncMetadataVersionManager and then updating the version to
     * a new value. For the test to succeed the callback has to be invoked
     * correctly by the asynchronous manager.
     *
     * This test also checks that callback is invoked only for the corresponding
     * store that was updated. Other callbacks should not be invoked.
     */
    @Test(timeout = 60000)
    public void testMultipleStoreDefinitionsChangeTracker() {
        String storeVersionKeys[] = new String[3];
        for(int i = 0; i < 3; i++) {
            storeVersionKeys[i] = "users" + i;
        }

        List<StoresVersionCallback> rebootstrapCallbacks = new ArrayList<AsyncMetadataVersionManagerTest.StoresVersionCallback>();
        for(int i = 0; i < 3; i++) {
            StoresVersionCallback callback = new StoresVersionCallback(i);
            rebootstrapCallbacks.add(callback);
        }

        try {
            // Write a base version of 100
            Properties versionProps = MetadataVersionStoreUtils.getProperties(this.sysVersionStore);
            for(int i = 0; i < 3; i++) {
                versionProps.setProperty(storeVersionKeys[i], Long.toString(100));
            }
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            // Giving enough time to complete the above put.
            Thread.sleep(500);

            // Starting the Version Metadata Managers
            for(int i = 0; i < 3; i++) {
                AsyncMetadataVersionManager versionManager = new AsyncMetadataVersionManager(this.repository,
                                                                                             rebootstrapCallbacks.get(i),
                                                                                             storeVersionKeys[i]);
                asyncVersionManagers.add(versionManager);

                scheduler.schedule(versionManager.getClass().getName(),
                                   versionManager,
                                   new Date(),
                                   500);
            }

            // Wait until the Version Manager is active
            while(!asyncVersionManagers.get(0).isActive && !asyncVersionManagers.get(1).isActive
                  && !asyncVersionManagers.get(2).isActive) {
                Thread.sleep(500);
            }

            // Updating the version metadata here for the Version Metadata
            // Manager to detect
            this.newVersion = 101;

            // Set this new version on the store: 'users1'
            System.out.println("Incrementing the version for : " + storeVersionKeys[1]);
            versionProps.setProperty(storeVersionKeys[1], Long.toString(this.newVersion));
            MetadataVersionStoreUtils.setProperties(this.sysVersionStore, versionProps);

            while(!callbacksDone[0] && !callbacksDone[1] && !callbacksDone[2]) {
                Thread.sleep(2000);
            }

            // Check that version for index 1 has been udpated correctly.
            assertEquals(false, (this.updatedVersions[1] == 0));
            long updatedVersion = this.updatedVersions[1];
            assertEquals(updatedVersion, this.newVersion);

            // Check that versions for other indices have not changed
            assertEquals(true, (this.updatedVersions[0] == 0));
            assertEquals(true, (this.updatedVersions[2] == 0));
        } catch(Exception e) {
            e.printStackTrace();
            fail("Failed to start the Metadata Version Manager : " + e.getMessage());
        }
    }

    private void callbackForClusterChange() {
        try {
            Long clusterVersion = this.asyncCheckMetadata.getClusterMetadataVersion();
            if(clusterVersion != null) {
                this.updatedClusterVersion = clusterVersion;
            }
        } catch(Exception e) {
            e.printStackTrace();
            fail("Error in updating cluster.xml version: " + e.getMessage());
        } finally {
            this.callbackDone = true;
        }
    }

    private void callbackForStoreChange() {
        try {
            Long storeVersion = this.asyncCheckMetadata.getStoreMetadataVersion();
            if(storeVersion != null) {
                this.updatedStoreVersion = storeVersion;
            }
        } catch(Exception e) {
            e.printStackTrace();
            fail("Error in updating store version: " + e.getMessage());
        } finally {
            this.callbackDone = true;
        }
    }

    private void callbacksForStoreChange(int index) {
        try {
            Long storeVersion = this.asyncVersionManagers.get(index).getStoreMetadataVersion();
            if(storeVersion != null) {
                this.updatedVersions[index] = storeVersion;
            }
        } catch(Exception e) {
            e.printStackTrace();
            fail("Error in updating store version: " + e.getMessage());
        } finally {
            this.callbacksDone[index] = true;
        }
    }

    class StoresVersionCallback implements Callable<Void> {

        private int index;

        public StoresVersionCallback(int index) {
            this.index = index;
        }

        @Override
        public Void call() throws Exception {
            callbacksForStoreChange(this.index);
            return null;
        }

    }

}
TOP

Related Classes of voldemort.store.system.AsyncMetadataVersionManagerTest$StoresVersionCallback

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.