Search in sources :

Example 96 with MessageInfo

use of com.github.ambry.store.MessageInfo in project ambry by linkedin.

the class MockHost method getMissingInfos.

/**
 * Gets the message infos that are present in this host but missing in {@code other}.
 * @param other the list of {@link MessageInfo} to check against.
 * @return the message infos that are present in this host but missing in {@code other}.
 */
Map<PartitionId, List<MessageInfo>> getMissingInfos(Map<PartitionId, List<MessageInfo>> other, StoreKeyConverter storeKeyConverter) throws Exception {
    Map<PartitionId, List<MessageInfo>> missingInfos = new HashMap<>();
    for (Map.Entry<PartitionId, List<MessageInfo>> entry : infosByPartition.entrySet()) {
        PartitionId partitionId = entry.getKey();
        for (MessageInfo messageInfo : entry.getValue()) {
            boolean found = false;
            StoreKey convertedKey;
            if (storeKeyConverter == null) {
                convertedKey = messageInfo.getStoreKey();
            } else {
                Map<StoreKey, StoreKey> map = storeKeyConverter.convert(Collections.singletonList(messageInfo.getStoreKey()));
                convertedKey = map.get(messageInfo.getStoreKey());
                if (convertedKey == null) {
                    continue;
                }
            }
            for (MessageInfo otherInfo : other.get(partitionId)) {
                if (convertedKey.equals(otherInfo.getStoreKey()) && messageInfo.isDeleted() == otherInfo.isDeleted()) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                missingInfos.computeIfAbsent(partitionId, partitionId1 -> new ArrayList<>()).add(messageInfo);
            }
        }
    }
    return missingInfos;
}
Also used : Arrays(java.util.Arrays) StoreKeyConverter(com.github.ambry.store.StoreKeyConverter) DataNodeId(com.github.ambry.clustermap.DataNodeId) ClusterMap(com.github.ambry.clustermap.ClusterMap) HashMap(java.util.HashMap) Function(java.util.function.Function) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) StoreKey(com.github.ambry.store.StoreKey) List(java.util.List) PortType(com.github.ambry.network.PortType) MessageInfo(com.github.ambry.store.MessageInfo) ReplicaId(com.github.ambry.clustermap.ReplicaId) Map(java.util.Map) SystemTime(com.github.ambry.utils.SystemTime) Port(com.github.ambry.network.Port) Collections(java.util.Collections) PartitionId(com.github.ambry.clustermap.PartitionId) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) PartitionId(com.github.ambry.clustermap.PartitionId) ClusterMap(com.github.ambry.clustermap.ClusterMap) HashMap(java.util.HashMap) Map(java.util.Map) StoreKey(com.github.ambry.store.StoreKey) MessageInfo(com.github.ambry.store.MessageInfo)

Example 97 with MessageInfo

use of com.github.ambry.store.MessageInfo in project ambry by linkedin.

the class ReplicationTestHelper method checkBlobMessagesAreEqualInLocalAndRemoteHosts.

/**
 * Verifies that blob messages across all partitions at local and remote hosts are equal.
 */
