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

New experimental page store.

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