forked from I2P_Developers/i2p.i2p
* BlockfileNamingService:
- Support readonly blockfiles
- Open blockfile readonly if not in router context
- Log warning if blockfile is locked
This commit is contained in:
@@ -38,13 +38,17 @@ import java.io.RandomAccessFile;
|
||||
public class RAIFile implements RandomAccessInterface, DataInput, DataOutput {
|
||||
private File f;
|
||||
private RandomAccessFile delegate;
|
||||
private boolean r=false, w=false;
|
||||
private final boolean r, w;
|
||||
|
||||
public RAIFile(RandomAccessFile file) throws FileNotFoundException {
|
||||
this.f = null;
|
||||
this.delegate = file;
|
||||
this.r = true;
|
||||
// fake, we don't really know
|
||||
this.w = true;
|
||||
}
|
||||
|
||||
/** @param read must be true */
|
||||
public RAIFile(File file, boolean read, boolean write) throws FileNotFoundException {
|
||||
this.f = file;
|
||||
this.r = read;
|
||||
@@ -55,6 +59,15 @@ public class RAIFile implements RandomAccessInterface, DataInput, DataOutput {
|
||||
this.delegate = new RandomAccessFile(file, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P is the file writable?
|
||||
* Only valid if the File constructor was used, not the RAF constructor
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public boolean canWrite() {
|
||||
return this.w;
|
||||
}
|
||||
|
||||
public long getFilePointer() throws IOException { return delegate.getFilePointer(); }
|
||||
public long length() throws IOException { return delegate.length(); }
|
||||
public int read() throws IOException { return delegate.read(); }
|
||||
|
||||
@@ -39,6 +39,13 @@ public interface RandomAccessInterface {
|
||||
public void seek(long pos) throws IOException;
|
||||
public void setLength(long newLength) throws IOException;
|
||||
|
||||
/**
|
||||
* I2P is the file writable?
|
||||
* Only valid if the File constructor was used, not the RAF constructor
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public boolean canWrite();
|
||||
|
||||
// Closeable Methods
|
||||
public void close() throws IOException;
|
||||
|
||||
|
||||
@@ -90,6 +90,9 @@ public class BlockFile {
|
||||
private int mounted = 0;
|
||||
public int spanSize = 16;
|
||||
|
||||
/** I2P was the file locked when we opened it? */
|
||||
private final boolean _wasMounted;
|
||||
|
||||
private BSkipList metaIndex;
|
||||
/** cached list of free pages, only valid if freListStart > 0 */
|
||||
private FreeListBlock flb;
|
||||
@@ -258,11 +261,19 @@ public class BlockFile {
|
||||
return curPage;
|
||||
}
|
||||
|
||||
/** Use this constructor with a readonly RAI for a readonly blockfile */
|
||||
public BlockFile(RandomAccessInterface rai) throws IOException { this(rai, false); }
|
||||
|
||||
/** RAF must be writable */
|
||||
public BlockFile(RandomAccessFile raf) throws IOException { this(new RAIFile(raf), false); }
|
||||
|
||||
/** RAF must be writable */
|
||||
public BlockFile(RandomAccessFile raf, boolean init) throws IOException { this(new RAIFile(raf), init); }
|
||||
|
||||
/** File must be writable */
|
||||
public BlockFile(File f, boolean init) throws IOException { this(new RAIFile(f, true, true), init); }
|
||||
|
||||
/** Use this constructor with a readonly RAI and init = false for a readonly blockfile */
|
||||
public BlockFile(RandomAccessInterface rai, boolean init) throws IOException {
|
||||
if(rai==null) { throw new NullPointerException(); }
|
||||
|
||||
@@ -283,16 +294,26 @@ public class BlockFile {
|
||||
throw new IOException("Bad magic number");
|
||||
}
|
||||
}
|
||||
if (mounted != 0)
|
||||
_wasMounted = mounted != 0;
|
||||
if (_wasMounted)
|
||||
log.warn("Warning - file was not previously closed");
|
||||
if(fileLen != file.length())
|
||||
throw new IOException("Expected file length " + fileLen +
|
||||
" but actually " + file.length());
|
||||
mount();
|
||||
if (rai.canWrite())
|
||||
mount();
|
||||
|
||||
metaIndex = new BSkipList(spanSize, this, METAINDEX_PAGE, new StringBytes(), new IntBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P was the file locked when we opened it?
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public boolean wasMounted() {
|
||||
return _wasMounted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to any page but the superblock.
|
||||
* Page 1 is the superblock, must use file.seek(0) to get there.
|
||||
@@ -454,8 +475,10 @@ public class BlockFile {
|
||||
}
|
||||
|
||||
// Unmount.
|
||||
file.seek(BlockFile.OFFSET_MOUNTED);
|
||||
file.writeShort(0);
|
||||
if (file.canWrite()) {
|
||||
file.seek(BlockFile.OFFSET_MOUNTED);
|
||||
file.writeShort(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void bfck(boolean fix) {
|
||||
|
||||
@@ -98,7 +98,8 @@ public class BSkipList extends SkipList {
|
||||
}
|
||||
if (BlockFile.log.shouldLog(Log.DEBUG))
|
||||
BlockFile.log.debug("Loaded " + this + " cached " + levelHash.size() + " levels and " + spanHash.size() + " spans with " + total + " entries");
|
||||
if (levelCount != levelHash.size() || spans != spanHash.size() || size != total) {
|
||||
if (bf.file.canWrite() &&
|
||||
(levelCount != levelHash.size() || spans != spanHash.size() || size != total)) {
|
||||
if (BlockFile.log.shouldLog(Log.WARN))
|
||||
BlockFile.log.warn("On-disk counts were " + levelCount + " / " + spans + " / " + size + ", correcting");
|
||||
size = total;
|
||||
@@ -117,6 +118,8 @@ public class BSkipList extends SkipList {
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
if (!bf.file.canWrite())
|
||||
return;
|
||||
if (isClosed) {
|
||||
BlockFile.log.error("Already closed!! " + this, new Exception());
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user