Search in sources :

Example 21 with AdminClient

use of voldemort.client.protocol.admin.AdminClient in project voldemort by voldemort.

the class AdminServiceRequestHandler method handleFetchFailure.

private Message handleFetchFailure(VAdminProto.HandleFetchFailureRequest handleFetchFailure) {
    String storeName = handleFetchFailure.getStoreName();
    long pushVersion = handleFetchFailure.getPushVersion();
    String extraInfo = handleFetchFailure.getInfo();
    Properties extraInfoProperties = new Properties();
    try {
        extraInfoProperties.load(new StringReader(extraInfo));
    } catch (IOException e) {
        logger.error("Got IOException while trying to decipher a HandleFetchFailureRequest's info.", e);
    }
    logger.info("Received HandleFetchFailureRequest:\n" + "\tstore_name: " + storeName + "\n" + "\tpush_version: " + pushVersion + "\n" + "\tinfo: " + extraInfoProperties.toString());
    VAdminProto.HandleFetchFailureResponse.Builder response = VAdminProto.HandleFetchFailureResponse.newBuilder();
    AdminClient adminClient = AdminClient.createTempAdminClient(voldemortConfig, metadataStore.getCluster(), 1);
    try {
        // Get replica.factor for current store
        StoreDefinition storeDef = adminClient.metadataMgmtOps.getStoreDefinition(storeName);
        if (null == storeDef) {
            throw new StoreNotFoundException(storeName);
        }
        int replicaFactor = storeDef.getReplicationFactor();
        int maxNodeFailure = voldemortConfig.getHighAvailabilityPushMaxNodeFailures();
        // Considering replicaFactor could be smaller than maxNodeFailure configured in cluster level,
        // we need to compare the node failure number with the smaller number of (RF - 1, maxNodeFailure)
        // to make sure there is at least one replica running.
        maxNodeFailure = Math.min(maxNodeFailure, replicaFactor - 1);
        Set<Integer> nodesFailedInThisFetch = Sets.newHashSet(handleFetchFailure.getFailedNodesList());
        int failureCount = nodesFailedInThisFetch.size();
        boolean swapIsPossible = false;
        String responseMessage = "";
        if (failureCount > maxNodeFailure) {
            // Too many nodes failed to tolerate this strategy... let's bail out.
            responseMessage = "We cannot use pushHighAvailability because there is more than " + maxNodeFailure + " nodes that failed their fetches and build.replica.factor is " + replicaFactor + "...";
            logger.error(responseMessage);
        } else {
            FailedFetchLock distributedLock = null;
            try {
                distributedLock = FailedFetchLock.getLock(voldemortConfig, new Props(extraInfoProperties));
                distributedLock.acquireLock();
                Set<Integer> alreadyDisabledNodes = distributedLock.getDisabledNodes();
                Set<Integer> allNodesToBeDisabled = Sets.newHashSet();
                allNodesToBeDisabled.addAll(alreadyDisabledNodes);
                allNodesToBeDisabled.addAll(nodesFailedInThisFetch);
                int disabledNodeSize = allNodesToBeDisabled.size();
                if (disabledNodeSize > maxNodeFailure) {
                    // Too many exceptions to tolerate this strategy... let's bail out.
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("We cannot use pushHighAvailability because it would bring the total ");
                    stringBuilder.append("number of nodes with disabled stores to more than ");
                    stringBuilder.append(maxNodeFailure);
                    stringBuilder.append("... alreadyDisabledNodes: [");
                    boolean firstItem = true;
                    for (Integer nodeId : alreadyDisabledNodes) {
                        if (firstItem) {
                            firstItem = false;
                        } else {
                            stringBuilder.append(", ");
                        }
                        stringBuilder.append(nodeId);
                    }
                    stringBuilder.append("], nodesFailedInThisFetch: [");
                    firstItem = true;
                    for (Integer nodeId : nodesFailedInThisFetch) {
                        if (firstItem) {
                            firstItem = false;
                        } else {
                            stringBuilder.append(", ");
                        }
                        stringBuilder.append(nodeId);
                    }
                    stringBuilder.append("]");
                    stringBuilder.append(", and build.replica.factor is ").append(replicaFactor);
                    responseMessage = stringBuilder.toString();
                    logger.error(responseMessage);
                } else {
                    String nodesString = "node";
                    if (nodesFailedInThisFetch.size() > 1) {
                        // Good grammar is important son
                        nodesString += "s";
                    }
                    nodesString += " [";
                    boolean firstNode = true;
                    for (Integer nodeId : nodesFailedInThisFetch) {
                        logger.warn("Will disable store '" + storeName + "' on node " + nodeId);
                        distributedLock.addDisabledNode(nodeId, storeName, pushVersion);
                        logger.warn("Store '" + storeName + "' is disabled on node " + nodeId);
                        if (firstNode) {
                            firstNode = false;
                        } else {
                            nodesString += ", ";
                        }
                        nodesString += nodeId;
                        response.addDisableStoreResponses(adminClient.readonlyOps.disableStoreVersion(nodeId, storeName, pushVersion, extraInfo));
                    }
                    nodesString += "]";
                    swapIsPossible = true;
                    responseMessage = "Swap will be possible even though " + nodesString + " failed to fetch.";
                    logger.info(responseMessage);
                }
            } catch (ClassNotFoundException e) {
                String logMessage = "Failed to find requested FailedFetchLock implementation while setting up pushHighAvailability. ";
                logger.error(responseMessage, e);
                responseMessage = logMessage + "\n" + ExceptionUtils.stackTraceToString(e);
            } catch (Exception e) {
                String logMessage = "Got exception while trying to execute pushHighAvailability. ";
                logger.error(responseMessage, e);
                responseMessage = logMessage + "\n" + ExceptionUtils.stackTraceToString(e);
            } finally {
                if (distributedLock != null) {
                    try {
                        distributedLock.releaseLock();
                    } catch (Exception e) {
                        logger.error("Error while trying to release the shared lock used for pushHighAvailability!", e);
                    } finally {
                        try {
                            distributedLock.close();
                        } catch (Exception inception) {
                            logger.error("Error while trying to close the shared lock used for pushHighAvailability!", inception);
                        }
                    }
                }
            }
        }
        response.setSwapIsPossible(swapIsPossible);
        response.setInfo(responseMessage);
    } finally {
        adminClient.close();
    }
    return response.build();
}
Also used : IOException(java.io.IOException) Properties(java.util.Properties) Props(voldemort.utils.Props) NoSuchCapabilityException(voldemort.store.NoSuchCapabilityException) ConfigurationException(voldemort.utils.ConfigurationException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) StoreOperationFailureException(voldemort.store.StoreOperationFailureException) VoldemortException(voldemort.VoldemortException) IOException(java.io.IOException) PersistenceFailureException(voldemort.store.PersistenceFailureException) StoreNotFoundException(voldemort.store.StoreNotFoundException) StoreNotFoundException(voldemort.store.StoreNotFoundException) StoreDefinition(voldemort.store.StoreDefinition) StringReader(java.io.StringReader) FailedFetchLock(voldemort.store.readonly.swapper.FailedFetchLock) AdminClient(voldemort.client.protocol.admin.AdminClient)

