- Fix FLB full check

- Cache FLB
- FLB logging, cleanups, checks
This commit is contained in:
zzz
2011-03-28 14:27:19 +00:00
parent 9fcb20a7bd
commit 33780ef359
2 changed files with 53 additions and 14 deletions

View File

@ -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);

View File

@ -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<len;i++) {
branches[i] = file.readUnsignedInt();
int fpg = file.readInt();
if (fpg > 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;
}
}