forked from I2P_Developers/i2p.i2p
- Fix FLB full check
- Cache FLB - FLB logging, cleanups, checks
This commit is contained in:
@@ -71,7 +71,7 @@ public class BlockFile {
|
|||||||
public static final long OFFSET_MOUNTED = 20;
|
public static final long OFFSET_MOUNTED = 20;
|
||||||
public static final Log log = I2PAppContext.getGlobalContext().logManager().getLog(BlockFile.class);
|
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 MAJOR = 0x01;
|
||||||
private static final int MINOR = 0x01;
|
private static final int MINOR = 0x01;
|
||||||
@@ -84,13 +84,16 @@ public class BlockFile {
|
|||||||
/** 2**32 pages of 1024 bytes each, more or less */
|
/** 2**32 pages of 1024 bytes each, more or less */
|
||||||
private static final long MAX_LEN = (2l << (32 + 10)) - 1;
|
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 long fileLen = PAGESIZE * 2;
|
||||||
private int freeListStart = 0;
|
private int freeListStart = 0;
|
||||||
private int mounted = 0;
|
private int mounted = 0;
|
||||||
public int spanSize = 16;
|
public int spanSize = 16;
|
||||||
|
|
||||||
private BSkipList metaIndex = null;
|
private BSkipList metaIndex;
|
||||||
private HashMap openIndices = new HashMap();
|
/** cached list of free pages, only valid if freListStart > 0 */
|
||||||
|
private FreeListBlock flb;
|
||||||
|
private final HashMap openIndices = new HashMap();
|
||||||
|
|
||||||
private void mount() throws IOException {
|
private void mount() throws IOException {
|
||||||
file.seek(BlockFile.OFFSET_MOUNTED);
|
file.seek(BlockFile.OFFSET_MOUNTED);
|
||||||
@@ -268,7 +271,7 @@ public class BlockFile {
|
|||||||
if(init) {
|
if(init) {
|
||||||
file.setLength(fileLen);
|
file.setLength(fileLen);
|
||||||
writeSuperBlock();
|
writeSuperBlock();
|
||||||
BSkipList.init(this, 2, spanSize);
|
BSkipList.init(this, METAINDEX_PAGE, spanSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
readSuperBlock();
|
readSuperBlock();
|
||||||
@@ -304,13 +307,20 @@ public class BlockFile {
|
|||||||
public int allocPage() throws IOException {
|
public int allocPage() throws IOException {
|
||||||
if(freeListStart != 0) {
|
if(freeListStart != 0) {
|
||||||
try {
|
try {
|
||||||
FreeListBlock flb = new FreeListBlock(file, freeListStart);
|
if (flb == null)
|
||||||
|
flb = new FreeListBlock(file, freeListStart);
|
||||||
if(!flb.isEmpty()) {
|
if(!flb.isEmpty()) {
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Alloc from " + flb);
|
||||||
return flb.takePage();
|
return flb.takePage();
|
||||||
} else {
|
} else {
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Alloc returning empty " + flb);
|
||||||
freeListStart = flb.getNextPage();
|
freeListStart = flb.getNextPage();
|
||||||
writeSuperBlock();
|
writeSuperBlock();
|
||||||
return flb.page;
|
int rv = flb.page;
|
||||||
|
flb = null;
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
log.error("Discarding corrupt free list block page " + freeListStart, 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.
|
* Does not throw exceptions; logs on failure.
|
||||||
*/
|
*/
|
||||||
public void freePage(int page) {
|
public void freePage(int page) {
|
||||||
if (page < METAINDEX_PAGE) {
|
if (page <= METAINDEX_PAGE) {
|
||||||
log.error("Negative page or superblock free attempt: " + page);
|
log.error("Bad page free attempt: " + page);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -339,29 +349,43 @@ public class BlockFile {
|
|||||||
freeListStart = page;
|
freeListStart = page;
|
||||||
FreeListBlock.initPage(file, page);
|
FreeListBlock.initPage(file, page);
|
||||||
writeSuperBlock();
|
writeSuperBlock();
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Freed page " + page + " as new FLB");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
FreeListBlock flb = new FreeListBlock(file, freeListStart);
|
if (flb == null)
|
||||||
|
flb = new FreeListBlock(file, freeListStart);
|
||||||
if(flb.isFull()) {
|
if(flb.isFull()) {
|
||||||
|
// Make the free page a new FLB
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Full: " + flb);
|
||||||
FreeListBlock.initPage(file, page);
|
FreeListBlock.initPage(file, page);
|
||||||
if(flb.getNextPage() == 0) {
|
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);
|
flb.setNextPage(page);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
|
// Put it at the head
|
||||||
flb = new FreeListBlock(file, page);
|
flb = new FreeListBlock(file, page);
|
||||||
flb.setNextPage(freeListStart);
|
flb.setNextPage(freeListStart);
|
||||||
freeListStart = page;
|
freeListStart = page;
|
||||||
writeSuperBlock();
|
writeSuperBlock();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Freed page " + page + " to full " + flb);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
flb.addPage(page);
|
flb.addPage(page);
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Freed page " + page + " to " + flb);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
log.error("Discarding corrupt free list block page " + freeListStart, ioe);
|
log.error("Discarding corrupt free list block page " + freeListStart, ioe);
|
||||||
freeListStart = page;
|
freeListStart = page;
|
||||||
FreeListBlock.initPage(file, page);
|
FreeListBlock.initPage(file, page);
|
||||||
writeSuperBlock();
|
writeSuperBlock();
|
||||||
|
flb = null;
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
log.error("Error freeing page: " + page, ioe);
|
log.error("Error freeing page: " + page, ioe);
|
||||||
|
|||||||
@@ -69,8 +69,16 @@ class FreeListBlock {
|
|||||||
throw new IOException("Bad freelist size " + len);
|
throw new IOException("Bad freelist size " + len);
|
||||||
branches = new int[MAX_SIZE];
|
branches = new int[MAX_SIZE];
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
|
int good = 0;
|
||||||
for(int i=0;i<len;i++) {
|
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() {
|
public boolean isFull() {
|
||||||
return len < MAX_SIZE;
|
return len >= MAX_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,6 +160,9 @@ class FreeListBlock {
|
|||||||
len--;
|
len--;
|
||||||
writeLen();
|
writeLen();
|
||||||
int rv = branches[len];
|
int rv = branches[len];
|
||||||
|
if (rv <= BlockFile.METAINDEX_PAGE)
|
||||||
|
// shouldn't happen
|
||||||
|
throw new IOException("Bad free page " + rv);
|
||||||
long magic = getMagic(rv);
|
long magic = getMagic(rv);
|
||||||
if (magic != MAGIC_FREE)
|
if (magic != MAGIC_FREE)
|
||||||
// TODO keep trying until empty
|
// TODO keep trying until empty
|
||||||
@@ -176,5 +187,9 @@ class FreeListBlock {
|
|||||||
file.writeInt(0);
|
file.writeInt(0);
|
||||||
file.writeInt(0);
|
file.writeInt(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FLB with " + len + " / " + MAX_SIZE + " page " + page + " next page " + nextPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user