Example 22 with AdminClient

use of voldemort.client.protocol.admin.AdminClient in project voldemort by voldemort.

the class AdminServiceRequestHandler method handleAddStore.

public VAdminProto.AddStoreResponse handleAddStore(VAdminProto.AddStoreRequest request) {
    VAdminProto.AddStoreResponse.Builder response = VAdminProto.AddStoreResponse.newBuilder();
    // don't try to add a store when not in normal or offline state
    if (!metadataStore.getServerStateUnlocked().equals(MetadataStore.VoldemortState.NORMAL_SERVER) && !metadataStore.getServerStateUnlocked().equals(MetadataStore.VoldemortState.OFFLINE_SERVER)) {
        response.setError(ProtoUtils.encodeError(errorCodeMapper, new VoldemortException("Voldemort server is neither in normal state nor in offline state")));
        return response.build();
    }
    AdminClient adminClient = null;
    try {
        // adding a store requires decoding the passed in store string
        StoreDefinitionsMapper mapper = new StoreDefinitionsMapper();
        StoreDefinition def = mapper.readStore(new StringReader(request.getStoreDefinition()));
        adminClient = new AdminClient(metadataStore.getCluster());
        synchronized (lock) {
            if (!storeRepository.hasLocalStore(def.getName())) {
                if (def.getReplicationFactor() > metadataStore.getCluster().getNumberOfNodes()) {
                    throw new StoreOperationFailureException("Cannot add a store whose replication factor ( " + def.getReplicationFactor() + " ) is greater than the number of nodes ( " + metadataStore.getCluster().getNumberOfNodes() + " )");
                }
                logger.info("Adding new store '" + def.getName() + "'");
                // open the store
                StorageEngine<ByteArray, byte[], byte[]> engine = storageService.openStore(def);
                // effect of updating the stores.xml file)
                try {
                    metadataStore.addStoreDefinition(def);
                    long defaultQuota = voldemortConfig.getDefaultStorageSpaceQuotaInKB();
                    QuotaUtils.setQuota(def.getName(), QuotaType.STORAGE_SPACE, storeRepository, metadataStore.getCluster().getNodeIds(), defaultQuota);
                } catch (Exception e) {
                    // rollback open store operation
                    boolean isReadOnly = ReadOnlyStorageConfiguration.TYPE_NAME.equals(def.getType());
                    storageService.removeEngine(engine, isReadOnly, def.getType(), true);
                    throw new VoldemortException(e);
                }
                logger.info("Successfully added new store '" + def.getName() + "'");
            } else {
                logger.error("Failure to add a store with the same name '" + def.getName() + "'");
                throw new StoreOperationFailureException(String.format("Store '%s' already exists on this server", def.getName()));
            }
        }
    } catch (VoldemortException e) {
        response.setError(ProtoUtils.encodeError(errorCodeMapper, e));
        logger.error("handleAddStore failed for request(" + request.toString() + ")", e);
    } finally {
        if (adminClient != null) {
            IOUtils.closeQuietly(adminClient);
        }
    }
    return response.build();
}
Also used : StoreDefinition(voldemort.store.StoreDefinition) StoreDefinitionsMapper(voldemort.xml.StoreDefinitionsMapper) StringReader(java.io.StringReader) ByteArray(voldemort.utils.ByteArray) StoreOperationFailureException(voldemort.store.StoreOperationFailureException) VoldemortException(voldemort.VoldemortException) NoSuchCapabilityException(voldemort.store.NoSuchCapabilityException) ConfigurationException(voldemort.utils.ConfigurationException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) StoreOperationFailureException(voldemort.store.StoreOperationFailureException) VoldemortException(voldemort.VoldemortException) IOException(java.io.IOException) PersistenceFailureException(voldemort.store.PersistenceFailureException) StoreNotFoundException(voldemort.store.StoreNotFoundException) AdminClient(voldemort.client.protocol.admin.AdminClient)

