| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * <p> |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * <p> |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.hadoop.ozone.recon.api; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.sql.DataSource; |
| import javax.ws.rs.core.Response; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.hadoop.hdds.client.BlockID; |
| import org.apache.hadoop.hdds.scm.pipeline.Pipeline; |
| import org.apache.hadoop.ozone.om.OMMetadataManager; |
| import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup; |
| import org.apache.hadoop.ozone.recon.AbstractOMMetadataManagerTest; |
| import org.apache.hadoop.ozone.recon.GuiceInjectorUtilsForTestsImpl; |
| import org.apache.hadoop.ozone.recon.api.types.ContainerMetadata; |
| import org.apache.hadoop.ozone.recon.api.types.ContainersResponse; |
| import org.apache.hadoop.ozone.recon.api.types.KeyMetadata; |
| import org.apache.hadoop.ozone.recon.api.types.KeysResponse; |
| import org.apache.hadoop.ozone.recon.recovery.ReconOMMetadataManager; |
| import org.apache.hadoop.ozone.recon.spi.ContainerDBServiceProvider; |
| import org.apache.hadoop.ozone.recon.spi.impl.OzoneManagerServiceProviderImpl; |
| import org.apache.hadoop.ozone.recon.tasks.ContainerKeyMapperTask; |
| import org.apache.hadoop.hdds.utils.db.Table; |
| import org.hadoop.ozone.recon.schema.StatsSchemaDefinition; |
| import org.jooq.impl.DSL; |
| import org.jooq.impl.DefaultConfiguration; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import com.google.inject.AbstractModule; |
| import com.google.inject.Injector; |
| |
| /** |
| * Test for container key service. |
| */ |
| public class TestContainerKeyService extends AbstractOMMetadataManagerTest { |
| |
| private ContainerDBServiceProvider containerDbServiceProvider; |
| private Injector injector; |
| private OzoneManagerServiceProviderImpl ozoneManagerServiceProvider; |
| private ContainerKeyService containerKeyService; |
| private GuiceInjectorUtilsForTestsImpl guiceInjectorTest = |
| new GuiceInjectorUtilsForTestsImpl(); |
| private boolean isSetupDone = false; |
| private ReconOMMetadataManager reconOMMetadataManager; |
| private void initializeInjector() throws Exception { |
| reconOMMetadataManager = getTestMetadataManager( |
| initializeNewOmMetadataManager()); |
| ozoneManagerServiceProvider = getMockOzoneManagerServiceProvider(); |
| |
| Injector parentInjector = guiceInjectorTest.getInjector( |
| ozoneManagerServiceProvider, reconOMMetadataManager, temporaryFolder); |
| |
| injector = parentInjector.createChildInjector(new AbstractModule() { |
| @Override |
| protected void configure() { |
| containerKeyService = new ContainerKeyService(); |
| bind(ContainerKeyService.class).toInstance(containerKeyService); |
| } |
| }); |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| // The following setup runs only once |
| if (!isSetupDone) { |
| initializeInjector(); |
| |
| DSL.using(new DefaultConfiguration().set( |
| injector.getInstance(DataSource.class))); |
| |
| containerDbServiceProvider = injector.getInstance( |
| ContainerDBServiceProvider.class); |
| |
| StatsSchemaDefinition schemaDefinition = injector.getInstance( |
| StatsSchemaDefinition.class); |
| schemaDefinition.initializeSchema(); |
| |
| isSetupDone = true; |
| } |
| |
| //Write Data to OM |
| Pipeline pipeline = getRandomPipeline(); |
| |
| List<OmKeyLocationInfo> omKeyLocationInfoList = new ArrayList<>(); |
| BlockID blockID1 = new BlockID(1, 101); |
| OmKeyLocationInfo omKeyLocationInfo1 = getOmKeyLocationInfo(blockID1, |
| pipeline); |
| omKeyLocationInfoList.add(omKeyLocationInfo1); |
| |
| BlockID blockID2 = new BlockID(2, 102); |
| OmKeyLocationInfo omKeyLocationInfo2 = getOmKeyLocationInfo(blockID2, |
| pipeline); |
| omKeyLocationInfoList.add(omKeyLocationInfo2); |
| |
| OmKeyLocationInfoGroup omKeyLocationInfoGroup = new |
| OmKeyLocationInfoGroup(0, omKeyLocationInfoList); |
| |
| //key = key_one, Blocks = [ {CID = 1, LID = 101}, {CID = 2, LID = 102} ] |
| writeDataToOm(reconOMMetadataManager, |
| "key_one", "bucketOne", "sampleVol", |
| Collections.singletonList(omKeyLocationInfoGroup)); |
| |
| List<OmKeyLocationInfoGroup> infoGroups = new ArrayList<>(); |
| BlockID blockID3 = new BlockID(1, 103); |
| OmKeyLocationInfo omKeyLocationInfo3 = getOmKeyLocationInfo(blockID3, |
| pipeline); |
| |
| List<OmKeyLocationInfo> omKeyLocationInfoListNew = new ArrayList<>(); |
| omKeyLocationInfoListNew.add(omKeyLocationInfo3); |
| infoGroups.add(new OmKeyLocationInfoGroup(0, |
| omKeyLocationInfoListNew)); |
| |
| BlockID blockID4 = new BlockID(1, 104); |
| OmKeyLocationInfo omKeyLocationInfo4 = getOmKeyLocationInfo(blockID4, |
| pipeline); |
| |
| omKeyLocationInfoListNew = new ArrayList<>(); |
| omKeyLocationInfoListNew.add(omKeyLocationInfo4); |
| infoGroups.add(new OmKeyLocationInfoGroup(1, |
| omKeyLocationInfoListNew)); |
| |
| //key = key_two, Blocks = [ {CID = 1, LID = 103}, {CID = 1, LID = 104} ] |
| writeDataToOm(reconOMMetadataManager, |
| "key_two", "bucketOne", "sampleVol", infoGroups); |
| |
| List<OmKeyLocationInfo> omKeyLocationInfoList2 = new ArrayList<>(); |
| BlockID blockID5 = new BlockID(2, 2); |
| OmKeyLocationInfo omKeyLocationInfo5 = getOmKeyLocationInfo(blockID5, |
| pipeline); |
| omKeyLocationInfoList2.add(omKeyLocationInfo5); |
| |
| BlockID blockID6 = new BlockID(2, 3); |
| OmKeyLocationInfo omKeyLocationInfo6 = getOmKeyLocationInfo(blockID6, |
| pipeline); |
| omKeyLocationInfoList2.add(omKeyLocationInfo6); |
| |
| OmKeyLocationInfoGroup omKeyLocationInfoGroup2 = new |
| OmKeyLocationInfoGroup(0, omKeyLocationInfoList2); |
| |
| //key = key_three, Blocks = [ {CID = 2, LID = 2}, {CID = 2, LID = 3} ] |
| writeDataToOm(reconOMMetadataManager, |
| "key_three", "bucketOne", "sampleVol", |
| Collections.singletonList(omKeyLocationInfoGroup2)); |
| |
| //Generate Recon container DB data. |
| OMMetadataManager omMetadataManagerMock = mock(OMMetadataManager.class); |
| Table tableMock = mock(Table.class); |
| when(tableMock.getName()).thenReturn("KeyTable"); |
| when(omMetadataManagerMock.getKeyTable()).thenReturn(tableMock); |
| ContainerKeyMapperTask containerKeyMapperTask = |
| new ContainerKeyMapperTask(containerDbServiceProvider); |
| containerKeyMapperTask.reprocess(reconOMMetadataManager); |
| } |
| |
| @Test |
| public void testGetKeysForContainer() { |
| |
| Response response = containerKeyService.getKeysForContainer(1L, -1, ""); |
| |
| KeysResponse responseObject = (KeysResponse) response.getEntity(); |
| KeysResponse.KeysResponseData data = responseObject.getKeysResponseData(); |
| Collection<KeyMetadata> keyMetadataList = data.getKeys(); |
| |
| assertEquals(3, data.getTotalCount()); |
| assertEquals(2, keyMetadataList.size()); |
| |
| Iterator<KeyMetadata> iterator = keyMetadataList.iterator(); |
| |
| KeyMetadata keyMetadata = iterator.next(); |
| assertEquals("key_one", keyMetadata.getKey()); |
| assertEquals(1, keyMetadata.getVersions().size()); |
| assertEquals(1, keyMetadata.getBlockIds().size()); |
| Map<Long, List<KeyMetadata.ContainerBlockMetadata>> blockIds = |
| keyMetadata.getBlockIds(); |
| assertEquals(101, blockIds.get(0L).iterator().next().getLocalID()); |
| |
| keyMetadata = iterator.next(); |
| assertEquals("key_two", keyMetadata.getKey()); |
| assertEquals(2, keyMetadata.getVersions().size()); |
| assertTrue(keyMetadata.getVersions().contains(0L) && keyMetadata |
| .getVersions().contains(1L)); |
| assertEquals(2, keyMetadata.getBlockIds().size()); |
| blockIds = keyMetadata.getBlockIds(); |
| assertEquals(103, blockIds.get(0L).iterator().next().getLocalID()); |
| assertEquals(104, blockIds.get(1L).iterator().next().getLocalID()); |
| |
| response = containerKeyService.getKeysForContainer(3L, -1, ""); |
| responseObject = (KeysResponse) response.getEntity(); |
| data = responseObject.getKeysResponseData(); |
| keyMetadataList = data.getKeys(); |
| assertTrue(keyMetadataList.isEmpty()); |
| assertEquals(0, data.getTotalCount()); |
| |
| // test if limit works as expected |
| response = containerKeyService.getKeysForContainer(1L, 1, ""); |
| responseObject = (KeysResponse) response.getEntity(); |
| data = responseObject.getKeysResponseData(); |
| keyMetadataList = data.getKeys(); |
| assertEquals(1, keyMetadataList.size()); |
| assertEquals(3, data.getTotalCount()); |
| } |
| |
| @Test |
| public void testGetKeysForContainerWithPrevKey() { |
| // test if prev-key param works as expected |
| Response response = containerKeyService.getKeysForContainer( |
| 1L, -1, "/sampleVol/bucketOne/key_one"); |
| |
| KeysResponse responseObject = |
| (KeysResponse) response.getEntity(); |
| |
| KeysResponse.KeysResponseData data = |
| responseObject.getKeysResponseData(); |
| assertEquals(3, data.getTotalCount()); |
| |
| Collection<KeyMetadata> keyMetadataList = data.getKeys(); |
| assertEquals(1, keyMetadataList.size()); |
| |
| Iterator<KeyMetadata> iterator = keyMetadataList.iterator(); |
| KeyMetadata keyMetadata = iterator.next(); |
| |
| assertEquals("key_two", keyMetadata.getKey()); |
| assertEquals(2, keyMetadata.getVersions().size()); |
| assertEquals(2, keyMetadata.getBlockIds().size()); |
| |
| response = containerKeyService.getKeysForContainer( |
| 1L, -1, StringUtils.EMPTY); |
| responseObject = (KeysResponse) response.getEntity(); |
| data = responseObject.getKeysResponseData(); |
| keyMetadataList = data.getKeys(); |
| |
| assertEquals(3, data.getTotalCount()); |
| assertEquals(2, keyMetadataList.size()); |
| iterator = keyMetadataList.iterator(); |
| keyMetadata = iterator.next(); |
| assertEquals("key_one", keyMetadata.getKey()); |
| |
| // test for negative cases |
| response = containerKeyService.getKeysForContainer( |
| 1L, -1, "/sampleVol/bucketOne/invalid_key"); |
| responseObject = (KeysResponse) response.getEntity(); |
| data = responseObject.getKeysResponseData(); |
| keyMetadataList = data.getKeys(); |
| assertEquals(3, data.getTotalCount()); |
| assertEquals(0, keyMetadataList.size()); |
| |
| response = containerKeyService.getKeysForContainer( |
| 5L, -1, ""); |
| responseObject = (KeysResponse) response.getEntity(); |
| data = responseObject.getKeysResponseData(); |
| keyMetadataList = data.getKeys(); |
| assertEquals(0, keyMetadataList.size()); |
| assertEquals(0, data.getTotalCount()); |
| } |
| |
| @Test |
| public void testGetContainers() { |
| |
| Response response = containerKeyService.getContainers(-1, 0L); |
| |
| ContainersResponse responseObject = |
| (ContainersResponse) response.getEntity(); |
| |
| ContainersResponse.ContainersResponseData data = |
| responseObject.getContainersResponseData(); |
| assertEquals(2, data.getTotalCount()); |
| |
| List<ContainerMetadata> containers = new ArrayList<>(data.getContainers()); |
| |
| Iterator<ContainerMetadata> iterator = containers.iterator(); |
| |
| ContainerMetadata containerMetadata = iterator.next(); |
| assertEquals(1L, containerMetadata.getContainerID()); |
| // Number of keys for CID:1 should be 3 because of two different versions |
| // of key_two stored in CID:1 |
| assertEquals(3L, containerMetadata.getNumberOfKeys()); |
| |
| containerMetadata = iterator.next(); |
| assertEquals(2L, containerMetadata.getContainerID()); |
| assertEquals(2L, containerMetadata.getNumberOfKeys()); |
| |
| // test if limit works as expected |
| response = containerKeyService.getContainers(1, 0L); |
| responseObject = (ContainersResponse) response.getEntity(); |
| data = responseObject.getContainersResponseData(); |
| containers = new ArrayList<>(data.getContainers()); |
| assertEquals(1, containers.size()); |
| assertEquals(2, data.getTotalCount()); |
| } |
| |
| @Test |
| public void testGetContainersWithPrevKey() { |
| |
| Response response = containerKeyService.getContainers(1, 1L); |
| |
| ContainersResponse responseObject = |
| (ContainersResponse) response.getEntity(); |
| |
| ContainersResponse.ContainersResponseData data = |
| responseObject.getContainersResponseData(); |
| assertEquals(2, data.getTotalCount()); |
| |
| List<ContainerMetadata> containers = new ArrayList<>(data.getContainers()); |
| |
| Iterator<ContainerMetadata> iterator = containers.iterator(); |
| |
| ContainerMetadata containerMetadata = iterator.next(); |
| |
| assertEquals(1, containers.size()); |
| assertEquals(2L, containerMetadata.getContainerID()); |
| |
| response = containerKeyService.getContainers(-1, 0L); |
| responseObject = (ContainersResponse) response.getEntity(); |
| data = responseObject.getContainersResponseData(); |
| containers = new ArrayList<>(data.getContainers()); |
| assertEquals(2, containers.size()); |
| assertEquals(2, data.getTotalCount()); |
| iterator = containers.iterator(); |
| containerMetadata = iterator.next(); |
| assertEquals(1L, containerMetadata.getContainerID()); |
| |
| // test for negative cases |
| response = containerKeyService.getContainers(-1, 5L); |
| responseObject = (ContainersResponse) response.getEntity(); |
| data = responseObject.getContainersResponseData(); |
| containers = new ArrayList<>(data.getContainers()); |
| assertEquals(0, containers.size()); |
| assertEquals(2, data.getTotalCount()); |
| |
| response = containerKeyService.getContainers(-1, -1L); |
| responseObject = (ContainersResponse) response.getEntity(); |
| data = responseObject.getContainersResponseData(); |
| containers = new ArrayList<>(data.getContainers()); |
| assertEquals(2, containers.size()); |
| assertEquals(2, data.getTotalCount()); |
| } |
| |
| private OzoneManagerServiceProviderImpl getMockOzoneManagerServiceProvider() { |
| OzoneManagerServiceProviderImpl omServiceProviderMock = |
| mock(OzoneManagerServiceProviderImpl.class); |
| return omServiceProviderMock; |
| } |
| } |