You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by si...@apache.org on 2012/06/06 18:13:56 UTC

svn commit: r1346966 - in /zookeeper/bookkeeper/trunk: CHANGES.txt bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java

Author: sijie
Date: Wed Jun  6 16:13:56 2012
New Revision: 1346966

URL: http://svn.apache.org/viewvc?rev=1346966&view=rev
Log:
BOOKKEEPER-287: NoSuchElementException in LedgerCacheImpl (sijie)

Modified:
    zookeeper/bookkeeper/trunk/CHANGES.txt
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java

Modified: zookeeper/bookkeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/CHANGES.txt?rev=1346966&r1=1346965&r2=1346966&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/CHANGES.txt (original)
+++ zookeeper/bookkeeper/trunk/CHANGES.txt Wed Jun  6 16:13:56 2012
@@ -140,6 +140,8 @@ Release 4.1.0 - 2012-05-31
 
         BOOKKEEPER-286: Compilation warning (ivank via sijie)
 
+        BOOKKEEPER-287: NoSuchElementException in LedgerCacheImpl (sijie)
+
       hedwig-client/
 
         BOOKKEEPER-217: NPE in hedwig client when enable DEBUG (sijie via ivank)

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java?rev=1346966&r1=1346965&r2=1346966&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java Wed Jun  6 16:13:56 2012
@@ -176,7 +176,7 @@ public class LedgerCacheImpl implements 
             }   
         } catch (IOException ie) {
             // if we grab a clean page, but failed to update the page
-            // we are exhuasting the count of ledger entry pages.
+            // we are exhausting the count of ledger entry pages.
             // since this page will be never used, so we need to decrement
             // page count of ledger cache.
             lep.releasePage();
@@ -317,7 +317,7 @@ public class LedgerCacheImpl implements 
                 if (!doAll) {
                     break;
                 }
-                // Yeild. if we are doing all the ledgers we don't want to block other flushes that
+                // Yield. if we are doing all the ledgers we don't want to block other flushes that
                 // need to happen
                 try {
                     dirtyLedgers.wait(1);
@@ -449,22 +449,22 @@ public class LedgerCacheImpl implements 
         if (entry % entriesPerPage != 0) {
             throw new IllegalArgumentException(entry + " is not a multiple of " + entriesPerPage);
         }
-        synchronized(this) {
-            if (pageCount  < pageLimit) {
-                // let's see if we can allocate something
-                LedgerEntryPage lep = new LedgerEntryPage(pageSize, entriesPerPage);
-                lep.setLedger(ledger);
-                lep.setFirstEntry(entry);
-
-                // note, this will not block since it is a new page
-                lep.usePage();
-                pageCount++;
-                return lep;
-            }
-        }
-
         outerLoop:
         while(true) {
+            synchronized(this) {
+                if (pageCount  < pageLimit) {
+                    // let's see if we can allocate something
+                    LedgerEntryPage lep = new LedgerEntryPage(pageSize, entriesPerPage);
+                    lep.setLedger(ledger);
+                    lep.setFirstEntry(entry);
+
+                    // note, this will not block since it is a new page
+                    lep.usePage();
+                    pageCount++;
+                    return lep;
+                }
+            }
+
             synchronized(cleanLedgers) {
                 if (cleanLedgers.isEmpty()) {
                     flushLedger(false);
@@ -475,6 +475,14 @@ public class LedgerCacheImpl implements 
                     }
                 }
                 synchronized(this) {
+                    // if ledgers deleted between checking pageCount and putting
+                    // ledgers into cleanLedgers list, the cleanLedgers list would be empty.
+                    // so give it a chance to go back to check pageCount again because
+                    // deleteLedger would decrement pageCount to return the number of pages
+                    // occupied by deleted ledgers.
+                    if (cleanLedgers.isEmpty()) {
+                        continue outerLoop;
+                    }
                     Long cleanLedger = cleanLedgers.getFirst();
                     Map<Long, LedgerEntryPage> map = pages.get(cleanLedger);
                     while (map == null || map.isEmpty()) {
@@ -610,7 +618,13 @@ public class LedgerCacheImpl implements 
 
         // remove pages first to avoid page flushed when deleting file info
         synchronized(this) {
-            pages.remove(ledgerId);
+            Map<Long, LedgerEntryPage> lpages = pages.remove(ledgerId);
+            if (null != lpages) {
+                pageCount -= lpages.size();
+                if (pageCount < 0) {
+                    LOG.error("Page count of ledger cache has been decremented to be less than zero.");
+                }
+            }
         }
         // Delete the ledger's index file and close the FileInfo
         FileInfo fi = null;

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java?rev=1346966&r1=1346965&r2=1346966&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java Wed Jun  6 16:13:56 2012
@@ -126,6 +126,41 @@ public class LedgerCacheTest extends Tes
     }
 
     @Test
+    public void testDeleteLedger() throws Exception {
+        int numEntries = 10;
+        // limit open files & pages
+        conf.setOpenFileLimit(999).setPageLimit(2)
+            .setPageSize(8 * numEntries);
+        // create ledger cache
+        newLedgerCache();
+        try {
+            int numLedgers = 2;
+            byte[] masterKey = "blah".getBytes();
+            for (int i=1; i<=numLedgers; i++) {
+                ledgerCache.setMasterKey((long)i, masterKey);
+                for (int j=0; j<numEntries; j++) {
+                    ledgerCache.putEntryOffset(i, j, i*numEntries + j);
+                }
+            }
+            // ledger cache is exhausted
+            // delete ledgers
+            for (int i=1; i<=numLedgers; i++) {
+                ledgerCache.deleteLedger((long)i);
+            }
+            // create num ledgers to add entries
+            for (int i=numLedgers+1; i<=2*numLedgers; i++) {
+                ledgerCache.setMasterKey((long)i, masterKey);
+                for (int j=0; j<numEntries; j++) {
+                    ledgerCache.putEntryOffset(i, j, i*numEntries + j);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Got Exception.", e);
+            fail("Failed to add entry.");
+        }
+    }
+
+    @Test
     public void testPageEviction() throws Exception {
         int numLedgers = 10;
         byte[] masterKey = "blah".getBytes();