You are viewing a plain text version of this content. The canonical link for it is here.
Posted to hdfs-commits@hadoop.apache.org by to...@apache.org on 2010/06/15 18:18:55 UTC
svn commit: r954947 - in /hadoop/hdfs/trunk: CHANGES.txt
src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java
Author: tomwhite
Date: Tue Jun 15 16:18:55 2010
New Revision: 954947
URL: http://svn.apache.org/viewvc?rev=954947&view=rev
Log:
HDFS-1170. Add more assertions to TestLargeDirectoryDelete. Contributed by Steve Loughran.
Modified:
hadoop/hdfs/trunk/CHANGES.txt
hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java
Modified: hadoop/hdfs/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/CHANGES.txt?rev=954947&r1=954946&r2=954947&view=diff
==============================================================================
--- hadoop/hdfs/trunk/CHANGES.txt (original)
+++ hadoop/hdfs/trunk/CHANGES.txt Tue Jun 15 16:18:55 2010
@@ -597,6 +597,9 @@ Release 0.21.0 - Unreleased
HDFS-1181. Move configuration and script files post split. (tomwhite)
+ HDFS-1170. Add more assertions to TestLargeDirectoryDelete.
+ (Steve Loughran via tomwhite)
+
OPTIMIZATIONS
HDFS-946. NameNode should not return full path name when lisitng a
Modified: hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java?rev=954947&r1=954946&r2=954947&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java (original)
+++ hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestLargeDirectoryDelete.java Tue Jun 15 16:18:55 2010
@@ -74,20 +74,25 @@ public class TestLargeDirectoryDelete {
}
private int getBlockCount() {
- return (int)mc.getNamesystem().getBlocksTotal();
+ Assert.assertNotNull("Null cluster", mc);
+ Assert.assertNotNull("No Namenode in cluster", mc.getNameNode());
+ FSNamesystem namesystem = mc.getNamesystem();
+ Assert.assertNotNull("Null Namesystem in cluster", namesystem);
+ Assert.assertNotNull("Null Namesystem.blockmanager", namesystem.blockManager);
+ return (int) namesystem.getBlocksTotal();
}
/** Run multiple threads doing simultaneous operations on the namenode
* while a large directory is being deleted.
*/
- private void runThreads() throws IOException {
- final Thread threads[] = new Thread[2];
+ private void runThreads() throws Throwable {
+ final TestThread threads[] = new TestThread[2];
// Thread for creating files
- threads[0] = new Thread() {
+ threads[0] = new TestThread() {
@Override
- public void run() {
- while(true) {
+ protected void execute() throws Throwable {
+ while(live) {
try {
int blockcount = getBlockCount();
if (blockcount < TOTAL_BLOCKS && blockcount > 0) {
@@ -105,10 +110,10 @@ public class TestLargeDirectoryDelete {
};
// Thread that periodically acquires the FSNamesystem lock
- threads[1] = new Thread() {
+ threads[1] = new TestThread() {
@Override
- public void run() {
- while(true) {
+ protected void execute() throws Throwable {
+ while(live) {
try {
int blockcount = getBlockCount();
if (blockcount < TOTAL_BLOCKS && blockcount > 0) {
@@ -131,19 +136,79 @@ public class TestLargeDirectoryDelete {
FSNamesystem.BLOCK_DELETION_INCREMENT = 1;
mc.getFileSystem().delete(new Path("/root"), true); // recursive delete
final long end = System.currentTimeMillis();
- threads[0].interrupt();
- threads[1].interrupt();
+ threads[0].endThread();
+ threads[1].endThread();
LOG.info("Deletion took " + (end - start) + "msecs");
LOG.info("createOperations " + createOps);
LOG.info("lockOperations " + lockOps);
Assert.assertTrue(lockOps + createOps > 0);
+ threads[0].rethrow();
+ threads[1].rethrow();
+ }
+
+
+ /**
+ * An abstract class for tests that catches exceptions and can
+ * rethrow them on a different thread, and has an {@link #endThread()}
+ * operation that flips a volatile boolean before interrupting the thread.
+ * Also: after running the implementation of {@link #execute()} in the
+ * implementation class, the thread is notified: other threads can wait
+ * for it to terminate
+ */
+ private abstract class TestThread extends Thread {
+ volatile Throwable thrown;
+ protected volatile boolean live = true;
+
+ @Override
+ public void run() {
+ try {
+ execute();
+ } catch (Throwable throwable) {
+ LOG.warn(throwable);
+ setThrown(throwable);
+ } finally {
+ synchronized (this) {
+ this.notify();
+ }
+ }
+ }
+
+ protected abstract void execute() throws Throwable;
+
+ protected synchronized void setThrown(Throwable thrown) {
+ this.thrown = thrown;
+ }
+
+ /**
+ * Rethrow anything caught
+ * @throws Throwable any non-null throwable raised by the execute method.
+ */
+ public synchronized void rethrow() throws Throwable {
+ if (thrown != null) {
+ throw thrown;
+ }
+ }
+
+ /**
+ * End the thread by setting the live p
+ */
+ public synchronized void endThread() {
+ live = false;
+ interrupt();
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ LOG.debug("Ignoring " + e, e);
+ }
+ }
}
@Test
- public void largeDelete() throws IOException, InterruptedException {
+ public void largeDelete() throws Throwable {
mc = new MiniDFSCluster(CONF, 1, true, null);
try {
mc.waitActive();
+ Assert.assertNotNull("No Namenode in cluster", mc.getNameNode());
createFiles();
Assert.assertEquals(TOTAL_BLOCKS, getBlockCount());
runThreads();