提交 587c4750 authored 作者: Thomas Mueller's avatar Thomas Mueller

The memory mapped file system (nioMapped: file prefix) couldn't seek past the file length.

上级 a710d997
...@@ -29,6 +29,12 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -29,6 +29,12 @@ public class FileObjectDiskMapped implements FileObject {
private RandomAccessFile file; private RandomAccessFile file;
private MappedByteBuffer mapped; private MappedByteBuffer mapped;
/**
* The position within the file. Can't use the position of the mapped buffer
* because it doesn't support seeking past the end of the file.
*/
private int pos;
FileObjectDiskMapped(String fileName, String mode) throws IOException { FileObjectDiskMapped(String fileName, String mode) throws IOException {
if ("r".equals(mode)) { if ("r".equals(mode)) {
this.mode = MapMode.READ_ONLY; this.mode = MapMode.READ_ONLY;
...@@ -88,12 +94,12 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -88,12 +94,12 @@ public class FileObjectDiskMapped implements FileObject {
private void reMap() throws IOException { private void reMap() throws IOException {
int oldPos = 0; int oldPos = 0;
if (mapped != null) { if (mapped != null) {
oldPos = mapped.position(); oldPos = pos;
mapped.force(); mapped.force();
unMap(); unMap();
} }
long length = file.length(); long length = file.length();
checkFileLength(length); checkFileSizeLimit(length);
// maps new MappedByteBuffer; the old one is disposed during GC // maps new MappedByteBuffer; the old one is disposed during GC
mapped = file.getChannel().map(mode, 0, length); mapped = file.getChannel().map(mode, 0, length);
int limit = mapped.limit(); int limit = mapped.limit();
...@@ -104,11 +110,10 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -104,11 +110,10 @@ public class FileObjectDiskMapped implements FileObject {
if (SysProperties.NIO_LOAD_MAPPED) { if (SysProperties.NIO_LOAD_MAPPED) {
mapped.load(); mapped.load();
} }
int pos = Math.min(oldPos, (int) length); this.pos = Math.min(oldPos, (int) length);
mapped.position(pos);
} }
private void checkFileLength(long length) throws IOException { private void checkFileSizeLimit(long length) throws IOException {
if (length > Integer.MAX_VALUE) { if (length > Integer.MAX_VALUE) {
throw new IOException("File over 2GB is not supported yet when using this file system"); throw new IOException("File over 2GB is not supported yet when using this file system");
} }
...@@ -121,7 +126,7 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -121,7 +126,7 @@ public class FileObjectDiskMapped implements FileObject {
} }
public long getFilePointer() { public long getFilePointer() {
return mapped.position(); return pos;
} }
public String getName() { public String getName() {
...@@ -134,7 +139,12 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -134,7 +139,12 @@ public class FileObjectDiskMapped implements FileObject {
public void readFully(byte[] b, int off, int len) throws EOFException { public void readFully(byte[] b, int off, int len) throws EOFException {
try { try {
mapped.position(pos);
mapped.get(b, off, len); mapped.get(b, off, len);
} catch (IllegalArgumentException e) {
EOFException e2 = new EOFException("EOF");
e2.initCause(e);
throw e2;
} catch (BufferUnderflowException e) { } catch (BufferUnderflowException e) {
EOFException e2 = new EOFException("EOF"); EOFException e2 = new EOFException("EOF");
e2.initCause(e); e2.initCause(e);
...@@ -143,26 +153,27 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -143,26 +153,27 @@ public class FileObjectDiskMapped implements FileObject {
} }
public void seek(long pos) throws IOException { public void seek(long pos) throws IOException {
checkFileLength(pos); checkFileSizeLimit(pos);
mapped.position((int) pos); this.pos = (int) pos;
} }
public void setFileLength(long newLength) throws IOException { public void setFileLength(long newLength) throws IOException {
checkFileLength(newLength); checkFileSizeLimit(newLength);
IOUtils.setLength(file, newLength); IOUtils.setLength(file, newLength);
reMap(); reMap();
} }
public void sync() throws IOException { public void sync() throws IOException {
file.getFD().sync();
mapped.force(); mapped.force();
file.getFD().sync();
} }
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
// check if need to expand file // check if need to expand file
if (mapped.capacity() < mapped.position() + len) { if (mapped.capacity() < pos + len) {
setFileLength(mapped.position() + len); setFileLength(pos + len);
} }
mapped.position(pos);
mapped.put(b, off, len); mapped.put(b, off, len);
} }
......
...@@ -43,6 +43,7 @@ public class TestFileSystem extends TestBase { ...@@ -43,6 +43,7 @@ public class TestFileSystem extends TestBase {
testDatabaseInJar(); testDatabaseInJar();
// set default part size to 1 << 10 // set default part size to 1 << 10
FileSystem.getInstance("split:10:" + getBaseDir() + "/fs"); FileSystem.getInstance("split:10:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:" + getBaseDir() + "/fs"); testFileSystem("split:" + getBaseDir() + "/fs");
testFileSystem(getBaseDir() + "/fs"); testFileSystem(getBaseDir() + "/fs");
testFileSystem(FileSystemMemory.PREFIX); testFileSystem(FileSystemMemory.PREFIX);
...@@ -151,6 +152,12 @@ public class TestFileSystem extends TestBase { ...@@ -151,6 +152,12 @@ public class TestFileSystem extends TestBase {
Random random = new Random(1); Random random = new Random(1);
random.nextBytes(buffer); random.nextBytes(buffer);
fo.write(buffer, 0, 10000); fo.write(buffer, 0, 10000);
fo.seek(20000);
try {
fo.readFully(buffer, 0, 1);
} catch (EOFException e) {
// expected
}
fo.close(); fo.close();
long lastMod = fs.getLastModified(fsBase + "/test"); long lastMod = fs.getLastModified(fsBase + "/test");
if (lastMod < time - 1999) { if (lastMod < time - 1999) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论