Example 23 with AdminClient

use of voldemort.client.protocol.admin.AdminClient in project voldemort by voldemort.

the class AdminServiceBasicTest method testStateTransitions.

@Test
public void testStateTransitions() {
    // change to REBALANCING STATE
    AdminClient client = getAdminClient();
    updateRemoteServerState(client, getVoldemortServer(0).getIdentityNode().getId(), MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER, ((VectorClock) client.rebalanceOps.getRemoteServerState(0).getVersion()).incremented(0, System.currentTimeMillis()));
    MetadataStore.VoldemortState state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to rebalancing state", MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER, state);
    // change back to NORMAL state
    updateRemoteServerState(client, getVoldemortServer(0).getIdentityNode().getId(), MetadataStore.VoldemortState.NORMAL_SERVER, ((VectorClock) client.rebalanceOps.getRemoteServerState(0).getVersion()).incremented(0, System.currentTimeMillis()));
    state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to rebalancing state", MetadataStore.VoldemortState.NORMAL_SERVER, state);
    // lets revert back to REBALANCING STATE AND CHECK
    updateRemoteServerState(client, getVoldemortServer(0).getIdentityNode().getId(), MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER, ((VectorClock) client.rebalanceOps.getRemoteServerState(0).getVersion()).incremented(0, System.currentTimeMillis()));
    state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to rebalancing state", MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER, state);
    // change back to NORMAL_SERVER
    updateRemoteServerState(client, getVoldemortServer(0).getIdentityNode().getId(), MetadataStore.VoldemortState.NORMAL_SERVER, ((VectorClock) client.rebalanceOps.getRemoteServerState(0).getVersion()).incremented(0, System.currentTimeMillis()));
    state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to normal state", MetadataStore.VoldemortState.NORMAL_SERVER, state);
    // change to OFFLINE_SERVER
    client.metadataMgmtOps.setRemoteOfflineState(getVoldemortServer(0).getIdentityNode().getId(), true);
    state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to offline state", MetadataStore.VoldemortState.OFFLINE_SERVER, state);
    // change back to NORMAL_SERVER
    client.metadataMgmtOps.setRemoteOfflineState(getVoldemortServer(0).getIdentityNode().getId(), false);
    state = getVoldemortServer(0).getMetadataStore().getServerStateUnlocked();
    assertEquals("State should be changed correctly to normal state", MetadataStore.VoldemortState.NORMAL_SERVER, state);
}
Also used : MetadataStore(voldemort.store.metadata.MetadataStore) AdminClient(voldemort.client.protocol.admin.AdminClient) Test(org.junit.Test)

