Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

BOOKKEEPER-287: NoSuchElementException in LedgerCacheImpl (sijie)

git-svn-id: https://svn.apache.org/repos/asf/zookeeper/bookkeeper/trunk@1346966 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
commit d5caab3aae143352f2d8c3faea71dce11fdb6b45 1 parent 25552d9
@sijie sijie authored
View
2  CHANGES.txt
@@ -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)
View
46 bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerCacheImpl.java
@@ -176,7 +176,7 @@ private LedgerEntryPage grabLedgerEntryPage(long ledger, long pageEntry) throws
}
} 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 void flushLedger(boolean doAll) throws IOException {
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 @@ private LedgerEntryPage grabCleanPage(long ledger, long entry) throws IOExceptio
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);
+ 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;
+ // note, this will not block since it is a new page
+ lep.usePage();
+ pageCount++;
+ return lep;
+ }
}
- }
- outerLoop:
- while(true) {
synchronized(cleanLedgers) {
if (cleanLedgers.isEmpty()) {
flushLedger(false);
@@ -475,6 +475,14 @@ private LedgerEntryPage grabCleanPage(long ledger, long entry) throws IOExceptio
}
}
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 void deleteLedger(long ledgerId) throws IOException {
// 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;
View
35 bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java
@@ -126,6 +126,41 @@ public void testLedgerEviction() throws Exception {
}
@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();
Please sign in to comment.
Something went wrong with that request. Please try again.