Search in sources :

Example 1 with BaseStoreRoutingPlan

use of voldemort.routing.BaseStoreRoutingPlan in project voldemort by voldemort.

the class RedirectingStore method redirectingPut.

/**
 * This is slightly different from other redirecting*** methods in that,
 * this updates the remote proxy node, with this put request, so we can
 * switch back to the old cluster topology if needed
 *
 * @param key
 * @param value
 * @param transforms
 * @throws VoldemortException
 */
private void redirectingPut(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws VoldemortException {
    Cluster currentCluster = metadata.getCluster();
    // TODO:refactor O(n) linear lookup of storedef here. Ideally should be
    // a hash lookup.
    StoreDefinition storeDef = metadata.getStoreDef(getName());
    /*
         * defensively, error out if this is a read-only store and someone is
         * doing puts against it. We don't to do extra work and fill the log
         * with errors in that case.
         */
    if (storeDef.getType().compareTo(ReadOnlyStorageConfiguration.TYPE_NAME) == 0) {
        throw new UnsupportedOperationException("put() not supported on read-only store");
    }
    BaseStoreRoutingPlan currentRoutingPlan = new BaseStoreRoutingPlan(currentCluster, storeDef);
    Integer redirectNode = getProxyNode(currentRoutingPlan, storeDef, key.get());
    /**
     * If I am rebalancing for this key, try to do remote get() if this node
     * does not have the key , put it locally first to get the correct
     * version ignoring any {@link ObsoleteVersionException}
     */
    if (redirectNode != null) {
        /*
             * first check if the key exists locally. If so, it means, it has
             * been moved over (either by a proxy fetch or background fetch) and
             * we are good simply issuing the put on top of that.
             */
        List<Versioned<byte[]>> vals = getInnerStore().get(key, transforms);
        if (vals.isEmpty()) {
            // if not, then go proxy fetch it
            if (logger.isTraceEnabled()) {
                logger.trace("Proxying GET (before PUT) on stealer:" + metadata.getNodeId() + " for  key " + ByteUtils.toHexString(key.get()) + " to node:" + redirectNode);
            }
            proxyGetAndLocalPut(key, redirectNode, transforms);
        }
    }
    // Here we are sure that the current node has caught up with the proxy
    // for this key. Moving on to the put logic.
    // put the data locally, if this step fails, there will be no proxy puts
    getInnerStore().put(key, value, transforms);
    // OVE). So do not send proxy puts in those cases.
    if (redirectNode != null && !currentRoutingPlan.getReplicationNodeList(key.get()).contains(redirectNode)) {
        AsyncProxyPutTask asyncProxyPutTask = new AsyncProxyPutTask(this, key, value, transforms, redirectNode);
        proxyPutStats.reportProxyPutSubmission();
        proxyPutWorkerPool.submit(asyncProxyPutTask);
    }
}
Also used : Versioned(voldemort.versioning.Versioned) StoreDefinition(voldemort.store.StoreDefinition) Cluster(voldemort.cluster.Cluster) BaseStoreRoutingPlan(voldemort.routing.BaseStoreRoutingPlan)

Example 2 with BaseStoreRoutingPlan

use of voldemort.routing.BaseStoreRoutingPlan in project voldemort by voldemort.

the class RedirectingStore method getProxyNode.

/**
 * Checks if the server has to do any proxying of gets/puts to another
 * server, as a part of an ongoing rebalance operation.
 *
 * Basic idea : Any given node which is a stealer of a partition, as the ith
 * replica of a given zone, will proxy to the old ith replica of the
 * partition in the given zone, as per the source cluster metadata.
 * Exception : if this amounts to proxying to itself.
 *
 * Note on Zone Expansion : For zone expansion, there will be no proxying
 * within the new zone. This is a practical assumption since if we fail, we
 * fallback to a cluster topology without the new zone. As a result, reads
 * from the new zone are not guaranteed to return some values during the
 * course of zone expansion. This is a also reasonable since any
 * organization undertaking such effort would need to have the data in place
 * in the new zone, before the client apps are moved over.
 *
 * TODO:refactor Add helper methods to StoreRoutingPlan to simplify this
 * code
 *
 * @param currentRoutingPlan routing plan object based on cluster's current
 *        topology
 * @param storeDef definition of the store being redirected
 * @param key to decide where to proxy to
 * @return Null if no proxying is required else node id of the server to
 *         proxy to
 */
private Integer getProxyNode(BaseStoreRoutingPlan currentRoutingPlan, StoreDefinition storeDef, byte[] key) {
    // get out if redirecting is disabled.
    if (!isRedirectingStoreEnabled.get()) {
        return null;
    }
    // TODO a better design would be to get these state changes from
    // metadata listener callbacks, so we need not allocate these objects
    // all the time. This has been implemented, but not integration tested,
    // on the following branch:
    // https://github.com/voldemort/voldemort/compare/proxy-put-metadata-listener
    Cluster sourceCluster = metadata.getRebalancingSourceCluster();
    // Logic to get the old storedef
    List<StoreDefinition> sourceStoreDefs = metadata.getRebalancingSourceStores();
    if (sourceCluster == null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Old Cluster is null.. bail");
        }
        return null;
    }
    if (sourceStoreDefs == null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Old stores def is null.. bail");
        }
        return null;
    }
    StoreDefinition sourceStoreDef = null;
    sourceStoreDef = StoreUtils.getStoreDef(sourceStoreDefs, storeDef.getName());
    Integer nodeId = metadata.getNodeId();
    Integer zoneId = currentRoutingPlan.getCluster().getNodeById(nodeId).getZoneId();
    // Use the old store definition to get the routing object
    BaseStoreRoutingPlan oldRoutingPlan = new BaseStoreRoutingPlan(sourceCluster, sourceStoreDef);
    // Check the current node's relationship to the key.
    int zoneNAry = currentRoutingPlan.getZoneNAry(zoneId, nodeId, key);
    // Determine which node held the key with the same relationship in the
    // old cluster. That is your man!
    Integer redirectNodeId;
    try {
        redirectNodeId = oldRoutingPlan.getNodeIdForZoneNary(zoneId, zoneNAry, key);
    } catch (VoldemortException ve) {
        /*
             * If the zone does not exist, as in the case of Zone Expansion,
             * there will be no proxy bridges built. The only other time an
             * exception can be thrown here is when the replicaType is invalid.
             * But that would mean we are changing say a 2/1/1 store to 3/2/2,
             * which Voldemort currently does not support anyway
             */
        return null;
    }
    // Unless he is the same as this node (where this is meaningless effort)
    if (redirectNodeId == nodeId) {
        return null;
    }
    return redirectNodeId;
}
Also used : StoreDefinition(voldemort.store.StoreDefinition) Cluster(voldemort.cluster.Cluster) BaseStoreRoutingPlan(voldemort.routing.BaseStoreRoutingPlan) VoldemortException(voldemort.VoldemortException)