Example 24 with AdminClient

use of voldemort.client.protocol.admin.AdminClient in project voldemort by voldemort.

the class AdminServiceBasicTest method testAddStore.

@Test
public void testAddStore() throws Exception {
    AdminClient adminClient = getAdminClient();
    doClientOperation();
    // Try to add a store whose replication factor is greater than the
    // number of nodes
    StoreDefinition definition = new StoreDefinitionBuilder().setName("updateTest").setType(InMemoryStorageConfiguration.TYPE_NAME).setKeySerializer(new SerializerDefinition("string")).setValueSerializer(new SerializerDefinition("string")).setRoutingPolicy(RoutingTier.CLIENT).setRoutingStrategyType(RoutingStrategyType.CONSISTENT_STRATEGY).setReplicationFactor(3).setPreferredReads(1).setRequiredReads(1).setPreferredWrites(1).setRequiredWrites(1).build();
    try {
        adminClient.storeMgmtOps.addStore(definition);
        fail("Should have thrown an exception because we cannot add a store with a replication factor greater than number of nodes");
    } catch (Exception e) {
    }
    // Try adding a legit store using inmemorystorage engine
    definition = new StoreDefinitionBuilder().setName("updateTest").setType(InMemoryStorageConfiguration.TYPE_NAME).setKeySerializer(new SerializerDefinition("string")).setValueSerializer(new SerializerDefinition("string")).setRoutingPolicy(RoutingTier.CLIENT).setRoutingStrategyType(RoutingStrategyType.CONSISTENT_STRATEGY).setReplicationFactor(1).setPreferredReads(1).setRequiredReads(1).setPreferredWrites(1).setRequiredWrites(1).build();
    adminClient.storeMgmtOps.addStore(definition);
    validateQuota(definition.getName());
    // now test the store
    StoreClientFactory factory = new SocketStoreClientFactory(new ClientConfig().setBootstrapUrls(cluster.getNodeById(0).getSocketUrl().toString()));
    StoreClient<Object, Object> client = factory.getStoreClient("updateTest");
    client.put("abc", "123");
    String s = (String) client.get("abc").getValue();
    assertEquals(s, "123");
    // test again with a unknown store
    try {
        client = factory.getStoreClient("updateTest2");
        client.put("abc", "123");
        s = (String) client.get("abc").getValue();
        assertEquals(s, "123");
        fail("Should have received bootstrap failure exception");
    } catch (Exception e) {
        if (!(e instanceof BootstrapFailureException))
            throw e;
    }
    // make sure that the store list we get back from AdminClient
    Versioned<List<StoreDefinition>> list = adminClient.metadataMgmtOps.getRemoteStoreDefList(0);
    assertTrue(list.getValue().contains(definition));
    // Now add a RO store
    definition = new StoreDefinitionBuilder().setName("addStoreROFormatTest").setType(ReadOnlyStorageConfiguration.TYPE_NAME).setKeySerializer(new SerializerDefinition("string")).setValueSerializer(new SerializerDefinition("string")).setRoutingPolicy(RoutingTier.CLIENT).setRoutingStrategyType(RoutingStrategyType.CONSISTENT_STRATEGY).setReplicationFactor(1).setPreferredReads(1).setRequiredReads(1).setPreferredWrites(1).setRequiredWrites(1).build();
    adminClient.storeMgmtOps.addStore(definition);
    validateQuota(definition.getName());
    // Retrieve list of read-only stores
    List<String> storeNames = Lists.newArrayList();
    for (StoreDefinition storeDef : adminClient.metadataMgmtOps.getRemoteStoreDefList(0).getValue()) {
        if (storeDef.getType().compareTo(ReadOnlyStorageConfiguration.TYPE_NAME) == 0) {
            storeNames.add(storeDef.getName());
        }
    }
    Map<String, String> storeToStorageFormat = adminClient.readonlyOps.getROStorageFormat(0, storeNames);
    for (String storeName : storeToStorageFormat.keySet()) {
        assertEquals(storeToStorageFormat.get(storeName), "ro2");
    }
    doClientOperation();
}
Also used : StoreDefinitionBuilder(voldemort.store.StoreDefinitionBuilder) VoldemortException(voldemort.VoldemortException) VoldemortApplicationException(voldemort.VoldemortApplicationException) IOException(java.io.IOException) InvalidMetadataException(voldemort.store.InvalidMetadataException) StoreDefinition(voldemort.store.StoreDefinition) List(java.util.List) ArrayList(java.util.ArrayList) AdminClientConfig(voldemort.client.protocol.admin.AdminClientConfig) SerializerDefinition(voldemort.serialization.SerializerDefinition) AdminClient(voldemort.client.protocol.admin.AdminClient) Test(org.junit.Test)

