Author: dhruba Date: Sat Jan 12 00:15:13 2008 New Revision: 611385 URL: http://svn.apache.org/viewvc?rev=611385&view=rev Log: HADOOP-2540. fsck reports missing blocks incorrectly. (dhruba)
Modified: lucene/hadoop/trunk/CHANGES.txt lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/FSNamesystem.java lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/NameNode.java lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/MiniDFSCluster.java lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/TestFileCreation.java Modified: lucene/hadoop/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/CHANGES.txt?rev=611385&r1=611384&r2=611385&view=diff ============================================================================== --- lucene/hadoop/trunk/CHANGES.txt (original) +++ lucene/hadoop/trunk/CHANGES.txt Sat Jan 12 00:15:13 2008 @@ -428,6 +428,8 @@ HADOOP-2562. globPaths supports {ab,cd}. (Hairong Kuang via dhruba) + HADOOP-2540. fsck reports missing blocks incorrectly. (dhruba) + Release 0.15.2 - 2008-01-02 BUG FIXES Modified: lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/FSNamesystem.java URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/FSNamesystem.java?rev=611385&r1=611384&r2=611385&view=diff ============================================================================== --- lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/FSNamesystem.java (original) +++ lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/FSNamesystem.java Sat Jan 12 00:15:13 2008 @@ -215,6 +215,9 @@ private long maxFsObjects = 0; // maximum number of fs objects + private long softLimit = LEASE_SOFTLIMIT_PERIOD; + private long hardLimit = LEASE_HARDLIMIT_PERIOD; + /** * FSNamesystem constructor. */ @@ -1115,7 +1118,7 @@ throw new LeaseExpiredException("No lease on " + src); } INodeFileUnderConstruction pendingFile = (INodeFileUnderConstruction)file; - if (!pendingFile.getClientName().equals(holder)) { + if (holder != null && !pendingFile.getClientName().equals(holder)) { throw new LeaseExpiredException("Lease mismatch on " + src + " owned by " + pendingFile.getClientName() + " but is accessed by " + holder); } @@ -1548,7 +1551,7 @@ * Returns true if the Hard Limit Timer has expired */ public boolean expiredHardLimit() { - if (now() - lastUpdate > LEASE_HARDLIMIT_PERIOD) { + if (now() - lastUpdate > hardLimit) { return true; } return false; @@ -1557,7 +1560,7 @@ * Returns true if the Soft Limit Timer has expired */ public boolean expiredSoftLimit() { - if (now() - lastUpdate > LEASE_SOFTLIMIT_PERIOD) { + if (now() - lastUpdate > softLimit) { return true; } return false; @@ -1704,7 +1707,7 @@ // will report this block as a missing block because no datanodes have it. // Delete this block. Block[] blocks = pendingFile.getBlocks(); - if (blocks != null && blocks.length > 1) { + if (blocks != null && blocks.length > 0) { Block last = blocks[blocks.length - 1]; if (last.getNumBytes() == 0) { pendingFile.removeBlock(last); @@ -3917,5 +3920,14 @@ */ long getMaxObjects() { return maxFsObjects; + } + + /** + * Used by unit tests to change lease periods + */ + void setLeasePeriod(long softLimit, long hardLimit) { + this.softLimit = softLimit; + this.hardLimit = hardLimit; + this.lmthread.interrupt(); } } Modified: lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/NameNode.java URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/NameNode.java?rev=611385&r1=611384&r2=611385&view=diff ============================================================================== --- lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/NameNode.java (original) +++ lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/NameNode.java Sat Jan 12 00:15:13 2008 @@ -85,7 +85,7 @@ public static final Log LOG = LogFactory.getLog("org.apache.hadoop.dfs.NameNode"); public static final Log stateChangeLog = LogFactory.getLog("org.apache.hadoop.dfs.StateChange"); - private FSNamesystem namesystem; + FSNamesystem namesystem; private Server server; private Thread emptier; private int handlerCount = 2; Modified: lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/MiniDFSCluster.java URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/MiniDFSCluster.java?rev=611385&r1=611384&r2=611385&view=diff ============================================================================== --- lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/MiniDFSCluster.java (original) +++ lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/MiniDFSCluster.java Sat Jan 12 00:15:13 2008 @@ -508,4 +508,11 @@ injectBlocks(i, blocksToInject[i]); } } + + /** + * Set the softLimit and hardLimit of client lease periods + */ + void setLeasePeriod(long soft, long hard) { + nameNode.namesystem.setLeasePeriod(soft, hard); + } } Modified: lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/TestFileCreation.java URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/TestFileCreation.java?rev=611385&r1=611384&r2=611385&view=diff ============================================================================== --- lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/TestFileCreation.java (original) +++ lucene/hadoop/trunk/src/test/org/apache/hadoop/dfs/TestFileCreation.java Sat Jan 12 00:15:13 2008 @@ -23,10 +23,8 @@ import java.util.Random; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FsShell; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; -import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.dfs.FSConstants.DatanodeReportType; @@ -47,16 +45,11 @@ // entire file is written, the first two blocks definitely get flushed to // the datanodes. - private static String TEST_ROOT_DIR = - new Path(System.getProperty("test.build.data","/tmp")) - .toString().replace(' ', '+'); - // // creates a file but does not close it // private FSDataOutputStream createFile(FileSystem fileSys, Path name, int repl) throws IOException { - // create and write a file that contains three blocks of data FSDataOutputStream stm = fileSys.create(name, true, fileSys.getConf().getInt("io.file.buffer.size", 4096), (short)repl, (long)blockSize); @@ -116,9 +109,9 @@ private void checkData(byte[] actual, int from, byte[] expected, String message) { for (int idx = 0; idx < actual.length; idx++) { - this.assertEquals(message+" byte "+(from+idx)+" differs. expected "+ - expected[from+idx]+" actual "+actual[idx], - expected[from+idx], actual[idx]); + assertEquals(message+" byte "+(from+idx)+" differs. expected "+ + expected[from+idx]+" actual "+actual[idx], + expected[from+idx], actual[idx]); actual[idx] = 0; } } @@ -262,6 +255,78 @@ locations.locatedBlockCount() == 0); } finally { fs.close(); + cluster.shutdown(); + } + } + + /** + * Test that the filesystem removes the last block from a file if its + * lease expires. + */ + public void testFileCreationError2() throws IOException { + long leasePeriod = 1000; + System.out.println("testFileCreationError2 start"); + Configuration conf = new Configuration(); + conf.setInt("heartbeat.recheck.interval", 1000); + conf.setInt("dfs.heartbeat.interval", 1); + if (simulatedStorage) { + conf.setBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, true); + } + // create cluster + MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null); + FileSystem fs = cluster.getFileSystem(); + cluster.waitActive(); + InetSocketAddress addr = new InetSocketAddress("localhost", + cluster.getNameNodePort()); + DFSClient client = new DFSClient(addr, conf); + + try { + + // create a new file. + // + Path file1 = new Path("/filestatus.dat"); + createFile(fs, file1, 1); + System.out.println("testFileCreationError2: " + + "Created file filestatus.dat with one " + + " replicas."); + + LocatedBlocks locations = client.namenode.getBlockLocations( + file1.toString(), 0, Long.MAX_VALUE); + System.out.println("The file has " + locations.locatedBlockCount() + + " blocks."); + + // add another block to the file + LocatedBlock location = client.namenode.addBlock(file1.toString(), + null); + System.out.println("Added block " + location.getBlock()); + + locations = client.namenode.getBlockLocations(file1.toString(), + 0, Long.MAX_VALUE); + System.out.println("The file now has " + locations.locatedBlockCount() + + " blocks."); + + // set the soft and hard limit to be 1 second so that the + // namenode triggers lease recovery + cluster.setLeasePeriod(leasePeriod, leasePeriod); + + // wait for the lease to expire + try { + Thread.sleep(5 * leasePeriod); + } catch (InterruptedException e) { + } + + // verify that the last block was cleaned up. + locations = client.namenode.getBlockLocations(file1.toString(), + 0, Long.MAX_VALUE); + System.out.println("locations = " + locations.locatedBlockCount()); + assertTrue("Error blocks were not cleaned up", + locations.locatedBlockCount() == 0); + System.out.println("testFileCreationError2 successful"); + } finally { + try { + fs.close(); + } catch (Exception e) { + } cluster.shutdown(); } }