protected void checkBlobMessagesAreEqualInLocalAndRemoteHosts(MockHost localHost, MockHost remoteHost, Map<PartitionId, List<StoreKey>> idsToBeIgnoredByPartition, Map<PartitionId, List<StoreKey>> idsToBeTtlUpdatedByPartition) {
    for (Map.Entry<PartitionId, List<MessageInfo>> remoteInfoEntry : remoteHost.infosByPartition.entrySet()) {
        List<MessageInfo> remoteInfos = remoteInfoEntry.getValue();
        List<MessageInfo> localInfos = localHost.infosByPartition.get(remoteInfoEntry.getKey());
        int remoteIndex = 0;
        Set<StoreKey> seen = new HashSet<>();
        for (MessageInfo remoteInfo : remoteInfos) {
            StoreKey id = remoteInfo.getStoreKey();
            if (seen.add(id)) {
                MessageInfo localInfo = getMessageInfo(id, localInfos, false, false, false);
                if (localInfo == null) {
                    assertTrue("Should be ignored", idsToBeIgnoredByPartition.get(remoteInfoEntry.getKey()).contains(id));
                } else {
                    assertFalse("Should not be ignored", idsToBeIgnoredByPartition.get(remoteInfoEntry.getKey()) != null && idsToBeIgnoredByPartition.get(remoteInfoEntry.getKey()).contains(id));
                    MessageInfo mergedLocalInfo = getMergedMessageInfo(id, localInfos);
                    MessageInfo mergedRemoteInfo = getMergedMessageInfo(id, remoteInfos);
                    assertEquals(mergedLocalInfo.isDeleted(), mergedRemoteInfo.isDeleted());
                    assertEquals(mergedLocalInfo.isTtlUpdated(), mergedRemoteInfo.isTtlUpdated());
                    assertEquals(mergedLocalInfo.isTtlUpdated(), idsToBeTtlUpdatedByPartition.get(remoteInfoEntry.getKey()).contains(id));
                    assertEquals(mergedLocalInfo.getLifeVersion(), mergedRemoteInfo.getLifeVersion());
                    assertEquals(mergedLocalInfo.getAccountId(), mergedRemoteInfo.getAccountId());
                    assertEquals(mergedLocalInfo.getContainerId(), mergedRemoteInfo.getContainerId());
                    assertEquals("Key " + id, mergedLocalInfo.getExpirationTimeInMs(), mergedRemoteInfo.getExpirationTimeInMs());
                    ByteBuffer putRecordBuffer = null;
                    for (int i = 0; i < localInfos.size(); i++) {
                        if (localInfo.equals(localInfos.get(i))) {
                            putRecordBuffer = localHost.buffersByPartition.get(remoteInfoEntry.getKey()).get(i).duplicate();
                            break;
                        }
                    }
                    assertNotNull(putRecordBuffer);
                    // Make sure the put buffer contains the same info as the message Info
                    assertPutRecord(putRecordBuffer, remoteHost.buffersByPartition.get(remoteInfoEntry.getKey()).get(remoteIndex).duplicate(), mergedLocalInfo);
                }
            }
            remoteIndex++;
        }
    }
}
Also used : List(java.util.List) ArrayList(java.util.ArrayList) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) Map(java.util.Map) HashMap(java.util.HashMap) ClusterMap(com.github.ambry.clustermap.ClusterMap) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) StoreKey(com.github.ambry.store.StoreKey) ByteBuffer(java.nio.ByteBuffer) MessageInfo(com.github.ambry.store.MessageInfo) HashSet(java.util.HashSet)

Example 98 with MessageInfo

use of com.github.ambry.store.MessageInfo in project ambry by linkedin.

the class ReplicationTestHelper method addPutMessagesToReplicasOfPartition.

public static void addPutMessagesToReplicasOfPartition(List<StoreKey> ids, List<Transformer> transformPerId, List<MockHost> hosts) throws MessageFormatException, IOException {
    Iterator<Transformer> transformerIterator = transformPerId.iterator();
    for (StoreKey storeKey : ids) {
        Transformer transformer = transformerIterator.next();
        BlobId id = (BlobId) storeKey;
        PutMsgInfoAndBuffer msgInfoAndBuffer = createPutMessage(id, id.getAccountId(), id.getContainerId(), BlobId.isEncrypted(id.toString()));
        MessageInfo msgInfo = msgInfoAndBuffer.messageInfo;
        ByteBuffer byteBuffer = msgInfoAndBuffer.byteBuffer;
        if (transformer != null) {
            Message message = new Message(msgInfo, new ByteBufferInputStream(byteBuffer));
            TransformationOutput output = transformer.transform(message);
            assertNull(output.getException());
            message = output.getMsg();
            byteBuffer = ByteBuffer.wrap(Utils.readBytesFromStream(message.getStream(), (int) message.getMessageInfo().getSize()));
            msgInfo = message.getMessageInfo();
        }
        for (MockHost host : hosts) {
            host.addMessage(id.getPartition(), msgInfo, byteBuffer.duplicate());
        }
    }
}
Also used : Transformer(com.github.ambry.store.Transformer) Message(com.github.ambry.store.Message) TransformationOutput(com.github.ambry.store.TransformationOutput) ByteBufferInputStream(com.github.ambry.utils.ByteBufferInputStream) StoreKey(com.github.ambry.store.StoreKey) BlobId(com.github.ambry.commons.BlobId) ByteBuffer(java.nio.ByteBuffer) MessageInfo(com.github.ambry.store.MessageInfo)

