use of voldemort.VoldemortException in project voldemort by voldemort.
the class VoldemortNativeRequestHandler method isCompleteRequest.
/**
* This is pretty ugly. We end up mimicking the request logic here, so this
* needs to stay in sync with handleRequest.
*/
@Override
public boolean isCompleteRequest(final ByteBuffer buffer) throws VoldemortException {
DataInputStream inputStream = new DataInputStream(new ByteBufferBackedInputStream(buffer));
try {
byte opCode = inputStream.readByte();
// Store Name
inputStream.readUTF();
// Store routing type
getRoutingType(inputStream);
switch(opCode) {
case VoldemortOpCode.GET_VERSION_OP_CODE:
if (!GetVersionRequestHandler.isCompleteRequest(inputStream, buffer))
return false;
break;
case VoldemortOpCode.GET_OP_CODE:
if (!GetRequestHandler.isCompleteRequest(inputStream, buffer, protocolVersion))
return false;
break;
case VoldemortOpCode.GET_ALL_OP_CODE:
if (!GetAllRequestHandler.isCompleteRequest(inputStream, buffer, protocolVersion))
return false;
break;
case VoldemortOpCode.PUT_OP_CODE:
{
if (!PutRequestHandler.isCompleteRequest(inputStream, buffer, protocolVersion))
return false;
break;
}
case VoldemortOpCode.DELETE_OP_CODE:
{
if (!DeleteRequestHandler.isCompleteRequest(inputStream, buffer))
return false;
break;
}
default:
throw new VoldemortException(" Unrecognized Voldemort OpCode " + opCode);
}
// data, there is something wrong.
if (buffer.hasRemaining()) {
logger.info("Probably a client bug, Discarding additional bytes in isCompleteRequest. Opcode: " + opCode + ", remaining bytes: " + buffer.remaining());
}
return true;
} catch (IOException e) {
// throws an InvalidArgumentException.
if (logger.isDebugEnabled())
logger.debug("Probable partial read occurred causing exception", e);
return false;
}
}
use of voldemort.VoldemortException in project voldemort by voldemort.
the class VoldemortNativeRequestHandler method handleRequest.
@Override
public StreamRequestHandler handleRequest(final DataInputStream inputStream, final DataOutputStream outputStream, final ByteBufferContainer outputContainer) throws IOException {
long startTimeMs = -1;
long startTimeNs = -1;
if (logger.isDebugEnabled()) {
startTimeMs = System.currentTimeMillis();
startTimeNs = System.nanoTime();
}
byte opCode = inputStream.readByte();
String storeName = inputStream.readUTF();
RequestRoutingType routingType = getRoutingType(inputStream);
Store<ByteArray, byte[], byte[]> store = getStore(storeName, routingType);
if (store == null) {
clearBuffer(outputContainer);
writeException(outputStream, new VoldemortException("No store named: '" + storeName + "'."));
return null;
}
ClientRequestHandler requestHandler = getClientRequestHandler(opCode, store);
try {
requestHandler.parseRequest(inputStream);
requestHandler.processRequest();
} catch (VoldemortException e) {
// they are harmless and indicates normal mode of operation.
if (!(e instanceof ObsoleteVersionException)) {
logger.error("Store: " + storeName + ". Error: " + e.getMessage());
}
clearBuffer(outputContainer);
writeException(outputStream, e);
return null;
}
// We are done with Input, clear the buffers
clearBuffer(outputContainer);
int size = requestHandler.getResponseSize();
if (outputContainer != null) {
outputContainer.growBuffer(size);
}
requestHandler.writeResponse(outputStream);
outputStream.flush();
if (logger.isDebugEnabled()) {
String debugPrefix = "OpCode: " + opCode + ", started at: " + startTimeMs + ", handlerRef: " + System.identityHashCode(inputStream) + ", Elapsed : " + (System.nanoTime() - startTimeNs) + " ns, ";
logger.debug(debugPrefix + requestHandler.getDebugMessage());
}
return null;
}
use of voldemort.VoldemortException in project voldemort by voldemort.
the class Rebalancer method swapROStores.
/**
* Goes through all the RO Stores in the plan and swaps it
*
* @param swappedStoreNames Names of stores already swapped
* @param useSwappedStoreNames Swap only the previously swapped stores (
* Happens during error )
*/
private void swapROStores(List<String> swappedStoreNames, boolean useSwappedStoreNames) {
try {
for (StoreDefinition storeDef : metadataStore.getStoreDefList()) {
// Only pick up the RO stores
if (storeDef.getType().compareTo(ReadOnlyStorageConfiguration.TYPE_NAME) == 0) {
if (useSwappedStoreNames && !swappedStoreNames.contains(storeDef.getName())) {
continue;
}
ReadOnlyStorageEngine engine = (ReadOnlyStorageEngine) storeRepository.getStorageEngine(storeDef.getName());
if (engine == null) {
throw new VoldemortException("Could not find storage engine for " + storeDef.getName() + " to swap ");
}
logger.info("Swapping RO store " + storeDef.getName());
// Time to swap this store - Could have used admin client,
// but why incur the overhead?
engine.swapFiles(engine.getCurrentDirPath());
// Add to list of stores already swapped
if (!useSwappedStoreNames)
swappedStoreNames.add(storeDef.getName());
}
}
} catch (Exception e) {
logger.error("Error while swapping RO store");
throw new VoldemortException(e);
}
}
use of voldemort.VoldemortException in project voldemort by voldemort.
the class Rebalancer method rebalanceStateChange.
/**
* Support four different stages <br>
* For normal operation:
*
* <pre>
* | swapRO | changeClusterMetadata | changeRebalanceState | Order |
* | f | t | t | rebalance -> cluster |
* | f | f | t | rebalance |
* | t | t | f | cluster -> swap |
* | t | t | t | rebalance -> cluster -> swap|
* </pre>
*
* In general we need to do [ cluster change -> swap -> rebalance state
* change ]
*
* NOTE: The update of the cluster metadata and the rebalancer state is not
* "atomic". Ergo, there could theoretically be a race where a client picks
* up new cluster metadata sends a request based on that, but the proxy
* bridges have not been setup and we either miss a proxy put or return a
* null for get/getalls
*
* TODO:refactor The rollback logic here is too convoluted. Specifically,
* the independent updates to each key could be split up into their own
* methods.
*
* @param cluster Cluster metadata to change
* @param rebalanceTaskInfo List of rebalance partitions info
* @param swapRO Boolean to indicate swapping of RO store
* @param changeClusterAndStoresMetadata Boolean to indicate a change of
* cluster metadata
* @param changeRebalanceState Boolean to indicate a change in rebalance
* state
* @param rollback Boolean to indicate that we are rolling back or not
*/
public void rebalanceStateChange(Cluster cluster, List<StoreDefinition> storeDefs, List<RebalanceTaskInfo> rebalanceTaskInfo, boolean swapRO, boolean changeClusterAndStoresMetadata, boolean changeRebalanceState, boolean rollback) {
Cluster currentCluster = metadataStore.getCluster();
List<StoreDefinition> currentStoreDefs = metadataStore.getStoreDefList();
logger.info("Server doing rebalance state change with options [ cluster metadata change - " + changeClusterAndStoresMetadata + " ], [ changing rebalancing state - " + changeRebalanceState + " ], [ changing swapping RO - " + swapRO + " ], [ rollback - " + rollback + " ]");
// Variables to track what has completed
List<RebalanceTaskInfo> completedRebalanceTaskInfo = Lists.newArrayList();
List<String> swappedStoreNames = Lists.newArrayList();
boolean completedClusterAndStoresChange = false;
boolean completedRebalanceSourceClusterChange = false;
Cluster previousRebalancingSourceCluster = null;
List<StoreDefinition> previousRebalancingSourceStores = null;
try {
// CHANGE REBALANCING STATE
if (changeRebalanceState) {
try {
previousRebalancingSourceCluster = metadataStore.getRebalancingSourceCluster();
previousRebalancingSourceStores = metadataStore.getRebalancingSourceStores();
if (!rollback) {
// Save up the current cluster and stores def for
// Redirecting store
changeClusterAndStores(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML, currentCluster, // for Redirecting store
MetadataStore.REBALANCING_SOURCE_STORES_XML, currentStoreDefs);
completedRebalanceSourceClusterChange = true;
for (RebalanceTaskInfo info : rebalanceTaskInfo) {
metadataStore.addRebalancingState(info);
completedRebalanceTaskInfo.add(info);
}
} else {
// Reset the rebalancing source cluster back to null
changeClusterAndStores(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML, null, // stores back to null
MetadataStore.REBALANCING_SOURCE_STORES_XML, null);
completedRebalanceSourceClusterChange = true;
for (RebalanceTaskInfo info : rebalanceTaskInfo) {
metadataStore.deleteRebalancingState(info);
completedRebalanceTaskInfo.add(info);
}
}
} catch (Exception e) {
throw new VoldemortException(e);
}
}
// CHANGE CLUSTER METADATA AND STORE METADATA
if (changeClusterAndStoresMetadata) {
logger.info("Switching cluster metadata from " + currentCluster + " to " + cluster);
logger.info("Switching stores metadata from " + currentStoreDefs + " to " + storeDefs);
changeClusterAndStores(MetadataStore.CLUSTER_KEY, cluster, MetadataStore.STORES_KEY, storeDefs);
completedClusterAndStoresChange = true;
}
// SWAP RO DATA FOR ALL STORES
if (swapRO) {
swapROStores(swappedStoreNames, false);
}
} catch (VoldemortException e) {
logger.error("Got exception while changing state, now rolling back changes", e);
// ROLLBACK CLUSTER AND STORES CHANGE
if (completedClusterAndStoresChange) {
try {
logger.info("Rolling back cluster.xml to " + currentCluster);
logger.info("Rolling back stores.xml to " + currentStoreDefs);
changeClusterAndStores(MetadataStore.CLUSTER_KEY, currentCluster, MetadataStore.STORES_KEY, currentStoreDefs);
} catch (Exception exception) {
logger.error("Error while rolling back cluster metadata to " + currentCluster + " Stores metadata to " + currentStoreDefs, exception);
}
}
// SWAP RO DATA FOR ALL COMPLETED STORES
if (swappedStoreNames.size() > 0) {
try {
swapROStores(swappedStoreNames, true);
} catch (Exception exception) {
logger.error("Error while swapping back to old state ", exception);
}
}
// CHANGE BACK ALL REBALANCING STATES FOR COMPLETED ONES
if (completedRebalanceTaskInfo.size() > 0) {
if (!rollback) {
for (RebalanceTaskInfo info : completedRebalanceTaskInfo) {
try {
metadataStore.deleteRebalancingState(info);
} catch (Exception exception) {
logger.error("Error while deleting back rebalance info during error rollback " + info, exception);
}
}
} else {
for (RebalanceTaskInfo info : completedRebalanceTaskInfo) {
try {
metadataStore.addRebalancingState(info);
} catch (Exception exception) {
logger.error("Error while adding back rebalance info during error rollback " + info, exception);
}
}
}
}
// REBALANCING_SOURCE_STORES_XML
if (completedRebalanceSourceClusterChange) {
logger.info("Reverting the REBALANCING_SOURCE_CLUSTER_XML back to " + previousRebalancingSourceCluster);
logger.info("Reverting the REBALANCING_SOURCE_STORES_XML back to " + previousRebalancingSourceStores);
changeClusterAndStores(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML, previousRebalancingSourceCluster, MetadataStore.REBALANCING_SOURCE_STORES_XML, previousRebalancingSourceStores);
}
throw e;
}
}
use of voldemort.VoldemortException in project voldemort by voldemort.
the class Rebalancer method rebalanceNode.
/**
* This function is responsible for starting the actual async rebalance
* operation. This is run if this node is the stealer node
*
* <br>
*
* We also assume that the check that this server is in rebalancing state
* has been done at a higher level
*
* @param stealInfo Partition info to steal
* @return Returns a id identifying the async operation
*/
public int rebalanceNode(final RebalanceTaskInfo stealInfo) {
final RebalanceTaskInfo info = metadataStore.getRebalancerState().find(stealInfo.getDonorId());
// Do we have the plan in the state?
if (info == null) {
throw new VoldemortException("Could not find plan " + stealInfo + " in the server state on " + metadataStore.getNodeId());
} else if (!info.equals(stealInfo)) {
// If we do have the plan, is it the same
throw new VoldemortException("The plan in server state " + info + " is not the same as the process passed " + stealInfo);
} else if (!acquireRebalancingPermit(stealInfo.getDonorId())) {
// Both are same, now try to acquire a lock for the donor node
throw new AlreadyRebalancingException("Node " + metadataStore.getNodeId() + " is already rebalancing from donor " + info.getDonorId() + " with info " + info);
}
// Acquired lock successfully, start rebalancing...
int requestId = asyncService.getUniqueRequestId();
// Why do we pass 'info' instead of 'stealInfo'? So that we can change
// the state as the stores finish rebalance
asyncService.submitOperation(requestId, new StealerBasedRebalanceAsyncOperation(this, voldemortConfig, metadataStore, requestId, info));
return requestId;
}
Aggregations