Example 3 with BaseStoreRoutingPlan

use of voldemort.routing.BaseStoreRoutingPlan in project voldemort by voldemort.

the class RoutedStoreTest method testReadRepairWithFailures.

/**
 * See Issue #89: Sequential retrieval in RoutedStore.get doesn't consider
 * repairReads.
 */
@Test
public void testReadRepairWithFailures() throws Exception {
    cluster = getNineNodeCluster();
    RoutedStore routedStore = getStore(cluster, 2, 2, 1, 0);
    BaseStoreRoutingPlan routingPlan = new BaseStoreRoutingPlan(cluster, this.storeDef);
    List<Integer> replicatingNodes = routingPlan.getReplicationNodeList(aKey.get());
    // This is node 1
    Node primaryNode = Iterables.get(cluster.getNodes(), replicatingNodes.get(0));
    // This is node 6
    Node secondaryNode = Iterables.get(cluster.getNodes(), replicatingNodes.get(1));
    // Disable primary node so that the first put happens with 6 as the
    // pseudo master
    recordException(failureDetector, primaryNode);
    Store<ByteArray, byte[], byte[]> store = new InconsistencyResolvingStore<ByteArray, byte[], byte[]>(routedStore, new VectorClockInconsistencyResolver<byte[]>());
    store.put(aKey, new Versioned<byte[]>(aValue), null);
    byte[] anotherValue = "john".getBytes();
    /*
         * Disable the secondary node and enable primary node to prevent the
         * secondary from getting the new version
         */
    recordException(failureDetector, secondaryNode);
    recordSuccess(failureDetector, primaryNode);
    // Generate the clock based off secondary so that the resulting clock
    // will be [1:1, 6:1] across the replicas, except for the secondary
    // which will be [6:1]
    VectorClock clock = getClock(6);
    store.put(aKey, new Versioned<byte[]>(anotherValue, clock), null);
    // Enable secondary and disable primary, the following get should cause
    // a read repair on the secondary in the code path that is only executed
    // if there are failures. This should repair the secondary with the
    // superceding clock [1:1,6:1]
    recordException(failureDetector, primaryNode);
    recordSuccess(failureDetector, secondaryNode);
    List<Versioned<byte[]>> versioneds = store.get(aKey, null);
    assertEquals(1, versioneds.size());
    assertEquals(new ByteArray(anotherValue), new ByteArray(versioneds.get(0).getValue()));
    // Read repairs are done asynchronously, so we sleep for a short period.
    // It may be a good idea to use a synchronous executor service.
    Thread.sleep(500);
    for (Map.Entry<Integer, Store<ByteArray, byte[], byte[]>> innerStoreEntry : routedStore.getInnerStores().entrySet()) {
        // Only look at the nodes in the pref list
        if (replicatingNodes.contains(innerStoreEntry.getKey())) {
            List<Versioned<byte[]>> innerVersioneds = innerStoreEntry.getValue().get(aKey, null);
            assertEquals(1, versioneds.size());
            assertEquals(new ByteArray(anotherValue), new ByteArray(innerVersioneds.get(0).getValue()));
        }
    }
}
Also used : Versioned(voldemort.versioning.Versioned) Node(voldemort.cluster.Node) VectorClock(voldemort.versioning.VectorClock) Store(voldemort.store.Store) SleepyStore(voldemort.store.SleepyStore) StatTrackingStore(voldemort.store.stats.StatTrackingStore) InconsistencyResolvingStore(voldemort.store.versioned.InconsistencyResolvingStore) FailingStore(voldemort.store.FailingStore) FailingReadsStore(voldemort.store.FailingReadsStore) InconsistencyResolvingStore(voldemort.store.versioned.InconsistencyResolvingStore) ByteArray(voldemort.utils.ByteArray) BaseStoreRoutingPlan(voldemort.routing.BaseStoreRoutingPlan) Map(java.util.Map) HashMap(java.util.HashMap) AbstractByteArrayStoreTest(voldemort.store.AbstractByteArrayStoreTest) Test(org.junit.Test)

