HDFS-11945. Internal lease recovery may not be retried for a long time. Contributed by Kihwal Lee

This commit is contained in:
Mingliang Liu 2017-06-08 14:36:47 -07:00
parent 164c222c4a
commit 1a33c9d589
4 changed files with 46 additions and 9 deletions

View File

@ -79,6 +79,8 @@ public class LeaseManager {
private long hardLimit = HdfsConstants.LEASE_HARDLIMIT_PERIOD; private long hardLimit = HdfsConstants.LEASE_HARDLIMIT_PERIOD;
static final int INODE_FILTER_WORKER_COUNT_MAX = 4; static final int INODE_FILTER_WORKER_COUNT_MAX = 4;
static final int INODE_FILTER_WORKER_TASK_MIN = 512; static final int INODE_FILTER_WORKER_TASK_MIN = 512;
private long lastHolderUpdateTime;
private String internalLeaseHolder;
// Used for handling lock-leases // Used for handling lock-leases
// Mapping: leaseHolder -> Lease // Mapping: leaseHolder -> Lease
@ -97,7 +99,26 @@ public int compare(Lease o1, Lease o2) {
private Daemon lmthread; private Daemon lmthread;
private volatile boolean shouldRunMonitor; private volatile boolean shouldRunMonitor;
LeaseManager(FSNamesystem fsnamesystem) {this.fsnamesystem = fsnamesystem;} LeaseManager(FSNamesystem fsnamesystem) {
this.fsnamesystem = fsnamesystem;
updateInternalLeaseHolder();
}
// Update the internal lease holder with the current time stamp.
private void updateInternalLeaseHolder() {
this.lastHolderUpdateTime = Time.monotonicNow();
this.internalLeaseHolder = HdfsServerConstants.NAMENODE_LEASE_HOLDER +
"-" + Time.formatTime(Time.now());
}
// Get the current internal lease holder name.
String getInternalLeaseHolder() {
long elapsed = Time.monotonicNow() - lastHolderUpdateTime;
if (elapsed > hardLimit) {
updateInternalLeaseHolder();
}
return internalLeaseHolder;
}
Lease getLease(String holder) { Lease getLease(String holder) {
return leases.get(holder); return leases.get(holder);
@ -467,6 +488,7 @@ synchronized boolean checkLeases() {
Long[] leaseINodeIds = files.toArray(new Long[files.size()]); Long[] leaseINodeIds = files.toArray(new Long[files.size()]);
FSDirectory fsd = fsnamesystem.getFSDirectory(); FSDirectory fsd = fsnamesystem.getFSDirectory();
String p = null; String p = null;
String newHolder = getInternalLeaseHolder();
for(Long id : leaseINodeIds) { for(Long id : leaseINodeIds) {
try { try {
INodesInPath iip = INodesInPath.fromINode(fsd.getInode(id)); INodesInPath iip = INodesInPath.fromINode(fsd.getInode(id));
@ -478,8 +500,7 @@ synchronized boolean checkLeases() {
boolean completed = false; boolean completed = false;
try { try {
completed = fsnamesystem.internalReleaseLease( completed = fsnamesystem.internalReleaseLease(
leaseToCheck, p, iip, leaseToCheck, p, iip, newHolder);
HdfsServerConstants.NAMENODE_LEASE_HOLDER);
} catch (IOException e) { } catch (IOException e) {
LOG.warn("Cannot release the path " + p + " in the lease " LOG.warn("Cannot release the path " + p + " in the lease "
+ leaseToCheck + ". It will be retried.", e); + leaseToCheck + ". It will be retried.", e);

View File

@ -465,7 +465,8 @@ public void hardLeaseRecoveryRestartHelper(boolean doRename, int size)
cluster.getNameNode(), fileStr); cluster.getNameNode(), fileStr);
assertFalse("original lease holder should not be the NN", assertFalse("original lease holder should not be the NN",
originalLeaseHolder.equals(HdfsServerConstants.NAMENODE_LEASE_HOLDER)); originalLeaseHolder.startsWith(
HdfsServerConstants.NAMENODE_LEASE_HOLDER));
// hflush file // hflush file
AppendTestUtil.LOG.info("hflush"); AppendTestUtil.LOG.info("hflush");
@ -501,8 +502,9 @@ public void hardLeaseRecoveryRestartHelper(boolean doRename, int size)
GenericTestUtils.waitFor(new Supplier<Boolean>() { GenericTestUtils.waitFor(new Supplier<Boolean>() {
@Override @Override
public Boolean get() { public Boolean get() {
return HdfsServerConstants.NAMENODE_LEASE_HOLDER.equals( String holder =
NameNodeAdapter.getLeaseHolderForPath(cluster.getNameNode(), path)); NameNodeAdapter.getLeaseHolderForPath(cluster.getNameNode(), path);
return holder.startsWith(HdfsServerConstants.NAMENODE_LEASE_HOLDER);
} }
}, (int)SHORT_LEASE_PERIOD, (int)SHORT_LEASE_PERIOD * 10); }, (int)SHORT_LEASE_PERIOD, (int)SHORT_LEASE_PERIOD * 10);
@ -563,8 +565,8 @@ static void checkLease(String f, int size) {
if (size == 0) { if (size == 0) {
assertEquals("lease holder should null, file is closed", null, holder); assertEquals("lease holder should null, file is closed", null, holder);
} else { } else {
assertEquals("lease holder should now be the NN", assertTrue("lease holder should now be the NN",
HdfsServerConstants.NAMENODE_LEASE_HOLDER, holder); holder.startsWith(HdfsServerConstants.NAMENODE_LEASE_HOLDER));
} }
} }

View File

@ -642,7 +642,7 @@ public void testTruncateFailure() throws IOException {
String leaseHolder = String leaseHolder =
NameNodeAdapter.getLeaseHolderForPath(cluster.getNameNode(), NameNodeAdapter.getLeaseHolderForPath(cluster.getNameNode(),
p.toUri().getPath()); p.toUri().getPath());
if(leaseHolder.equals(HdfsServerConstants.NAMENODE_LEASE_HOLDER)) { if(leaseHolder.startsWith(HdfsServerConstants.NAMENODE_LEASE_HOLDER)) {
recoveryTriggered = true; recoveryTriggered = true;
break; break;
} }

View File

@ -19,6 +19,7 @@
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -99,6 +100,19 @@ public void testCheckLease() throws InterruptedException {
assertTrue(lm.countLease() < numLease); assertTrue(lm.countLease() < numLease);
} }
/**
* Test whether the internal lease holder name is updated properly.
*/
@Test
public void testInternalLeaseHolder() throws Exception {
LeaseManager lm = new LeaseManager(makeMockFsNameSystem());
// Set the hard lease limit to 500ms.
lm.setLeasePeriod(100L, 500L);
String holder = lm.getInternalLeaseHolder();
Thread.sleep(1000);
assertNotEquals(holder, lm.getInternalLeaseHolder());
}
@Test @Test
public void testCountPath() { public void testCountPath() {
LeaseManager lm = new LeaseManager(makeMockFsNameSystem()); LeaseManager lm = new LeaseManager(makeMockFsNameSystem());