Return-Path: X-Original-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Delivered-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5B3FE6E10 for ; Tue, 12 Jul 2011 02:18:53 +0000 (UTC) Received: (qmail 10517 invoked by uid 500); 12 Jul 2011 02:18:53 -0000 Delivered-To: apmail-hadoop-hdfs-commits-archive@hadoop.apache.org Received: (qmail 10457 invoked by uid 500); 12 Jul 2011 02:18:52 -0000 Mailing-List: contact hdfs-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: hdfs-dev@hadoop.apache.org Delivered-To: mailing list hdfs-commits@hadoop.apache.org Received: (qmail 10447 invoked by uid 99); 12 Jul 2011 02:18:52 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Jul 2011 02:18:52 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Jul 2011 02:18:50 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 9610E23888FD; Tue, 12 Jul 2011 02:18:30 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1145428 - in /hadoop/common/trunk/hdfs: CHANGES.txt src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java Date: Tue, 12 Jul 2011 02:18:30 -0000 To: hdfs-commits@hadoop.apache.org From: atm@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110712021830.9610E23888FD@eris.apache.org> Author: atm Date: Tue Jul 12 02:18:30 2011 New Revision: 1145428 URL: http://svn.apache.org/viewvc?rev=1145428&view=rev Log: HDFS-2132. Potential resource leak in EditLogFileOutputStream.close. (atm) Modified: hadoop/common/trunk/hdfs/CHANGES.txt hadoop/common/trunk/hdfs/src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java hadoop/common/trunk/hdfs/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java Modified: hadoop/common/trunk/hdfs/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hdfs/CHANGES.txt?rev=1145428&r1=1145427&r2=1145428&view=diff ============================================================================== --- hadoop/common/trunk/hdfs/CHANGES.txt (original) +++ hadoop/common/trunk/hdfs/CHANGES.txt Tue Jul 12 02:18:30 2011 @@ -818,6 +818,8 @@ Trunk (unreleased changes) reading only from a currently being written block. (John George via szetszwo) + HDFS-2132. Potential resource leak in EditLogFileOutputStream.close. (atm) + Release 0.22.0 - Unreleased INCOMPATIBLE CHANGES Modified: hadoop/common/trunk/hdfs/src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hdfs/src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java?rev=1145428&r1=1145427&r2=1145428&view=diff ============================================================================== --- hadoop/common/trunk/hdfs/src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java (original) +++ hadoop/common/trunk/hdfs/src/java/org/apache/hadoop/hdfs/server/namenode/EditLogFileOutputStream.java Tue Jul 12 02:18:30 2011 @@ -28,8 +28,11 @@ import java.util.zip.Checksum; import org.apache.hadoop.hdfs.protocol.FSConstants; import org.apache.hadoop.io.DataOutputBuffer; +import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.Writable; +import com.google.common.annotations.VisibleForTesting; + /** * An implementation of the abstract class {@link EditLogOutputStream}, which * stores edits in a local file. @@ -120,32 +123,41 @@ class EditLogFileOutputStream extends Ed @Override public void close() throws IOException { - // close should have been called after all pending transactions - // have been flushed & synced. - // if already closed, just skip - if(bufCurrent != null) - { - int bufSize = bufCurrent.size(); - if (bufSize != 0) { - throw new IOException("FSEditStream has " + bufSize - + " bytes still to be flushed and cannot " + "be closed."); + try { + // close should have been called after all pending transactions + // have been flushed & synced. + // if already closed, just skip + if(bufCurrent != null) + { + int bufSize = bufCurrent.size(); + if (bufSize != 0) { + throw new IOException("FSEditStream has " + bufSize + + " bytes still to be flushed and cannot " + "be closed."); + } + bufCurrent.close(); + bufCurrent = null; } - bufCurrent.close(); - bufCurrent = null; - } - - if(bufReady != null) { - bufReady.close(); - bufReady = null; - } - - // remove the last INVALID marker from transaction log. - if (fc != null && fc.isOpen()) { - fc.truncate(fc.position()); - fc.close(); - } - if (fp != null) { - fp.close(); + + if(bufReady != null) { + bufReady.close(); + bufReady = null; + } + + // remove the last INVALID marker from transaction log. + if (fc != null && fc.isOpen()) { + fc.truncate(fc.position()); + fc.close(); + fc = null; + } + if (fp != null) { + fp.close(); + fp = null; + } + } finally { + IOUtils.cleanup(FSNamesystem.LOG, bufCurrent, bufReady, fc, fp); + bufCurrent = bufReady = null; + fc = null; + fp = null; } } @@ -225,4 +237,14 @@ class EditLogFileOutputStream extends Ed File getFile() { return file; } + + @VisibleForTesting + public void setFileChannelForTesting(FileChannel fc) { + this.fc = fc; + } + + @VisibleForTesting + public FileChannel getFileChannelForTesting() { + return fc; + } } Modified: hadoop/common/trunk/hdfs/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hdfs/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java?rev=1145428&r1=1145427&r2=1145428&view=diff ============================================================================== --- hadoop/common/trunk/hdfs/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java (original) +++ hadoop/common/trunk/hdfs/src/test/hdfs/org/apache/hadoop/hdfs/server/namenode/TestEditLogFileOutputStream.java Tue Jul 12 02:18:30 2011 @@ -20,9 +20,11 @@ package org.apache.hadoop.hdfs.server.na import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.nio.channels.FileChannel; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.DU; @@ -31,6 +33,7 @@ import org.apache.hadoop.fs.permission.F import org.apache.hadoop.hdfs.HdfsConfiguration; import org.apache.hadoop.hdfs.MiniDFSCluster; import org.junit.Test; +import org.mockito.Mockito; public class TestEditLogFileOutputStream { @@ -58,5 +61,29 @@ public class TestEditLogFileOutputStream assertTrue("Edit log disk space used should be at least 257 blocks", 257 * 4096 <= new DU(editLog, conf).getUsed()); } + + @Test + public void testClose() throws IOException { + String errorMessage = "TESTING: fc.truncate() threw IOE"; + + File testDir = new File(System.getProperty("test.build.data", "/tmp")); + assertTrue("could not create test directory", testDir.exists() || testDir.mkdirs()); + File f = new File(testDir, "edits"); + assertTrue("could not create test file", f.createNewFile()); + EditLogFileOutputStream elos = new EditLogFileOutputStream(f, 0); + + FileChannel mockFc = Mockito.spy(elos.getFileChannelForTesting()); + Mockito.doThrow(new IOException(errorMessage)).when(mockFc).truncate(Mockito.anyLong()); + elos.setFileChannelForTesting(mockFc); + + try { + elos.close(); + fail("elos.close() succeeded, but should have thrown"); + } catch (IOException e) { + assertEquals("wrong IOE thrown from elos.close()", e.getMessage(), errorMessage); + } + + assertEquals("fc was not nulled when elos.close() failed", elos.getFileChannelForTesting(), null); + } }