Example 4 with BaseStoreRoutingPlan

use of voldemort.routing.BaseStoreRoutingPlan in project voldemort by voldemort.

the class AbstractNonZonedRebalanceTest method populateData.

protected void populateData(Cluster cluster, StoreDefinition storeDef, AdminClient adminClient, boolean isReadOnly) throws Exception {
    // Populate Read write stores
    if (!isReadOnly) {
        // Create SocketStores for each Node first
        Map<Integer, Store<ByteArray, byte[], byte[]>> storeMap = new HashMap<Integer, Store<ByteArray, byte[], byte[]>>();
        for (Node node : cluster.getNodes()) {
            storeMap.put(node.getId(), getSocketStore(storeDef.getName(), node.getHost(), node.getSocketPort()));
        }
        BaseStoreRoutingPlan storeInstance = new BaseStoreRoutingPlan(cluster, storeDef);
        for (Entry<String, String> entry : testEntries.entrySet()) {
            ByteArray keyBytes = new ByteArray(ByteUtils.getBytes(entry.getKey(), "UTF-8"));
            List<Integer> preferenceNodes = storeInstance.getReplicationNodeList(keyBytes.get());
            // Go over every node
            for (int nodeId : preferenceNodes) {
                try {
                    storeMap.get(nodeId).put(keyBytes, new Versioned<byte[]>(ByteUtils.getBytes(entry.getValue(), "UTF-8")), null);
                } catch (ObsoleteVersionException e) {
                    logger.info("Why are we seeing this at all here ?? ");
                    e.printStackTrace();
                }
            }
        }
        // close all socket stores
        for (Store<ByteArray, byte[], byte[]> store : storeMap.values()) {
            store.close();
        }
    } else {
        // Populate Read only stores
        File baseDir = TestUtils.createTempDir();
        JsonReader reader = ReadOnlyStorageEngineTestInstance.makeTestDataReader(testEntries, baseDir);
        RoutingStrategy router = new RoutingStrategyFactory().updateRoutingStrategy(storeDef, cluster);
        File outputDir = TestUtils.createTempDir(baseDir);
        JsonStoreBuilder storeBuilder = new JsonStoreBuilder(reader, cluster, storeDef, router, outputDir, null, testEntries.size() / 5, 1, NUM_RO_CHUNKS_PER_BUCKET, 10000, false);
        storeBuilder.build(ReadOnlyStorageFormat.READONLY_V2);
        AdminStoreSwapper swapper = new AdminStoreSwapper(Executors.newFixedThreadPool(cluster.getNumberOfNodes()), adminClient, 100000);
        swapper.fetchAndSwapStoreData(testStoreNameRO, outputDir.getAbsolutePath(), 1L);
    }
}
Also used : HashMap(java.util.HashMap) RoutingStrategyFactory(voldemort.routing.RoutingStrategyFactory) Node(voldemort.cluster.Node) Store(voldemort.store.Store) MetadataStore(voldemort.store.metadata.MetadataStore) JsonStoreBuilder(voldemort.store.readonly.JsonStoreBuilder) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) AdminStoreSwapper(voldemort.store.readonly.swapper.AdminStoreSwapper) RoutingStrategy(voldemort.routing.RoutingStrategy) ByteArray(voldemort.utils.ByteArray) JsonReader(voldemort.serialization.json.JsonReader) BaseStoreRoutingPlan(voldemort.routing.BaseStoreRoutingPlan) File(java.io.File)

