Search in sources :

Example 76 with PartitionId

use of com.github.ambry.clustermap.PartitionId in project ambry by linkedin.

the class ServerTestUtil method endToEndTest.

static void endToEndTest(Port targetPort, String routerDatacenter, MockCluster cluster, SSLConfig clientSSLConfig, SSLSocketFactory clientSSLSocketFactory, Properties routerProps, boolean testEncryption) {
    try {
        MockClusterMap clusterMap = cluster.getClusterMap();
        BlobIdFactory blobIdFactory = new BlobIdFactory(clusterMap);
        byte[] userMetadata = new byte[1000];
        byte[] data = new byte[31870];
        byte[] encryptionKey = new byte[100];
        short accountId = Utils.getRandomShort(TestUtils.RANDOM);
        short containerId = Utils.getRandomShort(TestUtils.RANDOM);
        BlobProperties properties = new BlobProperties(31870, "serviceid1", accountId, containerId, testEncryption, cluster.time.milliseconds());
        TestUtils.RANDOM.nextBytes(userMetadata);
        TestUtils.RANDOM.nextBytes(data);
        if (testEncryption) {
            TestUtils.RANDOM.nextBytes(encryptionKey);
        }
        List<PartitionId> partitionIds = clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS);
        short blobIdVersion = CommonTestUtils.getCurrentBlobIdVersion();
        BlobId blobId1 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        BlobId blobId2 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        BlobId blobId3 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        BlobId blobId4 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        BlobId blobId5 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        // put blob 1
        PutRequest putRequest = new PutRequest(1, "client1", blobId1, properties, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        ConnectedChannel channel = getBlockingChannelBasedOnPortType(targetPort, "localhost", clientSSLSocketFactory, clientSSLConfig);
        channel.connect();
        DataInputStream putResponseStream = channel.sendAndReceive(putRequest).getInputStream();
        PutResponse response = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals(ServerErrorCode.No_Error, response.getError());
        // put blob 2 with an expiry time and apply TTL update later
        BlobProperties propertiesForTtlUpdate = new BlobProperties(31870, "serviceid1", "ownerid", "image/png", false, TestUtils.TTL_SECS, cluster.time.milliseconds(), accountId, containerId, testEncryption, null, null, null);
        long ttlUpdateBlobExpiryTimeMs = getExpiryTimeMs(propertiesForTtlUpdate);
        PutRequest putRequest2 = new PutRequest(1, "client1", blobId2, propertiesForTtlUpdate, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        putResponseStream = channel.sendAndReceive(putRequest2).getInputStream();
        PutResponse response2 = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals(ServerErrorCode.No_Error, response2.getError());
        // put blob 3
        PutRequest putRequest3 = new PutRequest(1, "client1", blobId3, properties, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        putResponseStream = channel.sendAndReceive(putRequest3).getInputStream();
        PutResponse response3 = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals(ServerErrorCode.No_Error, response3.getError());
        // put blob 4 that is expired
        BlobProperties propertiesExpired = new BlobProperties(31870, "serviceid1", "ownerid", "jpeg", false, 0, cluster.time.milliseconds(), accountId, containerId, testEncryption, null, null, null);
        PutRequest putRequest4 = new PutRequest(1, "client1", blobId4, propertiesExpired, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        putResponseStream = channel.sendAndReceive(putRequest4).getInputStream();
        PutResponse response4 = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals(ServerErrorCode.No_Error, response4.getError());
        cluster.time.sleep(10000);
        // get blob properties
        ArrayList<BlobId> ids = new ArrayList<>();
        MockPartitionId partition = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        ids.add(blobId1);
        ArrayList<PartitionRequestInfo> partitionRequestInfoList = new ArrayList<PartitionRequestInfo>();
        PartitionRequestInfo partitionRequestInfo = new PartitionRequestInfo(partition, ids);
        partitionRequestInfoList.add(partitionRequestInfo);
        GetRequest getRequest1 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoList, GetOption.None);
        DataInputStream stream = channel.sendAndReceive(getRequest1).getInputStream();
        GetResponse resp1 = GetResponse.readFrom(stream, clusterMap);
        try {
            BlobProperties propertyOutput = MessageFormatRecord.deserializeBlobProperties(resp1.getInputStream());
            assertEquals(31870, propertyOutput.getBlobSize());
            assertEquals("serviceid1", propertyOutput.getServiceId());
            assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
            assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
            releaseNettyBufUnderneathStream(stream);
        } catch (MessageFormatException e) {
            fail();
        }
        // get blob properties with expired flag set
        ids = new ArrayList<BlobId>();
        partition = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        ids.add(blobId1);
        partitionRequestInfoList = new ArrayList<>();
        partitionRequestInfo = new PartitionRequestInfo(partition, ids);
        partitionRequestInfoList.add(partitionRequestInfo);
        getRequest1 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoList, GetOption.Include_Expired_Blobs);
        stream = channel.sendAndReceive(getRequest1).getInputStream();
        resp1 = GetResponse.readFrom(stream, clusterMap);
        try {
            BlobProperties propertyOutput = MessageFormatRecord.deserializeBlobProperties(resp1.getInputStream());
            assertEquals(31870, propertyOutput.getBlobSize());
            assertEquals("serviceid1", propertyOutput.getServiceId());
            assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
            assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
            releaseNettyBufUnderneathStream(stream);
        } catch (MessageFormatException e) {
            fail();
        }
        // get blob properties for expired blob
        // 1. With no flag
        ArrayList<BlobId> idsExpired = new ArrayList<>();
        MockPartitionId partitionExpired = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        idsExpired.add(blobId4);
        ArrayList<PartitionRequestInfo> partitionRequestInfoListExpired = new ArrayList<>();
        PartitionRequestInfo partitionRequestInfoExpired = new PartitionRequestInfo(partitionExpired, idsExpired);
        partitionRequestInfoListExpired.add(partitionRequestInfoExpired);
        GetRequest getRequestExpired = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoListExpired, GetOption.None);
        DataInputStream streamExpired = channel.sendAndReceive(getRequestExpired).getInputStream();
        GetResponse respExpired = GetResponse.readFrom(streamExpired, clusterMap);
        assertEquals(ServerErrorCode.Blob_Expired, respExpired.getPartitionResponseInfoList().get(0).getErrorCode());
        releaseNettyBufUnderneathStream(streamExpired);
        // 2. With Include_Expired flag
        idsExpired = new ArrayList<>();
        partitionExpired = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        idsExpired.add(blobId4);
        partitionRequestInfoListExpired = new ArrayList<>();
        partitionRequestInfoExpired = new PartitionRequestInfo(partitionExpired, idsExpired);
        partitionRequestInfoListExpired.add(partitionRequestInfoExpired);
        getRequestExpired = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoListExpired, GetOption.Include_Expired_Blobs);
        streamExpired = channel.sendAndReceive(getRequestExpired).getInputStream();
        respExpired = GetResponse.readFrom(streamExpired, clusterMap);
        try {
            BlobProperties propertyOutput = MessageFormatRecord.deserializeBlobProperties(respExpired.getInputStream());
            assertEquals(31870, propertyOutput.getBlobSize());
            assertEquals("serviceid1", propertyOutput.getServiceId());
            assertEquals("ownerid", propertyOutput.getOwnerId());
            assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
            assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
            releaseNettyBufUnderneathStream(streamExpired);
        } catch (MessageFormatException e) {
            fail();
        }
        // get user metadata
        GetRequest getRequest2 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobUserMetadata, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest2).getInputStream();
        GetResponse resp2 = GetResponse.readFrom(stream, clusterMap);
        try {
            ByteBuffer userMetadataOutput = MessageFormatRecord.deserializeUserMetadata(resp2.getInputStream());
            assertArrayEquals(userMetadata, userMetadataOutput.array());
            if (testEncryption) {
                assertNotNull("MessageMetadata should not have been null", resp2.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0));
                assertArrayEquals("EncryptionKey mismatch", encryptionKey, resp2.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0).getEncryptionKey().array());
            } else {
                assertNull("MessageMetadata should have been null", resp2.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0));
            }
            releaseNettyBufUnderneathStream(stream);
        } catch (MessageFormatException e) {
            fail();
        }
        // get blob info
        GetRequest getRequest3 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobInfo, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest3).getInputStream();
        GetResponse resp3 = GetResponse.readFrom(stream, clusterMap);
        InputStream responseStream = resp3.getInputStream();
        // verify blob properties.
        BlobProperties propertyOutput = MessageFormatRecord.deserializeBlobProperties(responseStream);
        assertEquals(31870, propertyOutput.getBlobSize());
        assertEquals("serviceid1", propertyOutput.getServiceId());
        assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
        assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
        // verify user metadata
        ByteBuffer userMetadataOutput = MessageFormatRecord.deserializeUserMetadata(responseStream);
        assertArrayEquals(userMetadata, userMetadataOutput.array());
        if (testEncryption) {
            assertNotNull("MessageMetadata should not have been null", resp3.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0));
            assertArrayEquals("EncryptionKey mismatch", encryptionKey, resp3.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0).getEncryptionKey().array());
        } else {
            assertNull("MessageMetadata should have been null", resp3.getPartitionResponseInfoList().get(0).getMessageMetadataList().get(0));
        }
        releaseNettyBufUnderneathStream(stream);
        // get blob all
        GetRequest getRequest4 = new GetRequest(1, "clientid2", MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest4).getInputStream();
        GetResponse resp4 = GetResponse.readFrom(stream, clusterMap);
        responseStream = resp4.getInputStream();
        BlobAll blobAll = MessageFormatRecord.deserializeBlobAll(responseStream, blobIdFactory);
        byte[] actualBlobData = getBlobDataAndRelease(blobAll.getBlobData());
        // verify content
        assertArrayEquals("Content mismatch.", data, actualBlobData);
        if (testEncryption) {
            assertNotNull("EncryptionKey should not ne null", blobAll.getBlobEncryptionKey());
            assertArrayEquals("EncryptionKey mismatch", encryptionKey, blobAll.getBlobEncryptionKey().array());
        } else {
            assertNull("EncryptionKey should have been null", blobAll.getBlobEncryptionKey());
        }
        releaseNettyBufUnderneathStream(stream);
        // encryptionKey in this test doesn't have any relation to the content. Both are random bytes for test purposes.
        if (!testEncryption) {
            // Use router to get the blob
            Properties routerProperties = getRouterProps(routerDatacenter);
            routerProperties.putAll(routerProps);
            VerifiableProperties routerVerifiableProps = new VerifiableProperties(routerProperties);
            AccountService accountService = new InMemAccountService(false, true);
            Router router = new NonBlockingRouterFactory(routerVerifiableProps, clusterMap, new MockNotificationSystem(clusterMap), getSSLFactoryIfRequired(routerVerifiableProps), accountService).getRouter();
            checkBlobId(router, blobId1, data);
            router.close();
        }
        checkTtlUpdateStatus(channel, clusterMap, blobIdFactory, blobId2, data, false, ttlUpdateBlobExpiryTimeMs);
        updateBlobTtl(channel, blobId2, cluster.time.milliseconds());
        checkTtlUpdateStatus(channel, clusterMap, blobIdFactory, blobId2, data, true, Utils.Infinite_Time);
        // fetch blob that does not exist
        // get blob properties
        ids = new ArrayList<>();
        partition = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        ids.add(new BlobId(CommonTestUtils.getCurrentBlobIdVersion(), BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partition, false, BlobId.BlobDataType.DATACHUNK));
        partitionRequestInfoList.clear();
        partitionRequestInfo = new PartitionRequestInfo(partition, ids);
        partitionRequestInfoList.add(partitionRequestInfo);
        GetRequest getRequest5 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest5).getInputStream();
        GetResponse resp5 = GetResponse.readFrom(stream, clusterMap);
        assertEquals(ServerErrorCode.Blob_Not_Found, resp5.getPartitionResponseInfoList().get(0).getErrorCode());
        releaseNettyBufUnderneathStream(stream);
        // stop the store via AdminRequest
        System.out.println("Begin to stop a BlobStore");
        AdminRequest adminRequest = new AdminRequest(AdminRequestOrResponseType.BlobStoreControl, partitionIds.get(0), 1, "clientid2");
        BlobStoreControlAdminRequest controlRequest = new BlobStoreControlAdminRequest((short) 0, BlobStoreControlAction.StopStore, adminRequest);
        stream = channel.sendAndReceive(controlRequest).getInputStream();
        AdminResponse adminResponse = AdminResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Stop store admin request should succeed", ServerErrorCode.No_Error, adminResponse.getError());
        // put a blob on a stopped store, which should fail
        putRequest = new PutRequest(1, "client1", blobId5, properties, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        putResponseStream = channel.sendAndReceive(putRequest).getInputStream();
        response = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals("Put blob on stopped store should fail", ServerErrorCode.Replica_Unavailable, response.getError());
        // get a blob properties on a stopped store, which should fail
        ids = new ArrayList<>();
        partition = (MockPartitionId) blobId1.getPartition();
        ids.add(blobId1);
        partitionRequestInfoList = new ArrayList<>();
        partitionRequestInfo = new PartitionRequestInfo(partition, ids);
        partitionRequestInfoList.add(partitionRequestInfo);
        getRequest1 = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest1).getInputStream();
        resp1 = GetResponse.readFrom(stream, clusterMap);
        assertEquals("Get blob properties on stopped store should fail", ServerErrorCode.Replica_Unavailable, resp1.getPartitionResponseInfoList().get(0).getErrorCode());
        releaseNettyBufUnderneathStream(stream);
        // delete a blob on a stopped store, which should fail
        DeleteRequest deleteRequest = new DeleteRequest(1, "deleteClient", blobId1, System.currentTimeMillis());
        stream = channel.sendAndReceive(deleteRequest).getInputStream();
        DeleteResponse deleteResponse = DeleteResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Delete blob on stopped store should fail", ServerErrorCode.Replica_Unavailable, deleteResponse.getError());
        // start the store via AdminRequest
        System.out.println("Begin to restart the BlobStore");
        adminRequest = new AdminRequest(AdminRequestOrResponseType.BlobStoreControl, partitionIds.get(0), 1, "clientid2");
        controlRequest = new BlobStoreControlAdminRequest((short) 0, BlobStoreControlAction.StartStore, adminRequest);
        stream = channel.sendAndReceive(controlRequest).getInputStream();
        adminResponse = AdminResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Start store admin request should succeed", ServerErrorCode.No_Error, adminResponse.getError());
        List<? extends ReplicaId> replicaIds = partitionIds.get(0).getReplicaIds();
        for (ReplicaId replicaId : replicaIds) {
            // forcibly mark replicas and disks as up.
            MockReplicaId mockReplicaId = (MockReplicaId) replicaId;
            mockReplicaId.markReplicaDownStatus(false);
            ((MockDiskId) mockReplicaId.getDiskId()).setDiskState(HardwareState.AVAILABLE, false);
        }
        // put a blob on a restarted store , which should succeed
        PutRequest putRequest5 = new PutRequest(1, "client1", blobId5, properties, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, testEncryption ? ByteBuffer.wrap(encryptionKey) : null);
        putResponseStream = channel.sendAndReceive(putRequest5).getInputStream();
        PutResponse response5 = PutResponse.readFrom(putResponseStream);
        releaseNettyBufUnderneathStream(putResponseStream);
        assertEquals("Put blob on restarted store should succeed", ServerErrorCode.No_Error, response5.getError());
        // get a blob on a restarted store , which should succeed
        ids = new ArrayList<>();
        PartitionId partitionId = clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
        ids.add(blobId1);
        partitionRequestInfoList = new ArrayList<>();
        partitionRequestInfo = new PartitionRequestInfo(partitionId, ids);
        partitionRequestInfoList.add(partitionRequestInfo);
        getRequest1 = new GetRequest(1, "clientid1", MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest1).getInputStream();
        resp1 = GetResponse.readFrom(stream, clusterMap);
        responseStream = resp1.getInputStream();
        blobAll = MessageFormatRecord.deserializeBlobAll(responseStream, blobIdFactory);
        actualBlobData = getBlobDataAndRelease(blobAll.getBlobData());
        assertArrayEquals("Content mismatch.", data, actualBlobData);
        releaseNettyBufUnderneathStream(stream);
        // undelete a not-deleted blob should return fail
        UndeleteRequest undeleteRequest = new UndeleteRequest(1, "undeleteClient", blobId1, System.currentTimeMillis());
        stream = channel.sendAndReceive(undeleteRequest).getInputStream();
        UndeleteResponse undeleteResponse = UndeleteResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Undelete blob should succeed", ServerErrorCode.Blob_Not_Deleted, undeleteResponse.getError());
        // delete a blob on a restarted store , which should succeed
        deleteRequest = new DeleteRequest(1, "deleteClient", blobId1, System.currentTimeMillis());
        stream = channel.sendAndReceive(deleteRequest).getInputStream();
        deleteResponse = DeleteResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Delete blob on restarted store should succeed", ServerErrorCode.No_Error, deleteResponse.getError());
        // undelete a deleted blob, which should succeed
        undeleteRequest = new UndeleteRequest(2, "undeleteClient", blobId1, System.currentTimeMillis());
        stream = channel.sendAndReceive(undeleteRequest).getInputStream();
        undeleteResponse = UndeleteResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Undelete blob should succeed", ServerErrorCode.No_Error, undeleteResponse.getError());
        assertEquals("Undelete life version mismatch", undeleteResponse.getLifeVersion(), (short) 1);
        // undelete an already undeleted blob, which should fail
        undeleteRequest = new UndeleteRequest(3, "undeleteClient", blobId1, System.currentTimeMillis());
        stream = channel.sendAndReceive(undeleteRequest).getInputStream();
        undeleteResponse = UndeleteResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals("Undelete blob should fail", ServerErrorCode.Blob_Already_Undeleted, undeleteResponse.getError());
        assertEquals("LifeVersion Mismatch", (short) 1, undeleteResponse.getLifeVersion());
        // get an undeleted blob, which should succeed
        getRequest1 = new GetRequest(1, "clientid1", MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest1).getInputStream();
        resp1 = GetResponse.readFrom(stream, clusterMap);
        responseStream = resp1.getInputStream();
        blobAll = MessageFormatRecord.deserializeBlobAll(responseStream, blobIdFactory);
        actualBlobData = getBlobDataAndRelease(blobAll.getBlobData());
        assertArrayEquals("Content mismatch", data, actualBlobData);
        releaseNettyBufUnderneathStream(stream);
        // Bounce servers to make them read the persisted token file.
        cluster.stopServers();
        cluster.reinitServers();
        channel.disconnect();
        channel.connect();
        // get an undeleted blob after restart, which should succeed
        getRequest1 = new GetRequest(1, "clientid1", MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
        stream = channel.sendAndReceive(getRequest1).getInputStream();
        resp1 = GetResponse.readFrom(stream, clusterMap);
        responseStream = resp1.getInputStream();
        blobAll = MessageFormatRecord.deserializeBlobAll(responseStream, blobIdFactory);
        actualBlobData = getBlobDataAndRelease(blobAll.getBlobData());
        assertArrayEquals("Content mismatch", data, actualBlobData);
        releaseNettyBufUnderneathStream(stream);
        channel.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
        assertNull(e);
    } finally {
        List<? extends ReplicaId> replicaIds = cluster.getClusterMap().getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0).getReplicaIds();
        for (ReplicaId replicaId : replicaIds) {
            MockReplicaId mockReplicaId = (MockReplicaId) replicaId;
            ((MockDiskId) mockReplicaId.getDiskId()).setDiskState(HardwareState.AVAILABLE, true);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) UndeleteResponse(com.github.ambry.protocol.UndeleteResponse) PutResponse(com.github.ambry.protocol.PutResponse) BlobProperties(com.github.ambry.messageformat.BlobProperties) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) InMemAccountService(com.github.ambry.account.InMemAccountService) BlobAll(com.github.ambry.messageformat.BlobAll) GetRequest(com.github.ambry.protocol.GetRequest) BlobStoreControlAdminRequest(com.github.ambry.protocol.BlobStoreControlAdminRequest) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) NonBlockingRouterFactory(com.github.ambry.router.NonBlockingRouterFactory) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) VerifiableProperties(com.github.ambry.config.VerifiableProperties) NettyByteBufDataInputStream(com.github.ambry.utils.NettyByteBufDataInputStream) PutMessageFormatInputStream(com.github.ambry.messageformat.PutMessageFormatInputStream) ByteBufferInputStream(com.github.ambry.utils.ByteBufferInputStream) DataInputStream(java.io.DataInputStream) CrcInputStream(com.github.ambry.utils.CrcInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) PutRequest(com.github.ambry.protocol.PutRequest) Router(com.github.ambry.router.Router) ConnectedChannel(com.github.ambry.network.ConnectedChannel) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) NettyByteBufDataInputStream(com.github.ambry.utils.NettyByteBufDataInputStream) DataInputStream(java.io.DataInputStream) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) GetResponse(com.github.ambry.protocol.GetResponse) ByteBuffer(java.nio.ByteBuffer) ReplicaId(com.github.ambry.clustermap.ReplicaId) MockReplicaId(com.github.ambry.clustermap.MockReplicaId) IOException(java.io.IOException) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) RouterException(com.github.ambry.router.RouterException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) BlobIdFactory(com.github.ambry.commons.BlobIdFactory) ReplicationControlAdminRequest(com.github.ambry.protocol.ReplicationControlAdminRequest) BlobStoreControlAdminRequest(com.github.ambry.protocol.BlobStoreControlAdminRequest) AdminRequest(com.github.ambry.protocol.AdminRequest) AdminResponse(com.github.ambry.protocol.AdminResponse) DeleteResponse(com.github.ambry.protocol.DeleteResponse) BlobProperties(com.github.ambry.messageformat.BlobProperties) MockReplicaId(com.github.ambry.clustermap.MockReplicaId) MockDiskId(com.github.ambry.clustermap.MockDiskId) BlobId(com.github.ambry.commons.BlobId) InMemAccountService(com.github.ambry.account.InMemAccountService) AccountService(com.github.ambry.account.AccountService) DeleteRequest(com.github.ambry.protocol.DeleteRequest) MockClusterMap(com.github.ambry.clustermap.MockClusterMap)

