You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by fp...@apache.org on 2012/12/10 11:04:19 UTC

svn commit: r1419311 - in /zookeeper/bookkeeper/trunk: CHANGES.txt bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java

Author: fpj
Date: Mon Dec 10 10:04:18 2012
New Revision: 1419311

URL: http://svn.apache.org/viewvc?rev=1419311&view=rev
Log:
BOOKKEEPER-465: CreateNewLog may overwrite lastLogId with smaller value (yixue, fpj via fpj)


Added:
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
Modified:
    zookeeper/bookkeeper/trunk/CHANGES.txt
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java

Modified: zookeeper/bookkeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/CHANGES.txt?rev=1419311&r1=1419310&r2=1419311&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/CHANGES.txt (original)
+++ zookeeper/bookkeeper/trunk/CHANGES.txt Mon Dec 10 10:04:18 2012
@@ -128,6 +128,8 @@ Trunk (unreleased changes)
 
 	BOOKKEEPER-474:  BookieReadWriteTest#testShutdown doesn't make sense (ivank via fpj)
 
+	BOOKKEEPER-465: CreateNewLog may overwrite lastLogId with smaller value (yixue, fpj via fpj)
+
       hedwig-protocol:
 
         BOOKKEEPER-394: CompositeException message is not useful (Stu Hood via sijie)

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java?rev=1419311&r1=1419310&r2=1419311&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java Mon Dec 10 10:04:18 2012
@@ -63,6 +63,7 @@ public class EntryLogger {
     private AtomicBoolean shouldCreateNewEntryLog = new AtomicBoolean(false);
 
     private long logId;
+
     /**
      * The maximum size of a entry logger file.
      */
@@ -121,6 +122,7 @@ public class EntryLogger {
         // so there can be race conditions when entry logs are rolled over and
         // this header buffer is cleared before writing it into the new logChannel.
         LOGFILE_HEADER.put("BKLO".getBytes());
+
         // Find the largest logId
         logId = -1;
         for (File dir : ledgerDirsManager.getAllLedgerDirs()) {
@@ -190,28 +192,28 @@ public class EntryLogger {
         }
 
         // It would better not to overwrite existing entry log files
-        File newLogFile = null;
+        String logFileName = null;
         do {
-            String logFileName = Long.toHexString(++logId) + ".log";
-            File dir = ledgerDirsManager.pickRandomWritableDir();
-            newLogFile = new File(dir, logFileName);
-            currentDir = dir;
-            if (newLogFile.exists()) {
-                LOG.warn("Found existed entry log " + newLogFile
-                        + " when trying to create it as a new log.");
-                newLogFile = null;
-                continue;
+            logFileName = Long.toHexString(++logId) + ".log";
+            for (File dir : ledgerDirsManager.getAllLedgerDirs()) {
+                File newLogFile = new File(dir, logFileName);
+                if (newLogFile.exists()) {
+                    LOG.warn("Found existed entry log " + newLogFile
+                           + " when trying to create it as a new log.");
+                    logFileName = null;
+                    break;
+                }
             }
-        } while (newLogFile == null);
+        } while (logFileName == null);
 
+        // Update last log id first
+        currentDir = ledgerDirsManager.pickRandomWritableDir();
+        setLastLogId(currentDir, logId);
+
+        File newLogFile = new File(currentDir, logFileName);
         logChannel = new BufferedChannel(new RandomAccessFile(newLogFile, "rw").getChannel(), 64*1024);
         logChannel.write((ByteBuffer) LOGFILE_HEADER.clear());
         channels.put(logId, logChannel);
-
-        List<File> listOfDirs = ledgerDirsManager.getWritableLedgerDirs();
-        for (File f : listOfDirs) {
-            setLastLogId(f, logId);
-        }
     }
 
     /**

Added: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java?rev=1419311&view=auto
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java (added)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java Mon Dec 10 10:04:18 2012
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.bookkeeper.bookie;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.bookkeeper.conf.ServerConfiguration;
+
+import org.junit.Test;
+import org.junit.After;
+import org.junit.Before;
+import junit.framework.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CreateNewLogTest {
+    private static final Logger LOG = LoggerFactory
+    .getLogger(CreateNewLogTest.class);
+        
+    private String[] ledgerDirs; 
+    private int numDirs = 100;
+    
+    @Before
+    public void setUp() throws Exception{
+        ledgerDirs = new String[numDirs];
+        for(int i = 0; i < numDirs; i++){
+            File temp = File.createTempFile("bookie", "test");
+            temp.delete();
+            temp.mkdir();
+            File currentTemp = new File(temp.getAbsoluteFile() + "/current");
+            currentTemp.mkdir();
+            ledgerDirs[i] = temp.getPath();
+        }        
+    }
+    
+    @After
+    public void tearDown() throws Exception{
+        for(int i = 0; i < numDirs; i++){
+            File f = new File(ledgerDirs[i]);
+            deleteRecursive(f);
+        }
+    }
+    
+    private void deleteRecursive(File f) {
+        if (f.isDirectory()){
+            for (File c : f.listFiles()){
+                deleteRecursive(c);
+            }
+        }
+        
+        f.delete();
+    }
+    
+    /**
+     * Checks if new log file id is verified against all directories.
+     * 
+     * {@link https://issues.apache.org/jira/browse/BOOKKEEPER-465}
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testCreateNewLog() throws Exception {
+        ServerConfiguration conf = new ServerConfiguration();
+                     
+        // Creating a new configuration with a number of 
+        // ledger directories.
+        conf.setLedgerDirNames(ledgerDirs);
+        LedgerDirsManager ledgerDirsManager = new LedgerDirsManager(conf);
+        EntryLogger el = new EntryLogger(conf, ledgerDirsManager);
+        
+        // Extracted from createNewLog()
+        String logFileName = Long.toHexString(1) + ".log";
+        File dir = ledgerDirsManager.pickRandomWritableDir();
+        LOG.info("Picked this directory: " + dir);
+        File newLogFile = new File(dir, logFileName);
+        newLogFile.createNewFile();
+        
+        // Calls createNewLog, and with the number of directories we
+        // are using, if it picks one at random it will fail.
+        el.createNewLog();
+        LOG.info("This is the current log id: " + el.getCurrentLogId());
+        Assert.assertTrue("Wrong log id", el.getCurrentLogId() > 1);
+    }
+
+}
\ No newline at end of file