Example 99 with MessageInfo

use of com.github.ambry.store.MessageInfo in project ambry by linkedin.

the class ReplicationTestHelper method addPutMessagesToReplicasOfPartition.

/**
 * For the given partitionId, constructs a PUT messages and adds it to the given hosts.
 * @param id the {@link StoreKey} to create a put message for.
 * @param accountId the accountId of this message.
 * @param containerId the containerId of this message.
 * @param partitionId the {@link PartitionId} to use for generating the {@link StoreKey} of the message.
 * @param hosts the list of {@link MockHost} all of which will be populated with the messages.
 * @param operationTime the operation of this message.
 * @param expirationTime the expirationTime of this message.
 * @throws MessageFormatException
 * @throws IOException
 */
public static void addPutMessagesToReplicasOfPartition(StoreKey id, short accountId, short containerId, PartitionId partitionId, List<MockHost> hosts, long operationTime, long expirationTime) throws MessageFormatException, IOException {
    // add a PUT message with expiration time less than VCR threshold to remote host.
    boolean toEncrypt = TestUtils.RANDOM.nextBoolean();
    ReplicationTest.PutMsgInfoAndBuffer msgInfoAndBuffer = createPutMessage(id, accountId, containerId, toEncrypt);
    for (MockHost host : hosts) {
        host.addMessage(partitionId, new MessageInfo(id, msgInfoAndBuffer.byteBuffer.remaining(), false, false, false, expirationTime, null, accountId, containerId, operationTime, (short) 0), msgInfoAndBuffer.byteBuffer);
    }
}
Also used : MessageInfo(com.github.ambry.store.MessageInfo)

Example 100 with MessageInfo

use of com.github.ambry.store.MessageInfo in project ambry by linkedin.

the class ReplicationTestHelper method lifeVersionLocalGreaterThanRemote_Delete.

/**
 * Helepr function to test when the local lifeVersion is greater than the remote lifeVersion.
 * @param localTtlUpdated
 * @param remoteTtlUpdated
 * @throws Exception
 */
