HDFS-4346. Add SequentialNumber as a base class for INodeId and GenerationStamp.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1428167 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6f0eb6f5b1
commit
36c5fe9961
|
@ -174,6 +174,9 @@ Trunk (Unreleased)
|
||||||
|
|
||||||
HDFS-4334. Add a unique id to INode. (Brandon Li via szetszwo)
|
HDFS-4334. Add a unique id to INode. (Brandon Li via szetszwo)
|
||||||
|
|
||||||
|
HDFS-4346. Add SequentialNumber as a base class for INodeId and
|
||||||
|
GenerationStamp. (szetszwo)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -17,19 +17,18 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hdfs.server.common;
|
package org.apache.hadoop.hdfs.server.common;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.util.SequentialNumber;
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* A GenerationStamp is a Hadoop FS primitive, identified by a long.
|
* A GenerationStamp is a Hadoop FS primitive, identified by a long.
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public class GenerationStamp implements Comparable<GenerationStamp> {
|
public class GenerationStamp extends SequentialNumber {
|
||||||
/**
|
/**
|
||||||
* The first valid generation stamp.
|
* The last reserved generation stamp.
|
||||||
*/
|
*/
|
||||||
public static final long FIRST_VALID_STAMP = 1000L;
|
public static final long LAST_RESERVED_STAMP = 1000L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generation stamp of blocks that pre-date the introduction
|
* Generation stamp of blocks that pre-date the introduction
|
||||||
|
@ -37,62 +36,10 @@ public class GenerationStamp implements Comparable<GenerationStamp> {
|
||||||
*/
|
*/
|
||||||
public static final long GRANDFATHER_GENERATION_STAMP = 0;
|
public static final long GRANDFATHER_GENERATION_STAMP = 0;
|
||||||
|
|
||||||
private AtomicLong genstamp = new AtomicLong();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance, initialized to FIRST_VALID_STAMP.
|
* Create a new instance, initialized to {@link #LAST_RESERVED_STAMP}.
|
||||||
*/
|
*/
|
||||||
public GenerationStamp() {
|
public GenerationStamp() {
|
||||||
this(GenerationStamp.FIRST_VALID_STAMP);
|
super(LAST_RESERVED_STAMP);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance, initialized to the specified value.
|
|
||||||
*/
|
|
||||||
GenerationStamp(long stamp) {
|
|
||||||
genstamp.set(stamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current generation stamp
|
|
||||||
*/
|
|
||||||
public long getStamp() {
|
|
||||||
return genstamp.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current generation stamp
|
|
||||||
*/
|
|
||||||
public void setStamp(long stamp) {
|
|
||||||
genstamp.set(stamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First increments the counter and then returns the stamp
|
|
||||||
*/
|
|
||||||
public long nextStamp() {
|
|
||||||
return genstamp.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // Comparable
|
|
||||||
public int compareTo(GenerationStamp that) {
|
|
||||||
long stamp1 = this.genstamp.get();
|
|
||||||
long stamp2 = that.genstamp.get();
|
|
||||||
return stamp1 < stamp2 ? -1 :
|
|
||||||
stamp1 > stamp2 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // Object
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof GenerationStamp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return compareTo((GenerationStamp)o) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // Object
|
|
||||||
public int hashCode() {
|
|
||||||
long stamp = genstamp.get();
|
|
||||||
return (int) (stamp^(stamp>>>32));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,25 +378,29 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
private INodeId inodeId;
|
private INodeId inodeId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the last allocated inode id when fsimage is loaded or editlog is
|
* Set the last allocated inode id when fsimage or editlog is loaded.
|
||||||
* applied.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
public void resetLastInodeId(long newValue) throws IOException {
|
public void resetLastInodeId(long newValue) throws IOException {
|
||||||
inodeId.resetLastInodeId(newValue);
|
try {
|
||||||
|
inodeId.skipTo(newValue);
|
||||||
|
} catch(IllegalStateException ise) {
|
||||||
|
throw new IOException(ise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Should only be used for tests to reset to any value */
|
/** Should only be used for tests to reset to any value */
|
||||||
void resetLastInodeIdWithoutChecking(long newValue) {
|
void resetLastInodeIdWithoutChecking(long newValue) {
|
||||||
inodeId.resetLastInodeIdWithoutChecking(newValue);
|
inodeId.setCurrentValue(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the last inode ID. */
|
||||||
public long getLastInodeId() {
|
public long getLastInodeId() {
|
||||||
return inodeId.getLastInodeId();
|
return inodeId.getCurrentValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Allocate a new inode ID. */
|
||||||
public long allocateNewInodeId() {
|
public long allocateNewInodeId() {
|
||||||
return inodeId.allocateNewInodeId();
|
return inodeId.nextValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,9 +409,9 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
void clear() {
|
void clear() {
|
||||||
dir.reset();
|
dir.reset();
|
||||||
dtSecretManager.reset();
|
dtSecretManager.reset();
|
||||||
generationStamp.setStamp(GenerationStamp.FIRST_VALID_STAMP);
|
generationStamp.setCurrentValue(GenerationStamp.LAST_RESERVED_STAMP);
|
||||||
leaseManager.removeAllLeases();
|
leaseManager.removeAllLeases();
|
||||||
inodeId.resetLastInodeIdWithoutChecking(INodeId.LAST_RESERVED_ID);
|
inodeId.setCurrentValue(INodeId.LAST_RESERVED_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -2537,8 +2541,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
b.setBlockId(DFSUtil.getRandom().nextLong());
|
b.setBlockId(DFSUtil.getRandom().nextLong());
|
||||||
}
|
}
|
||||||
// Increment the generation stamp for every new block.
|
// Increment the generation stamp for every new block.
|
||||||
nextGenerationStamp();
|
b.setGenerationStamp(nextGenerationStamp());
|
||||||
b.setGenerationStamp(getGenerationStamp());
|
|
||||||
b = dir.addBlock(src, inodesInPath, b, targets);
|
b = dir.addBlock(src, inodesInPath, b, targets);
|
||||||
NameNode.stateChangeLog.info("BLOCK* allocateBlock: " + src + ". "
|
NameNode.stateChangeLog.info("BLOCK* allocateBlock: " + src + ". "
|
||||||
+ blockPoolId + " " + b);
|
+ blockPoolId + " " + b);
|
||||||
|
@ -4762,14 +4765,14 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
* Sets the generation stamp for this filesystem
|
* Sets the generation stamp for this filesystem
|
||||||
*/
|
*/
|
||||||
void setGenerationStamp(long stamp) {
|
void setGenerationStamp(long stamp) {
|
||||||
generationStamp.setStamp(stamp);
|
generationStamp.setCurrentValue(stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the generation stamp for this filesystem
|
* Gets the generation stamp for this filesystem
|
||||||
*/
|
*/
|
||||||
long getGenerationStamp() {
|
long getGenerationStamp() {
|
||||||
return generationStamp.getStamp();
|
return generationStamp.getCurrentValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4781,7 +4784,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
throw new SafeModeException(
|
throw new SafeModeException(
|
||||||
"Cannot get next generation stamp", safeMode);
|
"Cannot get next generation stamp", safeMode);
|
||||||
}
|
}
|
||||||
long gs = generationStamp.nextStamp();
|
final long gs = generationStamp.nextValue();
|
||||||
getEditLog().logGenerationStamp(gs);
|
getEditLog().logGenerationStamp(gs);
|
||||||
// NB: callers sync the log
|
// NB: callers sync the log
|
||||||
return gs;
|
return gs;
|
||||||
|
|
|
@ -17,16 +17,14 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hdfs.server.namenode;
|
package org.apache.hadoop.hdfs.server.namenode;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.util.SequentialNumber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An id which uniquely identifies an inode
|
* An id which uniquely identifies an inode
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
class INodeId implements Comparable<INodeId> {
|
class INodeId extends SequentialNumber {
|
||||||
/**
|
/**
|
||||||
* The last reserved inode id. Reserve id 1 to 1000 for potential future
|
* The last reserved inode id. Reserve id 1 to 1000 for potential future
|
||||||
* usage. The id won't be recycled and is not expected to wrap around in a
|
* usage. The id won't be recycled and is not expected to wrap around in a
|
||||||
|
@ -40,66 +38,7 @@ class INodeId implements Comparable<INodeId> {
|
||||||
*/
|
*/
|
||||||
public static final long GRANDFATHER_INODE_ID = 0;
|
public static final long GRANDFATHER_INODE_ID = 0;
|
||||||
|
|
||||||
private AtomicLong lastInodeId = new AtomicLong();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance, initialized to LAST_RESERVED_ID.
|
|
||||||
*/
|
|
||||||
INodeId() {
|
INodeId() {
|
||||||
lastInodeId.set(INodeId.LAST_RESERVED_ID);
|
super(LAST_RESERVED_ID);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the last allocated inode id when fsimage is loaded or editlog is
|
|
||||||
* applied.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void resetLastInodeId(long newValue) throws IOException {
|
|
||||||
if (newValue < getLastInodeId()) {
|
|
||||||
throw new IOException(
|
|
||||||
"Can't reset lastInodeId to be less than its current value "
|
|
||||||
+ getLastInodeId() + ", newValue=" + newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastInodeId.set(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetLastInodeIdWithoutChecking(long newValue) {
|
|
||||||
lastInodeId.set(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
long getLastInodeId() {
|
|
||||||
return lastInodeId.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First increment the counter and then get the id.
|
|
||||||
*/
|
|
||||||
long allocateNewInodeId() {
|
|
||||||
return lastInodeId.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// Comparable
|
|
||||||
public int compareTo(INodeId that) {
|
|
||||||
long id1 = this.getLastInodeId();
|
|
||||||
long id2 = that.getLastInodeId();
|
|
||||||
return id1 < id2 ? -1 : id1 > id2 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// Object
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof INodeId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return compareTo((INodeId) o) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// Object
|
|
||||||
public int hashCode() {
|
|
||||||
long id = getLastInodeId();
|
|
||||||
return (int) (id ^ (id >>> 32));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class TestBlockInfo {
|
||||||
|
|
||||||
LOG.info("Building block list...");
|
LOG.info("Building block list...");
|
||||||
for (int i = 0; i < MAX_BLOCKS; i++) {
|
for (int i = 0; i < MAX_BLOCKS; i++) {
|
||||||
blockList.add(new Block(i, 0, GenerationStamp.FIRST_VALID_STAMP));
|
blockList.add(new Block(i, 0, GenerationStamp.LAST_RESERVED_STAMP));
|
||||||
blockInfoList.add(new BlockInfo(blockList.get(i), 3));
|
blockInfoList.add(new BlockInfo(blockList.get(i), 3));
|
||||||
dd.addBlock(blockInfoList.get(i));
|
dd.addBlock(blockInfoList.get(i));
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class TestComputeInvalidateWork {
|
||||||
for (int i=0; i<nodes.length; i++) {
|
for (int i=0; i<nodes.length; i++) {
|
||||||
for(int j=0; j<3*blockInvalidateLimit+1; j++) {
|
for(int j=0; j<3*blockInvalidateLimit+1; j++) {
|
||||||
Block block = new Block(i*(blockInvalidateLimit+1)+j, 0,
|
Block block = new Block(i*(blockInvalidateLimit+1)+j, 0,
|
||||||
GenerationStamp.FIRST_VALID_STAMP);
|
GenerationStamp.LAST_RESERVED_STAMP);
|
||||||
bm.addToInvalidates(block, nodes[i]);
|
bm.addToInvalidates(block, nodes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class TestDatanodeDescriptor {
|
||||||
DatanodeDescriptor dd = DFSTestUtil.getLocalDatanodeDescriptor();
|
DatanodeDescriptor dd = DFSTestUtil.getLocalDatanodeDescriptor();
|
||||||
ArrayList<Block> blockList = new ArrayList<Block>(MAX_BLOCKS);
|
ArrayList<Block> blockList = new ArrayList<Block>(MAX_BLOCKS);
|
||||||
for (int i=0; i<MAX_BLOCKS; i++) {
|
for (int i=0; i<MAX_BLOCKS; i++) {
|
||||||
blockList.add(new Block(i, 0, GenerationStamp.FIRST_VALID_STAMP));
|
blockList.add(new Block(i, 0, GenerationStamp.LAST_RESERVED_STAMP));
|
||||||
}
|
}
|
||||||
dd.addBlocksToBeInvalidated(blockList);
|
dd.addBlocksToBeInvalidated(blockList);
|
||||||
Block[] bc = dd.getInvalidateBlocks(MAX_LIMIT);
|
Block[] bc = dd.getInvalidateBlocks(MAX_LIMIT);
|
||||||
|
|
|
@ -75,7 +75,8 @@ public class TestHeartbeatHandling {
|
||||||
synchronized(hm) {
|
synchronized(hm) {
|
||||||
for (int i=0; i<MAX_REPLICATE_BLOCKS; i++) {
|
for (int i=0; i<MAX_REPLICATE_BLOCKS; i++) {
|
||||||
dd.addBlockToBeReplicated(
|
dd.addBlockToBeReplicated(
|
||||||
new Block(i, 0, GenerationStamp.FIRST_VALID_STAMP), ONE_TARGET);
|
new Block(i, 0, GenerationStamp.LAST_RESERVED_STAMP),
|
||||||
|
ONE_TARGET);
|
||||||
}
|
}
|
||||||
DatanodeCommand[] cmds = NameNodeAdapter.sendHeartBeat(nodeReg, dd,
|
DatanodeCommand[] cmds = NameNodeAdapter.sendHeartBeat(nodeReg, dd,
|
||||||
namesystem).getCommands();
|
namesystem).getCommands();
|
||||||
|
@ -85,7 +86,7 @@ public class TestHeartbeatHandling {
|
||||||
|
|
||||||
ArrayList<Block> blockList = new ArrayList<Block>(MAX_INVALIDATE_BLOCKS);
|
ArrayList<Block> blockList = new ArrayList<Block>(MAX_INVALIDATE_BLOCKS);
|
||||||
for (int i=0; i<MAX_INVALIDATE_BLOCKS; i++) {
|
for (int i=0; i<MAX_INVALIDATE_BLOCKS; i++) {
|
||||||
blockList.add(new Block(i, 0, GenerationStamp.FIRST_VALID_STAMP));
|
blockList.add(new Block(i, 0, GenerationStamp.LAST_RESERVED_STAMP));
|
||||||
}
|
}
|
||||||
dd.addBlocksToBeInvalidated(blockList);
|
dd.addBlocksToBeInvalidated(blockList);
|
||||||
cmds = NameNodeAdapter.sendHeartBeat(nodeReg, dd, namesystem)
|
cmds = NameNodeAdapter.sendHeartBeat(nodeReg, dd, namesystem)
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class CreateEditsLog {
|
||||||
static final String EDITS_DIR = "/tmp/EditsLogOut";
|
static final String EDITS_DIR = "/tmp/EditsLogOut";
|
||||||
static String edits_dir = EDITS_DIR;
|
static String edits_dir = EDITS_DIR;
|
||||||
static final public long BLOCK_GENERATION_STAMP =
|
static final public long BLOCK_GENERATION_STAMP =
|
||||||
GenerationStamp.FIRST_VALID_STAMP;
|
GenerationStamp.LAST_RESERVED_STAMP;
|
||||||
|
|
||||||
static void addFiles(FSEditLog editLog, int numFiles, short replication,
|
static void addFiles(FSEditLog editLog, int numFiles, short replication,
|
||||||
int blocksPerFile, long startingBlockId,
|
int blocksPerFile, long startingBlockId,
|
||||||
|
|
Loading…
Reference in New Issue