From 33780ef35976d4c09a74bbf0040e0be72d29608e Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 28 Mar 2011 14:27:19 +0000 Subject: [PATCH] - Fix FLB full check - Cache FLB - FLB logging, cleanups, checks --- .../net/metanotion/io/block/BlockFile.java | 46 ++++++++++++++----- .../metanotion/io/block/FreeListBlock.java | 21 +++++++-- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/core/java/src/net/metanotion/io/block/BlockFile.java b/core/java/src/net/metanotion/io/block/BlockFile.java index 71710fd87..74b8f723c 100644 --- a/core/java/src/net/metanotion/io/block/BlockFile.java +++ b/core/java/src/net/metanotion/io/block/BlockFile.java @@ -71,7 +71,7 @@ public class BlockFile { public static final long OFFSET_MOUNTED = 20; public static final Log log = I2PAppContext.getGlobalContext().logManager().getLog(BlockFile.class); - public RandomAccessInterface file; + public final RandomAccessInterface file; private static final int MAJOR = 0x01; private static final int MINOR = 0x01; @@ -84,13 +84,16 @@ public class BlockFile { /** 2**32 pages of 1024 bytes each, more or less */ private static final long MAX_LEN = (2l << (32 + 10)) - 1; + /** new BlockFile length, containing a superblock page and a metaindex page. */ private long fileLen = PAGESIZE * 2; private int freeListStart = 0; private int mounted = 0; public int spanSize = 16; - private BSkipList metaIndex = null; - private HashMap openIndices = new HashMap(); + private BSkipList metaIndex; + /** cached list of free pages, only valid if freListStart > 0 */ + private FreeListBlock flb; + private final HashMap openIndices = new HashMap(); private void mount() throws IOException { file.seek(BlockFile.OFFSET_MOUNTED); @@ -268,7 +271,7 @@ public class BlockFile { if(init) { file.setLength(fileLen); writeSuperBlock(); - BSkipList.init(this, 2, spanSize); + BSkipList.init(this, METAINDEX_PAGE, spanSize); } readSuperBlock(); @@ -304,13 +307,20 @@ public class BlockFile { public int allocPage() throws IOException { if(freeListStart != 0) { try { - FreeListBlock flb = new FreeListBlock(file, freeListStart); + if (flb == null) + flb = new FreeListBlock(file, freeListStart); if(!flb.isEmpty()) { + if (log.shouldLog(Log.INFO)) + log.info("Alloc from " + flb); return flb.takePage(); } else { + if (log.shouldLog(Log.INFO)) + log.info("Alloc returning empty " + flb); freeListStart = flb.getNextPage(); writeSuperBlock(); - return flb.page; + int rv = flb.page; + flb = null; + return rv; } } catch (IOException ioe) { log.error("Discarding corrupt free list block page " + freeListStart, ioe); @@ -330,8 +340,8 @@ public class BlockFile { * Does not throw exceptions; logs on failure. */ public void freePage(int page) { - if (page < METAINDEX_PAGE) { - log.error("Negative page or superblock free attempt: " + page); + if (page <= METAINDEX_PAGE) { + log.error("Bad page free attempt: " + page); return; } try { @@ -339,29 +349,43 @@ public class BlockFile { freeListStart = page; FreeListBlock.initPage(file, page); writeSuperBlock(); + if (log.shouldLog(Log.INFO)) + log.info("Freed page " + page + " as new FLB"); return; } try { - FreeListBlock flb = new FreeListBlock(file, freeListStart); + if (flb == null) + flb = new FreeListBlock(file, freeListStart); if(flb.isFull()) { + // Make the free page a new FLB + if (log.shouldLog(Log.INFO)) + log.info("Full: " + flb); FreeListBlock.initPage(file, page); if(flb.getNextPage() == 0) { + // Put it at the tail. + // Next free will make a new FLB at the head, + // so we have one more FLB than we need. flb.setNextPage(page); - return; } else { + // Put it at the head flb = new FreeListBlock(file, page); flb.setNextPage(freeListStart); freeListStart = page; writeSuperBlock(); - return; } + if (log.shouldLog(Log.INFO)) + log.info("Freed page " + page + " to full " + flb); + return; } flb.addPage(page); + if (log.shouldLog(Log.INFO)) + log.info("Freed page " + page + " to " + flb); } catch (IOException ioe) { log.error("Discarding corrupt free list block page " + freeListStart, ioe); freeListStart = page; FreeListBlock.initPage(file, page); writeSuperBlock(); + flb = null; } } catch (IOException ioe) { log.error("Error freeing page: " + page, ioe); diff --git a/core/java/src/net/metanotion/io/block/FreeListBlock.java b/core/java/src/net/metanotion/io/block/FreeListBlock.java index ee55e1636..5a1360c84 100644 --- a/core/java/src/net/metanotion/io/block/FreeListBlock.java +++ b/core/java/src/net/metanotion/io/block/FreeListBlock.java @@ -69,8 +69,16 @@ class FreeListBlock { throw new IOException("Bad freelist size " + len); branches = new int[MAX_SIZE]; if(len > 0) { + int good = 0; for(int i=0;i BlockFile.METAINDEX_PAGE) + branches[good++] = fpg; + } + if (good != len) { + BlockFile.log.error((len - good) + " bad pages in " + this); + len = good; + writeBlock(); } } } @@ -123,7 +131,7 @@ class FreeListBlock { } public boolean isFull() { - return len < MAX_SIZE; + return len >= MAX_SIZE; } /** @@ -152,6 +160,9 @@ class FreeListBlock { len--; writeLen(); int rv = branches[len]; + if (rv <= BlockFile.METAINDEX_PAGE) + // shouldn't happen + throw new IOException("Bad free page " + rv); long magic = getMagic(rv); if (magic != MAGIC_FREE) // TODO keep trying until empty @@ -176,5 +187,9 @@ class FreeListBlock { file.writeInt(0); file.writeInt(0); } -} + @Override + public String toString() { + return "FLB with " + len + " / " + MAX_SIZE + " page " + page + " next page " + nextPage; + } +}