Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@
import org.apache.hadoop.ozone.om.snapshot.ReferenceCounted;
import org.apache.hadoop.ozone.om.snapshot.SnapshotCache;
import org.apache.ratis.util.ExitUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.io.TempDir;
import org.rocksdb.LiveFileMetaData;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -71,24 +75,21 @@
/**
* Test SST Filtering Service.
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(OrderAnnotation.class)
public class TestSstFilteringService {
public static final String SST_FILE_EXTENSION = ".sst";
@TempDir
private File folder;
private static final String SST_FILE_EXTENSION = ".sst";
private OzoneManagerProtocol writeClient;
private OzoneManager om;
private OzoneConfiguration conf;
private KeyManager keyManager;
private short countTotalSnapshots = 0;

@BeforeAll
public static void setup() {
void setup(@TempDir Path folder) throws Exception {
ExitUtils.disableSystemExit();
}

@BeforeEach
void init() throws Exception {
conf = new OzoneConfiguration();
conf.set(OZONE_METADATA_DIRS, folder.getAbsolutePath());
conf.set(OZONE_METADATA_DIRS, folder.toString());
conf.setTimeDuration(HDDS_CONTAINER_REPORT_INTERVAL, 200,
TimeUnit.MILLISECONDS);
conf.setTimeDuration(OZONE_SNAPSHOT_SST_FILTERING_SERVICE_INTERVAL, 100,
Expand All @@ -102,7 +103,7 @@ void init() throws Exception {
om = omTestManagers.getOzoneManager();
}

@AfterEach
@AfterAll
public void cleanup() throws Exception {
if (keyManager != null) {
keyManager.stop();
Expand Down Expand Up @@ -133,6 +134,7 @@ public void cleanup() throws Exception {
* @throws IOException - on Failure.
*/
@Test
@Order(1)
public void testIrrelevantSstFileDeletion()
throws Exception {
RDBStore activeDbStore = (RDBStore) om.getMetadataManager().getStore();
Expand All @@ -142,7 +144,8 @@ public void testIrrelevantSstFileDeletion()
final int keyCount = 100;
String volumeName = "vol1";
String bucketName1 = "buck1";
createVolumeAndBucket(volumeName, bucketName1);
createVolume(volumeName);
addBucketToVolume(volumeName, bucketName1);

createKeys(volumeName, bucketName1, keyCount / 2);
activeDbStore.getDb().flush(OmMetadataManagerImpl.KEY_TABLE);
Expand Down Expand Up @@ -180,13 +183,13 @@ public void testIrrelevantSstFileDeletion()
assertThat(nonLevel0FilesCountAfterCompact).isGreaterThan(0);

String bucketName2 = "buck2";
createVolumeAndBucket(volumeName, bucketName2);
addBucketToVolume(volumeName, bucketName2);
createKeys(volumeName, bucketName2, keyCount);

activeDbStore.getDb().flush(OmMetadataManagerImpl.KEY_TABLE);
List<LiveFileMetaData> allFiles = activeDbStore.getDb().getSstFileList();
String snapshotName1 = "snapshot1";
writeClient.createSnapshot(volumeName, bucketName2, snapshotName1);
createSnapshot(volumeName, bucketName2, snapshotName1);
SnapshotInfo snapshotInfo = om.getMetadataManager().getSnapshotInfoTable()
.get(SnapshotInfo.getTableKey(volumeName, bucketName2, snapshotName1));
assertFalse(snapshotInfo.isSstFiltered());
Expand Down Expand Up @@ -223,7 +226,7 @@ public void testIrrelevantSstFileDeletion()
try (BootstrapStateHandler.Lock lock =
filteringService.getBootstrapStateLock().lock()) {
count = filteringService.getSnapshotFilteredCount().get();
writeClient.createSnapshot(volumeName, bucketName2, snapshotName2);
createSnapshot(volumeName, bucketName2, snapshotName2);

assertThrows(TimeoutException.class,
() -> waitForSnapshotsAtLeast(filteringService, count + 1));
Expand All @@ -240,14 +243,16 @@ public void testIrrelevantSstFileDeletion()
}

@Test
@Order(2)
public void testActiveAndDeletedSnapshotCleanup() throws Exception {
RDBStore activeDbStore = (RDBStore) om.getMetadataManager().getStore();
String volumeName = "volume1";
List<String> bucketNames = Arrays.asList("bucket1", "bucket2");

createVolume(volumeName);
// Create 2 Buckets
for (String bucketName : bucketNames) {
createVolumeAndBucket(volumeName, bucketName);
addBucketToVolume(volumeName, bucketName);
}
// Write 25 keys in each bucket, 2 sst files would be generated each for
// keys in a single bucket
Expand All @@ -265,8 +270,8 @@ public void testActiveAndDeletedSnapshotCleanup() throws Exception {
keyManager.getSnapshotSstFilteringService();
sstFilteringService.pause();

writeClient.createSnapshot(volumeName, bucketNames.get(0), "snap1");
writeClient.createSnapshot(volumeName, bucketNames.get(0), "snap2");
createSnapshot(volumeName, bucketNames.get(0), "snap1");
createSnapshot(volumeName, bucketNames.get(0), "snap2");

SnapshotInfo snapshot1Info = om.getMetadataManager().getSnapshotInfoTable()
.get(SnapshotInfo.getTableKey(volumeName, bucketNames.get(0), "snap1"));
Expand All @@ -284,26 +289,28 @@ public void testActiveAndDeletedSnapshotCleanup() throws Exception {
await(10_000, 1_000, () -> snap1Current.exists() && snap2Current.exists());

long snap1SstFileCountBeforeFilter = Arrays.stream(snapshot1Dir.listFiles())
.filter(f -> f.getName().endsWith(".sst")).count();
.filter(f -> f.getName().endsWith(SST_FILE_EXTENSION)).count();
long snap2SstFileCountBeforeFilter = Arrays.stream(snapshot2Dir.listFiles())
.filter(f -> f.getName().endsWith(".sst")).count();
.filter(f -> f.getName().endsWith(SST_FILE_EXTENSION)).count();

// delete snap1
writeClient.deleteSnapshot(volumeName, bucketNames.get(0), "snap1");
sstFilteringService.resume();
// Filtering service will only act on snap2 as it is an active snaphot
waitForSnapshotsAtLeast(sstFilteringService, 2);
waitForSnapshotsAtLeast(sstFilteringService, countTotalSnapshots);
long snap1SstFileCountAfterFilter = Arrays.stream(snapshot1Dir.listFiles())
.filter(f -> f.getName().endsWith(SST_FILE_EXTENSION)).count();
long snap2SstFileCountAfterFilter = Arrays.stream(snapshot2Dir.listFiles())
.filter(f -> f.getName().endsWith(SST_FILE_EXTENSION)).count();
// one sst will be filtered in both active but not in deleted snapshot
// as sstFiltering svc won't run on already deleted snapshots but will mark
// it as filtered.
assertEquals(2, sstFilteringService.getSnapshotFilteredCount().get());
assertEquals(countTotalSnapshots, sstFilteringService.getSnapshotFilteredCount().get());
assertEquals(snap1SstFileCountBeforeFilter, snap1SstFileCountAfterFilter);
assertEquals(snap2SstFileCountBeforeFilter - 1,
snap2SstFileCountAfterFilter);
// If method with order 1 is run .sst file from /vol1/buck1 and /vol1/buck2 will be deleted.
// As part of this method .sst file from /volume1/bucket2/ will be deleted.
// sstFiltering won't run on deleted snapshots in /volume1/bucket1.
assertThat(snap2SstFileCountBeforeFilter).isGreaterThan(snap2SstFileCountAfterFilter);
}

private void createKeys(String volumeName,
Expand All @@ -316,16 +323,18 @@ private void createKeys(String volumeName,
}
}

private void createVolumeAndBucket(String volumeName,
String bucketName)
private void createVolume(String volumeName)
throws IOException {
OMRequestTestUtils.addVolumeToOM(keyManager.getMetadataManager(),
OmVolumeArgs.newBuilder()
.setOwnerName("o")
.setAdminName("a")
.setVolume(volumeName)
.build());
}

private void addBucketToVolume(String volumeName, String bucketName)
throws IOException {
OMRequestTestUtils.addBucketToOM(keyManager.getMetadataManager(),
OmBucketInfo.newBuilder().setVolumeName(volumeName)
.setBucketName(bucketName)
Expand Down Expand Up @@ -366,13 +375,15 @@ private void createKey(OzoneManagerProtocol managerProtocol,
* snapshot bucket.
*/
@Test
@Order(3)
public void testSstFilteringService() throws Exception {
RDBStore activeDbStore = (RDBStore) om.getMetadataManager().getStore();
String volumeName = "volume";
List<String> bucketNames = Arrays.asList("bucket", "bucket1", "bucket2");

createVolume(volumeName);
for (String bucketName : bucketNames) {
createVolumeAndBucket(volumeName, bucketName);
addBucketToVolume(volumeName, bucketName);
}

int keyCount = 150;
Expand Down Expand Up @@ -407,15 +418,14 @@ public void testSstFilteringService() throws Exception {
List<String> snapshotNames = Arrays.asList("snap", "snap-1", "snap-2");

for (int i = 0; i < 3; i++) {
writeClient.createSnapshot(volumeName, bucketNames.get(i),
snapshotNames.get(i));
createSnapshot(volumeName, bucketNames.get(i), snapshotNames.get(i));
}

SstFilteringService sstFilteringService =
keyManager.getSnapshotSstFilteringService();

waitForSnapshotsAtLeast(sstFilteringService, 3);
assertEquals(3, sstFilteringService.getSnapshotFilteredCount().get());
waitForSnapshotsAtLeast(sstFilteringService, countTotalSnapshots);
assertEquals(countTotalSnapshots, sstFilteringService.getSnapshotFilteredCount().get());

Set<String> keyInBucketAfterFilteringRun =
getKeysFromSnapshot(volumeName, bucketNames.get(0),
Expand Down Expand Up @@ -469,4 +479,9 @@ private Set<String> getKeysFromSnapshot(String volume,
return getKeysFromDb(omSnapshot.getMetadataManager(), volume, bucket);
}
}

private void createSnapshot(String volumeName, String bucketName, String snapshotName) throws IOException {
writeClient.createSnapshot(volumeName, bucketName, snapshotName);
countTotalSnapshots++;
}
}