protected void lifeVersionLocalGreaterThanRemote_Delete(boolean localTtlUpdated, boolean remoteTtlUpdated) throws Exception {
    MockClusterMap clusterMap = new MockClusterMap();
    Pair<MockHost, MockHost> localAndRemoteHosts = getLocalAndRemoteHosts(clusterMap);
    MockHost localHost = localAndRemoteHosts.getFirst();
    MockHost remoteHost = localAndRemoteHosts.getSecond();
    MockStoreKeyConverterFactory storeKeyConverterFactory = new MockStoreKeyConverterFactory(null, null);
    storeKeyConverterFactory.setConversionMap(new HashMap<>());
    storeKeyConverterFactory.setReturnInputIfAbsent(true);
    MockStoreKeyConverterFactory.MockStoreKeyConverter storeKeyConverter = storeKeyConverterFactory.getStoreKeyConverter();
    List<PartitionId> partitionIds = clusterMap.getWritablePartitionIds(null);
    for (int i = 0; i < partitionIds.size(); i++) {
        PartitionId partitionId = partitionIds.get(i);
        // add 1 messages to remote host with lifeVersion being 0 and add it local host with lifeVersion being 1.
        StoreKey toDeleteId = addPutMessagesToReplicasOfPartition(partitionId, Arrays.asList(remoteHost), 1).get(0);
        if (remoteTtlUpdated) {
            addTtlUpdateMessagesToReplicasOfPartition(partitionId, toDeleteId, Arrays.asList(remoteHost), UPDATED_EXPIRY_TIME_MS);
        }
        addDeleteMessagesToReplicasOfPartition(partitionId, toDeleteId, Collections.singletonList(remoteHost));
        BlobId blobId = (BlobId) toDeleteId;
        short accountId = blobId.getAccountId();
        short containerId = blobId.getContainerId();
        short lifeVersion = 1;
        // first put message has encryption turned on
        boolean toEncrypt = true;
        // create a put message with lifeVersion bigger than 0
        PutMsgInfoAndBuffer msgInfoAndBuffer = createPutMessage(toDeleteId, accountId, containerId, toEncrypt, lifeVersion);
        localHost.addMessage(partitionId, new MessageInfo(toDeleteId, msgInfoAndBuffer.byteBuffer.remaining(), false, false, false, Utils.Infinite_Time, null, accountId, containerId, msgInfoAndBuffer.messageInfo.getOperationTimeMs(), lifeVersion), msgInfoAndBuffer.byteBuffer);
        if (localTtlUpdated) {
            addTtlUpdateMessagesToReplicasOfPartition(partitionId, toDeleteId, Collections.singletonList(localHost), EXPIRY_TIME_MS, lifeVersion);
        }
        // ensure that the first key is not deleted in the local host
        assertNull(toDeleteId + " should not be deleted in the local host", getMessageInfo(toDeleteId, localHost.infosByPartition.get(partitionId), true, false, false));
    }
    int batchSize = 4;
    Pair<Map<DataNodeId, List<RemoteReplicaInfo>>, ReplicaThread> replicasAndThread = getRemoteReplicasAndReplicaThread(batchSize, clusterMap, localHost, remoteHost, storeKeyConverter, null, null, null);
    List<RemoteReplicaInfo> remoteReplicaInfos = replicasAndThread.getFirst().get(remoteHost.dataNodeId);
    ReplicaThread replicaThread = replicasAndThread.getSecond();
    // Do the replica metadata exchange.
    List<ReplicaThread.ExchangeMetadataResponse> response = replicaThread.exchangeMetadata(new MockConnectionPool.MockConnection(remoteHost, batchSize), remoteReplicaInfos);
    assertEquals("Response should contain a response for each replica", remoteReplicaInfos.size(), response.size());
    for (int i = 0; i < response.size(); i++) {
        // we don't have any missing key here.
        assertEquals(0, response.get(i).missingStoreMessages.size());
        remoteReplicaInfos.get(i).setToken(response.get(i).remoteToken);
        PartitionId partitionId = partitionIds.get(i);
        StoreKey key = localHost.infosByPartition.get(partitionId).get(0).getStoreKey();
        assertNull(key + " should not be deleted in the local host", getMessageInfo(key, localHost.infosByPartition.get(partitionId), true, false, false));
        if (!localTtlUpdated) {
            assertNull(key + " should not be ttlUpdated in the local host", getMessageInfo(key, localHost.infosByPartition.get(partitionId), false, false, true));
        }
    }
}
Also used : MockStoreKeyConverterFactory(com.github.ambry.store.MockStoreKeyConverterFactory) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) StoreKey(com.github.ambry.store.StoreKey) MessageInfo(com.github.ambry.store.MessageInfo) BlobId(com.github.ambry.commons.BlobId) Map(java.util.Map) HashMap(java.util.HashMap) ClusterMap(com.github.ambry.clustermap.ClusterMap) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) MockClusterMap(com.github.ambry.clustermap.MockClusterMap)

Aggregations

MessageInfo (com.github.ambry.store.MessageInfo)109 ArrayList (java.util.ArrayList)49 StoreKey (com.github.ambry.store.StoreKey)42 ByteBuffer (java.nio.ByteBuffer)38 BlobId (com.github.ambry.commons.BlobId)36 StoreException (com.github.ambry.store.StoreException)30 DataInputStream (java.io.DataInputStream)23 Test (org.junit.Test)22 HashMap (java.util.HashMap)21 MockPartitionId (com.github.ambry.clustermap.MockPartitionId)19 PartitionId (com.github.ambry.clustermap.PartitionId)19 IOException (java.io.IOException)19 MockClusterMap (com.github.ambry.clustermap.MockClusterMap)18 ByteBufferInputStream (com.github.ambry.utils.ByteBufferInputStream)18 InputStream (java.io.InputStream)17 List (java.util.List)16 ClusterMap (com.github.ambry.clustermap.ClusterMap)15 Map (java.util.Map)15 MockMessageWriteSet (com.github.ambry.store.MockMessageWriteSet)13 HashSet (java.util.HashSet)13