use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class AmbryRequests method handleDeleteRequest.
@Override
public void handleDeleteRequest(NetworkRequest request) throws IOException, InterruptedException {
DeleteRequest deleteRequest;
if (request instanceof LocalChannelRequest) {
// This is a case where handleDeleteRequest is called when frontends are talking to Azure. In this case, this method
// is called by request handler threads running within the frontend router itself. So, the request can be directly
// referenced as java objects without any need for deserialization.
deleteRequest = (DeleteRequest) ((LocalChannelRequest) request).getRequestInfo().getRequest();
} else {
deleteRequest = DeleteRequest.readFrom(new DataInputStream(request.getInputStream()), clusterMap);
}
long requestQueueTime = SystemTime.getInstance().milliseconds() - request.getStartTimeInMs();
long totalTimeSpent = requestQueueTime;
metrics.deleteBlobRequestQueueTimeInMs.update(requestQueueTime);
metrics.deleteBlobRequestRate.mark();
long startTime = SystemTime.getInstance().milliseconds();
DeleteResponse response = null;
try {
StoreKey convertedStoreKey = getConvertedStoreKeys(Collections.singletonList(deleteRequest.getBlobId())).get(0);
ServerErrorCode error = validateRequest(deleteRequest.getBlobId().getPartition(), RequestOrResponseType.DeleteRequest, false);
if (error != ServerErrorCode.No_Error) {
logger.error("Validating delete request failed with error {} for request {}", error, deleteRequest);
response = new DeleteResponse(deleteRequest.getCorrelationId(), deleteRequest.getClientId(), error);
} else {
BlobId convertedBlobId = (BlobId) convertedStoreKey;
MessageInfo info = new MessageInfo.Builder(convertedBlobId, -1, convertedBlobId.getAccountId(), convertedBlobId.getContainerId(), deleteRequest.getDeletionTimeInMs()).isDeleted(true).lifeVersion(MessageInfo.LIFE_VERSION_FROM_FRONTEND).build();
Store storeToDelete = storeManager.getStore(deleteRequest.getBlobId().getPartition());
storeToDelete.delete(Collections.singletonList(info));
response = new DeleteResponse(deleteRequest.getCorrelationId(), deleteRequest.getClientId(), ServerErrorCode.No_Error);
if (notification != null) {
notification.onBlobReplicaDeleted(currentNode.getHostname(), currentNode.getPort(), convertedStoreKey.getID(), BlobReplicaSourceType.PRIMARY);
}
}
} catch (StoreException e) {
boolean logInErrorLevel = false;
if (e.getErrorCode() == StoreErrorCodes.ID_Not_Found) {
metrics.idNotFoundError.inc();
} else if (e.getErrorCode() == StoreErrorCodes.TTL_Expired) {
metrics.ttlExpiredError.inc();
} else if (e.getErrorCode() == StoreErrorCodes.ID_Deleted) {
metrics.idDeletedError.inc();
} else if (e.getErrorCode() == StoreErrorCodes.Authorization_Failure) {
metrics.deleteAuthorizationFailure.inc();
} else {
logInErrorLevel = true;
metrics.unExpectedStoreDeleteError.inc();
}
if (logInErrorLevel) {
logger.error("Store exception on a delete with error code {} for request {}", e.getErrorCode(), deleteRequest, e);
} else {
logger.trace("Store exception on a delete with error code {} for request {}", e.getErrorCode(), deleteRequest, e);
}
response = new DeleteResponse(deleteRequest.getCorrelationId(), deleteRequest.getClientId(), ErrorMapping.getStoreErrorMapping(e.getErrorCode()));
} catch (Exception e) {
logger.error("Unknown exception for delete request {}", deleteRequest, e);
response = new DeleteResponse(deleteRequest.getCorrelationId(), deleteRequest.getClientId(), ServerErrorCode.Unknown_Error);
metrics.unExpectedStoreDeleteError.inc();
} finally {
long processingTime = SystemTime.getInstance().milliseconds() - startTime;
totalTimeSpent += processingTime;
publicAccessLogger.info("{} {} processingTime {}", deleteRequest, response, processingTime);
metrics.deleteBlobProcessingTimeInMs.update(processingTime);
}
requestResponseChannel.sendResponse(response, request, new ServerNetworkResponseMetrics(metrics.deleteBlobResponseQueueTimeInMs, metrics.deleteBlobSendTimeInMs, metrics.deleteBlobTotalTimeInMs, null, null, totalTimeSpent));
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class InMemoryStore method undelete.
@Override
public short undelete(MessageInfo info) throws StoreException {
StoreKey key = info.getStoreKey();
MessageInfo deleteInfo = getMessageInfo(key, messageInfos, true, false, false);
if (info.getLifeVersion() == -1 && deleteInfo == null) {
throw new StoreException("Key " + key + " not delete yet", StoreErrorCodes.ID_Not_Deleted);
}
short lifeVersion = info.getLifeVersion();
MessageInfo latestInfo = deleteInfo;
if (info.getLifeVersion() == MessageInfo.LIFE_VERSION_FROM_FRONTEND) {
if (deleteInfo == null) {
throw new StoreException("Id " + key + " requires first value to be a put and last value to be a delete", StoreErrorCodes.ID_Not_Deleted);
}
lifeVersion = (short) (deleteInfo.getLifeVersion() + 1);
} else {
if (deleteInfo == null) {
latestInfo = getMergedMessageInfo(key, messageInfos);
}
}
try {
MessageFormatInputStream stream = new UndeleteMessageFormatInputStream(key, info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion);
// Update info to add stream size;
info = new MessageInfo(key, stream.getSize(), false, latestInfo.isTtlUpdated(), true, latestInfo.getExpirationTimeInMs(), null, info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion);
MessageFormatWriteSet writeSet = new MessageFormatWriteSet(stream, Collections.singletonList(info), false);
writeSet.writeTo(log);
messageInfos.add(info);
return lifeVersion;
} catch (Exception e) {
throw new StoreException("Unknown error while trying to undelete blobs from store", e, StoreErrorCodes.Unknown_Error);
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class InMemoryStore method put.
@Override
public void put(MessageWriteSet messageSetToWrite) throws StoreException {
List<MessageInfo> newInfos = messageSetToWrite.getMessageSetInfo();
try {
messageSetToWrite.writeTo(log);
} catch (StoreException e) {
throw new IllegalStateException(e);
}
List<MessageInfo> infos = new ArrayList<>();
for (MessageInfo info : newInfos) {
short lifeVersion = 0;
if (info.getLifeVersion() != MessageInfo.LIFE_VERSION_FROM_FRONTEND) {
lifeVersion = info.getLifeVersion();
}
if (info.isTtlUpdated()) {
info = new MessageInfo(info.getStoreKey(), info.getSize(), info.isDeleted(), false, info.isUndeleted(), info.getExpirationTimeInMs(), info.getCrc(), info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion);
}
infos.add(info);
}
messageInfos.addAll(infos);
if (listener != null) {
listener.onPut(this, infos);
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class ReplicaThread method applyTtlUpdate.
/**
* Applies a TTL update to the blob described by {@code messageInfo}.
* @param messageInfo the {@link MessageInfo} that will be transformed into a TTL update
* @param remoteReplicaInfo The remote replica that is being replicated from
* @throws StoreException
*/
private void applyTtlUpdate(MessageInfo messageInfo, RemoteReplicaInfo remoteReplicaInfo) throws StoreException {
DataNodeId remoteNode = remoteReplicaInfo.getReplicaId().getDataNodeId();
try {
// NOTE: It is possible that the key in question may have expired and this TTL update is being applied after it
// is deemed expired. The store will accept the op (BlobStore looks at whether the op was valid to do at the time
// of the op, not current time) but if compaction is running at the same time and has decided to clean up the
// record before this ttl update was applied (and this didn't find the key missing because compaction has not yet
// committed), then we have a bad situation where only a TTL update exists in the store. This problem has to be
// addressed. This can only happen if replication is far behind (for e.g due to a server being down for a long
// time). Won't happen if a server is being recreated.
messageInfo = new MessageInfo.Builder(messageInfo).isTtlUpdated(true).build();
remoteReplicaInfo.getLocalStore().updateTtl(Collections.singletonList(messageInfo));
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key ttl updated id: {}", remoteNode, threadName, remoteReplicaInfo.getReplicaId(), messageInfo.getStoreKey());
} catch (StoreException e) {
// The blob may be deleted or updated which is alright
if (e.getErrorCode() == StoreErrorCodes.ID_Deleted || e.getErrorCode() == StoreErrorCodes.Already_Updated) {
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key already updated: {}", remoteNode, threadName, remoteReplicaInfo.getReplicaId(), messageInfo.getStoreKey());
} else {
throw e;
}
}
// as long as the update is guaranteed to have taken effect locally.
if (notification != null) {
notification.onBlobReplicaUpdated(dataNodeId.getHostname(), dataNodeId.getPort(), messageInfo.getStoreKey().getID(), BlobReplicaSourceType.REPAIRED, UpdateType.TTL_UPDATE, messageInfo);
}
}
Aggregations