HDFS-7467. Provide storage tier information for a directory via fsck. (Benoy Antony)

This commit is contained in:
Benoy Antony 2015-02-25 16:19:35 -08:00
parent d389a1ae98
commit 4e400030f6
5 changed files with 549 additions and 14 deletions

View File

@ -25,6 +25,7 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
@ -45,6 +46,7 @@ import org.apache.hadoop.hdfs.DFSClient;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.RemotePeerFactory;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.net.Peer;
import org.apache.hadoop.hdfs.net.TcpPeerServer;
import org.apache.hadoop.hdfs.protocol.Block;
@ -127,6 +129,7 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
private boolean showBlocks = false;
private boolean showLocations = false;
private boolean showRacks = false;
private boolean showStoragePolcies = false;
private boolean showCorruptFileBlocks = false;
/**
@ -163,6 +166,7 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
private List<String> snapshottableDirs = null;
private final BlockPlacementPolicy bpPolicy;
private StoragePolicySummary storageTypeSummary = null;
/**
* Filesystem checker.
@ -199,6 +203,7 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
else if (key.equals("blocks")) { this.showBlocks = true; }
else if (key.equals("locations")) { this.showLocations = true; }
else if (key.equals("racks")) { this.showRacks = true; }
else if (key.equals("storagepolicies")) { this.showStoragePolcies = true; }
else if (key.equals("openforwrite")) {this.showOpenFiles = true; }
else if (key.equals("listcorruptfileblocks")) {
this.showCorruptFileBlocks = true;
@ -332,6 +337,11 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
return;
}
if (this.showStoragePolcies) {
storageTypeSummary = new StoragePolicySummary(
namenode.getNamesystem().getBlockManager().getStoragePolicies());
}
Result res = new Result(conf);
check(path, file, res);
@ -340,6 +350,10 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
out.println(" Number of data-nodes:\t\t" + totalDatanodes);
out.println(" Number of racks:\t\t" + networktopology.getNumOfRacks());
if (this.showStoragePolcies) {
out.print(storageTypeSummary.toString());
}
out.println("FSCK ended at " + new Date() + " in "
+ (Time.now() - startTime + " milliseconds"));
@ -487,7 +501,8 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
boolean isCorrupt = lBlk.isCorrupt();
String blkName = block.toString();
DatanodeInfo[] locs = lBlk.getLocations();
NumberReplicas numberReplicas = namenode.getNamesystem().getBlockManager().countNodes(block.getLocalBlock());
NumberReplicas numberReplicas =
namenode.getNamesystem().getBlockManager().countNodes(block.getLocalBlock());
int liveReplicas = numberReplicas.liveReplicas();
res.totalReplicas += liveReplicas;
short targetFileReplication = file.getReplication();
@ -496,6 +511,12 @@ public class NamenodeFsck implements DataEncryptionKeyFactory {
res.excessiveReplicas += (liveReplicas - targetFileReplication);
res.numOverReplicatedBlocks += 1;
}
//keep track of storage tier counts
if (this.showStoragePolcies && lBlk.getStorageTypes() != null) {
StorageType[] storageTypes = lBlk.getStorageTypes();
storageTypeSummary.add(Arrays.copyOf(storageTypes, storageTypes.length),
fsn.getBlockManager().getStoragePolicy(file.getStoragePolicy()));
}
// Check if block is Corrupt
if (isCorrupt) {
corrupt++;

View File

@ -0,0 +1,257 @@
/**
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.hdfs.server.namenode;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.Formatter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
/**
* Aggregate the storage type information for a set of blocks
*
*/
public class StoragePolicySummary {
Map<StorageTypeAllocation, Long> storageComboCounts = new HashMap<>();
final BlockStoragePolicy[] storagePolicies;
int totalBlocks;
StoragePolicySummary(BlockStoragePolicy[] storagePolicies) {
this.storagePolicies = storagePolicies;
}
// Add a storage type combination
void add(StorageType[] storageTypes, BlockStoragePolicy policy) {
StorageTypeAllocation storageCombo =
new StorageTypeAllocation(storageTypes, policy);
Long count = storageComboCounts.get(storageCombo);
if (count == null) {
storageComboCounts.put(storageCombo, 1l);
storageCombo.setActualStoragePolicy(
getStoragePolicy(storageCombo.getStorageTypes()));
} else {
storageComboCounts.put(storageCombo, count.longValue()+1);
}
totalBlocks++;
}
// sort the storageType combinations based on the total blocks counts
// in descending order
static List<Entry<StorageTypeAllocation, Long>> sortByComparator(
Map<StorageTypeAllocation, Long> unsortMap) {
List<Entry<StorageTypeAllocation, Long>> storageAllocations =
new LinkedList<>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(storageAllocations,
new Comparator<Entry<StorageTypeAllocation, Long>>() {
public int compare(Entry<StorageTypeAllocation, Long> o1,
Entry<StorageTypeAllocation, Long> o2)
{
return o2.getValue().compareTo(o1.getValue());
}
});
return storageAllocations;
}
public String toString() {
StringBuilder compliantBlocksSB = new StringBuilder();
compliantBlocksSB.append("\nBlocks satisfying the specified storage policy:");
compliantBlocksSB.append("\nStorage Policy # of blocks % of blocks\n");
StringBuilder nonCompliantBlocksSB = new StringBuilder();
Formatter compliantFormatter = new Formatter(compliantBlocksSB);
Formatter nonCompliantFormatter = new Formatter(nonCompliantBlocksSB);
NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMinimumFractionDigits(4);
percentFormat.setMaximumFractionDigits(4);
for (Map.Entry<StorageTypeAllocation, Long> storageComboCount:
sortByComparator(storageComboCounts)) {
double percent = (double) storageComboCount.getValue() /
(double) totalBlocks;
StorageTypeAllocation sta = storageComboCount.getKey();
if (sta.policyMatches()) {
compliantFormatter.format("%-25s %10d %20s%n",
sta.getStoragePolicyDescriptor(),
storageComboCount.getValue(),
percentFormat.format(percent));
} else {
if (nonCompliantBlocksSB.length() == 0) {
nonCompliantBlocksSB.append("\nBlocks NOT satisfying the specified storage policy:");
nonCompliantBlocksSB.append("\nStorage Policy ");
nonCompliantBlocksSB.append(
"Specified Storage Policy # of blocks % of blocks\n");
}
nonCompliantFormatter.format("%-35s %-20s %10d %20s%n",
sta.getStoragePolicyDescriptor(),
sta.getSpecifiedStoragePolicy().getName(),
storageComboCount.getValue(),
percentFormat.format(percent));
}
}
if (nonCompliantBlocksSB.length() == 0) {
nonCompliantBlocksSB.append("\nAll blocks satisfy specified storage policy.\n");
}
compliantFormatter.close();
nonCompliantFormatter.close();
return compliantBlocksSB.toString() + nonCompliantBlocksSB;
}
/**
*
* @param storageTypes - sorted array of storageTypes
* @return Storage Policy which matches the specific storage Combination
*/
private BlockStoragePolicy getStoragePolicy(StorageType[] storageTypes) {
for (BlockStoragePolicy storagePolicy:storagePolicies) {
StorageType[] policyStorageTypes = storagePolicy.getStorageTypes();
policyStorageTypes = Arrays.copyOf(policyStorageTypes, policyStorageTypes.length);
Arrays.sort(policyStorageTypes);
if (policyStorageTypes.length <= storageTypes.length) {
int i = 0;
for (; i < policyStorageTypes.length; i++) {
if (policyStorageTypes[i] != storageTypes[i]) {
break;
}
}
if (i < policyStorageTypes.length) {
continue;
}
int j=policyStorageTypes.length;
for (; j < storageTypes.length; j++) {
if (policyStorageTypes[i-1] != storageTypes[j]) {
break;
}
}
if (j==storageTypes.length) {
return storagePolicy;
}
}
}
return null;
}
/**
* Internal class which represents a unique Storage type combination
*
*/
static class StorageTypeAllocation {
private final BlockStoragePolicy specifiedStoragePolicy;
private final StorageType[] storageTypes;
private BlockStoragePolicy actualStoragePolicy;
StorageTypeAllocation(StorageType[] storageTypes,
BlockStoragePolicy specifiedStoragePolicy) {
Arrays.sort(storageTypes);
this.storageTypes = storageTypes;
this.specifiedStoragePolicy = specifiedStoragePolicy;
}
StorageType[] getStorageTypes() {
return storageTypes;
}
BlockStoragePolicy getSpecifiedStoragePolicy() {
return specifiedStoragePolicy;
}
void setActualStoragePolicy(BlockStoragePolicy actualStoragePolicy) {
this.actualStoragePolicy = actualStoragePolicy;
}
BlockStoragePolicy getActualStoragePolicy() {
return actualStoragePolicy;
}
private static String getStorageAllocationAsString
(Map<StorageType, Integer> storageType_countmap) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<StorageType, Integer>
storageTypeCountEntry:storageType_countmap.entrySet()) {
sb.append(storageTypeCountEntry.getKey().name()+ ":"
+ storageTypeCountEntry.getValue() + ",");
}
if (sb.length() > 1) {
sb.deleteCharAt(sb.length()-1);
}
return sb.toString();
}
private String getStorageAllocationAsString() {
Map<StorageType, Integer> storageType_countmap =
new EnumMap<>(StorageType.class);
for (StorageType storageType: storageTypes) {
Integer count = storageType_countmap.get(storageType);
if (count == null) {
storageType_countmap.put(storageType, 1);
} else {
storageType_countmap.put(storageType, count.intValue()+1);
}
}
return (getStorageAllocationAsString(storageType_countmap));
}
String getStoragePolicyDescriptor() {
StringBuilder storagePolicyDescriptorSB = new StringBuilder();
if (actualStoragePolicy!=null) {
storagePolicyDescriptorSB.append(getStorageAllocationAsString())
.append("(")
.append(actualStoragePolicy.getName())
.append(")");
} else {
storagePolicyDescriptorSB.append(getStorageAllocationAsString());
}
return storagePolicyDescriptorSB.toString();
}
boolean policyMatches() {
return specifiedStoragePolicy.equals(actualStoragePolicy);
}
@Override
public String toString() {
return specifiedStoragePolicy.getName() + "|" + getStoragePolicyDescriptor();
}
@Override
public int hashCode() {
return Objects.hash(specifiedStoragePolicy,Arrays.hashCode(storageTypes));
}
@Override
public boolean equals(Object another) {
return (another instanceof StorageTypeAllocation &&
Objects.equals(specifiedStoragePolicy,
((StorageTypeAllocation)another).specifiedStoragePolicy) &&
Arrays.equals(storageTypes,
((StorageTypeAllocation)another).storageTypes));
}
}
}

