HDFS-12140. Remove BPOfferService lock contention to get block pool id. Contributed by Daryn Sharp.
This commit is contained in:
parent
8d86a93915
commit
e7d187a1b6
|
@ -72,6 +72,7 @@ class BPOfferService {
|
||||||
volatile DatanodeRegistration bpRegistration;
|
volatile DatanodeRegistration bpRegistration;
|
||||||
|
|
||||||
private final String nameserviceId;
|
private final String nameserviceId;
|
||||||
|
private volatile String bpId;
|
||||||
private final DataNode dn;
|
private final DataNode dn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,6 +185,11 @@ class BPOfferService {
|
||||||
}
|
}
|
||||||
|
|
||||||
String getBlockPoolId(boolean quiet) {
|
String getBlockPoolId(boolean quiet) {
|
||||||
|
// avoid lock contention unless the registration hasn't completed.
|
||||||
|
String id = bpId;
|
||||||
|
if (id != null) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
readLock();
|
readLock();
|
||||||
try {
|
try {
|
||||||
if (bpNSInfo != null) {
|
if (bpNSInfo != null) {
|
||||||
|
@ -205,7 +211,7 @@ class BPOfferService {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasBlockPoolId() {
|
boolean hasBlockPoolId() {
|
||||||
return getNamespaceInfo() != null;
|
return getBlockPoolId(true) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
NamespaceInfo getNamespaceInfo() {
|
NamespaceInfo getNamespaceInfo() {
|
||||||
|
@ -217,6 +223,28 @@ class BPOfferService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
NamespaceInfo setNamespaceInfo(NamespaceInfo nsInfo) throws IOException {
|
||||||
|
writeLock();
|
||||||
|
try {
|
||||||
|
NamespaceInfo old = bpNSInfo;
|
||||||
|
if (bpNSInfo != null && nsInfo != null) {
|
||||||
|
checkNSEquality(bpNSInfo.getBlockPoolID(), nsInfo.getBlockPoolID(),
|
||||||
|
"Blockpool ID");
|
||||||
|
checkNSEquality(bpNSInfo.getNamespaceID(), nsInfo.getNamespaceID(),
|
||||||
|
"Namespace ID");
|
||||||
|
checkNSEquality(bpNSInfo.getClusterID(), nsInfo.getClusterID(),
|
||||||
|
"Cluster ID");
|
||||||
|
}
|
||||||
|
bpNSInfo = nsInfo;
|
||||||
|
// cache the block pool id for lock-free access.
|
||||||
|
bpId = (nsInfo != null) ? nsInfo.getBlockPoolID() : null;
|
||||||
|
return old;
|
||||||
|
} finally {
|
||||||
|
writeUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
readLock();
|
readLock();
|
||||||
|
@ -289,9 +317,10 @@ class BPOfferService {
|
||||||
private void checkBlock(ExtendedBlock block) {
|
private void checkBlock(ExtendedBlock block) {
|
||||||
Preconditions.checkArgument(block != null,
|
Preconditions.checkArgument(block != null,
|
||||||
"block is null");
|
"block is null");
|
||||||
Preconditions.checkArgument(block.getBlockPoolId().equals(getBlockPoolId()),
|
final String bpId = getBlockPoolId();
|
||||||
|
Preconditions.checkArgument(block.getBlockPoolId().equals(bpId),
|
||||||
"block belongs to BP %s instead of BP %s",
|
"block belongs to BP %s instead of BP %s",
|
||||||
block.getBlockPoolId(), getBlockPoolId());
|
block.getBlockPoolId(), bpId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//This must be called only by blockPoolManager
|
//This must be called only by blockPoolManager
|
||||||
|
@ -337,8 +366,7 @@ class BPOfferService {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.bpNSInfo == null) {
|
if (setNamespaceInfo(nsInfo) == null) {
|
||||||
this.bpNSInfo = nsInfo;
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
// Now that we know the namespace ID, etc, we can pass this to the DN.
|
// Now that we know the namespace ID, etc, we can pass this to the DN.
|
||||||
|
@ -352,16 +380,9 @@ class BPOfferService {
|
||||||
// The datanode failed to initialize the BP. We need to reset
|
// The datanode failed to initialize the BP. We need to reset
|
||||||
// the namespace info so that other BPService actors still have
|
// the namespace info so that other BPService actors still have
|
||||||
// a chance to set it, and re-initialize the datanode.
|
// a chance to set it, and re-initialize the datanode.
|
||||||
this.bpNSInfo = null;
|
setNamespaceInfo(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
checkNSEquality(bpNSInfo.getBlockPoolID(), nsInfo.getBlockPoolID(),
|
|
||||||
"Blockpool ID");
|
|
||||||
checkNSEquality(bpNSInfo.getNamespaceID(), nsInfo.getNamespaceID(),
|
|
||||||
"Namespace ID");
|
|
||||||
checkNSEquality(bpNSInfo.getClusterID(), nsInfo.getClusterID(),
|
|
||||||
"Cluster ID");
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
writeUnlock();
|
writeUnlock();
|
||||||
|
|
|
@ -225,6 +225,35 @@ public class TestBPOfferService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocklessBlockPoolId() throws Exception {
|
||||||
|
BPOfferService bpos = Mockito.spy(setupBPOSForNNs(mockNN1));
|
||||||
|
|
||||||
|
// bpNSInfo is not set, should take lock to check nsInfo.
|
||||||
|
assertNull(bpos.getBlockPoolId());
|
||||||
|
Mockito.verify(bpos).readLock();
|
||||||
|
|
||||||
|
// setting the bpNSInfo should cache the bp id, thus no locking.
|
||||||
|
Mockito.reset(bpos);
|
||||||
|
NamespaceInfo nsInfo = new NamespaceInfo(1, FAKE_CLUSTERID, FAKE_BPID, 0);
|
||||||
|
assertNull(bpos.setNamespaceInfo(nsInfo));
|
||||||
|
assertEquals(FAKE_BPID, bpos.getBlockPoolId());
|
||||||
|
Mockito.verify(bpos, Mockito.never()).readLock();
|
||||||
|
|
||||||
|
// clearing the bpNSInfo should clear the cached bp id, thus requiring
|
||||||
|
// locking to check the bpNSInfo.
|
||||||
|
Mockito.reset(bpos);
|
||||||
|
assertEquals(nsInfo, bpos.setNamespaceInfo(null));
|
||||||
|
assertNull(bpos.getBlockPoolId());
|
||||||
|
Mockito.verify(bpos).readLock();
|
||||||
|
|
||||||
|
// test setting it again.
|
||||||
|
Mockito.reset(bpos);
|
||||||
|
assertNull(bpos.setNamespaceInfo(nsInfo));
|
||||||
|
assertEquals(FAKE_BPID, bpos.getBlockPoolId());
|
||||||
|
Mockito.verify(bpos, Mockito.never()).readLock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that DNA_INVALIDATE commands from the standby are ignored.
|
* Test that DNA_INVALIDATE commands from the standby are ignored.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue