blob: e0e4c61d3e54fa9492240e0abae93addec4ad57e [file] [log] [blame]
/**
* 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.om;
import com.google.common.base.Optional;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.StorageType;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.request.TestOMRequestUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.List;
import java.util.TreeSet;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_DB_DIRS;
/**
* Tests OzoneManager MetadataManager.
*/
public class TestOmMetadataManager {
private OMMetadataManager omMetadataManager;
private OzoneConfiguration ozoneConfiguration;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Before
public void setup() throws Exception {
ozoneConfiguration = new OzoneConfiguration();
ozoneConfiguration.set(OZONE_OM_DB_DIRS,
folder.getRoot().getAbsolutePath());
omMetadataManager = new OmMetadataManagerImpl(ozoneConfiguration);
}
@Test
public void testListBuckets() throws Exception {
String volumeName1 = "volumeA";
String prefixBucketNameWithOzoneOwner = "ozoneBucket";
String prefixBucketNameWithHadoopOwner = "hadoopBucket";
TestOMRequestUtils.addVolumeToDB(volumeName1, omMetadataManager);
TreeSet<String> volumeABucketsPrefixWithOzoneOwner = new TreeSet<>();
TreeSet<String> volumeABucketsPrefixWithHadoopOwner = new TreeSet<>();
for (int i=1; i<= 100; i++) {
if (i % 2 == 0) {
volumeABucketsPrefixWithOzoneOwner.add(
prefixBucketNameWithOzoneOwner + i);
addBucketsToCache(volumeName1, prefixBucketNameWithOzoneOwner + i);
} else {
volumeABucketsPrefixWithHadoopOwner.add(
prefixBucketNameWithHadoopOwner + i);
addBucketsToCache(volumeName1, prefixBucketNameWithHadoopOwner + i);
}
}
String volumeName2 = "volumeB";
TreeSet<String> volumeBBucketsPrefixWithOzoneOwner = new TreeSet<>();
TreeSet<String> volumeBBucketsPrefixWithHadoopOwner = new TreeSet<>();
TestOMRequestUtils.addVolumeToDB(volumeName2, omMetadataManager);
for (int i=1; i<= 100; i++) {
if (i % 2 == 0) {
volumeBBucketsPrefixWithOzoneOwner.add(
prefixBucketNameWithOzoneOwner + i);
addBucketsToCache(volumeName2, prefixBucketNameWithOzoneOwner + i);
} else {
volumeBBucketsPrefixWithHadoopOwner.add(
prefixBucketNameWithHadoopOwner + i);
addBucketsToCache(volumeName2, prefixBucketNameWithHadoopOwner + i);
}
}
// List all buckets which have prefix ozoneBucket
List<OmBucketInfo> omBucketInfoList =
omMetadataManager.listBuckets(volumeName1,
null, prefixBucketNameWithOzoneOwner, 100);
Assert.assertEquals(omBucketInfoList.size(), 50);
for (OmBucketInfo omBucketInfo : omBucketInfoList) {
Assert.assertTrue(omBucketInfo.getBucketName().startsWith(
prefixBucketNameWithOzoneOwner));
}
String startBucket = prefixBucketNameWithOzoneOwner + 10;
omBucketInfoList =
omMetadataManager.listBuckets(volumeName1,
startBucket, prefixBucketNameWithOzoneOwner,
100);
Assert.assertEquals(volumeABucketsPrefixWithOzoneOwner.tailSet(
startBucket).size() - 1, omBucketInfoList.size());
startBucket = prefixBucketNameWithOzoneOwner + 38;
omBucketInfoList =
omMetadataManager.listBuckets(volumeName1,
startBucket, prefixBucketNameWithOzoneOwner,
100);
Assert.assertEquals(volumeABucketsPrefixWithOzoneOwner.tailSet(
startBucket).size() - 1, omBucketInfoList.size());
for (OmBucketInfo omBucketInfo : omBucketInfoList) {
Assert.assertTrue(omBucketInfo.getBucketName().startsWith(
prefixBucketNameWithOzoneOwner));
Assert.assertFalse(omBucketInfo.getBucketName().equals(
prefixBucketNameWithOzoneOwner + 10));
}
omBucketInfoList = omMetadataManager.listBuckets(volumeName2,
null, prefixBucketNameWithHadoopOwner, 100);
Assert.assertEquals(omBucketInfoList.size(), 50);
for (OmBucketInfo omBucketInfo : omBucketInfoList) {
Assert.assertTrue(omBucketInfo.getBucketName().startsWith(
prefixBucketNameWithHadoopOwner));
}
// Try to get buckets by count 10, like that get all buckets in the
// volumeB with prefixBucketNameWithHadoopOwner.
startBucket = null;
TreeSet<String> expectedBuckets = new TreeSet<>();
for (int i=0; i<5; i++) {
omBucketInfoList = omMetadataManager.listBuckets(volumeName2,
startBucket, prefixBucketNameWithHadoopOwner, 10);
Assert.assertEquals(omBucketInfoList.size(), 10);
for (OmBucketInfo omBucketInfo : omBucketInfoList) {
expectedBuckets.add(omBucketInfo.getBucketName());
Assert.assertTrue(omBucketInfo.getBucketName().startsWith(
prefixBucketNameWithHadoopOwner));
startBucket = omBucketInfo.getBucketName();
}
}
Assert.assertEquals(volumeBBucketsPrefixWithHadoopOwner, expectedBuckets);
// As now we have iterated all 50 buckets, calling next time should
// return empty list.
omBucketInfoList = omMetadataManager.listBuckets(volumeName2,
startBucket, prefixBucketNameWithHadoopOwner, 10);
Assert.assertEquals(omBucketInfoList.size(), 0);
}
private void addBucketsToCache(String volumeName, String bucketName) {
OmBucketInfo omBucketInfo = OmBucketInfo.newBuilder()
.setVolumeName(volumeName)
.setBucketName(bucketName)
.setStorageType(StorageType.DISK)
.setIsVersionEnabled(false)
.build();
omMetadataManager.getBucketTable().addCacheEntry(
new CacheKey<>(omMetadataManager.getBucketKey(volumeName, bucketName)),
new CacheValue<>(Optional.of(omBucketInfo), 1));
}
@Test
public void testListKeys() throws Exception {
String volumeNameA = "volumeA";
String volumeNameB = "volumeB";
String ozoneBucket = "ozoneBucket";
String hadoopBucket = "hadoopBucket";
// Create volumes and buckets.
TestOMRequestUtils.addVolumeToDB(volumeNameA, omMetadataManager);
TestOMRequestUtils.addVolumeToDB(volumeNameB, omMetadataManager);
addBucketsToCache(volumeNameA, ozoneBucket);
addBucketsToCache(volumeNameB, hadoopBucket);
String prefixKeyA = "key-a";
String prefixKeyB = "key-b";
TreeSet<String> keysASet = new TreeSet<>();
TreeSet<String> keysBSet = new TreeSet<>();
for (int i=1; i<= 100; i++) {
if (i % 2 == 0) {
keysASet.add(
prefixKeyA + i);
addKeysToOM(volumeNameA, ozoneBucket, prefixKeyA + i, i);
} else {
keysBSet.add(
prefixKeyB + i);
addKeysToOM(volumeNameA, hadoopBucket, prefixKeyB + i, i);
}
}
TreeSet<String> keysAVolumeBSet = new TreeSet<>();
TreeSet<String> keysBVolumeBSet = new TreeSet<>();
for (int i=1; i<= 100; i++) {
if (i % 2 == 0) {
keysAVolumeBSet.add(
prefixKeyA + i);
addKeysToOM(volumeNameB, ozoneBucket, prefixKeyA + i, i);
} else {
keysBVolumeBSet.add(
prefixKeyB + i);
addKeysToOM(volumeNameB, hadoopBucket, prefixKeyB + i, i);
}
}
// List all keys which have prefix "key-a"
List<OmKeyInfo> omKeyInfoList =
omMetadataManager.listKeys(volumeNameA, ozoneBucket,
null, prefixKeyA, 100);
Assert.assertEquals(omKeyInfoList.size(), 50);
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(
prefixKeyA));
}
String startKey = prefixKeyA + 10;
omKeyInfoList =
omMetadataManager.listKeys(volumeNameA, ozoneBucket,
startKey, prefixKeyA, 100);
Assert.assertEquals(keysASet.tailSet(
startKey).size() - 1, omKeyInfoList.size());
startKey = prefixKeyA + 38;
omKeyInfoList =
omMetadataManager.listKeys(volumeNameA, ozoneBucket,
startKey, prefixKeyA, 100);
Assert.assertEquals(keysASet.tailSet(
startKey).size() - 1, omKeyInfoList.size());
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(
prefixKeyA));
Assert.assertFalse(omKeyInfo.getBucketName().equals(
prefixKeyA + 38));
}
omKeyInfoList = omMetadataManager.listKeys(volumeNameB, hadoopBucket,
null, prefixKeyB, 100);
Assert.assertEquals(omKeyInfoList.size(), 50);
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(
prefixKeyB));
}
// Try to get keys by count 10, like that get all keys in the
// volumeB/ozoneBucket with "key-a".
startKey = null;
TreeSet<String> expectedKeys = new TreeSet<>();
for (int i=0; i<5; i++) {
omKeyInfoList = omMetadataManager.listKeys(volumeNameB, hadoopBucket,
startKey, prefixKeyB, 10);
Assert.assertEquals(10, omKeyInfoList.size());
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
expectedKeys.add(omKeyInfo.getKeyName());
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(
prefixKeyB));
startKey = omKeyInfo.getKeyName();
}
}
Assert.assertEquals(expectedKeys, keysBVolumeBSet);
// As now we have iterated all 50 buckets, calling next time should
// return empty list.
omKeyInfoList = omMetadataManager.listKeys(volumeNameB, hadoopBucket,
startKey, prefixKeyB, 10);
Assert.assertEquals(omKeyInfoList.size(), 0);
}
@Test
public void testListKeysWithFewDeleteEntriesInCache() throws Exception {
String volumeNameA = "volumeA";
String ozoneBucket = "ozoneBucket";
// Create volumes and bucket.
TestOMRequestUtils.addVolumeToDB(volumeNameA, omMetadataManager);
addBucketsToCache(volumeNameA, ozoneBucket);
String prefixKeyA = "key-a";
TreeSet<String> keysASet = new TreeSet<>();
TreeSet<String> deleteKeySet = new TreeSet<>();
for (int i=1; i<= 100; i++) {
if (i % 2 == 0) {
keysASet.add(
prefixKeyA + i);
addKeysToOM(volumeNameA, ozoneBucket, prefixKeyA + i, i);
} else {
addKeysToOM(volumeNameA, ozoneBucket, prefixKeyA + i, i);
String key = omMetadataManager.getOzoneKey(volumeNameA,
ozoneBucket, prefixKeyA + i);
// Mark as deleted in cache.
omMetadataManager.getKeyTable().addCacheEntry(
new CacheKey<>(key),
new CacheValue<>(Optional.absent(), 100L));
deleteKeySet.add(key);
}
}
// Now list keys which match with prefixKeyA.
List<OmKeyInfo> omKeyInfoList =
omMetadataManager.listKeys(volumeNameA, ozoneBucket,
null, prefixKeyA, 100);
// As in total 100, 50 are marked for delete. It should list only 50 keys.
Assert.assertEquals(50, omKeyInfoList.size());
TreeSet<String> expectedKeys = new TreeSet<>();
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
expectedKeys.add(omKeyInfo.getKeyName());
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(prefixKeyA));
}
Assert.assertEquals(expectedKeys, keysASet);
// Now get key count by 10.
String startKey = null;
expectedKeys = new TreeSet<>();
for (int i=0; i<5; i++) {
omKeyInfoList = omMetadataManager.listKeys(volumeNameA, ozoneBucket,
startKey, prefixKeyA, 10);
System.out.println(i);
Assert.assertEquals(10, omKeyInfoList.size());
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
expectedKeys.add(omKeyInfo.getKeyName());
Assert.assertTrue(omKeyInfo.getKeyName().startsWith(
prefixKeyA));
startKey = omKeyInfo.getKeyName();
}
}
Assert.assertEquals(keysASet, expectedKeys);
// As now we have iterated all 50 buckets, calling next time should
// return empty list.
omKeyInfoList = omMetadataManager.listKeys(volumeNameA, ozoneBucket,
startKey, prefixKeyA, 10);
Assert.assertEquals(omKeyInfoList.size(), 0);
}
private void addKeysToOM(String volumeName, String bucketName,
String keyName, int i) throws Exception {
if (i%2== 0) {
TestOMRequestUtils.addKeyToTable(false, volumeName, bucketName, keyName,
1000L, HddsProtos.ReplicationType.RATIS,
HddsProtos.ReplicationFactor.ONE, omMetadataManager);
} else {
TestOMRequestUtils.addKeyToTableCache(volumeName, bucketName, keyName,
HddsProtos.ReplicationType.RATIS, HddsProtos.ReplicationFactor.ONE,
omMetadataManager);
}
}
}