Search in sources :

Example 1 with ClockEntry

use of voldemort.versioning.ClockEntry in project voldemort by voldemort.

the class ZonedRebalanceNonContiguousZonesTest method testProxyPutDuringRebalancing.

@Test(timeout = 600000)
public void testProxyPutDuringRebalancing() throws Exception {
    logger.info("Starting testProxyPutDuringRebalancing");
    try {
        int[] zoneIds = new int[] { 1, 3 };
        int[][] nodesPerZone = new int[][] { { 3, 4, 5 }, { 9, 10, 11 } };
        int[][] partitionMap = new int[][] { { 0 }, { 1, 6 }, { 2 }, { 3 }, { 4, 7 }, { 5 } };
        Cluster currentCluster = ServerTestUtils.getLocalNonContiguousZonedCluster(zoneIds, nodesPerZone, partitionMap, ClusterTestUtils.getClusterPorts());
        Cluster finalCluster = UpdateClusterUtils.createUpdatedCluster(currentCluster, 5, Lists.newArrayList(7));
        finalCluster = UpdateClusterUtils.createUpdatedCluster(finalCluster, 11, Lists.newArrayList(6));
        /**
         * Original partition map
         *
         * [s3 : p0] [s4 : p1, p6] [s5 : p2]
         *
         * [s9 : p3] [s10 : p4, p7] [s11 : p5]
         *
         * final server partition ownership
         *
         * [s3 : p0] [s4 : p1] [s5 : p2, p7]
         *
         * [s9 : p3] [s10 : p4] [s11 : p5, p6]
         *
         * Note that rwStoreDefFileWithReplication is a "2/1/1" store def.
         *
         * Original server n-ary partition ownership
         *
         * [s3 : p0, p3-7] [s4 : p0-p7] [s5 : p1-2]
         *
         * [s9 : p0-3, p6-7] [s10 : p0-p7] [s11 : p4-5]
         *
         * final server n-ary partition ownership
         *
         * [s3 : p0, p2-7] [s4 : p0-1] [s5 : p1-p7]
         *
         * [s9 : p0-3, p5-7] [s10 : p0-4, p7] [s11 : p4-6]
         */
        List<Integer> serverList = Arrays.asList(3, 4, 5, 9, 10, 11);
        Map<String, String> configProps = new HashMap<String, String>();
        configProps.put("admin.max.threads", "5");
        final Cluster updatedCurrentCluster = startServers(currentCluster, rwStoreDefFileWithReplication, serverList, configProps);
        ExecutorService executors = Executors.newFixedThreadPool(2);
        final AtomicBoolean rebalancingComplete = new AtomicBoolean(false);
        final List<Exception> exceptions = Collections.synchronizedList(new ArrayList<Exception>());
        // Its is imperative that we test in a single shot since multiple batches would mean the proxy bridges
        // being torn down and established multiple times and we cannot test against the source
        // cluster topology then. getRebalanceKit uses batch size of infinite, so this should be fine.
        String bootstrapUrl = getBootstrapUrl(updatedCurrentCluster, 3);
        int maxParallel = 2;
        final ClusterTestUtils.RebalanceKit rebalanceKit = ClusterTestUtils.getRebalanceKit(bootstrapUrl, maxParallel, finalCluster);
        populateData(currentCluster, rwStoreDefWithReplication);
        final AdminClient adminClient = rebalanceKit.controller.getAdminClient();
        // the plan would cause these partitions to move:
        // Partition : Donor -> stealer
        // 
        // p2 (Z-SEC) : s4 -> s3
        // p3-6 (Z-PRI) : s4 -> s5
        // p7 (Z-PRI) : s3 -> s5
        // 
        // p5 (Z-SEC): s10 -> s9
        // p6 (Z-PRI): s10 -> s11
        // 
        // Rebalancing will run on servers 3, 5, 9, & 11
        final List<ByteArray> movingKeysList = sampleKeysFromPartition(adminClient, 4, rwStoreDefWithReplication.getName(), Arrays.asList(6), 20);
        assertTrue("Empty list of moving keys...", movingKeysList.size() > 0);
        final AtomicBoolean rebalancingStarted = new AtomicBoolean(false);
        final AtomicBoolean proxyWritesDone = new AtomicBoolean(false);
        final HashMap<String, String> baselineTuples = new HashMap<String, String>(testEntries);
        final HashMap<String, VectorClock> baselineVersions = new HashMap<String, VectorClock>();
        for (String key : baselineTuples.keySet()) {
            baselineVersions.put(key, new VectorClock());
        }
        final CountDownLatch latch = new CountDownLatch(2);
        // start get operation.
        executors.execute(new Runnable() {

            @Override
            public void run() {
                SocketStoreClientFactory factory = null;
                try {
                    // wait for the rebalancing to begin
                    List<VoldemortServer> serverList = Lists.newArrayList(serverMap.get(3), serverMap.get(5), serverMap.get(9), serverMap.get(11));
                    while (!rebalancingComplete.get()) {
                        Iterator<VoldemortServer> serverIterator = serverList.iterator();
                        while (serverIterator.hasNext()) {
                            VoldemortServer server = serverIterator.next();
                            if (ByteUtils.getString(server.getMetadataStore().get(MetadataStore.SERVER_STATE_KEY, null).get(0).getValue(), "UTF-8").compareTo(VoldemortState.REBALANCING_MASTER_SERVER.toString()) == 0) {
                                logger.info("Server " + server.getIdentityNode().getId() + " transitioned into REBALANCING MODE");
                                serverIterator.remove();
                            }
                        }
                        if (serverList.size() == 0) {
                            rebalancingStarted.set(true);
                            break;
                        }
                    }
                    if (rebalancingStarted.get()) {
                        factory = new SocketStoreClientFactory(new ClientConfig().setBootstrapUrls(getBootstrapUrl(updatedCurrentCluster, 3)).setEnableLazy(false).setSocketTimeout(120, TimeUnit.SECONDS).setClientZoneId(3));
                        final StoreClient<String, String> storeClientRW = new DefaultStoreClient<String, String>(testStoreNameRW, null, factory, 3);
                        // Initially, all data now with zero vector clock
                        for (ByteArray movingKey : movingKeysList) {
                            try {
                                String keyStr = ByteUtils.getString(movingKey.get(), "UTF-8");
                                String valStr = "proxy_write";
                                storeClientRW.put(keyStr, valStr);
                                baselineTuples.put(keyStr, valStr);
                                baselineVersions.get(keyStr).incrementVersion(11, System.currentTimeMillis());
                                proxyWritesDone.set(true);
                                if (rebalancingComplete.get()) {
                                    break;
                                }
                            } catch (InvalidMetadataException e) {
                                logger.error("Encountered an invalid metadata exception.. ", e);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("Exception in proxy write thread..", e);
                    exceptions.add(e);
                } finally {
                    if (factory != null)
                        factory.close();
                    latch.countDown();
                }
            }
        });
        executors.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    rebalanceKit.rebalance();
                } catch (Exception e) {
                    logger.error("Error in rebalancing... ", e);
                    exceptions.add(e);
                } finally {
                    rebalancingComplete.set(true);
                    latch.countDown();
                }
            }
        });
        latch.await();
        executors.shutdown();
        executors.awaitTermination(300, TimeUnit.SECONDS);
        assertEquals("Client did not see all server transition into rebalancing state", rebalancingStarted.get(), true);
        assertEquals("Not enough time to begin proxy writing", proxyWritesDone.get(), true);
        checkEntriesPostRebalance(updatedCurrentCluster, finalCluster, Lists.newArrayList(rwStoreDefWithReplication), Arrays.asList(3, 4, 5, 9, 10, 11), baselineTuples, baselineVersions);
        checkConsistentMetadata(finalCluster, serverList);
        // check No Exception
        if (exceptions.size() > 0) {
            for (Exception e : exceptions) {
                e.printStackTrace();
            }
            fail("Should not see any exceptions.");
        }
        // check that the proxy writes were made to the original donor, node 4
        List<ClockEntry> clockEntries = new ArrayList<ClockEntry>(serverList.size());
        for (Integer nodeid : serverList) clockEntries.add(new ClockEntry(nodeid.shortValue(), System.currentTimeMillis()));
        VectorClock clusterXmlClock = new VectorClock(clockEntries, System.currentTimeMillis());
        for (Integer nodeid : serverList) adminClient.metadataMgmtOps.updateRemoteCluster(nodeid, currentCluster, clusterXmlClock);
        adminClient.setAdminClientCluster(currentCluster);
        checkForTupleEquivalence(adminClient, 4, testStoreNameRW, movingKeysList, baselineTuples, baselineVersions);
        // stop servers
        try {
            stopServer(serverList);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    } catch (AssertionError ae) {
        logger.error("Assertion broken in testProxyPutDuringRebalancing ", ae);
        throw ae;
    }
}
Also used : DefaultStoreClient(voldemort.client.DefaultStoreClient) StoreClient(voldemort.client.StoreClient) HashMap(java.util.HashMap) InvalidMetadataException(voldemort.store.InvalidMetadataException) ArrayList(java.util.ArrayList) VoldemortServer(voldemort.server.VoldemortServer) SocketStoreClientFactory(voldemort.client.SocketStoreClientFactory) Iterator(java.util.Iterator) ByteArray(voldemort.utils.ByteArray) List(java.util.List) ArrayList(java.util.ArrayList) ClientConfig(voldemort.client.ClientConfig) VectorClock(voldemort.versioning.VectorClock) Cluster(voldemort.cluster.Cluster) CountDownLatch(java.util.concurrent.CountDownLatch) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) IOException(java.io.IOException) InvalidMetadataException(voldemort.store.InvalidMetadataException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClusterTestUtils(voldemort.ClusterTestUtils) ExecutorService(java.util.concurrent.ExecutorService) ClockEntry(voldemort.versioning.ClockEntry) AdminClient(voldemort.client.protocol.admin.AdminClient) Test(org.junit.Test)

Example 2 with ClockEntry

use of voldemort.versioning.ClockEntry in project voldemort by voldemort.

the class ClusterForkLiftToolTest method testForkLiftOverWrite.

@Test
public void testForkLiftOverWrite() throws Exception {
    StoreRoutingPlan srcStoreInstance = new StoreRoutingPlan(srcCluster, globallyResolvingStoreDef);
    // populate data on the source cluster..
    for (Map.Entry<String, String> entry : kvPairs.entrySet()) {
        srcGloballyResolvingStoreClient.put(entry.getKey(), entry.getValue());
    }
    // generate a conflict on the primary and a secondary
    List<Integer> nodeList = srcStoreInstance.getReplicationNodeList(srcStoreInstance.getMasterPartitionId(conflictKey.getBytes("UTF-8")));
    VectorClock losingClock = new VectorClock(Lists.newArrayList(new ClockEntry((short) 0, 5)), System.currentTimeMillis());
    VectorClock winningClock = new VectorClock(Lists.newArrayList(new ClockEntry((short) 1, 5)), losingClock.getTimestamp() + 1);
    srcAdminClient.storeOps.putNodeKeyValue(GLOBALLY_RESOLVING_STORE_NAME, new NodeValue<ByteArray, byte[]>(nodeList.get(0), new ByteArray(conflictKey.getBytes("UTF-8")), new Versioned<byte[]>("losing value".getBytes("UTF-8"), losingClock)));
    srcAdminClient.storeOps.putNodeKeyValue(GLOBALLY_RESOLVING_STORE_NAME, new NodeValue<ByteArray, byte[]>(nodeList.get(1), new ByteArray(conflictKey.getBytes("UTF-8")), new Versioned<byte[]>("winning value".getBytes("UTF-8"), winningClock)));
    // *** do a write to destination cluster ***
    // This is the main test , where after fork lift this value should be
    // overwritten. This is the only difference.
    dstGloballyResolvingStoreClient.put(firstKey, "before forklift");
    // Make the current thread sleep , so when the new clock is generated
    // using milliSeconds it is greater and must be overwritten.
    Thread.sleep(2);
    // perform the forklifting..
    ClusterForkLiftTool forkLiftTool = new ClusterForkLiftTool(srcBootStrapUrl, dstBootStrapUrl, // OverWrite
    true, // ignore
    false, // mismatch
    10000, 1, 1000, Lists.newArrayList(GLOBALLY_RESOLVING_STORE_NAME), null, ClusterForkLiftTool.ForkLiftTaskMode.global_resolution);
    forkLiftTool.run();
    // do a write to destination cluster
    dstGloballyResolvingStoreClient.put(lastKey, "after forklift");
    // verify data on the destination is as expected
    for (Map.Entry<String, String> entry : kvPairs.entrySet()) {
        String dstClusterValue = dstGloballyResolvingStoreClient.get(entry.getKey()).getValue();
        if (entry.getKey().equals(lastKey)) {
            assertEquals("can't update value after forklift", dstClusterValue, "after forklift");
        } else if (entry.getKey().equals(conflictKey)) {
            assertEquals("Conflict resolution incorrect", dstClusterValue, "winning value");
        } else {
            if (!dstClusterValue.equals(entry.getValue())) {
                assertEquals("fork lift data missing", dstClusterValue, entry.getValue());
            }
        }
    }
}
Also used : StoreRoutingPlan(voldemort.routing.StoreRoutingPlan) Versioned(voldemort.versioning.Versioned) VectorClock(voldemort.versioning.VectorClock) HashMap(java.util.HashMap) Map(java.util.Map) ClockEntry(voldemort.versioning.ClockEntry) Test(org.junit.Test)

Example 3 with ClockEntry

use of voldemort.versioning.ClockEntry in project voldemort by voldemort.

the class ClusterForkLiftToolTest method testGloballyResolvingForkLift.

@Test
public void testGloballyResolvingForkLift() throws Exception {
    StoreRoutingPlan srcStoreInstance = new StoreRoutingPlan(srcCluster, globallyResolvingStoreDef);
    // populate data on the source cluster..
    for (Map.Entry<String, String> entry : kvPairs.entrySet()) {
        srcGloballyResolvingStoreClient.put(entry.getKey(), entry.getValue());
    }
    // generate a conflict on the primary and a secondary
    List<Integer> nodeList = srcStoreInstance.getReplicationNodeList(srcStoreInstance.getMasterPartitionId(conflictKey.getBytes("UTF-8")));
    VectorClock losingClock = new VectorClock(Lists.newArrayList(new ClockEntry((short) 0, 5)), System.currentTimeMillis());
    VectorClock winningClock = new VectorClock(Lists.newArrayList(new ClockEntry((short) 1, 5)), losingClock.getTimestamp() + 1);
    srcAdminClient.storeOps.putNodeKeyValue(GLOBALLY_RESOLVING_STORE_NAME, new NodeValue<ByteArray, byte[]>(nodeList.get(0), new ByteArray(conflictKey.getBytes("UTF-8")), new Versioned<byte[]>("losing value".getBytes("UTF-8"), losingClock)));
    srcAdminClient.storeOps.putNodeKeyValue(GLOBALLY_RESOLVING_STORE_NAME, new NodeValue<ByteArray, byte[]>(nodeList.get(1), new ByteArray(conflictKey.getBytes("UTF-8")), new Versioned<byte[]>("winning value".getBytes("UTF-8"), winningClock)));
    // do a write to destination cluster
    dstGloballyResolvingStoreClient.put(firstKey, "before forklift");
    // perform the forklifting..
    ClusterForkLiftTool forkLiftTool = new ClusterForkLiftTool(srcBootStrapUrl, dstBootStrapUrl, false, // ignoreSchemaMismatch
    false, 10000, 1, 1000, Lists.newArrayList(GLOBALLY_RESOLVING_STORE_NAME), null, ClusterForkLiftTool.ForkLiftTaskMode.global_resolution);
    forkLiftTool.run();
    // do a write to destination cluster
    dstGloballyResolvingStoreClient.put(lastKey, "after forklift");
    // verify data on the destination is as expected
    for (Map.Entry<String, String> entry : kvPairs.entrySet()) {
        if (entry.getKey().equals(firstKey)) {
            assertEquals("Online write overwritten", dstGloballyResolvingStoreClient.get(firstKey).getValue(), "before forklift");
        } else if (entry.getKey().equals(lastKey)) {
            assertEquals("can't update value after forklift", dstGloballyResolvingStoreClient.get(lastKey).getValue(), "after forklift");
        } else if (entry.getKey().equals(conflictKey)) {
            assertEquals("Conflict resolution incorrect", dstGloballyResolvingStoreClient.get(conflictKey).getValue(), "winning value");
        } else {
            assertEquals("fork lift data missing", dstGloballyResolvingStoreClient.get(entry.getKey()).getValue(), entry.getValue());
        }
    }
}
Also used : StoreRoutingPlan(voldemort.routing.StoreRoutingPlan) Versioned(voldemort.versioning.Versioned) VectorClock(voldemort.versioning.VectorClock) HashMap(java.util.HashMap) Map(java.util.Map) ClockEntry(voldemort.versioning.ClockEntry) Test(org.junit.Test)

Example 4 with ClockEntry

use of voldemort.versioning.ClockEntry in project voldemort by voldemort.

the class ProtoUtils method encodeClock.

public static VProto.VectorClock.Builder encodeClock(Version version) {
    VectorClock clock = (VectorClock) version;
    VProto.VectorClock.Builder encoded = VProto.VectorClock.newBuilder();
    encoded.setTimestamp(clock.getTimestamp());
    for (ClockEntry entry : clock.getEntries()) encoded.addEntries(VProto.ClockEntry.newBuilder().setNodeId(entry.getNodeId()).setVersion(entry.getVersion()));
    return encoded;
}
Also used : VectorClock(voldemort.versioning.VectorClock) ClockEntry(voldemort.versioning.ClockEntry)

Example 5 with ClockEntry

use of voldemort.versioning.ClockEntry in project voldemort by voldemort.

the class RedirectingStoreTest method makeSuperClock.

private VectorClock makeSuperClock(long time) {
    List<ClockEntry> clockEntries = new ArrayList<ClockEntry>();
    clockEntries.add(new ClockEntry((short) 0, time));
    clockEntries.add(new ClockEntry((short) 1, time));
    clockEntries.add(new ClockEntry((short) 2, time));
    return new VectorClock(clockEntries, time);
}
Also used : VectorClock(voldemort.versioning.VectorClock) ArrayList(java.util.ArrayList) ClockEntry(voldemort.versioning.ClockEntry)

Aggregations

ClockEntry (voldemort.versioning.ClockEntry)10 VectorClock (voldemort.versioning.VectorClock)10 Test (org.junit.Test)7 HashMap (java.util.HashMap)6 ArrayList (java.util.ArrayList)5 Versioned (voldemort.versioning.Versioned)5 AdminClient (voldemort.client.protocol.admin.AdminClient)4 StoreRoutingPlan (voldemort.routing.StoreRoutingPlan)4 IOException (java.io.IOException)3 Iterator (java.util.Iterator)3 List (java.util.List)3 Map (java.util.Map)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 ExecutorService (java.util.concurrent.ExecutorService)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 ClusterTestUtils (voldemort.ClusterTestUtils)3 ClientConfig (voldemort.client.ClientConfig)3 DefaultStoreClient (voldemort.client.DefaultStoreClient)3 SocketStoreClientFactory (voldemort.client.SocketStoreClientFactory)3 StoreClient (voldemort.client.StoreClient)3