提交 7495f1f5 authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 6047e2f4
...@@ -10,7 +10,6 @@ import java.io.IOException; ...@@ -10,7 +10,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.engine.Constants;
import org.h2.index.Page; import org.h2.index.Page;
import org.h2.message.Message; import org.h2.message.Message;
...@@ -94,7 +93,7 @@ public class PageInputStream extends InputStream { ...@@ -94,7 +93,7 @@ public class PageInputStream extends InputStream {
} }
page.reset(); page.reset();
try { try {
page = store.readPage(nextPage); store.readPage(nextPage, page);
int p = page.readInt(); int p = page.readInt();
int t = page.readByte(); int t = page.readByte();
boolean last = (t & Page.FLAG_LAST) != 0; boolean last = (t & Page.FLAG_LAST) != 0;
...@@ -111,8 +110,8 @@ public class PageInputStream extends InputStream { ...@@ -111,8 +110,8 @@ public class PageInputStream extends InputStream {
remaining = page.readInt(); remaining = page.readInt();
} else { } else {
nextPage = page.readInt(); nextPage = page.readInt();
remaining = store.getPageSize() - page.length();
} }
remaining = Constants.FILE_BLOCK_SIZE - page.length();
} catch (SQLException e) { } catch (SQLException e) {
throw Message.convertToIOException(e); throw Message.convertToIOException(e);
} }
......
...@@ -49,7 +49,7 @@ public class PageLog { ...@@ -49,7 +49,7 @@ public class PageLog {
// prepareOutput(); // prepareOutput();
// } // }
private void prepareOutput() { private void prepareOutput() throws SQLException {
output.reset(); output.reset();
output.writeInt(0); output.writeInt(0);
output.writeByte((byte) Page.TYPE_LOG); output.writeByte((byte) Page.TYPE_LOG);
......
...@@ -55,7 +55,7 @@ public class PageOutputStream extends OutputStream { ...@@ -55,7 +55,7 @@ public class PageOutputStream extends OutputStream {
page.writeInt(parentPage); page.writeInt(parentPage);
page.writeByte((byte) type); page.writeByte((byte) type);
page.writeInt(0); page.writeInt(0);
remaining = page.length(); remaining = store.getPageSize() - page.length();
} }
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
...@@ -67,7 +67,12 @@ public class PageOutputStream extends OutputStream { ...@@ -67,7 +67,12 @@ public class PageOutputStream extends OutputStream {
off += remaining; off += remaining;
len -= remaining; len -= remaining;
parentPage = nextPage; parentPage = nextPage;
pageId = nextPage;
try {
nextPage = store.allocatePage(); nextPage = store.allocatePage();
} catch (SQLException e) {
throw Message.convertToIOException(e);
}
page.setInt(5, nextPage); page.setInt(5, nextPage);
storePage(); storePage();
initPage(); initPage();
...@@ -88,6 +93,7 @@ public class PageOutputStream extends OutputStream { ...@@ -88,6 +93,7 @@ public class PageOutputStream extends OutputStream {
page.setPos(4); page.setPos(4);
page.writeByte((byte) (type | Page.FLAG_LAST)); page.writeByte((byte) (type | Page.FLAG_LAST));
page.writeInt(store.getPageSize() - remaining - 9); page.writeInt(store.getPageSize() - remaining - 9);
pageId = nextPage;
storePage(); storePage();
store = null; store = null;
} }
......
...@@ -40,6 +40,7 @@ public class PageStore implements CacheWriter { ...@@ -40,6 +40,7 @@ public class PageStore implements CacheWriter {
private static final int PAGE_SIZE_MAX = 32768; private static final int PAGE_SIZE_MAX = 32768;
private static final int PAGE_SIZE_DEFAULT = 1024; private static final int PAGE_SIZE_DEFAULT = 1024;
private static final int FILE_HEADER_SIZE = 128; private static final int FILE_HEADER_SIZE = 128;
private static final int INCREMENT_PAGES = 128;
private static final int READ_VERSION = 0; private static final int READ_VERSION = 0;
private static final int WRITE_VERSION = 0; private static final int WRITE_VERSION = 0;
...@@ -57,6 +58,9 @@ public class PageStore implements CacheWriter { ...@@ -57,6 +58,9 @@ public class PageStore implements CacheWriter {
private int freePageCount; private int freePageCount;
private int pageCount; private int pageCount;
private int writeCount; private int writeCount;
private long fileLength;
private long currentPos;
/** /**
* Create a new page store object. * Create a new page store object.
* *
...@@ -92,7 +96,8 @@ public class PageStore implements CacheWriter { ...@@ -92,7 +96,8 @@ public class PageStore implements CacheWriter {
file = database.openFile(fileName, accessMode, false); file = database.openFile(fileName, accessMode, false);
writeHeader(); writeHeader();
} }
pageCount = (int) (file.length() / pageSize); fileLength = file.length();
pageCount = (int) (fileLength / pageSize);
} catch (SQLException e) { } catch (SQLException e) {
close(); close();
throw e; throw e;
...@@ -144,7 +149,13 @@ public class PageStore implements CacheWriter { ...@@ -144,7 +149,13 @@ public class PageStore implements CacheWriter {
freePageCount = fileHeader.readInt(); freePageCount = fileHeader.readInt();
} }
private void setPageSize(int size) throws SQLException { /**
* Set the page size. The size must be a power of two. This method must be
* called before opening.
*
* @param size the page size
*/
public void setPageSize(int size) throws SQLException {
if (size < PAGE_SIZE_MIN || size > PAGE_SIZE_MAX) { if (size < PAGE_SIZE_MIN || size > PAGE_SIZE_MAX) {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName); throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName);
} }
...@@ -230,8 +241,13 @@ public class PageStore implements CacheWriter { ...@@ -230,8 +241,13 @@ public class PageStore implements CacheWriter {
* *
* @return the page id * @return the page id
*/ */
public int allocatePage() { public int allocatePage() throws SQLException {
if (freePageCount == 0) { if (freePageCount == 0) {
if (pageCount * pageSize >= fileLength) {
long newLength = (pageCount + INCREMENT_PAGES) * pageSize;
file.setLength(newLength);
fileLength = newLength;
}
return pageCount++; return pageCount++;
} }
int todoReturnAFreePage; int todoReturnAFreePage;
...@@ -265,12 +281,22 @@ public class PageStore implements CacheWriter { ...@@ -265,12 +281,22 @@ public class PageStore implements CacheWriter {
* @return the page * @return the page
*/ */
public DataPageBinary readPage(int pos) throws SQLException { public DataPageBinary readPage(int pos) throws SQLException {
file.seek(pos << pageSizeShift);
DataPageBinary page = createDataPage(); DataPageBinary page = createDataPage();
file.readFully(page.getBytes(), 0, pageSize); readPage(pos, page);
return page; return page;
} }
/**
* Read a page.
*
* @param pos the page id
* @return the page
*/
public void readPage(int pos, DataPageBinary page) throws SQLException {
file.seek(pos << pageSizeShift);
file.readFully(page.getBytes(), 0, pageSize);
}
/** /**
* Get the page size. * Get the page size.
* *
......
...@@ -6,7 +6,13 @@ ...@@ -6,7 +6,13 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random; import java.util.Random;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
import org.h2.engine.Database; import org.h2.engine.Database;
...@@ -31,6 +37,59 @@ public class TestPageStoreStreams extends TestBase { ...@@ -31,6 +37,59 @@ public class TestPageStoreStreams extends TestBase {
} }
public void test() throws Exception { public void test() throws Exception {
testFuzz();
// for (int i = 0; i < 4; i++) {
// testPerformance(true);
// testPerformance(false);
// }
}
private void testPerformance(boolean file) throws Exception {
String name = "mem:pageStoreStreams";
ConnectionInfo ci = new ConnectionInfo(name);
Database db = new Database(name, ci, null);
String fileName = getTestDir("/pageStoreStreams");
new File(fileName).delete();
File f = new File(fileName + ".dat");
f.delete();
PageStore store = new PageStore(db, fileName, "rw", 8192);
store.setPageSize(8 * 1024);
byte[] buff = new byte[100];
store.open();
int head = store.allocatePage();
OutputStream out;
InputStream in;
long start = System.currentTimeMillis();
if (file) {
out = new BufferedOutputStream(new FileOutputStream(f), 4 * 1024);
} else {
out = new PageOutputStream(store, 0, head, Page.TYPE_LOG);
}
for (int i = 0; i < 1000000; i++) {
out.write(buff);
}
out.close();
if (file) {
in = new BufferedInputStream(new FileInputStream(f), 4 * 1024);
} else {
in = new PageInputStream(store, 0, head, Page.TYPE_LOG);
}
while (true) {
int len = in.read(buff);
if (len < 0) {
break;
}
}
in.close();
System.out.println((file ? "file" : "pageStore") +
" " + (System.currentTimeMillis() - start));
store.close();
db.shutdownImmediately();
new File(fileName).delete();
f.delete();
}
private void testFuzz() throws Exception {
String name = "mem:pageStoreStreams"; String name = "mem:pageStoreStreams";
ConnectionInfo ci = new ConnectionInfo(name); ConnectionInfo ci = new ConnectionInfo(name);
Database db = new Database(name, ci, null); Database db = new Database(name, ci, null);
...@@ -45,8 +104,8 @@ public class TestPageStoreStreams extends TestBase { ...@@ -45,8 +104,8 @@ public class TestPageStoreStreams extends TestBase {
random.nextBytes(data); random.nextBytes(data);
int head = store.allocatePage(); int head = store.allocatePage();
PageOutputStream out = new PageOutputStream(store, 0, head, Page.TYPE_LOG); PageOutputStream out = new PageOutputStream(store, 0, head, Page.TYPE_LOG);
for (int p = 0; len > 0;) { for (int p = 0; p < len;) {
int l = len == 0 ? 0 : random.nextInt(len / 10); int l = len == 0 ? 0 : Math.min(len - p, random.nextInt(len / 10));
out.write(data, p, l); out.write(data, p, l);
p += l; p += l;
} }
...@@ -54,7 +113,7 @@ public class TestPageStoreStreams extends TestBase { ...@@ -54,7 +113,7 @@ public class TestPageStoreStreams extends TestBase {
PageInputStream in = new PageInputStream(store, 0, head, Page.TYPE_LOG); PageInputStream in = new PageInputStream(store, 0, head, Page.TYPE_LOG);
byte[] data2 = new byte[len]; byte[] data2 = new byte[len];
for (int off = 0;;) { for (int off = 0;;) {
int l = random.nextInt(1 + len / 10) - 1; int l = random.nextInt(1 + len / 10) + 1;
l = in.read(data2, off, l); l = in.read(data2, off, l);
if (l < 0) { if (l < 0) {
break; break;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论