use of voldemort.utils.ByteArray in project voldemort by voldemort.
the class RestRequestValidator method parseKeys.
/**
* Method to read a key (or keys) present in the HTTP request URI. The URI
* must be of the format /<store_name>/<key>[,<key>,...]
*
* @param requestURI The URI of the HTTP request
*/
protected void parseKeys(String requestURI) {
this.parsedKeys = null;
String[] parts = requestURI.split("/");
if (parts.length > 2) {
String base64KeyList = parts[2];
this.parsedKeys = new ArrayList<ByteArray>();
if (!base64KeyList.contains(",")) {
String rawKey = base64KeyList.trim();
this.parsedKeys.add(new ByteArray(RestUtils.decodeVoldemortKey(rawKey)));
} else {
String[] base64KeyArray = base64KeyList.split(",");
for (String base64Key : base64KeyArray) {
String rawKey = base64Key.trim();
this.parsedKeys.add(new ByteArray(RestUtils.decodeVoldemortKey(rawKey)));
}
}
}
}
use of voldemort.utils.ByteArray in project voldemort by voldemort.
the class CoordinatorProxyService method initializeFatClient.
/**
* Initialize the fat client for the given store.
*
* 1. Updates the coordinatorMetadata 2.Gets the new store configs from the
* config file 3.Creates a new @SocketStoreClientFactory 4. Subsequently
* caches the @StoreClient obtained from the factory.
*
*
* This is synchronized because if Coordinator Admin is already doing some
* change we want the AsyncMetadataVersionManager to wait.
*
* @param storeName
*/
private synchronized void initializeFatClient(String storeName, Properties storeClientProps) {
// updates the coordinator metadata with recent stores and cluster xml
updateCoordinatorMetadataWithLatestState();
logger.info("Creating a Fat client for store: " + storeName);
SocketStoreClientFactory fatClientFactory = getFatClientFactory(this.coordinatorConfig.getBootstrapURLs(), storeClientProps);
if (this.fatClientMap == null) {
this.fatClientMap = new HashMap<String, DynamicTimeoutStoreClient<ByteArray, byte[]>>();
}
DynamicTimeoutStoreClient<ByteArray, byte[]> fatClient = new DynamicTimeoutStoreClient<ByteArray, byte[]>(storeName, fatClientFactory, 1, this.coordinatorMetadata.getStoreDefs(), this.coordinatorMetadata.getClusterXmlStr());
this.fatClientMap.put(storeName, fatClient);
}
use of voldemort.utils.ByteArray in project voldemort by voldemort.
the class ReadOnlyStoreManagementServlet method getReadOnlyStores.
private List<ReadOnlyStorageEngine> getReadOnlyStores(VoldemortServer server) {
StorageService storage = (StorageService) Utils.notNull(server).getService(ServiceType.STORAGE);
List<ReadOnlyStorageEngine> l = Lists.newArrayList();
for (StorageEngine<ByteArray, byte[], byte[]> engine : storage.getStoreRepository().getStorageEnginesByClass(ReadOnlyStorageEngine.class)) {
l.add((ReadOnlyStorageEngine) engine);
}
return l;
}
use of voldemort.utils.ByteArray in project voldemort by voldemort.
the class GetAllResponseSender method sendResponse.
/**
* Sends nested multipart response. Outer multipart wraps all the keys
* requested. Each key has a separate multipart for the versioned values.
*/
@Override
public void sendResponse(StoreStats performanceStats, boolean isFromLocalZone, long startTimeInMs) throws Exception {
/*
* Pay attention to the code below. Note that in this method we wrap a multiPart object with a mimeMessage.
* However when writing to the outputStream we only send the multiPart object and not the entire
* mimeMessage. This is intentional.
*
* In the earlier version of this code we used to create a multiPart object and just send that multiPart
* across the wire.
*
* However, we later discovered that upon setting the content of a MimeBodyPart, JavaMail internally creates
* a DataHandler object wrapping the object you passed in. The part's Content-Type header is not updated
* immediately. In order to get the headers updated, one needs to to call MimeMessage.saveChanges() on the
* enclosing message, which cascades down the MIME structure into a call to MimeBodyPart.updateHeaders()
* on the body part. It's this updateHeaders call that transfers the content type from the
* DataHandler to the part's MIME Content-Type header.
*
* To make sure that the Content-Type headers are being updated (without changing too much code), we decided
* to wrap the multiPart in a mimeMessage, call mimeMessage.saveChanges() and then just send the multiPart.
* This is to make sure multiPart's headers are updated accurately.
*/
MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
// multiPartKeys is the outer multipart
MimeMultipart multiPartKeys = new MimeMultipart();
ByteArrayOutputStream keysOutputStream = new ByteArrayOutputStream();
for (Entry<ByteArray, List<Versioned<byte[]>>> entry : versionedResponses.entrySet()) {
ByteArray key = entry.getKey();
String base64Key = RestUtils.encodeVoldemortKey(key.get());
String contentLocationKey = "/" + this.storeName + "/" + base64Key;
// Create the individual body part - for each key requested
MimeBodyPart keyBody = new MimeBodyPart();
try {
// Add the right headers
keyBody.addHeader(CONTENT_TYPE, "application/octet-stream");
keyBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary");
keyBody.addHeader(CONTENT_LOCATION, contentLocationKey);
} catch (MessagingException me) {
logger.error("Exception while constructing key body headers", me);
keysOutputStream.close();
throw me;
}
// multiPartValues is the inner multipart
MimeMultipart multiPartValues = new MimeMultipart();
for (Versioned<byte[]> versionedValue : entry.getValue()) {
byte[] responseValue = versionedValue.getValue();
VectorClock vectorClock = (VectorClock) versionedValue.getVersion();
String eTag = RestUtils.getSerializedVectorClock(vectorClock);
numVectorClockEntries += vectorClock.getVersionMap().size();
// Create the individual body part - for each versioned value of
// a key
MimeBodyPart valueBody = new MimeBodyPart();
try {
// Add the right headers
valueBody.addHeader(CONTENT_TYPE, "application/octet-stream");
valueBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary");
valueBody.addHeader(RestMessageHeaders.X_VOLD_VECTOR_CLOCK, eTag);
valueBody.setContent(responseValue, "application/octet-stream");
valueBody.addHeader(RestMessageHeaders.CONTENT_LENGTH, Integer.toString(responseValue.length));
multiPartValues.addBodyPart(valueBody);
} catch (MessagingException me) {
logger.error("Exception while constructing value body part", me);
keysOutputStream.close();
throw me;
}
}
try {
// Add the inner multipart as the content of the outer body part
keyBody.setContent(multiPartValues);
multiPartKeys.addBodyPart(keyBody);
} catch (MessagingException me) {
logger.error("Exception while constructing key body part", me);
keysOutputStream.close();
throw me;
}
}
message.setContent(multiPartKeys);
message.saveChanges();
try {
multiPartKeys.writeTo(keysOutputStream);
} catch (Exception e) {
logger.error("Exception while writing mutipart to output stream", e);
throw e;
}
ChannelBuffer responseContent = ChannelBuffers.dynamicBuffer();
responseContent.writeBytes(keysOutputStream.toByteArray());
// Create the Response object
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
// Set the right headers
response.setHeader(CONTENT_TYPE, "multipart/binary");
response.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
// Copy the data into the payload
response.setContent(responseContent);
response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
// Write the response to the Netty Channel
if (logger.isDebugEnabled()) {
String keyStr = getKeysHexString(this.versionedResponses.keySet());
debugLog("GET_ALL", this.storeName, keyStr, startTimeInMs, System.currentTimeMillis(), numVectorClockEntries);
}
this.messageEvent.getChannel().write(response);
if (performanceStats != null && isFromLocalZone) {
recordStats(performanceStats, startTimeInMs, Tracked.GET_ALL);
}
keysOutputStream.close();
}
use of voldemort.utils.ByteArray in project voldemort by voldemort.
the class DynamicTimeoutStoreClient method putWithCustomTimeout.
/**
* Performs a put operation with the specified composite request object
*
* @param requestWrapper A composite request object containing the key and
* value
* @return Version of the value for the successful put
*/
public Version putWithCustomTimeout(CompositeVoldemortRequest<K, V> requestWrapper) {
validateTimeout(requestWrapper.getRoutingTimeoutInMs());
List<Versioned<V>> versionedValues;
long startTime = System.currentTimeMillis();
String keyHexString = "";
if (logger.isDebugEnabled()) {
ByteArray key = (ByteArray) requestWrapper.getKey();
keyHexString = RestUtils.getKeyHexString(key);
logger.debug("PUT requested for key: " + keyHexString + " , for store: " + this.storeName + " at time(in ms): " + startTime + " . Nested GET and PUT VERSION requests to follow ---");
}
// We use the full timeout for doing the Get. In this, we're being
// optimistic that the subsequent put might be faster such that all the
// steps might finish within the allotted time
requestWrapper.setResolveConflicts(true);
versionedValues = getWithCustomTimeout(requestWrapper);
Versioned<V> versioned = getItemOrThrow(requestWrapper.getKey(), null, versionedValues);
long endTime = System.currentTimeMillis();
if (versioned == null)
versioned = Versioned.value(requestWrapper.getRawValue(), new VectorClock());
else
versioned.setObject(requestWrapper.getRawValue());
// This should not happen unless there's a bug in the
// getWithCustomTimeout
long timeLeft = requestWrapper.getRoutingTimeoutInMs() - (endTime - startTime);
if (timeLeft <= 0) {
throw new StoreTimeoutException("PUT request timed out");
}
CompositeVersionedPutVoldemortRequest<K, V> putVersionedRequestObject = new CompositeVersionedPutVoldemortRequest<K, V>(requestWrapper.getKey(), versioned, timeLeft);
putVersionedRequestObject.setRequestOriginTimeInMs(requestWrapper.getRequestOriginTimeInMs());
Version result = putVersionedWithCustomTimeout(putVersionedRequestObject);
long endTimeInMs = System.currentTimeMillis();
if (logger.isDebugEnabled()) {
logger.debug("PUT response received for key: " + keyHexString + " , for store: " + this.storeName + " at time(in ms): " + endTimeInMs);
}
return result;
}
Aggregations