use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class ReplicaThread method applyUndelete.
/**
* Applies an undelete to the blob described by {@code messageInfo}.
* @param messageInfo the {@link MessageInfo} that will be transformed into an undelete
* @param remoteReplicaInfo The remote replica that is being replicated from
* @throws StoreException
*/
private void applyUndelete(MessageInfo messageInfo, RemoteReplicaInfo remoteReplicaInfo) throws StoreException {
DataNodeId remoteNode = remoteReplicaInfo.getReplicaId().getDataNodeId();
try {
messageInfo = new MessageInfo.Builder(messageInfo).isUndeleted(true).isDeleted(false).build();
remoteReplicaInfo.getLocalStore().undelete(messageInfo);
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key undelete id: {}", remoteNode, threadName, remoteReplicaInfo.getReplicaId(), messageInfo.getStoreKey());
} catch (StoreException e) {
// The blob may be undeleted, which is alright
if (e.getErrorCode() == StoreErrorCodes.Life_Version_Conflict || e.getErrorCode() == StoreErrorCodes.ID_Undeleted) {
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key {}: {}", remoteNode, threadName, remoteReplicaInfo.getReplicaId(), messageInfo.getStoreKey(), e.getErrorCode().name());
} else {
throw e;
}
}
// as long as the undelete is guaranteed to have taken effect locally.
if (notification != null) {
notification.onBlobReplicaUndeleted(dataNodeId.getHostname(), dataNodeId.getPort(), messageInfo.getStoreKey().getID(), BlobReplicaSourceType.REPAIRED);
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class ReplicaThread method refreshMissingStoreMessagesForStandbyReplica.
/**
* Refreshes missing messages found in the exchange metadata response for the input replica by checking in the local store again.
* @param remoteReplicaInfo remote replica information
*/
private void refreshMissingStoreMessagesForStandbyReplica(RemoteReplicaInfo remoteReplicaInfo) {
ExchangeMetadataResponse exchangeMetadataResponse = remoteReplicaInfo.getExchangeMetadataResponse();
Set<MessageInfo> missingStoreMessages = exchangeMetadataResponse.getMissingStoreMessages();
if (!missingStoreMessages.isEmpty()) {
Set<MessageInfo> missingStoreMessagesFoundInStore = new HashSet<>();
try {
// construct map of message info -> converted non-null local key
Map<StoreKey, StoreKey> remoteKeyToLocalKeyMap = exchangeMetadataResponse.remoteKeyToLocalKeyMap;
Map<MessageInfo, StoreKey> remoteMessageToConvertedKeyNonNull = new HashMap<>();
for (MessageInfo messageInfo : missingStoreMessages) {
StoreKey convertedKey = remoteKeyToLocalKeyMap.get(messageInfo.getStoreKey());
if (convertedKey != null) {
remoteMessageToConvertedKeyNonNull.put(messageInfo, convertedKey);
}
}
// Find the set of store keys that are still missing in the store
Set<StoreKey> convertedMissingStoreKeys = remoteReplicaInfo.getLocalStore().findMissingKeys(new ArrayList<>(remoteMessageToConvertedKeyNonNull.values()));
// Filter the remote messages whose keys are now found in store, i.e. not present in convertedMissingStoreKeys set.
remoteMessageToConvertedKeyNonNull.forEach((messageInfo, convertedKey) -> {
if (!convertedMissingStoreKeys.contains(convertedKey)) {
missingStoreMessagesFoundInStore.add(messageInfo);
}
});
// update the missing store messages being tracked for this replica
exchangeMetadataResponse.removeMissingStoreMessages(missingStoreMessagesFoundInStore);
} catch (StoreException e) {
logger.error("Exception occurred while checking for missing keys in local store for partition {} and Remote replica: {}", remoteReplicaInfo.getReplicaId().getPartitionId().toPathString(), remoteReplicaInfo.getReplicaId(), e);
// reset stored metadata response so that metadata request is sent again for this replica
remoteReplicaInfo.setExchangeMetadataResponse(new ExchangeMetadataResponse(ServerErrorCode.No_Error));
}
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class ReplicaThread method applyDelete.
/**
* Applies a delete to the blob described by {@code messageInfo}.
* @param messageInfo the {@link MessageInfo} that will be transformed into a delete
* @param remoteReplicaInfo The remote replica that is being replicated from
* @throws StoreException
*/
private void applyDelete(MessageInfo messageInfo, RemoteReplicaInfo remoteReplicaInfo) throws StoreException {
DataNodeId remoteNode = remoteReplicaInfo.getReplicaId().getDataNodeId();
try {
messageInfo = new MessageInfo.Builder(messageInfo).isDeleted(true).isUndeleted(false).build();
remoteReplicaInfo.getLocalStore().delete(Collections.singletonList(messageInfo));
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key delete: {}", 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.Life_Version_Conflict) {
logger.trace("Remote node: {} Thread name: {} Remote replica: {} Key {}: {}", remoteNode, threadName, remoteReplicaInfo.getReplicaId(), messageInfo.getStoreKey(), e.getErrorCode().name());
} else {
throw e;
}
}
// as long as the Delete is guaranteed to have taken effect locally.
if (notification != null) {
notification.onBlobReplicaDeleted(dataNodeId.getHostname(), dataNodeId.getPort(), messageInfo.getStoreKey().getID(), BlobReplicaSourceType.REPAIRED);
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class InMemoryStore method delete.
@Override
public void delete(List<MessageInfo> infos) throws StoreException {
List<MessageInfo> infosToDelete = new ArrayList<>(infos.size());
List<InputStream> inputStreams = new ArrayList<>();
try {
for (MessageInfo info : infos) {
short lifeVersion = info.getLifeVersion();
MessageInfo latestInfo = getMergedMessageInfo(info.getStoreKey(), messageInfos);
if (latestInfo == null) {
throw new StoreException("Cannot delete id " + info.getStoreKey() + " since it is not present in the index.", StoreErrorCodes.ID_Not_Found);
}
if (lifeVersion == MessageInfo.LIFE_VERSION_FROM_FRONTEND) {
if (latestInfo.isDeleted()) {
throw new StoreException("Cannot delete id " + info.getStoreKey() + " since it is already deleted in the index.", StoreErrorCodes.ID_Deleted);
}
lifeVersion = latestInfo.getLifeVersion();
} else {
if ((latestInfo.isDeleted() && latestInfo.getLifeVersion() >= info.getLifeVersion()) || (latestInfo.getLifeVersion() > info.getLifeVersion())) {
throw new StoreException("Cannot delete id " + info.getStoreKey() + " since it is already deleted in the index.", StoreErrorCodes.Life_Version_Conflict);
}
lifeVersion = info.getLifeVersion();
}
MessageFormatInputStream stream = new DeleteMessageFormatInputStream(info.getStoreKey(), info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion);
infosToDelete.add(new MessageInfo(info.getStoreKey(), stream.getSize(), true, info.isTtlUpdated(), false, info.getExpirationTimeInMs(), null, info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion));
inputStreams.add(stream);
}
MessageFormatWriteSet writeSet = new MessageFormatWriteSet(new SequenceInputStream(Collections.enumeration(inputStreams)), infosToDelete, false);
writeSet.writeTo(log);
messageInfos.addAll(infosToDelete);
} catch (Exception e) {
throw (e instanceof StoreException ? (StoreException) e : new StoreException(e, StoreErrorCodes.Unknown_Error));
}
}
use of com.github.ambry.store.StoreException in project ambry by linkedin.
the class InMemoryStore method updateTtl.
@Override
public void updateTtl(List<MessageInfo> infos) throws StoreException {
List<MessageInfo> infosToUpdate = new ArrayList<>(infos.size());
List<InputStream> inputStreams = new ArrayList<>();
try {
for (MessageInfo info : infos) {
if (info.getExpirationTimeInMs() != Utils.Infinite_Time) {
throw new StoreException("BlobStore only supports removing the expiration time", StoreErrorCodes.Update_Not_Allowed);
}
MessageInfo latestInfo = getMergedMessageInfo(info.getStoreKey(), messageInfos);
if (latestInfo == null) {
throw new StoreException("Cannot update TTL of " + info.getStoreKey() + " since it's not in the index", StoreErrorCodes.ID_Not_Found);
} else if (latestInfo.isDeleted()) {
throw new StoreException("Cannot update TTL of " + info.getStoreKey() + " since it is already deleted in the index.", StoreErrorCodes.ID_Deleted);
} else if (latestInfo.isTtlUpdated()) {
throw new StoreException("TTL of " + info.getStoreKey() + " is already updated in the index.", StoreErrorCodes.Already_Updated);
}
short lifeVersion = latestInfo.getLifeVersion();
MessageFormatInputStream stream = new TtlUpdateMessageFormatInputStream(info.getStoreKey(), info.getAccountId(), info.getContainerId(), info.getExpirationTimeInMs(), info.getOperationTimeMs(), lifeVersion);
infosToUpdate.add(new MessageInfo(info.getStoreKey(), stream.getSize(), false, true, false, info.getExpirationTimeInMs(), null, info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), lifeVersion));
inputStreams.add(stream);
}
MessageFormatWriteSet writeSet = new MessageFormatWriteSet(new SequenceInputStream(Collections.enumeration(inputStreams)), infosToUpdate, false);
writeSet.writeTo(log);
messageInfos.addAll(infosToUpdate);
} catch (Exception e) {
throw (e instanceof StoreException ? (StoreException) e : new StoreException(e, StoreErrorCodes.Unknown_Error));
}
}
Aggregations