Example 25 with AdminClient

use of voldemort.client.protocol.admin.AdminClient in project voldemort by voldemort.

the class AdminServiceBasicTest method testRebalanceQuota.

@Test
public void testRebalanceQuota() throws InterruptedException {
    AdminClient client = getAdminClient();
    String storeName = storeDefs.get(0).getName();
    QuotaType quotaType = QuotaType.GET_THROUGHPUT;
    Long quota = 1000L, targetQuota = quota / 2;
    client.quotaMgmtOps.setQuotaForNode(storeName, quotaType, 0, quota);
    client.quotaMgmtOps.rebalanceQuota(storeName, quotaType);
    // rebalanceQuota use put. Put completes as soon as the required nodes
    // are completed and rest of them are done in async. There is a race
    // condition here if you poll too soon you will see inconsistent result,
    // as some of the puts are still in async. Sleep here to avoid those
    // conditions.
    Thread.sleep(100);
    Long getQuota0 = Long.parseLong(client.quotaMgmtOps.getQuotaForNode(storeName, quotaType, 0).getValue());
    Long getQuota1 = Long.parseLong(client.quotaMgmtOps.getQuotaForNode(storeName, quotaType, 1).getValue());
    assertEquals(targetQuota, getQuota0);
    assertEquals(targetQuota, getQuota1);
}
Also used : QuotaType(voldemort.store.quota.QuotaType) AdminClient(voldemort.client.protocol.admin.AdminClient) Test(org.junit.Test)

Aggregations

AdminClient (voldemort.client.protocol.admin.AdminClient)80 Test (org.junit.Test)35 Cluster (voldemort.cluster.Cluster)26 Node (voldemort.cluster.Node)26 Properties (java.util.Properties)19 StoreDefinition (voldemort.store.StoreDefinition)19 ArrayList (java.util.ArrayList)18 AdminClientConfig (voldemort.client.protocol.admin.AdminClientConfig)18 VoldemortException (voldemort.VoldemortException)17 IOException (java.io.IOException)14 Before (org.junit.Before)14 ByteArray (voldemort.utils.ByteArray)14 HashMap (java.util.HashMap)13 StoreDefinitionsMapper (voldemort.xml.StoreDefinitionsMapper)13 File (java.io.File)11 VoldemortServer (voldemort.server.VoldemortServer)11 ClientConfig (voldemort.client.ClientConfig)10 VectorClock (voldemort.versioning.VectorClock)10 Versioned (voldemort.versioning.Versioned)9 ClusterMapper (voldemort.xml.ClusterMapper)9