Example 77 with PartitionId

use of com.github.ambry.clustermap.PartitionId in project ambry by linkedin.

the class ServerTestUtil method undeleteRecoveryTest.

static void undeleteRecoveryTest(Port targetPort, MockCluster cluster, SSLConfig clientSSLConfig, SSLSocketFactory clientSSLSocketFactory) {
    try {
        MockClusterMap clusterMap = cluster.getClusterMap();
        byte[] userMetadata = new byte[1000];
        byte[] data = new byte[31870];
        short accountId = Utils.getRandomShort(TestUtils.RANDOM);
        short containerId = Utils.getRandomShort(TestUtils.RANDOM);
        BlobProperties properties = new BlobProperties(31870, "serviceid1", accountId, containerId, false, cluster.time.milliseconds());
        TestUtils.RANDOM.nextBytes(userMetadata);
        TestUtils.RANDOM.nextBytes(data);
        List<PartitionId> partitionIds = clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS);
        short blobIdVersion = CommonTestUtils.getCurrentBlobIdVersion();
        BlobId blobId1 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        // put blob 1
        PutRequest putRequest = new PutRequest(1, "client1", blobId1, properties, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, null);
        ConnectedChannel channel = getBlockingChannelBasedOnPortType(targetPort, "localhost", clientSSLSocketFactory, clientSSLConfig);
        channel.connect();
        DataInputStream stream = channel.sendAndReceive(putRequest).getInputStream();
        PutResponse response = PutResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals(ServerErrorCode.No_Error, response.getError());
        for (int i = 0; i < 2; i++) {
            // delete blob 1
            deleteBlob(channel, blobId1, cluster.time.milliseconds());
            // undelete blob 1
            undeleteBlob(channel, blobId1, cluster.time.milliseconds(), (short) (i + 1));
        }
        // put blob 2 that is expired (Add additional 5 secs to avoid Blob_Update_Not_Allowed failure as TtlUpdate op time
        // is also cluster.time.milliseconds(). Theoretically, it should succeed as op time = expiry time - buffer time.
        // However, the index value converts ms to sec when putting a blob, so the milliseconds part of initial put blob
        // time is wiped out and makes op time > expiry time - buffer time. Adding some time should avoid this failure.)
        long ttl = 24 * 60 * 60 + 5;
        BlobProperties propertiesExpired = new BlobProperties(31870, "serviceid1", "ownerid", "jpeg", false, ttl, cluster.time.milliseconds(), accountId, containerId, false, null, null, null);
        BlobId blobId2 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), propertiesExpired.getAccountId(), propertiesExpired.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
        PutRequest putRequest2 = new PutRequest(1, "client1", blobId2, propertiesExpired, ByteBuffer.wrap(userMetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, null);
        stream = channel.sendAndReceive(putRequest2).getInputStream();
        PutResponse response2 = PutResponse.readFrom(stream);
        releaseNettyBufUnderneathStream(stream);
        assertEquals(ServerErrorCode.No_Error, response2.getError());
        for (int i = 0; i < 2; i++) {
            // delete blob 2
            deleteBlob(channel, blobId2, cluster.time.milliseconds());
            // undelete blob 2
            undeleteBlob(channel, blobId2, cluster.time.milliseconds(), (short) (i + 1));
        }
        // ttl update blob 2
        updateBlobTtl(channel, blobId2, cluster.time.milliseconds());
        cluster.time.sleep(ttl + 10000);
        // Now stops the server and remove all the index files for this partition and test its recovery.
        channel.disconnect();
        AmbryServer server = cluster.getServers().get(0);
        server.shutdown();
        server.awaitShutdown();
        MockDataNodeId dataNode = (MockDataNodeId) clusterMap.getDataNodeId("localhost", channel.getRemotePort());
        for (ReplicaId replica : partitionIds.get(0).getReplicaIds()) {
            if (replica.getDataNodeId().equals(dataNode)) {
                for (File file : Objects.requireNonNull(new File(replica.getReplicaPath()).listFiles((file, filename) -> filename.endsWith("index")))) {
                    file.delete();
                }
            }
        }
        cluster.reinitServer(0);
        channel = getBlockingChannelBasedOnPortType(targetPort, "localhost", clientSSLSocketFactory, clientSSLConfig);
        channel.connect();
        // Now verify that we can fetch blob1 and blob2.
        for (BlobId blobId : new BlobId[] { blobId1, blobId2 }) {
            long deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
            while (true) {
                // get blob properties
                ArrayList<BlobId> ids = new ArrayList<>();
                ids.add(blobId);
                ArrayList<PartitionRequestInfo> partitionRequestInfoList = new ArrayList<>();
                PartitionRequestInfo partitionRequestInfo = new PartitionRequestInfo(partitionIds.get(0), ids);
                partitionRequestInfoList.add(partitionRequestInfo);
                GetRequest getRequest = new GetRequest(1, "clientid2", MessageFormatFlags.BlobProperties, partitionRequestInfoList, GetOption.None);
                stream = channel.sendAndReceive(getRequest).getInputStream();
                GetResponse getResponse = GetResponse.readFrom(stream, clusterMap);
                if (getResponse.getPartitionResponseInfoList().get(0).getErrorCode() == ServerErrorCode.No_Error) {
                    BlobProperties propertyOutput = MessageFormatRecord.deserializeBlobProperties(getResponse.getInputStream());
                    assertEquals(31870, propertyOutput.getBlobSize());
                    assertEquals("serviceid1", propertyOutput.getServiceId());
                    assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
                    assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
                    releaseNettyBufUnderneathStream(stream);
                    break;
                } else {
                    Thread.sleep(1000);
                    if (System.currentTimeMillis() > deadline) {
                        throw new TimeoutException("Fail to get blob " + blobId + " at  " + channel.getRemoteHost());
                    }
                }
            }
        }
        channel.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
        fail();
    }
}
Also used : AdminRequestOrResponseType(com.github.ambry.protocol.AdminRequestOrResponseType) GetOption(com.github.ambry.protocol.GetOption) Arrays(java.util.Arrays) Http2ClientConfig(com.github.ambry.config.Http2ClientConfig) BlobProperties(com.github.ambry.messageformat.BlobProperties) BlobAll(com.github.ambry.messageformat.BlobAll) SubRecord(com.github.ambry.messageformat.SubRecord) Future(java.util.concurrent.Future) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) TtlUpdateResponse(com.github.ambry.protocol.TtlUpdateResponse) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) RouterErrorCode(com.github.ambry.router.RouterErrorCode) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) SSLFactory(com.github.ambry.commons.SSLFactory) BlobData(com.github.ambry.messageformat.BlobData) Set(java.util.Set) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) SSLSocketFactory(javax.net.ssl.SSLSocketFactory) CountDownLatch(java.util.concurrent.CountDownLatch) MockDiskId(com.github.ambry.clustermap.MockDiskId) UpdateType(com.github.ambry.notification.UpdateType) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) ArrayList(java.util.ArrayList) NettyByteBufDataInputStream(com.github.ambry.utils.NettyByteBufDataInputStream) ReplicationControlAdminRequest(com.github.ambry.protocol.ReplicationControlAdminRequest) BlockingChannel(com.github.ambry.network.BlockingChannel) BlockingChannelConnectionPool(com.github.ambry.network.BlockingChannelConnectionPool) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) PutMessageFormatInputStream(com.github.ambry.messageformat.PutMessageFormatInputStream) Offset(com.github.ambry.store.Offset) VerifiableProperties(com.github.ambry.config.VerifiableProperties) IOException(java.io.IOException) BlobIdFactory(com.github.ambry.commons.BlobIdFactory) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) PutResponse(com.github.ambry.protocol.PutResponse) RouterException(com.github.ambry.router.RouterException) LatchBasedInMemoryCloudDestinationFactory(com.github.ambry.cloud.LatchBasedInMemoryCloudDestinationFactory) File(java.io.File) ExecutionException(java.util.concurrent.ExecutionException) GetBlobResult(com.github.ambry.router.GetBlobResult) ReplicaId(com.github.ambry.clustermap.ReplicaId) PutBlobOptionsBuilder(com.github.ambry.router.PutBlobOptionsBuilder) ByteBufferInputStream(com.github.ambry.utils.ByteBufferInputStream) ClusterMapConfig(com.github.ambry.config.ClusterMapConfig) BlobStoreControlAdminRequest(com.github.ambry.protocol.BlobStoreControlAdminRequest) StoreFindToken(com.github.ambry.store.StoreFindToken) Assert(org.junit.Assert) GetBlobOptionsBuilder(com.github.ambry.router.GetBlobOptionsBuilder) Http2BlockingChannel(com.github.ambry.network.http2.Http2BlockingChannel) ConnectionPoolConfig(com.github.ambry.config.ConnectionPoolConfig) DataNodeId(com.github.ambry.clustermap.DataNodeId) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) TimeoutException(java.util.concurrent.TimeoutException) Http2ClientMetrics(com.github.ambry.network.http2.Http2ClientMetrics) Random(java.util.Random) ByteBuffer(java.nio.ByteBuffer) Unpooled(io.netty.buffer.Unpooled) MockReplicaId(com.github.ambry.clustermap.MockReplicaId) GetResponse(com.github.ambry.protocol.GetResponse) PortType(com.github.ambry.network.PortType) BlobStoreControlAction(com.github.ambry.protocol.BlobStoreControlAction) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SSLBlockingChannel(com.github.ambry.network.SSLBlockingChannel) GetRequest(com.github.ambry.protocol.GetRequest) VcrServer(com.github.ambry.cloud.VcrServer) StoreKeyFactory(com.github.ambry.store.StoreKeyFactory) Utils(com.github.ambry.utils.Utils) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) Collectors(java.util.stream.Collectors) ConnectedChannel(com.github.ambry.network.ConnectedChannel) NettySslHttp2Factory(com.github.ambry.commons.NettySslHttp2Factory) Objects(java.util.Objects) RouterConfig(com.github.ambry.config.RouterConfig) List(java.util.List) TtlUpdateRequest(com.github.ambry.protocol.TtlUpdateRequest) MessageFormatFlags(com.github.ambry.messageformat.MessageFormatFlags) QuotaTestUtils(com.github.ambry.quota.QuotaTestUtils) Callback(com.github.ambry.commons.Callback) BlobType(com.github.ambry.messageformat.BlobType) InMemAccountService(com.github.ambry.account.InMemAccountService) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) DataInputStream(java.io.DataInputStream) FindTokenFactory(com.github.ambry.replication.FindTokenFactory) CloudDestinationFactory(com.github.ambry.cloud.CloudDestinationFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AccountService(com.github.ambry.account.AccountService) UndeleteResponse(com.github.ambry.protocol.UndeleteResponse) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) HardwareState(com.github.ambry.clustermap.HardwareState) AdminResponse(com.github.ambry.protocol.AdminResponse) AtomicReference(java.util.concurrent.atomic.AtomicReference) CrcInputStream(com.github.ambry.utils.CrcInputStream) HashSet(java.util.HashSet) AdminRequest(com.github.ambry.protocol.AdminRequest) SSLConfig(com.github.ambry.config.SSLConfig) ByteBuf(io.netty.buffer.ByteBuf) LatchBasedInMemoryCloudDestination(com.github.ambry.cloud.LatchBasedInMemoryCloudDestination) DeleteResponse(com.github.ambry.protocol.DeleteResponse) CommonTestUtils(com.github.ambry.commons.CommonTestUtils) HelixControllerManager(com.github.ambry.utils.HelixControllerManager) PutRequest(com.github.ambry.protocol.PutRequest) Router(com.github.ambry.router.Router) MockDataNodeId(com.github.ambry.clustermap.MockDataNodeId) VcrTestUtil(com.github.ambry.cloud.VcrTestUtil) DeleteRequest(com.github.ambry.protocol.DeleteRequest) Pair(com.github.ambry.utils.Pair) Iterator(java.util.Iterator) ClusterAgentsFactory(com.github.ambry.clustermap.ClusterAgentsFactory) ReplicaType(com.github.ambry.clustermap.ReplicaType) ConnectionPool(com.github.ambry.network.ConnectionPool) QuotaChargeCallback(com.github.ambry.quota.QuotaChargeCallback) ClusterMap(com.github.ambry.clustermap.ClusterMap) FileInputStream(java.io.FileInputStream) NonBlockingRouterFactory(com.github.ambry.router.NonBlockingRouterFactory) TimeUnit(java.util.concurrent.TimeUnit) MessageInfo(com.github.ambry.store.MessageInfo) MessageFormatRecord(com.github.ambry.messageformat.MessageFormatRecord) Port(com.github.ambry.network.Port) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) PutResponse(com.github.ambry.protocol.PutResponse) GetRequest(com.github.ambry.protocol.GetRequest) TimeoutException(java.util.concurrent.TimeoutException) PutRequest(com.github.ambry.protocol.PutRequest) ConnectedChannel(com.github.ambry.network.ConnectedChannel) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) NettyByteBufDataInputStream(com.github.ambry.utils.NettyByteBufDataInputStream) DataInputStream(java.io.DataInputStream) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) GetResponse(com.github.ambry.protocol.GetResponse) ReplicaId(com.github.ambry.clustermap.ReplicaId) MockReplicaId(com.github.ambry.clustermap.MockReplicaId) IOException(java.io.IOException) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) RouterException(com.github.ambry.router.RouterException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) BlobProperties(com.github.ambry.messageformat.BlobProperties) MockDataNodeId(com.github.ambry.clustermap.MockDataNodeId) BlobId(com.github.ambry.commons.BlobId) File(java.io.File) MockClusterMap(com.github.ambry.clustermap.MockClusterMap)

