提交 4a489638 authored 作者: Thomas Mueller's avatar Thomas Mueller

Improve code coverage.

上级 ad26195b
...@@ -6,12 +6,13 @@ ...@@ -6,12 +6,13 @@
*/ */
package org.h2.store.fs; package org.h2.store.fs;
import java.io.FileNotFoundException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.FileLock; import java.nio.channels.FileLock;
import java.nio.channels.NonWritableChannelException;
/** /**
* File which uses NIO FileChannel. * File which uses NIO FileChannel.
...@@ -19,17 +20,21 @@ import java.nio.channels.FileLock; ...@@ -19,17 +20,21 @@ import java.nio.channels.FileLock;
public class FileObjectDiskChannel implements FileObject { public class FileObjectDiskChannel implements FileObject {
private final String name; private final String name;
private FileChannel channel; private final RandomAccessFile file;
private final FileChannel channel;
private FileLock lock; private FileLock lock;
private long length;
FileObjectDiskChannel(String fileName, String mode) throws FileNotFoundException { FileObjectDiskChannel(String fileName, String mode) throws IOException {
this.name = fileName; this.name = fileName;
RandomAccessFile file = new RandomAccessFile(fileName, mode); file = new RandomAccessFile(fileName, mode);
channel = file.getChannel(); channel = file.getChannel();
length = file.length();
} }
public void close() throws IOException { public void close() throws IOException {
channel.close(); channel.close();
file.close();
} }
public long getFilePointer() throws IOException { public long getFilePointer() throws IOException {
...@@ -37,7 +42,7 @@ public class FileObjectDiskChannel implements FileObject { ...@@ -37,7 +42,7 @@ public class FileObjectDiskChannel implements FileObject {
} }
public String getName() { public String getName() {
return name; return FileSystemDiskNio.PREFIX + name;
} }
public long length() throws IOException { public long length() throws IOException {
...@@ -48,10 +53,9 @@ public class FileObjectDiskChannel implements FileObject { ...@@ -48,10 +53,9 @@ public class FileObjectDiskChannel implements FileObject {
if (len == 0) { if (len == 0) {
return; return;
} }
// reading the size can reduce the performance if (channel.position() + len > length) {
// if (channel.size() <= off + len) { throw new EOFException();
// throw new java.io.EOFException(); }
// }
ByteBuffer buf = ByteBuffer.wrap(b); ByteBuffer buf = ByteBuffer.wrap(b);
buf.position(off); buf.position(off);
buf.limit(off + len); buf.limit(off + len);
...@@ -65,7 +69,11 @@ public class FileObjectDiskChannel implements FileObject { ...@@ -65,7 +69,11 @@ public class FileObjectDiskChannel implements FileObject {
public void setFileLength(long newLength) throws IOException { public void setFileLength(long newLength) throws IOException {
if (newLength <= channel.size()) { if (newLength <= channel.size()) {
long oldPos = channel.position(); long oldPos = channel.position();
channel.truncate(newLength); try {
channel.truncate(newLength);
} catch (NonWritableChannelException e) {
throw new IOException("read only");
}
if (oldPos > newLength) { if (oldPos > newLength) {
oldPos = newLength; oldPos = newLength;
} }
...@@ -75,6 +83,7 @@ public class FileObjectDiskChannel implements FileObject { ...@@ -75,6 +83,7 @@ public class FileObjectDiskChannel implements FileObject {
ByteBuffer b = ByteBuffer.allocate(1); ByteBuffer b = ByteBuffer.allocate(1);
channel.write(b, newLength - 1); channel.write(b, newLength - 1);
} }
length = newLength;
} }
public void sync() throws IOException { public void sync() throws IOException {
...@@ -85,7 +94,11 @@ public class FileObjectDiskChannel implements FileObject { ...@@ -85,7 +94,11 @@ public class FileObjectDiskChannel implements FileObject {
ByteBuffer buf = ByteBuffer.wrap(b); ByteBuffer buf = ByteBuffer.wrap(b);
buf.position(off); buf.position(off);
buf.limit(off + len); buf.limit(off + len);
channel.write(buf); try {
channel.write(buf);
} catch (NonWritableChannelException e) {
throw new IOException("read only");
}
} }
public synchronized boolean tryLock() { public synchronized boolean tryLock() {
......
...@@ -130,7 +130,7 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -130,7 +130,7 @@ public class FileObjectDiskMapped implements FileObject {
} }
public String getName() { public String getName() {
return name; return FileSystemDiskNioMapped.PREFIX + name;
} }
public long length() throws IOException { public long length() throws IOException {
......
...@@ -14,10 +14,12 @@ import java.io.IOException; ...@@ -14,10 +14,12 @@ import java.io.IOException;
public class FileObjectMemory implements FileObject { public class FileObjectMemory implements FileObject {
private final FileObjectMemoryData data; private final FileObjectMemoryData data;
private final boolean readOnly;
private long pos; private long pos;
FileObjectMemory(FileObjectMemoryData data) { FileObjectMemory(FileObjectMemoryData data, boolean readOnly) {
this.data = data; this.data = data;
this.readOnly = readOnly;
} }
public long length() { public long length() {
...@@ -25,7 +27,7 @@ public class FileObjectMemory implements FileObject { ...@@ -25,7 +27,7 @@ public class FileObjectMemory implements FileObject {
} }
public void setFileLength(long newLength) throws IOException { public void setFileLength(long newLength) throws IOException {
data.touch(); data.touch(readOnly);
if (newLength < length()) { if (newLength < length()) {
pos = Math.min(pos, newLength); pos = Math.min(pos, newLength);
} }
...@@ -37,7 +39,7 @@ public class FileObjectMemory implements FileObject { ...@@ -37,7 +39,7 @@ public class FileObjectMemory implements FileObject {
} }
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
data.touch(); data.touch(readOnly);
pos = data.readWrite(pos, b, off, len, true); pos = data.readWrite(pos, b, off, len, true);
} }
...@@ -57,18 +59,10 @@ public class FileObjectMemory implements FileObject { ...@@ -57,18 +59,10 @@ public class FileObjectMemory implements FileObject {
// do nothing // do nothing
} }
public void setName(String name) {
data.setName(name);
}
public String getName() { public String getName() {
return data.getName(); return data.getName();
} }
public long getLastModified() {
return data.getLastModified();
}
public boolean tryLock() { public boolean tryLock() {
return data.tryLock(); return data.tryLock();
} }
......
...@@ -152,8 +152,8 @@ class FileObjectMemoryData { ...@@ -152,8 +152,8 @@ class FileObjectMemoryData {
/** /**
* Update the last modified time. * Update the last modified time.
*/ */
void touch() throws IOException { void touch(boolean openReadOnly) throws IOException {
if (isReadOnly) { if (isReadOnly || openReadOnly) {
throw new IOException("Read only"); throw new IOException("Read only");
} }
lastModified = System.currentTimeMillis(); lastModified = System.currentTimeMillis();
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
package org.h2.store.fs; package org.h2.store.fs;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -55,6 +56,9 @@ public class FileObjectSplit implements FileObject { ...@@ -55,6 +56,9 @@ public class FileObjectSplit implements FileObject {
} }
public void readFully(byte[] b, int off, int len) throws IOException { public void readFully(byte[] b, int off, int len) throws IOException {
if (filePointer + len > length) {
throw new EOFException();
}
while (true) { while (true) {
int l = read(b, off, len); int l = read(b, off, len);
len -= l; len -= l;
...@@ -149,7 +153,7 @@ public class FileObjectSplit implements FileObject { ...@@ -149,7 +153,7 @@ public class FileObjectSplit implements FileObject {
} }
public String getName() { public String getName() {
return name; return FileSystemSplit.PREFIX + name;
} }
public boolean tryLock() { public boolean tryLock() {
......
...@@ -15,7 +15,7 @@ import java.io.InputStream; ...@@ -15,7 +15,7 @@ import java.io.InputStream;
*/ */
public class FileSystemDiskNio extends FileSystemDisk { public class FileSystemDiskNio extends FileSystemDisk {
private static final String PREFIX = "nio:"; static final String PREFIX = "nio:";
static { static {
FileSystem.register(new FileSystemDiskNio()); FileSystem.register(new FileSystemDiskNio());
......
...@@ -14,7 +14,7 @@ import java.io.IOException; ...@@ -14,7 +14,7 @@ import java.io.IOException;
*/ */
public class FileSystemDiskNioMapped extends FileSystemDiskNio { public class FileSystemDiskNioMapped extends FileSystemDiskNio {
private static final String PREFIX = "nioMapped:"; static final String PREFIX = "nioMapped:";
static { static {
FileSystem.register(new FileSystemDiskNioMapped()); FileSystem.register(new FileSystemDiskNioMapped());
......
...@@ -128,9 +128,9 @@ public class FileSystemMemory extends FileSystem { ...@@ -128,9 +128,9 @@ public class FileSystemMemory extends FileSystem {
public String normalize(String fileName) { public String normalize(String fileName) {
fileName = fileName.replace('\\', '/'); fileName = fileName.replace('\\', '/');
int idx = fileName.indexOf(":/"); int idx = fileName.indexOf(':') + 1;
if (idx > 0) { if (fileName.length() >= idx && fileName.charAt(idx) != '/') {
fileName = fileName.substring(0, idx + 1) + fileName.substring(idx + 2); fileName = fileName.substring(0, idx) + "/" + fileName.substring(idx);
} }
return fileName; return fileName;
} }
...@@ -196,7 +196,7 @@ public class FileSystemMemory extends FileSystem { ...@@ -196,7 +196,7 @@ public class FileSystemMemory extends FileSystem {
public OutputStream openFileOutputStream(String fileName, boolean append) { public OutputStream openFileOutputStream(String fileName, boolean append) {
try { try {
FileObjectMemoryData obj = getMemoryFile(fileName); FileObjectMemoryData obj = getMemoryFile(fileName);
FileObjectMemory m = new FileObjectMemory(obj); FileObjectMemory m = new FileObjectMemory(obj, false);
return new FileObjectOutputStream(m, append); return new FileObjectOutputStream(m, append);
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, fileName); throw DbException.convertIOException(e, fileName);
...@@ -205,13 +205,13 @@ public class FileSystemMemory extends FileSystem { ...@@ -205,13 +205,13 @@ public class FileSystemMemory extends FileSystem {
public InputStream openFileInputStream(String fileName) { public InputStream openFileInputStream(String fileName) {
FileObjectMemoryData obj = getMemoryFile(fileName); FileObjectMemoryData obj = getMemoryFile(fileName);
FileObjectMemory m = new FileObjectMemory(obj); FileObjectMemory m = new FileObjectMemory(obj, true);
return new FileObjectInputStream(m); return new FileObjectInputStream(m);
} }
public FileObject openFileObject(String fileName, String mode) { public FileObject openFileObject(String fileName, String mode) {
FileObjectMemoryData obj = getMemoryFile(fileName); FileObjectMemoryData obj = getMemoryFile(fileName);
return new FileObjectMemory(obj); return new FileObjectMemory(obj, "r".equals(mode));
} }
private FileObjectMemoryData getMemoryFile(String fileName) { private FileObjectMemoryData getMemoryFile(String fileName) {
......
...@@ -17,14 +17,16 @@ import org.h2.util.Utils; ...@@ -17,14 +17,16 @@ import org.h2.util.Utils;
*/ */
public class FileObjectDatabase implements FileObject { public class FileObjectDatabase implements FileObject {
private FileSystemDatabase db; private final FileSystemDatabase db;
private String fileName; private final boolean readOnly;
private final String fileName;
private byte[] data; private byte[] data;
private int pos, length; private int pos, length;
private boolean changed; private boolean changed;
FileObjectDatabase(FileSystemDatabase db, String fileName, byte[] data, boolean changed) { FileObjectDatabase(FileSystemDatabase db, String fileName, byte[] data, boolean changed, boolean readOnly) {
this.db = db; this.db = db;
this.readOnly = readOnly;
this.fileName = fileName; this.fileName = fileName;
this.data = data; this.data = data;
this.length = data.length; this.length = data.length;
...@@ -55,7 +57,10 @@ public class FileObjectDatabase implements FileObject { ...@@ -55,7 +57,10 @@ public class FileObjectDatabase implements FileObject {
this.pos = (int) newPos; this.pos = (int) newPos;
} }
public void setFileLength(long newLength) { public void setFileLength(long newLength) throws IOException {
if (readOnly) {
throw new IOException("read only");
}
this.length = (int) newLength; this.length = (int) newLength;
if (length != data.length) { if (length != data.length) {
byte[] n = Utils.newBytes(length); byte[] n = Utils.newBytes(length);
...@@ -73,7 +78,10 @@ public class FileObjectDatabase implements FileObject { ...@@ -73,7 +78,10 @@ public class FileObjectDatabase implements FileObject {
} }
} }
public void write(byte[] b, int off, int len) { public void write(byte[] b, int off, int len) throws IOException {
if (readOnly) {
throw new IOException("read only");
}
if (pos + len > data.length) { if (pos + len > data.length) {
int newLen = Math.max(data.length * 2, pos + len); int newLen = Math.max(data.length * 2, pos + len);
byte[] n = Utils.newBytes(newLen); byte[] n = Utils.newBytes(newLen);
......
...@@ -378,9 +378,9 @@ public class FileSystemDatabase extends FileSystem { ...@@ -378,9 +378,9 @@ public class FileSystemDatabase extends FileSystem {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.copyAndClose(in, out); IOUtils.copyAndClose(in, out);
byte[] data = out.toByteArray(); byte[] data = out.toByteArray();
return new FileObjectDatabase(this, fileName, data, false); return new FileObjectDatabase(this, fileName, data, false, "r".equals(mode));
} }
return new FileObjectDatabase(this, fileName, new byte[0], true); return new FileObjectDatabase(this, fileName, new byte[0], true, "r".equals(mode));
} catch (SQLException e) { } catch (SQLException e) {
throw convert(e); throw convert(e);
} }
......
...@@ -8,6 +8,7 @@ package org.h2.test.unit; ...@@ -8,6 +8,7 @@ package org.h2.test.unit;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
...@@ -43,7 +44,8 @@ public class TestFileSystem extends TestBase { ...@@ -43,7 +44,8 @@ public class TestFileSystem extends TestBase {
testDatabaseInMemFileSys(); testDatabaseInMemFileSys();
testDatabaseInJar(); testDatabaseInJar();
// set default part size to 1 << 10 // set default part size to 1 << 10
FileSystem.getInstance("split:10:" + getBaseDir() + "/fs"); String f = "split:10:" + getBaseDir() + "/fs";
FileSystem.getInstance(f).getAbsolutePath(f);
testFileSystem(getBaseDir() + "/fs"); testFileSystem(getBaseDir() + "/fs");
testFileSystem(FileSystemMemory.PREFIX); testFileSystem(FileSystemMemory.PREFIX);
FileSystemDatabase fs = FileSystemDatabase.register("jdbc:h2:mem:fs"); FileSystemDatabase fs = FileSystemDatabase.register("jdbc:h2:mem:fs");
...@@ -55,9 +57,16 @@ public class TestFileSystem extends TestBase { ...@@ -55,9 +57,16 @@ public class TestFileSystem extends TestBase {
try { try {
if (!config.splitFileSystem) { if (!config.splitFileSystem) {
testFileSystem("split:" + getBaseDir() + "/fs"); testFileSystem("split:" + getBaseDir() + "/fs");
testFileSystem("nio:" + getBaseDir() + "/fs");
testFileSystem("nioMapped:" + getBaseDir() + "/fs"); testFileSystem("nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs"); testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
} }
} catch (Exception e) {
e.printStackTrace();
throw e;
} catch (Error e) {
e.printStackTrace();
throw e;
} finally { } finally {
IOUtils.delete(getBaseDir() + "/fs"); IOUtils.delete(getBaseDir() + "/fs");
} }
...@@ -160,11 +169,35 @@ public class TestFileSystem extends TestBase { ...@@ -160,11 +169,35 @@ public class TestFileSystem extends TestBase {
random.nextBytes(buffer); random.nextBytes(buffer);
fo.write(buffer, 0, 10000); fo.write(buffer, 0, 10000);
fo.seek(20000); fo.seek(20000);
assertEquals(20000, fo.getFilePointer());
try { try {
fo.readFully(buffer, 0, 1); fo.readFully(buffer, 0, 1);
fail();
} catch (EOFException e) { } catch (EOFException e) {
// expected // expected
} }
assertEquals(fsBase + "/test", fo.getName());
assertEquals("test", fs.getFileName(fo.getName()));
assertEquals(fsBase, fs.getParent(fo.getName()));
fo.tryLock();
fo.releaseLock();
fo.close();
fo = fs.openFileObject(fsBase + "/test", "r");
byte[] test = new byte[10000];
fo.readFully(test, 0, 10000);
assertEquals(buffer, test);
try {
fo.write(test, 0, 10);
fail();
} catch (IOException e) {
// expected
}
try {
fo.setFileLength(10);
fail();
} catch (IOException 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论