HDFS-8372. Erasure coding: compute storage type quotas for striped files, to be consistent with HDFS-8327. Contributed by Zhe Zhang.

This commit is contained in:
Jing Zhao 2015-05-12 11:43:04 -07:00 committed by Zhe Zhang
parent 8d3030f064
commit 97a2396af6
4 changed files with 64 additions and 26 deletions

View File

@ -198,3 +198,6 @@
HDFS-7678. Erasure coding: DFSInputStream with decode functionality (pread). HDFS-7678. Erasure coding: DFSInputStream with decode functionality (pread).
(Zhe Zhang) (Zhe Zhang)
HDFS-8372. Erasure coding: compute storage type quotas for striped files,
to be consistent with HDFS-8327. (Zhe Zhang via jing9)

View File

@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
import org.apache.hadoop.hdfs.protocol.Block; import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguous; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguous;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStripedUnderConstruction;
/** /**
* Feature for file with striped blocks * Feature for file with striped blocks
@ -78,20 +79,23 @@ class FileWithStripedBlocksFeature implements INode.Feature {
} }
} }
boolean removeLastBlock(Block oldblock) { BlockInfoStripedUnderConstruction removeLastBlock(
Block oldblock) {
if (blocks == null || blocks.length == 0) { if (blocks == null || blocks.length == 0) {
return false; return null;
} }
int newSize = blocks.length - 1; int newSize = blocks.length - 1;
if (!blocks[newSize].equals(oldblock)) { if (!blocks[newSize].equals(oldblock)) {
return false; return null;
} }
BlockInfoStripedUnderConstruction uc =
(BlockInfoStripedUnderConstruction) blocks[newSize];
//copy to a new list //copy to a new list
BlockInfoStriped[] newlist = new BlockInfoStriped[newSize]; BlockInfoStriped[] newlist = new BlockInfoStriped[newSize];
System.arraycopy(blocks, 0, newlist, 0, newSize); System.arraycopy(blocks, 0, newlist, 0, newSize);
setBlocks(newlist); setBlocks(newlist);
return true; return uc;
} }
void truncateStripedBlocks(int n) { void truncateStripedBlocks(int n) {

View File

@ -43,6 +43,7 @@ import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguous;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguousUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguousUnderConstruction;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStripedUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStripedUnderConstruction;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite; import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite;
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStorageInfo; import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStorageInfo;
import org.apache.hadoop.hdfs.server.namenode.snapshot.FileDiff; import org.apache.hadoop.hdfs.server.namenode.snapshot.FileDiff;
@ -295,7 +296,7 @@ public class INodeFile extends INodeWithAdditionalFields
* Remove a block from the block list. This block should be * Remove a block from the block list. This block should be
* the last one on the list. * the last one on the list.
*/ */
BlockInfoContiguousUnderConstruction removeLastBlock(Block oldblock) { BlockInfoUnderConstruction removeLastBlock(Block oldblock) {
Preconditions.checkState(isUnderConstruction(), Preconditions.checkState(isUnderConstruction(),
"file is no longer under construction"); "file is no longer under construction");
FileWithStripedBlocksFeature sb = getStripedBlocksFeature(); FileWithStripedBlocksFeature sb = getStripedBlocksFeature();
@ -317,7 +318,7 @@ public class INodeFile extends INodeWithAdditionalFields
return uc; return uc;
} else { } else {
assert hasNoContiguousBlock(); assert hasNoContiguousBlock();
return null; return sb.removeLastBlock(oldblock);
} }
} }
@ -676,7 +677,7 @@ public class INodeFile extends INodeWithAdditionalFields
final long ssDeltaNoReplication; final long ssDeltaNoReplication;
short replication; short replication;
if (isStriped()) { if (isStriped()) {
return computeQuotaUsageWithStriped(bsps, counts); return computeQuotaUsageWithStriped(bsp, counts);
} }
if (last < lastSnapshotId) { if (last < lastSnapshotId) {
@ -702,11 +703,15 @@ public class INodeFile extends INodeWithAdditionalFields
} }
/** /**
* Compute quota of striped file * Compute quota of striped file. Note that currently EC files do not support
* append/hflush/hsync, thus the file length recorded in snapshots should be
* the same with the current file length.
*/ */
public final QuotaCounts computeQuotaUsageWithStriped( public final QuotaCounts computeQuotaUsageWithStriped(
BlockStoragePolicySuite bsps, QuotaCounts counts) { BlockStoragePolicy bsp, QuotaCounts counts) {
return null; counts.addNameSpace(1);
counts.add(storagespaceConsumed(bsp));
return counts;
} }
@Override @Override
@ -828,21 +833,44 @@ public class INodeFile extends INodeWithAdditionalFields
* Use preferred block size for the last block if it is under construction. * Use preferred block size for the last block if it is under construction.
*/ */
public final QuotaCounts storagespaceConsumed(BlockStoragePolicy bsp) { public final QuotaCounts storagespaceConsumed(BlockStoragePolicy bsp) {
QuotaCounts counts = new QuotaCounts.Builder().build();
if (isStriped()) { if (isStriped()) {
return storagespaceConsumedWithStriped(bsp); return storagespaceConsumedWithStriped();
} else { } else {
return storagespaceConsumedWithReplication(bsp); return storagespaceConsumedWithReplication(bsp);
} }
} }
public final QuotaCounts storagespaceConsumedWithStriped( // TODO: support EC with heterogeneous storage
BlockStoragePolicy bsp) { public final QuotaCounts storagespaceConsumedWithStriped() {
return null; QuotaCounts counts = new QuotaCounts.Builder().build();
BlockInfo[] blockInfos = getBlocks();
if (blockInfos == null || blockInfos.length == 0) {
return counts;
}
long size;
final int last = blockInfos.length - 1;
if (blockInfos[last] instanceof BlockInfoStripedUnderConstruction) {
BlockInfoStripedUnderConstruction blockInfoStripedUC
=(BlockInfoStripedUnderConstruction)blockInfos[last];
size = getPreferredBlockSize() * blockInfoStripedUC.getTotalBlockNum();
} else {
// In case of last block is complete
BlockInfoStriped blockInfoStriped = (BlockInfoStriped)blockInfos[last];
size = blockInfoStriped.spaceConsumed();
}
for (int i = 0; i < last; i++) {
BlockInfoStriped blockInfoStriped = (BlockInfoStriped)blockInfos[i];
size += blockInfoStriped.spaceConsumed();
}
counts.addStorageSpace(size);
return counts;
} }
public final QuotaCounts storagespaceConsumedWithReplication( public final QuotaCounts storagespaceConsumedWithReplication(
BlockStoragePolicy bsp) { QuotaCounts counts = new QuotaCounts.Builder().build(); BlockStoragePolicy bsp) {
QuotaCounts counts = new QuotaCounts.Builder().build();
final Iterable<BlockInfo> blocks; final Iterable<BlockInfo> blocks;
FileWithSnapshotFeature sf = getFileWithSnapshotFeature(); FileWithSnapshotFeature sf = getFileWithSnapshotFeature();
if (sf == null) { if (sf == null) {
@ -965,6 +993,7 @@ public class INodeFile extends INodeWithAdditionalFields
/** /**
* compute the quota usage change for a truncate op * compute the quota usage change for a truncate op
* @param newLength the length for truncation * @param newLength the length for truncation
* TODO: properly handle striped blocks (HDFS-7622)
**/ **/
void computeQuotaDeltaForTruncate( void computeQuotaDeltaForTruncate(
long newLength, BlockStoragePolicy bsps, long newLength, BlockStoragePolicy bsps,

View File

@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.permission.PermissionStatus; import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.protocol.Block; import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
import org.apache.hadoop.hdfs.protocol.HdfsConstants; import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStriped;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStripedUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoStripedUnderConstruction;
@ -45,6 +46,11 @@ public class TestStripedINodeFile {
private static final PermissionStatus perm = new PermissionStatus( private static final PermissionStatus perm = new PermissionStatus(
"userName", null, FsPermission.getDefault()); "userName", null, FsPermission.getDefault());
private final BlockStoragePolicySuite defaultSuite =
BlockStoragePolicySuite.createDefaultSuite();
private final BlockStoragePolicy defaultPolicy =
defaultSuite.getDefaultPolicy();
private static INodeFile createStripedINodeFile() { private static INodeFile createStripedINodeFile() {
return new INodeFile(HdfsConstants.GRANDFATHER_INODE_ID, null, perm, 0L, 0L, return new INodeFile(HdfsConstants.GRANDFATHER_INODE_ID, null, perm, 0L, 0L,
null, (short)0, 1024L, HdfsServerConstants.COLD_STORAGE_POLICY_ID); null, (short)0, 1024L, HdfsServerConstants.COLD_STORAGE_POLICY_ID);
@ -109,8 +115,8 @@ public class TestStripedINodeFile {
// a. <Cell Size> * (<Num Stripes> - 1) * <Total Block Num> = 0 // a. <Cell Size> * (<Num Stripes> - 1) * <Total Block Num> = 0
// b. <Num Bytes> % <Num Bytes per Stripes> = 1 // b. <Num Bytes> % <Num Bytes per Stripes> = 1
// c. <Last Stripe Length> * <Parity Block Num> = 1 * 3 // c. <Last Stripe Length> * <Parity Block Num> = 1 * 3
assertEquals(4, inf.storagespaceConsumedWithStriped(null)); assertEquals(4, inf.storagespaceConsumedWithStriped().getStorageSpace());
assertEquals(4, inf.storagespaceConsumed(null)); assertEquals(4, inf.storagespaceConsumed(defaultPolicy).getStorageSpace());
} }
@Test @Test
@ -134,8 +140,8 @@ public class TestStripedINodeFile {
inf.addBlock(blockInfoStriped1); inf.addBlock(blockInfoStriped1);
inf.addBlock(blockInfoStriped2); inf.addBlock(blockInfoStriped2);
// This is the double size of one block in above case. // This is the double size of one block in above case.
assertEquals(4 * 2, inf.storagespaceConsumedWithStriped(null)); assertEquals(4 * 2, inf.storagespaceConsumedWithStriped().getStorageSpace());
assertEquals(4 * 2, inf.storagespaceConsumed(null)); assertEquals(4 * 2, inf.storagespaceConsumed(defaultPolicy).getStorageSpace());
} }
@Test @Test
@ -188,10 +194,8 @@ public class TestStripedINodeFile {
blockInfoStriped.setNumBytes(100); blockInfoStriped.setNumBytes(100);
inf.addBlock(blockInfoStriped); inf.addBlock(blockInfoStriped);
BlockStoragePolicySuite suite =
BlockStoragePolicySuite.createDefaultSuite();
QuotaCounts counts = QuotaCounts counts =
inf.computeQuotaUsageWithStriped(suite, inf.computeQuotaUsageWithStriped(defaultPolicy,
new QuotaCounts.Builder().build()); new QuotaCounts.Builder().build());
assertEquals(1, counts.getNameSpace()); assertEquals(1, counts.getNameSpace());
// The total consumed space is the sum of // The total consumed space is the sum of
@ -215,10 +219,8 @@ public class TestStripedINodeFile {
bInfoStripedUC.setNumBytes(100); bInfoStripedUC.setNumBytes(100);
inf.addBlock(bInfoStripedUC); inf.addBlock(bInfoStripedUC);
BlockStoragePolicySuite suite
= BlockStoragePolicySuite.createDefaultSuite();
QuotaCounts counts QuotaCounts counts
= inf.computeQuotaUsageWithStriped(suite, = inf.computeQuotaUsageWithStriped(defaultPolicy,
new QuotaCounts.Builder().build()); new QuotaCounts.Builder().build());
assertEquals(1024, inf.getPreferredBlockSize()); assertEquals(1024, inf.getPreferredBlockSize());
assertEquals(1, counts.getNameSpace()); assertEquals(1, counts.getNameSpace());