Search in sources :

Example 56 with StoreException

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));
}
Also used : ServerNetworkResponseMetrics(com.github.ambry.network.ServerNetworkResponseMetrics) Store(com.github.ambry.store.Store) DataInputStream(java.io.DataInputStream) StoreKey(com.github.ambry.store.StoreKey) ServerErrorCode(com.github.ambry.server.ServerErrorCode) IdUndeletedStoreException(com.github.ambry.store.IdUndeletedStoreException) StoreException(com.github.ambry.store.StoreException) IOException(java.io.IOException) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) MessageInfo(com.github.ambry.store.MessageInfo) IdUndeletedStoreException(com.github.ambry.store.IdUndeletedStoreException) StoreException(com.github.ambry.store.StoreException) LocalChannelRequest(com.github.ambry.network.LocalRequestResponseChannel.LocalChannelRequest) BlobId(com.github.ambry.commons.BlobId)

Example 57 with StoreException

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);
    }
}
Also used : DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) StoreKey(com.github.ambry.store.StoreKey) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) StoreException(com.github.ambry.store.StoreException) IOException(java.io.IOException) MessageInfo(com.github.ambry.store.MessageInfo) StoreException(com.github.ambry.store.StoreException) MessageFormatWriteSet(com.github.ambry.messageformat.MessageFormatWriteSet)

Example 58 with StoreException

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);
    }
}
Also used : ArrayList(java.util.ArrayList) MessageInfo(com.github.ambry.store.MessageInfo) StoreException(com.github.ambry.store.StoreException)

Example 59 with StoreException

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);
    }
}
Also used : DataNodeId(com.github.ambry.clustermap.DataNodeId) MessageInfo(com.github.ambry.store.MessageInfo) StoreException(com.github.ambry.store.StoreException)

Aggregations

StoreException (com.github.ambry.store.StoreException)59 MessageInfo (com.github.ambry.store.MessageInfo)31 IOException (java.io.IOException)22 ArrayList (java.util.ArrayList)17 BlobId (com.github.ambry.commons.BlobId)16 Store (com.github.ambry.store.Store)16 StoreErrorCodes (com.github.ambry.store.StoreErrorCodes)12 StoreKey (com.github.ambry.store.StoreKey)11 MessageFormatException (com.github.ambry.messageformat.MessageFormatException)10 MockMessageWriteSet (com.github.ambry.store.MockMessageWriteSet)10 DataInputStream (java.io.DataInputStream)10 MessageFormatWriteSet (com.github.ambry.messageformat.MessageFormatWriteSet)9 IdUndeletedStoreException (com.github.ambry.store.IdUndeletedStoreException)8 StoreGetOptions (com.github.ambry.store.StoreGetOptions)8 Test (org.junit.Test)8 PartitionId (com.github.ambry.clustermap.PartitionId)7 MessageFormatInputStream (com.github.ambry.messageformat.MessageFormatInputStream)7 StoreInfo (com.github.ambry.store.StoreInfo)7 DeleteMessageFormatInputStream (com.github.ambry.messageformat.DeleteMessageFormatInputStream)6 ServerNetworkResponseMetrics (com.github.ambry.network.ServerNetworkResponseMetrics)6