package io.blobkeeper.cluster.service; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMultimap; import io.blobkeeper.common.configuration.MetricModule; import io.blobkeeper.common.configuration.RootModule; import io.blobkeeper.common.service.IdGeneratorService; import io.blobkeeper.file.configuration.FileConfiguration; import io.blobkeeper.file.configuration.FileModule; import io.blobkeeper.file.domain.StorageFile; import io.blobkeeper.file.service.BaseFileTest; import io.blobkeeper.file.service.FileStorage; import io.blobkeeper.file.service.PartitionService; import io.blobkeeper.file.util.FileUtils; import io.blobkeeper.index.domain.Partition; import io.blobkeeper.index.service.IndexService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Guice; import org.testng.annotations.Test; import javax.inject.Inject; import static com.jayway.awaitility.Awaitility.await; import static com.jayway.awaitility.Duration.FIVE_HUNDRED_MILLISECONDS; import static org.testng.Assert.assertTrue; /** * @author Denis Gabaydulin * @since 10/01/2017 */ @Guice(modules = {RootModule.class, MetricModule.class, FileModule.class}) public class BalancingServiceIntegrationTest extends BaseFileTest { private static final Logger log = LoggerFactory.getLogger(CompactionServiceTest.class); @Inject private FileStorage fileStorage; @Inject private IndexService indexService; @Inject private IdGeneratorService generatorService; @Inject private FileConfiguration fileConfiguration; @Inject private CompactionService compactionService; @Inject private ClusterMembershipService clusterMembershipService; @Inject private BalancingService balancingService; @Inject private PartitionService partitionService; @Test public void balanceSingleDisk() { // add some files to disk 0 for (int i = 0; i < 32; i++) { Long fileId = generatorService.generate(1); StorageFile file = new StorageFile.StorageFileBuilder() .id(fileId) .type(0) .name("test") .data(Strings.repeat("1234", 10).getBytes()) .headers(ImmutableMultimap.of()) .build(); fileStorage.addFile(0, file); } for (int i = 0; i < 8; i++) { balancingService.balance(0); } await().forever().pollInterval(FIVE_HUNDRED_MILLISECONDS).until( () -> { log.trace("Waiting for resource cleanup"); return !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 0)).exists() && !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 1)).exists() && !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 2)).exists() && !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 3)).exists(); }); } @Test public void completeRebalancing() { // add some files to disk 0 for (int i = 0; i < 10; i++) { Long fileId = generatorService.generate(1); StorageFile file = new StorageFile.StorageFileBuilder() .id(fileId) .type(0) .name("test") .data(Strings.repeat("1234", 10).getBytes()) .headers(ImmutableMultimap.of()) .build(); fileStorage.addFile(0, file); } // emulate starting of rebalancing Partition dst = partitionService.getNextActivePartition(1); partitionService.move(new Partition(0, 0), dst); balancingService.balance(0); await().forever().pollInterval(FIVE_HUNDRED_MILLISECONDS).until( () -> { log.trace("Waiting for resource cleanup"); return !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 0)).exists(); }); } @Test public void completeRebalancingWithStatusChangedToRebalancing() { // add some files to disk 0 for (int i = 0; i < 10; i++) { Long fileId = generatorService.generate(1); StorageFile file = new StorageFile.StorageFileBuilder() .id(fileId) .type(0) .name("test") .data(Strings.repeat("1234", 10).getBytes()) .headers(ImmutableMultimap.of()) .build(); fileStorage.addFile(0, file); } // emulate starting of rebalancing Partition src = partitionService.getById(0, 0); Partition dst = partitionService.getNextActivePartition(1); partitionService.move(src, dst); partitionService.tryStartRebalancing(src); balancingService.balance(0); await().forever().pollInterval(FIVE_HUNDRED_MILLISECONDS).until( () -> { log.trace("Waiting for resource cleanup"); return !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 0)).exists(); }); } @Test public void completeRebalancingWithStatusChangedToDataMoved() { // add some files to disk 0 for (int i = 0; i < 10; i++) { Long fileId = generatorService.generate(1); StorageFile file = new StorageFile.StorageFileBuilder() .id(fileId) .type(0) .name("test") .data(Strings.repeat("1234", 10).getBytes()) .headers(ImmutableMultimap.of()) .build(); fileStorage.addFile(0, file); } // emulate starting of rebalancing Partition src = partitionService.getById(0, 0); Partition dst = partitionService.getNextActivePartition(1); partitionService.move(src, dst); partitionService.tryStartRebalancing(src); partitionService.tryFinishRebalancing(src); balancingService.balance(0); await().forever().pollInterval(FIVE_HUNDRED_MILLISECONDS).until( () -> { log.trace("Waiting for resource cleanup"); return !FileUtils.getFilePathByPartition(fileConfiguration, new Partition(0, 0)).exists(); }); } @BeforeMethod(dependsOnMethods = {"deleteFiles"}) private void start() throws InterruptedException { clusterMembershipService.start("node1"); indexService.clear(); fileStorage.start(); compactionService.start(); } @AfterMethod private void stop() throws InterruptedException { compactionService.stop(); fileStorage.stop(); clusterMembershipService.stop(); } }