View File

@ -91,7 +91,8 @@ public class DFSck extends Configured implements Tool {
+ "blocks and files they belong to\n"
+ "\t-blocks\tprint out block report\n"
+ "\t-locations\tprint out locations for every block\n"
+ "\t-racks\tprint out network topology for data-node locations\n\n"
+ "\t-racks\tprint out network topology for data-node locations\n"
+ "\t-storagepolicies\tprint out storage policy summary for the blocks\n\n"
+ "\t-blockId\tprint out which file this blockId belongs to, locations"
+ " (nodes, racks) of this block, and other diagnostics info"
+ " (under replicated, corrupted or not, etc)\n\n"
@ -264,6 +265,7 @@ public class DFSck extends Configured implements Tool {
else if (args[idx].equals("-blocks")) { url.append("&blocks=1"); }
else if (args[idx].equals("-locations")) { url.append("&locations=1"); }
else if (args[idx].equals("-racks")) { url.append("&racks=1"); }
else if (args[idx].equals("-storagepolicies")) { url.append("&storagepolicies=1"); }
else if (args[idx].equals("-list-corruptfileblocks")) {
url.append("&listcorruptfileblocks=1");
doListCorruptFileBlocks = true;

View File

@ -18,6 +18,18 @@
package org.apache.hadoop.hdfs.server.namenode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -41,7 +53,6 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.collect.Sets;
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
@ -58,6 +69,7 @@ import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
@ -83,17 +95,7 @@ import org.apache.log4j.PatternLayout;
import org.apache.log4j.RollingFileAppender;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.collect.Sets;
/**
* A JUnit test for doing fsck
@ -1326,4 +1328,56 @@ public class TestFsck {
}
}
}
private void writeFile(final DistributedFileSystem dfs,
Path dir, String fileName) throws IOException {
Path filePath = new Path(dir.toString() + Path.SEPARATOR + fileName);
final FSDataOutputStream out = dfs.create(filePath);
out.writeChars("teststring");
out.close();
}
private void writeFile(final DistributedFileSystem dfs,
String dirName, String fileName, String StoragePolicy) throws IOException {
Path dirPath = new Path(dirName);
dfs.mkdirs(dirPath);
dfs.setStoragePolicy(dirPath, StoragePolicy);
writeFile(dfs, dirPath, fileName);
}
/**
* Test storage policy display
*/
@Test
public void testStoragePoliciesCK() throws Exception {
final Configuration conf = new HdfsConfiguration();
final MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf)
.numDataNodes(3)
.storageTypes(
new StorageType[] {StorageType.DISK, StorageType.ARCHIVE})
.build();
try {
cluster.waitActive();
final DistributedFileSystem dfs = cluster.getFileSystem();
writeFile(dfs, "/testhot", "file", "HOT");
writeFile(dfs, "/testwarm", "file", "WARM");
writeFile(dfs, "/testcold", "file", "COLD");
String outStr = runFsck(conf, 0, true, "/", "-storagepolicies");
assertTrue(outStr.contains("DISK:3(HOT)"));
assertTrue(outStr.contains("DISK:1,ARCHIVE:2(WARM)"));
assertTrue(outStr.contains("ARCHIVE:3(COLD)"));
assertTrue(outStr.contains("All blocks satisfy specified storage policy."));
dfs.setStoragePolicy(new Path("/testhot"), "COLD");
dfs.setStoragePolicy(new Path("/testwarm"), "COLD");
outStr = runFsck(conf, 0, true, "/", "-storagepolicies");
assertTrue(outStr.contains("DISK:3(HOT)"));
assertTrue(outStr.contains("DISK:1,ARCHIVE:2(WARM)"));
assertTrue(outStr.contains("ARCHIVE:3(COLD)"));
assertFalse(outStr.contains("All blocks satisfy specified storage policy."));
} finally {
if (cluster != null) {
cluster.shutdown();
}
}
}
}

View File

@ -0,0 +1,201 @@
/**
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.hdfs.server.namenode;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite;
import org.apache.hadoop.hdfs.server.namenode.StoragePolicySummary.StorageTypeAllocation;
import org.junit.Assert;
import org.junit.Test;
public class TestStoragePolicySummary {
private Map<String, Long> convertToStringMap(StoragePolicySummary sts) {
LinkedHashMap<String, Long> actualOutput = new LinkedHashMap<>();
for (Map.Entry<StorageTypeAllocation, Long> entry:
StoragePolicySummary.sortByComparator(sts.storageComboCounts)) {
actualOutput.put(entry.getKey().toString(), entry.getValue());
}
return actualOutput;
}
@Test
public void testMultipleHots() {
BlockStoragePolicySuite bsps = BlockStoragePolicySuite.createDefaultSuite();
StoragePolicySummary sts = new StoragePolicySummary(bsps.getAllPolicies());
BlockStoragePolicy hot = bsps.getPolicy("HOT");
sts.add(new StorageType[]{StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
Map<String, Long> actualOutput = convertToStringMap(sts);
Assert.assertEquals(4,actualOutput.size());
Map<String, Long> expectedOutput = new HashMap<>();
expectedOutput.put("HOT|DISK:1(HOT)", 1l);
expectedOutput.put("HOT|DISK:2(HOT)", 1l);
expectedOutput.put("HOT|DISK:3(HOT)", 1l);
expectedOutput.put("HOT|DISK:4(HOT)", 1l);
Assert.assertEquals(expectedOutput,actualOutput);
}
@Test
public void testMultipleHotsWithDifferentCounts() {
BlockStoragePolicySuite bsps = BlockStoragePolicySuite.createDefaultSuite();
StoragePolicySummary sts = new StoragePolicySummary(bsps.getAllPolicies());
BlockStoragePolicy hot = bsps.getPolicy("HOT");
sts.add(new StorageType[]{StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
Map<String, Long> actualOutput = convertToStringMap(sts);
Assert.assertEquals(4,actualOutput.size());
Map<String, Long> expectedOutput = new HashMap<>();
expectedOutput.put("HOT|DISK:1(HOT)", 1l);
expectedOutput.put("HOT|DISK:2(HOT)", 2l);
expectedOutput.put("HOT|DISK:3(HOT)", 2l);
expectedOutput.put("HOT|DISK:4(HOT)", 1l);
Assert.assertEquals(expectedOutput,actualOutput);
}
@Test
public void testMultipleWarmsInDifferentOrder() {
BlockStoragePolicySuite bsps = BlockStoragePolicySuite.createDefaultSuite();
StoragePolicySummary sts = new StoragePolicySummary(bsps.getAllPolicies());
BlockStoragePolicy warm = bsps.getPolicy("WARM");
//DISK:1,ARCHIVE:1
sts.add(new StorageType[]{StorageType.DISK,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,StorageType.DISK},warm);
//DISK:2,ARCHIVE:1
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.DISK,StorageType.DISK},warm);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.ARCHIVE,StorageType.DISK},warm);
sts.add(new StorageType[]{StorageType.DISK,
StorageType.DISK,StorageType.ARCHIVE},warm);
//DISK:1,ARCHIVE:2
sts.add(new StorageType[]{StorageType.DISK,
StorageType.ARCHIVE,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.DISK,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.DISK},warm);
//DISK:2,ARCHIVE:2
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.DISK,StorageType.DISK},warm);
Map<String, Long> actualOutput = convertToStringMap(sts);
Assert.assertEquals(4,actualOutput.size());
Map<String, Long> expectedOutput = new HashMap<>();
expectedOutput.put("WARM|DISK:1,ARCHIVE:1(WARM)", 2l);
expectedOutput.put("WARM|DISK:2,ARCHIVE:1", 3l);
expectedOutput.put("WARM|DISK:1,ARCHIVE:2(WARM)", 3l);
expectedOutput.put("WARM|DISK:2,ARCHIVE:2", 1l);
Assert.assertEquals(expectedOutput,actualOutput);
}
@Test
public void testDifferentSpecifiedPolicies() {
BlockStoragePolicySuite bsps = BlockStoragePolicySuite.createDefaultSuite();
StoragePolicySummary sts = new StoragePolicySummary(bsps.getAllPolicies());
BlockStoragePolicy hot = bsps.getPolicy("HOT");
BlockStoragePolicy warm = bsps.getPolicy("WARM");
BlockStoragePolicy cold = bsps.getPolicy("COLD");
//DISK:3
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},warm);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},cold);
//DISK:1,ARCHIVE:2
sts.add(new StorageType[]{StorageType.DISK,
StorageType.ARCHIVE,StorageType.ARCHIVE},hot);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.DISK,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.DISK},cold);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.DISK},cold);
//ARCHIVE:3
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},hot);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},hot);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},cold);
Map<String, Long> actualOutput = convertToStringMap(sts);
Assert.assertEquals(9,actualOutput.size());
Map<String, Long> expectedOutput = new HashMap<>();
expectedOutput.put("HOT|DISK:3(HOT)", 2l);
expectedOutput.put("COLD|DISK:1,ARCHIVE:2(WARM)", 2l);
expectedOutput.put("HOT|ARCHIVE:3(COLD)", 2l);
expectedOutput.put("WARM|DISK:3(HOT)", 1l);
expectedOutput.put("COLD|DISK:3(HOT)", 1l);
expectedOutput.put("WARM|ARCHIVE:3(COLD)", 1l);
expectedOutput.put("WARM|DISK:1,ARCHIVE:2(WARM)", 1l);
expectedOutput.put("COLD|ARCHIVE:3(COLD)", 1l);
expectedOutput.put("HOT|DISK:1,ARCHIVE:2(WARM)", 1l);
Assert.assertEquals(expectedOutput,actualOutput);
}
@Test
public void testSortInDescendingOrder() {
BlockStoragePolicySuite bsps = BlockStoragePolicySuite.createDefaultSuite();
StoragePolicySummary sts = new StoragePolicySummary(bsps.getAllPolicies());
BlockStoragePolicy hot = bsps.getPolicy("HOT");
BlockStoragePolicy warm = bsps.getPolicy("WARM");
BlockStoragePolicy cold = bsps.getPolicy("COLD");
//DISK:3
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
sts.add(new StorageType[]{StorageType.DISK,StorageType.DISK,StorageType.DISK},hot);
//DISK:1,ARCHIVE:2
sts.add(new StorageType[]{StorageType.DISK,
StorageType.ARCHIVE,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.DISK,StorageType.ARCHIVE},warm);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.DISK},warm);
//ARCHIVE:3
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},cold);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},cold);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},cold);
sts.add(new StorageType[]{StorageType.ARCHIVE,
StorageType.ARCHIVE,StorageType.ARCHIVE},cold);
Map<String, Long> actualOutput = convertToStringMap(sts);
Assert.assertEquals(3,actualOutput.size());
Map<String, Long> expectedOutput = new LinkedHashMap<>();
expectedOutput.put("COLD|ARCHIVE:3(COLD)", 4l);
expectedOutput.put("WARM|DISK:1,ARCHIVE:2(WARM)", 3l);
expectedOutput.put("HOT|DISK:3(HOT)", 2l);
Assert.assertEquals(expectedOutput.toString(),actualOutput.toString());
}
}