Example 78 with PartitionId

use of com.github.ambry.clustermap.PartitionId in project ambry by linkedin.

the class VcrBackupTest method multipleVcrTest.

/**
 * A multiple VCR test to test helix assignment and backup.
 */
@Test
public void multipleVcrTest() throws Exception {
    StrictMatchExternalViewVerifier helixBalanceVerifier = new StrictMatchExternalViewVerifier(zkConnectString, vcrClusterName, Collections.singleton(VcrTestUtil.helixResource), null);
    int initialNumOfVcrs = 5;
    // create a shared in memory destination.
    LatchBasedInMemoryCloudDestination latchBasedInMemoryCloudDestination = new LatchBasedInMemoryCloudDestination(new ArrayList<>(), mockCluster.getClusterMap());
    CloudDestinationFactory cloudDestinationFactory = new LatchBasedInMemoryCloudDestinationFactory(latchBasedInMemoryCloudDestination);
    // 1st phase: Start VCRs to do backup.
    List<VcrServer> vcrServers = new ArrayList<>();
    List<MockNotificationSystem> vcrNotificationSystems = new ArrayList<>();
    for (int port = 12310; port < 12310 + initialNumOfVcrs; port++) {
        Properties props = VcrTestUtil.createVcrProperties(dataNode.getDatacenterName(), vcrClusterName, zkConnectString, port, port + 100, port + 200, null, vcrHelixStateModelFactoryClass, true);
        MockNotificationSystem vcrNotificationSystem = new MockNotificationSystem(mockCluster.getClusterMap());
        VcrServer vcrServer = VcrTestUtil.createVcrServer(new VerifiableProperties(props), mockCluster.getClusterAgentsFactory(), vcrNotificationSystem, cloudDestinationFactory);
        vcrServer.startup();
        vcrServers.add(vcrServer);
        vcrNotificationSystems.add(vcrNotificationSystem);
    }
    makeSureHelixBalance(vcrServers.get(vcrServers.size() - 1), helixBalanceVerifier);
    int numOfBlobs = 100;
    sendBlobToDataNode(dataNode, numOfBlobs);
    // Make sure blobs are backed up.
    TestUtils.checkAndSleep(numOfBlobs, () -> vcrNotificationSystems.stream().mapToInt(i -> i.getBlobIds().size()).sum(), 5000);
    // verify each VCR is only replicating partitions assigned to it.
    for (int i = 0; i < initialNumOfVcrs; i++) {
        Set<PartitionId> partitionIdSet = vcrNotificationSystems.get(i).getBlobIds().stream().map(blobIdStr -> {
            try {
                return new BlobId(blobIdStr, mockCluster.getClusterMap()).getPartition();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }).collect(Collectors.toSet());
        assertTrue("Each VCR should have some assignment.", vcrServers.get(i).getVcrClusterParticipant().getAssignedPartitionIds().size() > 0);
        assertTrue("Each VCR should only backup its assigned partitions.", new HashSet<>(vcrServers.get(i).getVcrClusterParticipant().getAssignedPartitionIds()).containsAll(partitionIdSet));
    }
    logger.info("Phase 1 done.");
    // 2nd phase: Add a new VCR to cluster.
    Properties props = VcrTestUtil.createVcrProperties(dataNode.getDatacenterName(), vcrClusterName, zkConnectString, 12310 + initialNumOfVcrs, 12310 + initialNumOfVcrs + 100, 12310 + initialNumOfVcrs + 200, null, vcrHelixStateModelFactoryClass, true);
    MockNotificationSystem vcrNotificationSystem = new MockNotificationSystem(mockCluster.getClusterMap());
    VcrServer vcrServer = VcrTestUtil.createVcrServer(new VerifiableProperties(props), mockCluster.getClusterAgentsFactory(), vcrNotificationSystem, cloudDestinationFactory);
    vcrServer.startup();
    vcrServers.add(vcrServer);
    vcrNotificationSystems.add(vcrNotificationSystem);
    makeSureHelixBalance(vcrServers.get(vcrServers.size() - 1), helixBalanceVerifier);
    int secondNumOfBlobs = 100;
    sendBlobToDataNode(dataNode, secondNumOfBlobs);
    Assert.assertTrue("All blobs should be back up.", TestUtils.checkAndSleep(numOfBlobs + secondNumOfBlobs, () -> vcrNotificationSystems.stream().mapToInt(i -> i.getBlobIds().size()).sum(), 5000));
    logger.info("Phase 2 done.");
    // 3rd phase: Remove last VCR from cluster.
    vcrServers.get(vcrServers.size() - 1).shutdown();
    assertTrue("VCR server shutdown timeout.", vcrServers.get(vcrServers.size() - 1).awaitShutdown(5000));
    // Error metrics should be zero.
    Assert.assertEquals("Error count should be zero", 0, vcrServers.get(vcrServers.size() - 1).getVcrReplicationManager().getVcrMetrics().addPartitionErrorCount.getCount());
    Assert.assertEquals("Error count should be zero", 0, vcrServers.get(vcrServers.size() - 1).getVcrReplicationManager().getVcrMetrics().removePartitionErrorCount.getCount());
    int temp = vcrNotificationSystems.get(vcrNotificationSystems.size() - 1).getBlobIds().size();
    assertTrue("Helix balance timeout.", helixBalanceVerifier.verify(5000));
    int thirdNumOfBlobs = 100;
    sendBlobToDataNode(dataNode, thirdNumOfBlobs);
    Assert.assertTrue("All blobs should be back up.", TestUtils.checkAndSleep(numOfBlobs + secondNumOfBlobs + thirdNumOfBlobs, () -> vcrNotificationSystems.stream().mapToInt(i -> i.getBlobIds().size()).sum(), 5000));
    Assert.assertEquals("The removed vcr shouldn't have any change", temp, vcrNotificationSystems.get(vcrNotificationSystems.size() - 1).getBlobIds().size());
    logger.info("Phase 3 done.");
    // Shutdown all others.
    for (int i = 0; i < initialNumOfVcrs; i++) {
        // Error metrics should be zero.
        Assert.assertEquals("Error count should be zero", 0, vcrServers.get(i).getVcrReplicationManager().getVcrMetrics().addPartitionErrorCount.getCount());
        Assert.assertEquals("Error count should be zero", 0, vcrServers.get(i).getVcrReplicationManager().getVcrMetrics().removePartitionErrorCount.getCount());
        vcrServers.get(i).shutdown();
        assertTrue("VCR server shutdown timeout.", vcrServers.get(i).awaitShutdown(5000));
    }
    logger.info("Test done.");
}
Also used : GetOption(com.github.ambry.protocol.GetOption) Arrays(java.util.Arrays) BlobProperties(com.github.ambry.messageformat.BlobProperties) DataNodeId(com.github.ambry.clustermap.DataNodeId) LoggerFactory(org.slf4j.LoggerFactory) GetResponse(com.github.ambry.protocol.GetResponse) PortType(com.github.ambry.network.PortType) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) After(org.junit.After) GetRequest(com.github.ambry.protocol.GetRequest) Parameterized(org.junit.runners.Parameterized) VcrServer(com.github.ambry.cloud.VcrServer) SSLFactory(com.github.ambry.commons.SSLFactory) LeaderStandbySMD(org.apache.helix.model.LeaderStandbySMD) Set(java.util.Set) Utils(com.github.ambry.utils.Utils) Collectors(java.util.stream.Collectors) StrictMatchExternalViewVerifier(org.apache.helix.tools.ClusterVerifiers.StrictMatchExternalViewVerifier) ConnectedChannel(com.github.ambry.network.ConnectedChannel) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) MessageFormatFlags(com.github.ambry.messageformat.MessageFormatFlags) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) DataInputStream(java.io.DataInputStream) CloudDestinationFactory(com.github.ambry.cloud.CloudDestinationFactory) RunWith(org.junit.runner.RunWith) ArrayList(java.util.ArrayList) LeaderStandbyHelixVcrStateModelFactory(com.github.ambry.cloud.LeaderStandbyHelixVcrStateModelFactory) HashSet(java.util.HashSet) SSLConfig(com.github.ambry.config.SSLConfig) LatchBasedInMemoryCloudDestination(com.github.ambry.cloud.LatchBasedInMemoryCloudDestination) SystemTime(com.github.ambry.utils.SystemTime) HelixControllerManager(com.github.ambry.utils.HelixControllerManager) OnlineOfflineSMD(org.apache.helix.model.OnlineOfflineSMD) Before(org.junit.Before) VcrTestUtil(com.github.ambry.cloud.VcrTestUtil) Properties(java.util.Properties) Logger(org.slf4j.Logger) OnlineOfflineHelixVcrStateModelFactory(com.github.ambry.cloud.OnlineOfflineHelixVcrStateModelFactory) VerifiableProperties(com.github.ambry.config.VerifiableProperties) TestSSLUtils(com.github.ambry.commons.TestSSLUtils) IOException(java.io.IOException) Test(org.junit.Test) MessageFormatException(com.github.ambry.messageformat.MessageFormatException) LatchBasedInMemoryCloudDestinationFactory(com.github.ambry.cloud.LatchBasedInMemoryCloudDestinationFactory) File(java.io.File) TimeUnit(java.util.concurrent.TimeUnit) ServerTestUtil(com.github.ambry.server.ServerTestUtil) MessageFormatRecord(com.github.ambry.messageformat.MessageFormatRecord) Port(com.github.ambry.network.Port) Assert(org.junit.Assert) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) VerifiableProperties(com.github.ambry.config.VerifiableProperties) ArrayList(java.util.ArrayList) CloudDestinationFactory(com.github.ambry.cloud.CloudDestinationFactory) LatchBasedInMemoryCloudDestinationFactory(com.github.ambry.cloud.LatchBasedInMemoryCloudDestinationFactory) IOException(java.io.IOException) BlobProperties(com.github.ambry.messageformat.BlobProperties) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) PartitionId(com.github.ambry.clustermap.PartitionId) LatchBasedInMemoryCloudDestination(com.github.ambry.cloud.LatchBasedInMemoryCloudDestination) StrictMatchExternalViewVerifier(org.apache.helix.tools.ClusterVerifiers.StrictMatchExternalViewVerifier) LatchBasedInMemoryCloudDestinationFactory(com.github.ambry.cloud.LatchBasedInMemoryCloudDestinationFactory) VcrServer(com.github.ambry.cloud.VcrServer) BlobId(com.github.ambry.commons.BlobId) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 79 with PartitionId

