Search in sources :

Example 1 with TtlUpdateMessageFormatInputStream

use of com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream 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));
    }
}
Also used : TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) SequenceInputStream(java.io.SequenceInputStream) DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) SequenceInputStream(java.io.SequenceInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) 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 2 with TtlUpdateMessageFormatInputStream

use of com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream in project ambry by linkedin.

the class ReplicationTestHelper method getTtlUpdateMessage.

public static ByteBuffer getTtlUpdateMessage(StoreKey id, short accountId, short containerId, long expiresAtMs, long updateTimeMs, short lifeVersion) throws MessageFormatException, IOException {
    MessageFormatInputStream stream = new TtlUpdateMessageFormatInputStream(id, accountId, containerId, expiresAtMs, updateTimeMs, lifeVersion);
    byte[] message = Utils.readBytesFromStream(stream, (int) stream.getSize());
    return ByteBuffer.wrap(message);
}
Also used : TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) PutMessageFormatInputStream(com.github.ambry.messageformat.PutMessageFormatInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream)

Example 3 with TtlUpdateMessageFormatInputStream

use of com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream in project ambry by linkedin.

the class BlobStore method updateTtl.

@Override
public void updateTtl(List<MessageInfo> infosToUpdate) throws StoreException {
    checkStarted();
    checkDuplicates(infosToUpdate);
    final Timer.Context context = metrics.ttlUpdateResponse.time();
    try {
        List<IndexValue> indexValuesToUpdate = new ArrayList<>();
        List<Short> lifeVersions = new ArrayList<>();
        Offset indexEndOffsetBeforeCheck = index.getCurrentEndOffset();
        for (MessageInfo info : infosToUpdate) {
            if (info.getExpirationTimeInMs() != Utils.Infinite_Time) {
                throw new StoreException("BlobStore only supports removing the expiration time", StoreErrorCodes.Update_Not_Allowed);
            }
            IndexValue value = index.findKey(info.getStoreKey(), new FileSpan(index.getStartOffset(), indexEndOffsetBeforeCheck));
            if (value == null) {
                throw new StoreException("Cannot update TTL of " + info.getStoreKey() + " since it's not in the index", StoreErrorCodes.ID_Not_Found);
            } else if (!info.getStoreKey().isAccountContainerMatch(value.getAccountId(), value.getContainerId())) {
                if (config.storeValidateAuthorization) {
                    throw new StoreException("UPDATE authorization failure. Key: " + info.getStoreKey() + " AccountId in store: " + value.getAccountId() + " ContainerId in store: " + value.getContainerId(), StoreErrorCodes.Authorization_Failure);
                } else {
                    logger.warn("UPDATE authorization failure. Key: {} AccountId in store: {} ContainerId in store: {}", info.getStoreKey(), value.getAccountId(), value.getContainerId());
                    metrics.ttlUpdateAuthorizationFailureCount.inc();
                }
            } else if (value.isDelete()) {
                throw new StoreException("Cannot update TTL of " + info.getStoreKey() + " since it is already deleted in the index.", StoreErrorCodes.ID_Deleted);
            } else if (value.isTtlUpdate()) {
                throw new StoreException("TTL of " + info.getStoreKey() + " is already updated in the index.", StoreErrorCodes.Already_Updated);
            } else if (!IndexValue.hasLifeVersion(info.getLifeVersion()) && value.getExpiresAtMs() != Utils.Infinite_Time && value.getExpiresAtMs() < info.getOperationTimeMs() + ttlUpdateBufferTimeMs) {
                // When the request is from replication, we don't care about the operation time.
                throw new StoreException("TTL of " + info.getStoreKey() + " cannot be updated because it is too close to expiry. Op time (ms): " + info.getOperationTimeMs() + ". ExpiresAtMs: " + value.getExpiresAtMs(), StoreErrorCodes.Update_Not_Allowed);
            }
            indexValuesToUpdate.add(value);
            lifeVersions.add(value.getLifeVersion());
        }
        synchronized (storeWriteLock) {
            Offset currentIndexEndOffset = index.getCurrentEndOffset();
            if (!currentIndexEndOffset.equals(indexEndOffsetBeforeCheck)) {
                FileSpan fileSpan = new FileSpan(indexEndOffsetBeforeCheck, currentIndexEndOffset);
                for (MessageInfo info : infosToUpdate) {
                    IndexValue value = index.findKey(info.getStoreKey(), fileSpan, EnumSet.allOf(PersistentIndex.IndexEntryType.class));
                    if (value != null) {
                        if (value.isDelete()) {
                            throw new StoreException("Cannot update TTL of " + info.getStoreKey() + " since it is already deleted in the index.", StoreErrorCodes.ID_Deleted);
                        } else if (value.isTtlUpdate()) {
                            throw new StoreException("TTL of " + info.getStoreKey() + " is already updated in the index.", StoreErrorCodes.Already_Updated);
                        }
                    }
                }
            }
            List<InputStream> inputStreams = new ArrayList<>(infosToUpdate.size());
            List<MessageInfo> updatedInfos = new ArrayList<>(infosToUpdate.size());
            int i = 0;
            for (MessageInfo info : infosToUpdate) {
                MessageFormatInputStream stream = new TtlUpdateMessageFormatInputStream(info.getStoreKey(), info.getAccountId(), info.getContainerId(), info.getExpirationTimeInMs(), info.getOperationTimeMs(), lifeVersions.get(i));
                // we only need change the stream size.
                updatedInfos.add(new MessageInfo(info.getStoreKey(), stream.getSize(), info.getAccountId(), info.getContainerId(), info.getOperationTimeMs(), info.getLifeVersion()));
                inputStreams.add(stream);
                i++;
            }
            Offset endOffsetOfLastMessage = log.getEndOffset();
            MessageFormatWriteSet writeSet = new MessageFormatWriteSet(new SequenceInputStream(Collections.enumeration(inputStreams)), updatedInfos, false);
            writeSet.writeTo(log);
            logger.trace("Store : {} ttl update mark written to log", dataDir);
            int correspondingPutIndex = 0;
            for (MessageInfo info : updatedInfos) {
                FileSpan fileSpan = log.getFileSpanForMessage(endOffsetOfLastMessage, info.getSize());
                // Ttl update should aways use the same lifeVersion as it's previous value of the same key, that's why we are
                // using LIFE_VERSION_FROM_FRONTEND here no matter the lifeVersion from the message info.
                IndexValue ttlUpdateValue = index.markAsPermanent(info.getStoreKey(), fileSpan, null, info.getOperationTimeMs(), MessageInfo.LIFE_VERSION_FROM_FRONTEND);
                endOffsetOfLastMessage = fileSpan.getEndOffset();
                blobStoreStats.handleNewTtlUpdateEntry(info.getStoreKey(), ttlUpdateValue, indexValuesToUpdate.get(correspondingPutIndex++));
            }
            logger.trace("Store : {} ttl update has been marked in the index ", dataDir);
        }
        onSuccess();
    } catch (StoreException e) {
        if (e.getErrorCode() == StoreErrorCodes.IOError) {
            onError();
        }
        throw e;
    } catch (Exception e) {
        throw new StoreException("Unknown error while trying to update ttl of blobs from store " + dataDir, e, StoreErrorCodes.Unknown_Error);
    } finally {
        context.stop();
    }
}
Also used : DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) SequenceInputStream(java.io.SequenceInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) DeleteMessageFormatInputStream(com.github.ambry.messageformat.DeleteMessageFormatInputStream) UndeleteMessageFormatInputStream(com.github.ambry.messageformat.UndeleteMessageFormatInputStream) MessageFormatInputStream(com.github.ambry.messageformat.MessageFormatInputStream) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) IOException(java.io.IOException) TtlUpdateMessageFormatInputStream(com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream) Timer(com.codahale.metrics.Timer) SequenceInputStream(java.io.SequenceInputStream) MessageFormatWriteSet(com.github.ambry.messageformat.MessageFormatWriteSet)

Aggregations

DeleteMessageFormatInputStream (com.github.ambry.messageformat.DeleteMessageFormatInputStream)3 MessageFormatInputStream (com.github.ambry.messageformat.MessageFormatInputStream)3 TtlUpdateMessageFormatInputStream (com.github.ambry.messageformat.TtlUpdateMessageFormatInputStream)3 UndeleteMessageFormatInputStream (com.github.ambry.messageformat.UndeleteMessageFormatInputStream)3 MessageFormatWriteSet (com.github.ambry.messageformat.MessageFormatWriteSet)2 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 SequenceInputStream (java.io.SequenceInputStream)2 ArrayList (java.util.ArrayList)2 Timer (com.codahale.metrics.Timer)1 PutMessageFormatInputStream (com.github.ambry.messageformat.PutMessageFormatInputStream)1 MessageInfo (com.github.ambry.store.MessageInfo)1 StoreException (com.github.ambry.store.StoreException)1