HDFS-6057. DomainSocketWatcher.watcherThread should be marked as a daemon thread (cmccabe)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1574789 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Colin McCabe 2014-03-06 08:01:41 +00:00
parent 94ac5ba669
commit 6f2dd3a25a
5 changed files with 92 additions and 16 deletions

View File

@ -235,6 +235,7 @@ public final class DomainSocketWatcher implements Closeable {
Preconditions.checkArgument(interruptCheckPeriodMs > 0); Preconditions.checkArgument(interruptCheckPeriodMs > 0);
this.interruptCheckPeriodMs = interruptCheckPeriodMs; this.interruptCheckPeriodMs = interruptCheckPeriodMs;
notificationSockets = DomainSocket.socketpair(); notificationSockets = DomainSocket.socketpair();
watcherThread.setDaemon(true);
watcherThread.start(); watcherThread.start();
} }
@ -263,6 +264,16 @@ public final class DomainSocketWatcher implements Closeable {
Uninterruptibles.joinUninterruptibly(watcherThread); Uninterruptibles.joinUninterruptibly(watcherThread);
} }
@VisibleForTesting
public boolean isClosed() {
lock.lock();
try {
return closed;
} finally {
lock.unlock();
}
}
/** /**
* Add a socket. * Add a socket.
* *
@ -274,7 +285,11 @@ public final class DomainSocketWatcher implements Closeable {
public void add(DomainSocket sock, Handler handler) { public void add(DomainSocket sock, Handler handler) {
lock.lock(); lock.lock();
try { try {
checkNotClosed(); if (closed) {
handler.handle(sock);
IOUtils.cleanup(LOG, sock);
return;
}
Entry entry = new Entry(sock, handler); Entry entry = new Entry(sock, handler);
try { try {
sock.refCount.reference(); sock.refCount.reference();
@ -295,7 +310,6 @@ public final class DomainSocketWatcher implements Closeable {
if (!toAdd.contains(entry)) { if (!toAdd.contains(entry)) {
break; break;
} }
checkNotClosed();
} }
} finally { } finally {
lock.unlock(); lock.unlock();
@ -310,7 +324,7 @@ public final class DomainSocketWatcher implements Closeable {
public void remove(DomainSocket sock) { public void remove(DomainSocket sock) {
lock.lock(); lock.lock();
try { try {
checkNotClosed(); if (closed) return;
toRemove.put(sock.fd, sock); toRemove.put(sock.fd, sock);
kick(); kick();
while (true) { while (true) {
@ -322,7 +336,6 @@ public final class DomainSocketWatcher implements Closeable {
if (!toRemove.containsKey(sock.fd)) { if (!toRemove.containsKey(sock.fd)) {
break; break;
} }
checkNotClosed();
} }
} finally { } finally {
lock.unlock(); lock.unlock();
@ -342,17 +355,6 @@ public final class DomainSocketWatcher implements Closeable {
} }
} }
/**
* Check that the DomainSocketWatcher is not closed.
* Must be called while holding the lock.
*/
private void checkNotClosed() {
Preconditions.checkState(lock.isHeldByCurrentThread());
if (closed) {
throw new RuntimeException("DomainSocketWatcher is closed.");
}
}
private void sendCallback(String caller, TreeMap<Integer, Entry> entries, private void sendCallback(String caller, TreeMap<Integer, Entry> entries,
FdSet fdSet, int fd) { FdSet fdSet, int fd) {
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {

View File

@ -303,6 +303,9 @@ Release 2.4.0 - UNRELEASED
HDFS-5898. Allow NFS gateway to login/relogin from its kerberos keytab. HDFS-5898. Allow NFS gateway to login/relogin from its kerberos keytab.
(Abin Shahab via atm) (Abin Shahab via atm)
HDFS-6057. DomainSocketWatcher.watcherThread should be marked as daemon
thread (cmccabe)
BREAKDOWN OF HDFS-5698 SUBTASKS AND RELATED JIRAS BREAKDOWN OF HDFS-5698 SUBTASKS AND RELATED JIRAS
HDFS-5717. Save FSImage header in protobuf. (Haohui Mai via jing9) HDFS-5717. Save FSImage header in protobuf. (Haohui Mai via jing9)

View File

@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -59,7 +60,7 @@ import org.apache.hadoop.classification.InterfaceAudience;
* See {@link ShortCircuitRegistry} for more information on the communication protocol. * See {@link ShortCircuitRegistry} for more information on the communication protocol.
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
public class DfsClientShmManager { public class DfsClientShmManager implements Closeable {
private static final Log LOG = LogFactory.getLog(DfsClientShmManager.class); private static final Log LOG = LogFactory.getLog(DfsClientShmManager.class);
/** /**
@ -225,6 +226,12 @@ public class DfsClientShmManager {
Slot allocSlot(DomainPeer peer, MutableBoolean usedPeer, Slot allocSlot(DomainPeer peer, MutableBoolean usedPeer,
String clientName, ExtendedBlockId blockId) throws IOException { String clientName, ExtendedBlockId blockId) throws IOException {
while (true) { while (true) {
if (closed) {
if (LOG.isTraceEnabled()) {
LOG.trace(this + ": the DfsClientShmManager has been closed.");
}
return null;
}
if (disabled) { if (disabled) {
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace(this + ": shared memory segment access is disabled."); LOG.trace(this + ": shared memory segment access is disabled.");
@ -374,6 +381,8 @@ public class DfsClientShmManager {
} }
} }
private boolean closed = false;
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
/** /**
@ -409,6 +418,10 @@ public class DfsClientShmManager {
String clientName) throws IOException { String clientName) throws IOException {
lock.lock(); lock.lock();
try { try {
if (closed) {
LOG.trace(this + ": the DfsClientShmManager isclosed.");
return null;
}
EndpointShmManager shmManager = datanodes.get(datanode); EndpointShmManager shmManager = datanodes.get(datanode);
if (shmManager == null) { if (shmManager == null) {
shmManager = new EndpointShmManager(datanode); shmManager = new EndpointShmManager(datanode);
@ -466,9 +479,32 @@ public class DfsClientShmManager {
} }
} }
/**
* Close the DfsClientShmManager.
*/
@Override
public void close() throws IOException {
lock.lock();
try {
if (closed) return;
closed = true;
} finally {
lock.unlock();
}
// When closed, the domainSocketWatcher will issue callbacks that mark
// all the outstanding DfsClientShm segments as stale.
IOUtils.cleanup(LOG, domainSocketWatcher);
}
@Override @Override
public String toString() { public String toString() {
return String.format("ShortCircuitShmManager(%08x)", return String.format("ShortCircuitShmManager(%08x)",
System.identityHashCode(this)); System.identityHashCode(this));
} }
@VisibleForTesting
public DomainSocketWatcher getDomainSocketWatcher() {
return domainSocketWatcher;
}
} }

View File

@ -887,6 +887,7 @@ public class ShortCircuitCache implements Closeable {
/** /**
* Close the cache and free all associated resources. * Close the cache and free all associated resources.
*/ */
@Override
public void close() { public void close() {
try { try {
lock.lock(); lock.lock();
@ -911,6 +912,7 @@ public class ShortCircuitCache implements Closeable {
} finally { } finally {
lock.unlock(); lock.unlock();
} }
IOUtils.cleanup(LOG, shmManager);
} }
@VisibleForTesting // ONLY for testing @VisibleForTesting // ONLY for testing

View File

@ -376,4 +376,37 @@ public class TestBlockReaderFactory {
Assert.assertEquals(null, cache.getDfsClientShmManager()); Assert.assertEquals(null, cache.getDfsClientShmManager());
cluster.shutdown(); cluster.shutdown();
} }
/**
* Test shutting down the ShortCircuitCache while there are things in it.
*/
@Test
public void testShortCircuitCacheShutdown() throws Exception {
TemporarySocketDirectory sockDir = new TemporarySocketDirectory();
Configuration conf = createShortCircuitConf(
"testShortCircuitCacheShutdown", sockDir);
conf.set(DFS_CLIENT_CONTEXT, "testShortCircuitCacheShutdown");
Configuration serverConf = new Configuration(conf);
DFSInputStream.tcpReadsDisabledForTesting = true;
final MiniDFSCluster cluster =
new MiniDFSCluster.Builder(serverConf).numDataNodes(1).build();
cluster.waitActive();
final DistributedFileSystem fs =
(DistributedFileSystem)FileSystem.get(cluster.getURI(0), conf);
final String TEST_FILE = "/test_file";
final int TEST_FILE_LEN = 4000;
final int SEED = 0xFADEC;
DFSTestUtil.createFile(fs, new Path(TEST_FILE), TEST_FILE_LEN,
(short)1, SEED);
byte contents[] = DFSTestUtil.readFileBuffer(fs, new Path(TEST_FILE));
byte expected[] = DFSTestUtil.
calculateFileContentsFromSeed(SEED, TEST_FILE_LEN);
Assert.assertTrue(Arrays.equals(contents, expected));
final ShortCircuitCache cache =
fs.dfs.getClientContext().getShortCircuitCache();
cache.close();
Assert.assertTrue(cache.getDfsClientShmManager().
getDomainSocketWatcher().isClosed());
cluster.shutdown();
}
} }