use of com.github.ambry.clustermap.PartitionId in project ambry by linkedin.

the class StatsManager method collectAndAggregatePartitionClassStorageStats.

/**
 * Fetch and aggregate partition class stats from a given {@link Store}
 * @param hostPartitionClassStorageStatsMap map from partition class to all partition storage stats.
 * @param partitionId specifies the {@link Store} to be fetched from
 * @param unreachablePartitions a {@link List} containing partition Ids that were unable to successfully fetch from
 */
void collectAndAggregatePartitionClassStorageStats(Map<String, Map<Long, Map<Short, Map<Short, ContainerStorageStats>>>> hostPartitionClassStorageStatsMap, PartitionId partitionId, List<PartitionId> unreachablePartitions) {
    Store store = storageManager.getStore(partitionId, false);
    if (store == null) {
        unreachablePartitions.add(partitionId);
    } else {
        try {
            long fetchAndAggregatePerStoreStartTimeMs = time.milliseconds();
            StoreStats storeStats = store.getStoreStats();
            Map<Short, Map<Short, ContainerStorageStats>> containerStatsMap = storeStats.getContainerStorageStats(time.milliseconds(), publishExcludeAccountIds);
            String partitionClassName = partitionId.getPartitionClass();
            hostPartitionClassStorageStatsMap.computeIfAbsent(partitionClassName, k -> new HashMap<>()).put(partitionId.getId(), containerStatsMap);
            metrics.fetchAndAggregateTimePerStoreMs.update(time.milliseconds() - fetchAndAggregatePerStoreStartTimeMs);
        } catch (StoreException e) {
            unreachablePartitions.add(partitionId);
        }
    }
}
Also used : HostPartitionClassStorageStats(com.github.ambry.server.storagestats.HostPartitionClassStorageStats) StorageManager(com.github.ambry.store.StorageManager) LoggerFactory(org.slf4j.LoggerFactory) StoreStats(com.github.ambry.store.StoreStats) AccountService(com.github.ambry.account.AccountService) HostAccountStorageStats(com.github.ambry.server.storagestats.HostAccountStorageStats) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) HashSet(java.util.HashSet) Map(java.util.Map) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) ClusterParticipant(com.github.ambry.clustermap.ClusterParticipant) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) StoreException(com.github.ambry.store.StoreException) Time(com.github.ambry.utils.Time) StatsManagerConfig(com.github.ambry.config.StatsManagerConfig) StateModelListenerType(com.github.ambry.clustermap.StateModelListenerType) MetricRegistry(com.codahale.metrics.MetricRegistry) Logger(org.slf4j.Logger) Pair(com.github.ambry.utils.Pair) Iterator(java.util.Iterator) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Set(java.util.Set) Utils(com.github.ambry.utils.Utils) Collectors(java.util.stream.Collectors) File(java.io.File) AccountStatsStore(com.github.ambry.accountstats.AccountStatsStore) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Store(com.github.ambry.store.Store) List(java.util.List) PartitionStateChangeListener(com.github.ambry.clustermap.PartitionStateChangeListener) StateTransitionException(com.github.ambry.clustermap.StateTransitionException) ReplicaId(com.github.ambry.clustermap.ReplicaId) Account(com.github.ambry.account.Account) TransitionErrorCode(com.github.ambry.clustermap.StateTransitionException.TransitionErrorCode) Collections(java.util.Collections) PartitionId(com.github.ambry.clustermap.PartitionId) StoreStats(com.github.ambry.store.StoreStats) HashMap(java.util.HashMap) AccountStatsStore(com.github.ambry.accountstats.AccountStatsStore) Store(com.github.ambry.store.Store) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) StoreException(com.github.ambry.store.StoreException)

