提交 b3443d1e authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 fa0ba065
...@@ -20,16 +20,18 @@ public class PageInputStream extends InputStream { ...@@ -20,16 +20,18 @@ public class PageInputStream extends InputStream {
private PageStore store; private PageStore store;
private final Trace trace; private final Trace trace;
private int trunkNext; private int trunkNext;
private int dataPage;
private PageStreamTrunk trunk; private PageStreamTrunk trunk;
private PageStreamData data; private PageStreamData data;
private boolean endOfFile; private boolean endOfFile;
private int remaining; private int remaining;
private byte[] buffer = new byte[1]; private byte[] buffer = new byte[1];
public PageInputStream(PageStore store, int trunkPage) { public PageInputStream(PageStore store, int trunkPage, int dataPage) {
this.store = store; this.store = store;
this.trace = store.getTrace(); this.trace = store.getTrace();
this.trunkNext = trunkPage; this.trunkNext = trunkPage;
this.dataPage = dataPage;
} }
public int read() throws IOException { public int read() throws IOException {
...@@ -87,16 +89,19 @@ public class PageInputStream extends InputStream { ...@@ -87,16 +89,19 @@ public class PageInputStream extends InputStream {
} }
int next; int next;
while (true) { while (true) {
next = trunk.getNextPage(); next = trunk.getNextDataPage();
if (next >= 0) { if (dataPage == -1 || dataPage == next) {
break; if (next != 0) {
break;
}
trunk = new PageStreamTrunk(store, trunkNext);
trunk.read();
} }
trunk = new PageStreamTrunk(store, trunkNext);
trunk.read();
} }
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("pageIn.readPage " + next); trace.debug("pageIn.readPage " + next);
} }
dataPage = -1;
data = new PageStreamData(store, next, 0); data = new PageStreamData(store, next, 0);
data.read(); data.read();
remaining = data.getLength(); remaining = data.getLength();
......
...@@ -6,31 +6,29 @@ ...@@ -6,31 +6,29 @@
*/ */
package org.h2.store; package org.h2.store;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.index.Page;
import org.h2.log.LogSystem; import org.h2.log.LogSystem;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.util.BitField; import org.h2.util.BitField;
import org.h2.util.IntIntHashMap;
import org.h2.value.Value; import org.h2.value.Value;
/** /**
* Transaction log mechanism. * Transaction log mechanism. The stream contains a list of records. The data
* The format is: * format for a record is:
* <ul><li>0-3: log id * <ul>
* </li><li>records * <li>0-0: type (0: undo,...)</li>
* </li></ul> * <li>1-4: page id</li>
* The data format for a record is: * <li>5-: data</li>
* <ul><li>0-0: type (0: undo,...) * </ul>
* </li><li>1-4: page id
* </li><li>5-: data
* </li></ul>
*/ */
public class PageLog { public class PageLog {
...@@ -62,17 +60,18 @@ public class PageLog { ...@@ -62,17 +60,18 @@ public class PageLog {
private int pos; private int pos;
private Trace trace; private Trace trace;
private PageOutputStream pageOut;
private DataOutputStream out; private DataOutputStream out;
private PageOutputStream pageOut;
private DataInputStream in; private DataInputStream in;
private int firstPage; private int firstTrunkPage;
private DataPage data; private DataPage data;
private long operation; private int logId, logPos;
private int firstLogId;
private BitField undo = new BitField(); private BitField undo = new BitField();
private IntIntHashMap logIdPageMap = new IntIntHashMap();
PageLog(PageStore store, int firstPage) { PageLog(PageStore store) {
this.store = store; this.store = store;
this.firstPage = firstPage;
data = store.createDataPage(); data = store.createDataPage();
trace = store.getTrace(); trace = store.getTrace();
} }
...@@ -80,20 +79,25 @@ public class PageLog { ...@@ -80,20 +79,25 @@ public class PageLog {
/** /**
* Open the log for writing. For an existing database, the recovery * Open the log for writing. For an existing database, the recovery
* must be run first. * must be run first.
*
* @param firstTrunkPage the first trunk page
*/ */
void openForWriting() { void openForWriting(int firstTrunkPage) {
trace.debug("log openForWriting firstPage:" + firstPage); trace.debug("log openForWriting firstPage:" + firstTrunkPage);
pageOut = new PageOutputStream(store, firstPage); pageOut = new PageOutputStream(store, firstTrunkPage);
out = new DataOutputStream(pageOut);
} }
/** /**
* Open the log for reading. * Open the log for reading.
*
* @param firstTrunkPage the first trunk page
* @param firstDataPage the index of the first data page
*/ */
void openForReading() { void openForReading(int firstTrunkPage, int firstDataPage) {
in = new DataInputStream(new PageInputStream(store, firstPage)); this.firstTrunkPage = firstTrunkPage;
in = new DataInputStream(new PageInputStream(store, firstTrunkPage, firstDataPage));
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("log openForReading firstPage:" + firstPage); trace.debug("log openForReading firstPage:" + firstTrunkPage);
} }
} }
...@@ -205,7 +209,7 @@ public class PageLog { ...@@ -205,7 +209,7 @@ public class PageLog {
trace.debug("log undo " + pageId); trace.debug("log undo " + pageId);
} }
undo.set(pageId); undo.set(pageId);
pageOut.prepareWriting(store.getPageSize() * 3); pageOut.reserve(store.getPageSize() * 3);
out.write(UNDO); out.write(UNDO);
out.writeInt(pageId); out.writeInt(pageId);
out.write(page.getBytes(), 0, store.getPageSize()); out.write(page.getBytes(), 0, store.getPageSize());
...@@ -229,7 +233,7 @@ public class PageLog { ...@@ -229,7 +233,7 @@ public class PageLog {
// database already closed // database already closed
return; return;
} }
pageOut.prepareWriting(store.getPageSize()); pageOut.reserve(store.getPageSize());
out.write(COMMIT); out.write(COMMIT);
out.writeInt(session.getId()); out.writeInt(session.getId());
if (log.getFlushOnEachCommit()) { if (log.getFlushOnEachCommit()) {
...@@ -254,15 +258,14 @@ public class PageLog { ...@@ -254,15 +258,14 @@ public class PageLog {
trace.debug("log " + (add?"+":"-") + " s:" + session.getId() + " table:" + tableId + trace.debug("log " + (add?"+":"-") + " s:" + session.getId() + " table:" + tableId +
" row:" + row); " row:" + row);
} }
int todoLogPosShouldBeLong; session.addLogPos(logId, logPos);
session.addLogPos(0, (int) operation); row.setLastLog(logId, logPos);
row.setLastLog(0, (int) operation);
data.reset(); data.reset();
int todoWriteIntoOutputDirectly; int todoWriteIntoOutputDirectly;
row.write(data); row.write(data);
pageOut.prepareWriting(data.length() + store.getPageSize()); pageOut.reserve(data.length() + store.getPageSize());
out.write(add ? ADD : REMOVE); out.write(add ? ADD : REMOVE);
out.writeInt(session.getId()); out.writeInt(session.getId());
out.writeInt(tableId); out.writeInt(tableId);
...@@ -275,58 +278,75 @@ public class PageLog { ...@@ -275,58 +278,75 @@ public class PageLog {
} }
/** /**
* Close the log. * Flush the transaction log.
*/ */
void close() throws SQLException { void flush() throws SQLException {
try { try {
trace.debug("log close"); out.flush();
if (out != null) {
out.close();
}
out = null;
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, null); throw Message.convertIOException(e, null);
} }
} }
/** /**
* Close the log, truncate it, and re-open it. * Switch to a new log id.
* *
* @param id the new log id * @throws SQLException
*/ */
private void reopen() throws SQLException { void checkpoint() {
try { int currentDataPage = pageOut.getCurrentDataPageId();
trace.debug("log reopen"); logIdPageMap.put(logId, currentDataPage);
out.close(); logId++;
openForWriting(); }
flush();
int todoDeleteOrReUsePages; int getLogId() {
} catch (IOException e) { return logId;
throw Message.convertIOException(e, null); }
int getLogPos() {
return logPos;
}
/**
* Remove all pages until the given log (excluding).
*
* @param firstUncommittedLog the first log id to keep
*/
void removeUntil(int firstUncommittedLog) throws SQLException {
if (firstUncommittedLog == logId) {
return;
}
int firstDataPageToKeep = logIdPageMap.get(firstUncommittedLog);
while (true) {
// TODO keep trunk page in the cache
PageStreamTrunk t = new PageStreamTrunk(store, firstTrunkPage);
t.read();
if (t.contains(firstDataPageToKeep)) {
store.setLogFirstPage(t.getPos(), firstDataPageToKeep);
break;
}
t.free();
}
while (firstLogId < firstUncommittedLog) {
logIdPageMap.remove(firstLogId);
firstLogId++;
} }
} }
/** /**
* Flush the transaction log. * Close the log.
*/ */
void flush() throws SQLException { void close() throws SQLException {
try { try {
out.flush(); trace.debug("log close");
if (out != null) {
out.close();
}
out = null;
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, null); throw Message.convertIOException(e, null);
} }
} }
/**
* Flush and close the log.
*/
// public void close() throws SQLException {
// try {
// trace.debug("log close");
// out.close();
// } catch (IOException e) {
// throw Message.convertIOException(e, null);
// }
// }
} }
...@@ -20,6 +20,7 @@ public class PageOutputStream extends OutputStream { ...@@ -20,6 +20,7 @@ public class PageOutputStream extends OutputStream {
private PageStore store; private PageStore store;
private final Trace trace; private final Trace trace;
private int firstTrunkPageId;
private int trunkPageId; private int trunkPageId;
private int trunkNext; private int trunkNext;
private IntArray reservedPages = new IntArray(); private IntArray reservedPages = new IntArray();
...@@ -41,6 +42,7 @@ public class PageOutputStream extends OutputStream { ...@@ -41,6 +42,7 @@ public class PageOutputStream extends OutputStream {
this.trace = store.getTrace(); this.trace = store.getTrace();
this.store = store; this.store = store;
this.trunkPageId = trunkPage; this.trunkPageId = trunkPage;
firstTrunkPageId = trunkPage;
} }
/** /**
...@@ -49,7 +51,7 @@ public class PageOutputStream extends OutputStream { ...@@ -49,7 +51,7 @@ public class PageOutputStream extends OutputStream {
* *
* @param minBuffer the number of bytes to allocate * @param minBuffer the number of bytes to allocate
*/ */
void prepareWriting(int minBuffer) throws SQLException { void reserve(int minBuffer) throws SQLException {
if (reserved < minBuffer) { if (reserved < minBuffer) {
int pageSize = store.getPageSize(); int pageSize = store.getPageSize();
int capacityPerPage = PageStreamData.getCapacity(pageSize); int capacityPerPage = PageStreamData.getCapacity(pageSize);
...@@ -71,6 +73,9 @@ public class PageOutputStream extends OutputStream { ...@@ -71,6 +73,9 @@ public class PageOutputStream extends OutputStream {
int page = store.allocatePage(); int page = store.allocatePage();
reservedPages.add(page); reservedPages.add(page);
} }
if (data == null) {
initNextData();
}
} }
} }
...@@ -84,8 +89,8 @@ public class PageOutputStream extends OutputStream { ...@@ -84,8 +89,8 @@ public class PageOutputStream extends OutputStream {
} }
private void initNextData() { private void initNextData() {
int nextData = trunk == null ? -1 : trunk.getNextPage(); int nextData = trunk == null ? 0 : trunk.getNextDataPage();
if (nextData < 0) { if (nextData == -1) {
int parent = trunkPageId; int parent = trunkPageId;
if (trunkNext == 0) { if (trunkNext == 0) {
trunkPageId = reservedPages.get(0); trunkPageId = reservedPages.get(0);
...@@ -102,7 +107,7 @@ public class PageOutputStream extends OutputStream { ...@@ -102,7 +107,7 @@ public class PageOutputStream extends OutputStream {
trunk = new PageStreamTrunk(store, parent, trunkPageId, trunkNext, pageIds); trunk = new PageStreamTrunk(store, parent, trunkPageId, trunkNext, pageIds);
reservedPages.removeRange(0, len + 1); reservedPages.removeRange(0, len + 1);
} }
data = new PageStreamData(store, trunk.getNextPage(), trunk.getPos()); data = new PageStreamData(store, trunk.getNextDataPage(), trunk.getPos());
data.initWrite(); data.initWrite();
} }
...@@ -115,6 +120,7 @@ public class PageOutputStream extends OutputStream { ...@@ -115,6 +120,7 @@ public class PageOutputStream extends OutputStream {
} }
writing = true; writing = true;
try { try {
reserve(len);
while (len >= 0) { while (len >= 0) {
int l = data.write(b, off, len); int l = data.write(b, off, len);
if (l <= len) { if (l <= len) {
...@@ -157,4 +163,8 @@ public class PageOutputStream extends OutputStream { ...@@ -157,4 +163,8 @@ public class PageOutputStream extends OutputStream {
store = null; store = null;
} }
public int getCurrentDataPageId() {
return data.getPos();
}
} }
...@@ -19,6 +19,7 @@ import org.h2.index.Index; ...@@ -19,6 +19,7 @@ import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.index.PageBtreeIndex; import org.h2.index.PageBtreeIndex;
import org.h2.index.PageScanIndex; import org.h2.index.PageScanIndex;
import org.h2.log.LogSystem;
import org.h2.log.SessionState; import org.h2.log.SessionState;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.Trace; import org.h2.message.Trace;
...@@ -56,8 +57,9 @@ import org.h2.value.ValueString; ...@@ -56,8 +57,9 @@ import org.h2.value.ValueString;
* The format of page 1 and 2 is: * The format of page 1 and 2 is:
* <ul> * <ul>
* <li>0-7: write counter (incremented each time the header changes)</li> * <li>0-7: write counter (incremented each time the header changes)</li>
* <li>8-11: log head page (initially 4)</li> * <li>8-11: log trunk page (initially 4)</li>
* <li>12-19: checksum of bytes 0-16 (CRC32)</li> * <li>12-15: log data page (initially 5)</li>
* <li>16-23: checksum of bytes 0-15 (CRC32)</li>
* </ul> * </ul>
* Page 2 contains the first free list page. * Page 2 contains the first free list page.
* Page 3 contains the meta table root page. * Page 3 contains the meta table root page.
...@@ -65,12 +67,14 @@ import org.h2.value.ValueString; ...@@ -65,12 +67,14 @@ import org.h2.value.ValueString;
*/ */
public class PageStore implements CacheWriter { public class PageStore implements CacheWriter {
// TODO currently working on PageLog.removeUntil
// TODO unlimited number of log streams (TestPageStoreDb) // TODO unlimited number of log streams (TestPageStoreDb)
// TODO check if PageLog.reservePages is required - yes it is - change it // TODO check if PageLog.reservePages is required - yes it is - change it
// TODO PageStore.openMetaIndex (desc and nulls first / last) // TODO PageStore.openMetaIndex (desc and nulls first / last)
// TODO btree index with fixed size values doesn't need offset and so on // TODO btree index with fixed size values doesn't need offset and so on
// TODO better checksums (for example, multiple fletcher) // TODO better checksums (for example, multiple fletcher)
// TODO replace CRC32
// TODO log block allocation // TODO log block allocation
// TODO block compression: maybe http://en.wikipedia.org/wiki/LZJB // TODO block compression: maybe http://en.wikipedia.org/wiki/LZJB
// with RLE, specially for 0s. // with RLE, specially for 0s.
...@@ -137,7 +141,7 @@ public class PageStore implements CacheWriter { ...@@ -137,7 +141,7 @@ public class PageStore implements CacheWriter {
private int pageSize; private int pageSize;
private int pageSizeShift; private int pageSizeShift;
private long writeCounter; private long writeCounter;
private int logFirstTrunkPage; private int logFirstTrunkPage, logFirstDataPage;
private int cacheSize; private int cacheSize;
private Cache cache; private Cache cache;
...@@ -221,7 +225,7 @@ public class PageStore implements CacheWriter { ...@@ -221,7 +225,7 @@ public class PageStore implements CacheWriter {
freeListPagesPerList = PageFreeList.getPagesAddressed(pageSize); freeListPagesPerList = PageFreeList.getPagesAddressed(pageSize);
fileLength = file.length(); fileLength = file.length();
pageCount = (int) (fileLength / pageSize); pageCount = (int) (fileLength / pageSize);
initLog(); log = new PageLog(this);
recover(true); recover(true);
recover(false); recover(false);
checkpoint(); checkpoint();
...@@ -234,12 +238,9 @@ public class PageStore implements CacheWriter { ...@@ -234,12 +238,9 @@ public class PageStore implements CacheWriter {
pageCount = 5; pageCount = 5;
increaseFileSize(INCREMENT_PAGES - pageCount); increaseFileSize(INCREMENT_PAGES - pageCount);
writeStaticHeader(); writeStaticHeader();
writeVariableHeader(); log = new PageLog(this);
initLog(); log.openForWriting(logFirstTrunkPage);
openMetaIndex(); openMetaIndex();
log.openForWriting();
switchLog();
log.flush();
systemTableHeadPos = Index.EMPTY_HEAD; systemTableHeadPos = Index.EMPTY_HEAD;
} }
// lastUsedPage = getFreeList().getLastUsed() + 1; // lastUsedPage = getFreeList().getLastUsed() + 1;
...@@ -265,18 +266,12 @@ public class PageStore implements CacheWriter { ...@@ -265,18 +266,12 @@ public class PageStore implements CacheWriter {
for (CacheObject rec : list) { for (CacheObject rec : list) {
writeBack(rec); writeBack(rec);
} }
int todoFlushBeforeReopen;
switchLog(); switchLog();
int todoWriteDeletedPages; // TODO shrink file if required here
// int pageCount = getFreeList().getLastUsed() + 1;
// trace.debug("pageCount:" + pageCount);
// file.setLength(pageSize * pageCount);
} }
// TODO shrink file if required here
// int pageCount = getFreeList().getLastUsed() + 1;
// trace.debug("pageCount:" + pageCount);
// file.setLength(pageSize * pageCount);
}
private void initLog() {
log = new PageLog(this, logFirstTrunkPage);
} }
private void switchLog() throws SQLException { private void switchLog() throws SQLException {
...@@ -284,30 +279,18 @@ public class PageStore implements CacheWriter { ...@@ -284,30 +279,18 @@ public class PageStore implements CacheWriter {
if (database.isReadOnly()) { if (database.isReadOnly()) {
return; return;
} }
log.close(); Session[] sessions = database.getSessions(true);
int todoCanOnlyReuseAfterLoggedChangesAreWritten; int firstUncommittedLog = log.getLogId();
log.openForWriting(); for (int i = 0; i < sessions.length; i++) {
Session session = sessions[i];
// Session[] sessions = database.getSessions(true); int log = session.getFirstUncommittedLog();
// int firstUncommittedLog = getLog().getId(); if (log != LogSystem.LOG_WRITTEN) {
// int firstUncommittedPos = getLog().getPos(); if (log < firstUncommittedLog) {
// for (int i = 0; i < sessions.length; i++) { firstUncommittedLog = log;
// Session session = sessions[i]; }
// int log = session.getFirstUncommittedLog(); }
// int pos = session.getFirstUncommittedPos(); }
// if (pos != LOG_WRITTEN) { log.removeUntil(firstUncommittedLog);
// if (log < firstUncommittedLog ||
// (log == firstUncommittedLog && pos < firstUncommittedPos)) {
// firstUncommittedLog = log;
// firstUncommittedPos = pos;
// }
// }
// }
// if (nextLog.containsUncommitted())
// activeLog = nextLogId;
// getLog().reopen();
} }
private void readHeader() throws SQLException { private void readHeader() throws SQLException {
...@@ -334,7 +317,6 @@ public class PageStore implements CacheWriter { ...@@ -334,7 +317,6 @@ public class PageStore implements CacheWriter {
accessMode = "r"; accessMode = "r";
file = database.openFile(fileName, accessMode, true); file = database.openFile(fileName, accessMode, true);
} }
CRC32 crc = new CRC32();
for (int i = 1;; i++) { for (int i = 1;; i++) {
if (i == 3) { if (i == 3) {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName); throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName);
...@@ -343,13 +325,14 @@ public class PageStore implements CacheWriter { ...@@ -343,13 +325,14 @@ public class PageStore implements CacheWriter {
readPage(i, page); readPage(i, page);
writeCounter = page.readLong(); writeCounter = page.readLong();
logFirstTrunkPage = page.readInt(); logFirstTrunkPage = page.readInt();
crc.update(page.getBytes(), 0, 12); logFirstDataPage = page.readInt();
CRC32 crc = new CRC32();
crc.update(page.getBytes(), 0, page.length());
long expected = crc.getValue(); long expected = crc.getValue();
long got = page.readLong(); long got = page.readLong();
if (expected == got) { if (expected == got) {
break; break;
} }
crc.reset();
} }
} }
...@@ -389,6 +372,18 @@ public class PageStore implements CacheWriter { ...@@ -389,6 +372,18 @@ public class PageStore implements CacheWriter {
file.write(page.getBytes(), 0, pageSize - FileStore.HEADER_LENGTH); file.write(page.getBytes(), 0, pageSize - FileStore.HEADER_LENGTH);
} }
/**
* Set the trunk page and data page id of the log.
*
* @param trunkPageId the trunk page id
* @param dataPageId the data page id
*/
void setLogFirstPage(int trunkPageId, int dataPageId) throws SQLException {
this.logFirstTrunkPage = trunkPageId;
this.logFirstDataPage = dataPageId;
writeVariableHeader();
}
private void writeVariableHeader() throws SQLException { private void writeVariableHeader() throws SQLException {
DataPage page = DataPage.create(database, new byte[pageSize]); DataPage page = DataPage.create(database, new byte[pageSize]);
page.writeLong(writeCounter); page.writeLong(writeCounter);
...@@ -671,25 +666,7 @@ public class PageStore implements CacheWriter { ...@@ -671,25 +666,7 @@ public class PageStore implements CacheWriter {
} }
try { try {
recoveryRunning = true; recoveryRunning = true;
int maxId = 0; log.recover(undo);
// for (int i = 0; i < LOG_COUNT; i++) {
// int id = logs[i].openForReading();
// if (id > maxId) {
// maxId = id;
// activeLog = i;
// }
// }
// for (int i = 0; i < LOG_COUNT; i++) {
// int j;
// if (undo) {
// // undo: start with the newest file and go backward
// j = Math.abs(activeLog - i) % LOG_COUNT;
// } else {
// // redo: start with the oldest log file
// j = (activeLog + 1 + i) % LOG_COUNT;
// }
// logs[j].recover(undo);
// }
if (!undo) { if (!undo) {
switchLog(); switchLog();
int todoProbablyStillRequiredForTwoPhaseCommit; int todoProbablyStillRequiredForTwoPhaseCommit;
......
...@@ -67,11 +67,11 @@ public class PageStreamTrunk extends Record { ...@@ -67,11 +67,11 @@ public class PageStreamTrunk extends Record {
} }
} }
void setNextPage(int page) { void setNextDataPage(int page) {
pageIds[index++] = page; pageIds[index++] = page;
} }
int getNextPage() { int getNextDataPage() {
if (index >= pageIds.length) { if (index >= pageIds.length) {
return -1; return -1;
} }
...@@ -108,4 +108,29 @@ public class PageStreamTrunk extends Record { ...@@ -108,4 +108,29 @@ public class PageStreamTrunk extends Record {
return (pageSize - DATA_START) / 4; return (pageSize - DATA_START) / 4;
} }
/**
* Check if the given data page is in this trunk page.
*
* @param dataPageId the page id
* @return true if it is
*/
boolean contains(int dataPageId) {
for (int i = 0; i < pageCount; i++) {
if (pageIds[i] == dataPageId) {
return true;
}
}
return false;
}
/**
* Free this page and all data pages.
*/
void free() throws SQLException {
store.freePage(getPos(), false, null);
for (int i = 0; i < pageCount; i++) {
store.freePage(pageIds[i], false, null);
}
}
} }
...@@ -17,7 +17,6 @@ import java.sql.Connection; ...@@ -17,7 +17,6 @@ import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Iterator;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
...@@ -27,7 +26,6 @@ import org.h2.engine.Database; ...@@ -27,7 +26,6 @@ import org.h2.engine.Database;
import org.h2.index.Cursor; import org.h2.index.Cursor;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.index.Page;
import org.h2.index.PageScanIndex; import org.h2.index.PageScanIndex;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
...@@ -322,7 +320,7 @@ public class TestPageStore extends TestBase { ...@@ -322,7 +320,7 @@ public class TestPageStore extends TestBase {
if (file) { if (file) {
in = new BufferedInputStream(new FileInputStream(f), 4 * 1024); in = new BufferedInputStream(new FileInputStream(f), 4 * 1024);
} else { } else {
in = new PageInputStream(store, 0); in = new PageInputStream(store, 0, 0);
} }
while (true) { while (true) {
int len = in.read(buff); int len = in.read(buff);
...@@ -360,7 +358,7 @@ public class TestPageStore extends TestBase { ...@@ -360,7 +358,7 @@ public class TestPageStore extends TestBase {
p += l; p += l;
} }
out.close(); out.close();
PageInputStream in = new PageInputStream(store, 0); PageInputStream in = new PageInputStream(store, 0, 0);
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;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论