|
@@ -17,7 +17,11 @@
|
|
|
*/
|
|
|
package org.apache.hadoop.hdfs.server.namenode.snapshot;
|
|
|
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
+import org.apache.hadoop.hdfs.protocol.Block;
|
|
|
+import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.INodeFile;
|
|
|
|
|
|
/**
|
|
@@ -65,4 +69,73 @@ public class INodeFileWithLink extends INodeFile {
|
|
|
}
|
|
|
return max;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * {@inheritDoc}
|
|
|
+ *
|
|
|
+ * Remove the current inode from the circular linked list.
|
|
|
+ * If some blocks at the end of the block list no longer belongs to
|
|
|
+ * any other inode, collect them and update the block list.
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ protected int collectSubtreeBlocksAndClear(List<Block> v) {
|
|
|
+ if (next == this) {
|
|
|
+ //this is the only remaining inode.
|
|
|
+ super.collectSubtreeBlocksAndClear(v);
|
|
|
+ } else {
|
|
|
+ //There are other inode(s) using the blocks.
|
|
|
+ //Compute max file size excluding this and find the last inode.
|
|
|
+ long max = next.computeFileSize(true);
|
|
|
+ INodeFileWithLink last = next;
|
|
|
+ for(INodeFileWithLink i = next.getNext(); i != this; i = i.getNext()) {
|
|
|
+ final long size = i.computeFileSize(true);
|
|
|
+ if (size > max) {
|
|
|
+ max = size;
|
|
|
+ }
|
|
|
+ last = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ collectBlocksBeyondMaxAndClear(max, v);
|
|
|
+
|
|
|
+ //remove this from the circular linked list.
|
|
|
+ last.next = this.next;
|
|
|
+ this.next = null;
|
|
|
+ //clear parent
|
|
|
+ parent = null;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void collectBlocksBeyondMaxAndClear(final long max, final List<Block> v) {
|
|
|
+ if (blocks != null) {
|
|
|
+ //find the minimum n such that the size of the first n blocks > max
|
|
|
+ int n = 0;
|
|
|
+ for(long size = 0; n < blocks.length && max > size; n++) {
|
|
|
+ size += blocks[n].getNumBytes();
|
|
|
+ }
|
|
|
+
|
|
|
+ //starting from block[n], the data is beyond max.
|
|
|
+ if (n < blocks.length) {
|
|
|
+ //resize the array.
|
|
|
+ final BlockInfo[] newBlocks;
|
|
|
+ if (n == 0) {
|
|
|
+ newBlocks = null;
|
|
|
+ } else {
|
|
|
+ newBlocks = new BlockInfo[n];
|
|
|
+ System.arraycopy(blocks, 0, newBlocks, 0, n);
|
|
|
+ }
|
|
|
+ for(INodeFileWithLink i = next; i != this; i = i.getNext()) {
|
|
|
+ i.blocks = newBlocks;
|
|
|
+ }
|
|
|
+
|
|
|
+ //collect the blocks beyond max.
|
|
|
+ if (v != null) {
|
|
|
+ for(; n < blocks.length; n++) {
|
|
|
+ v.add(blocks[n]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ blocks = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|