Example 80 with PartitionId

use of com.github.ambry.clustermap.PartitionId in project ambry by linkedin.

the class AmbryServerRequests method isRemoteLagLesserOrEqual.

/**
 * Provides catch up status of all the remote replicas of {@code partitionIds}.
 * @param partitionIds the {@link PartitionId}s for which lag has to be <= {@code acceptableLagInBytes}.
 * @param acceptableLagInBytes the maximum lag in bytes that is considered "acceptable".
 * @param numReplicasCaughtUpPerPartition the number of replicas that have to be within {@code acceptableLagInBytes}
 *                                        (per partition). The min of this value or the total count of replicas - 1 is
 *                                        considered.
 * @return {@code true} if the lag of each of the remote replicas of each of the {@link PartitionId} in
 * {@code partitionIds} <= {@code acceptableLagInBytes}. {@code false} otherwise.
 */
private boolean isRemoteLagLesserOrEqual(Collection<PartitionId> partitionIds, long acceptableLagInBytes, short numReplicasCaughtUpPerPartition) {
    boolean isAcceptable = true;
    for (PartitionId partitionId : partitionIds) {
        List<? extends ReplicaId> replicaIds = partitionId.getReplicaIds();
        int caughtUpCount = 0;
        for (ReplicaId replicaId : replicaIds) {
            if (!replicaId.getDataNodeId().equals(currentNode)) {
                long lagInBytes = replicationEngine.getRemoteReplicaLagFromLocalInBytes(partitionId, replicaId.getDataNodeId().getHostname(), replicaId.getReplicaPath());
                logger.debug("Lag of {} is {}", replicaId, lagInBytes);
                if (lagInBytes <= acceptableLagInBytes) {
                    caughtUpCount++;
                }
                if (caughtUpCount >= numReplicasCaughtUpPerPartition) {
                    break;
                }
            }
        }
        // -1 because we shouldn't consider the replica hosted on this node.
        if (caughtUpCount < Math.min(replicaIds.size() - 1, numReplicasCaughtUpPerPartition)) {
            isAcceptable = false;
            break;
        }
    }
    return isAcceptable;
}
Also used : PartitionId(com.github.ambry.clustermap.PartitionId) ReplicaId(com.github.ambry.clustermap.ReplicaId)

Aggregations

PartitionId (com.github.ambry.clustermap.PartitionId)183 MockPartitionId (com.github.ambry.clustermap.MockPartitionId)111 Test (org.junit.Test)95 ReplicaId (com.github.ambry.clustermap.ReplicaId)70 ArrayList (java.util.ArrayList)68 MockClusterMap (com.github.ambry.clustermap.MockClusterMap)53 BlobId (com.github.ambry.commons.BlobId)50 HashMap (java.util.HashMap)48 Map (java.util.Map)41 List (java.util.List)40 MockDataNodeId (com.github.ambry.clustermap.MockDataNodeId)39 DataNodeId (com.github.ambry.clustermap.DataNodeId)36 MetricRegistry (com.codahale.metrics.MetricRegistry)33 ClusterMap (com.github.ambry.clustermap.ClusterMap)32 MockReplicaId (com.github.ambry.clustermap.MockReplicaId)30 VerifiableProperties (com.github.ambry.config.VerifiableProperties)30 IOException (java.io.IOException)29 HashSet (java.util.HashSet)29 StoreKey (com.github.ambry.store.StoreKey)26 StoreKeyFactory (com.github.ambry.store.StoreKeyFactory)25