Example 5 with BaseStoreRoutingPlan

use of voldemort.routing.BaseStoreRoutingPlan in project voldemort by voldemort.

the class AbstractZonedRebalanceTest method populateData.

private void populateData(Cluster cluster, StoreDefinition storeDef) throws Exception {
    // Create SocketStores for each Node first
    Map<Integer, Store<ByteArray, byte[], byte[]>> storeMap = new HashMap<Integer, Store<ByteArray, byte[], byte[]>>();
    for (Node node : cluster.getNodes()) {
        storeMap.put(node.getId(), getSocketStore(storeDef.getName(), node.getHost(), node.getSocketPort()));
    }
    BaseStoreRoutingPlan storeInstance = new BaseStoreRoutingPlan(cluster, storeDef);
    for (Entry<String, String> entry : testEntries.entrySet()) {
        ByteArray keyBytes = new ByteArray(ByteUtils.getBytes(entry.getKey(), "UTF-8"));
        List<Integer> preferenceNodes = storeInstance.getReplicationNodeList(keyBytes.get());
        // Go over every node
        for (int nodeId : preferenceNodes) {
            try {
                storeMap.get(nodeId).put(keyBytes, new Versioned<byte[]>(ByteUtils.getBytes(entry.getValue(), "UTF-8")), null);
            } catch (ObsoleteVersionException e) {
                logger.info("Why are we seeing this at all here ?? ");
                e.printStackTrace();
            }
        }
    }
    // close all socket stores
    for (Store<ByteArray, byte[], byte[]> store : storeMap.values()) {
        store.close();
    }
}
Also used : HashMap(java.util.HashMap) Node(voldemort.cluster.Node) Store(voldemort.store.Store) MetadataStore(voldemort.store.metadata.MetadataStore) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) ByteArray(voldemort.utils.ByteArray) BaseStoreRoutingPlan(voldemort.routing.BaseStoreRoutingPlan)

Aggregations

BaseStoreRoutingPlan (voldemort.routing.BaseStoreRoutingPlan)14 StoreDefinition (voldemort.store.StoreDefinition)7 ByteArray (voldemort.utils.ByteArray)7 HashMap (java.util.HashMap)6 Store (voldemort.store.Store)6 Node (voldemort.cluster.Node)5 Versioned (voldemort.versioning.Versioned)5 Test (org.junit.Test)4 Cluster (voldemort.cluster.Cluster)4 File (java.io.File)3 MetadataStore (voldemort.store.metadata.MetadataStore)3 ObsoleteVersionException (voldemort.versioning.ObsoleteVersionException)3 VectorClock (voldemort.versioning.VectorClock)3 StoreDefinitionsMapper (voldemort.xml.StoreDefinitionsMapper)3 IOException (java.io.IOException)2 StringReader (java.io.StringReader)2 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 VoldemortException (voldemort.VoldemortException)2 AbstractByteArrayStoreTest (voldemort.store.AbstractByteArrayStoreTest)2