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

--no commit message

--no commit message
上级 6fad76b1
......@@ -161,18 +161,18 @@ td.searchLink a:hover {
}
table.content {
width: 100%;
height: 100%;
width: 100%;
height: 100%;
border: 0px;
}
tr.content {
border:0px;
border:0px;
border-left:1px solid #aca899;
}
td.content {
border:0px;
border:0px;
border-left:1px solid #aca899;
}
......@@ -196,4 +196,3 @@ td.content {
.compareN {
color: #800;
}
\ No newline at end of file
......@@ -291,6 +291,19 @@ public class SysProperties {
*/
public static final int REDO_BUFFER_SIZE = getIntSetting("h2.redoBufferSize", 256 * 1024);
/**
* System property <code>h2.reuseSpaceAfter</code> (default: 16).<br />
* Reuse space in database files after this many pages are free.
*/
public static final int REUSE_SPACE_AFTER = getIntSetting("h2.reuseSpaceAfter", 1);
/**
* System property <code>h2.reuseSpaceQuickly</code> (default: true).<br />
* Reuse space in database files quickly.
*/
private int test;
public static final boolean REUSE_SPACE_QUICKLY = getBooleanSetting("h2.reuseSpaceQuickly", true);
/**
* System property <code>h2.runFinalize</code> (default: true).<br />
* Run finalizers to detect unclosed connections.
......
......@@ -33,6 +33,7 @@ import org.h2.util.CacheObject;
import org.h2.util.CacheWriter;
import org.h2.util.FileUtils;
import org.h2.util.IntArray;
import org.h2.util.IntHashMap;
import org.h2.util.MathUtils;
import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
......@@ -79,6 +80,8 @@ public class DiskFile implements CacheWriter {
private HashSet potentiallyFreePages;
private int fileBlockCount;
private IntArray pageOwners;
// the latest delete in a page
private IntArray pageDelete;
private Cache cache;
private LogSystem log;
......@@ -92,8 +95,7 @@ public class DiskFile implements CacheWriter {
private int redoBufferSize;
private int readCount, writeCount;
private String mode;
private int nextDeleteId;
private int nextDeleteId = 1;
public DiskFile(Database database, String fileName, String mode, boolean dataFile, boolean logChanges, int cacheSize) throws SQLException {
reset();
......@@ -531,6 +533,7 @@ public class DiskFile implements CacheWriter {
}
int allocate(Storage storage, int blockCount) throws SQLException {
reuseSpace();
synchronized (database) {
if (file == null) {
throw Message.getSQLException(ErrorCode.SIMULATED_POWER_OFF);
......@@ -598,59 +601,64 @@ public class DiskFile implements CacheWriter {
if (pos + blockCount > fileBlockCount) {
setBlockCount(pos + blockCount);
}
int deleteId = 0;
if (session != null) {
deleteId = nextDeleteId++;
setUncommittedDelete(session, getPage(pos), deleteId);
}
uncommittedDelete(session);
for (int i = pos; i < pos + blockCount; i++) {
used.clear(i);
if ((i % BLOCKS_PER_PAGE == 0) && (pos + blockCount >= i + BLOCKS_PER_PAGE)) {
// if this is the first page of a block and if the whole page is free
if (session != null && logChanges) {
setUncommittedDelete(session, getPage(i), deleteId);
} else {
setPageOwner(getPage(i), FREE_PAGE);
freePage(getPage(i));
}
}
int start = getPage(pos), end = getPage(pos + blockCount);
for (int i = start; i <= end; i++) {
pageDelete.set(i, nextDeleteId);
}
}
void reuseSpace() throws SQLException {
if (SysProperties.REUSE_SPACE_QUICKLY) {
if (potentiallyFreePages.size() >= SysProperties.REUSE_SPACE_AFTER) {
Session[] sessions = database.getSessions();
int oldest = 0;
for (int i = 0; i < sessions.length; i++) {
int deleteId = sessions[i].getLastUncommittedDelete();
if (oldest == 0 || deleteId < oldest) {
oldest = deleteId;
}
}
for (Iterator it = potentiallyFreePages.iterator(); it.hasNext();) {
int p = ((Integer) it.next()).intValue();
int testingReallyCareful;
if (oldest == 0 /*|| oldest > pageDelete.get(p)*/) {
setPageOwner(p, FREE_PAGE);
it.remove();
}
}
}
}
}
void uncommittedDelete(Session session) throws SQLException {
if (session != null && logChanges && SysProperties.REUSE_SPACE_QUICKLY) {
int deleteId = session.getLastUncommittedDelete();
if (deleteId == 0 || deleteId < nextDeleteId) {
deleteId = ++nextDeleteId;
session.setLastUncommittedDelete(deleteId);
}
}
}
void freePage(int page) throws SQLException {
if (!logChanges) {
setPageOwner(page, FREE_PAGE);
} else {
int todoTestThis;
// synchronized (potentiallyFreePages) {
// potentiallyFreePages.add(ObjectUtils.getInteger(page));
// if (potentiallyFreePages.size() > 20) {
// Session[] sessions = database.getSessions();
// int oldest = 0;
// for (int i = 0; i < sessions.length; i++) {
// int deleteId = sessions[i].getLastUncommittedDelete();
// if (oldest == 0 || deleteId < oldest) {
// oldest = deleteId;
// }
// }
// for (Iterator it = potentiallyFreePages.iterator(); it.hasNext();) {
// int p = ((Integer) it.next()).intValue();
// if (oldest == 0 || oldest > pageDelete.get(p)) {
// setPageOwner(p, FREE_PAGE);
////int testing;
////System.out.println("free page " + p);
// it.remove();
// }
// }
// }
// }
if (SysProperties.REUSE_SPACE_QUICKLY) {
potentiallyFreePages.add(ObjectUtils.getInteger(page));
reuseSpace();
}
}
}
private void setUncommittedDelete(Session session, int page, int deleteId) {
session.setLastUncommittedDelete(deleteId);
pageDelete.set(page, deleteId);
}
int getPage(int pos) {
return pos >>> BLOCK_PAGE_PAGE_SHIFT;
}
......@@ -688,6 +696,10 @@ public class DiskFile implements CacheWriter {
}
if (storageId >= 0) {
database.getStorage(storageId, this).addPage(page);
if (SysProperties.REUSE_SPACE_QUICKLY) {
potentiallyFreePages.remove(ObjectUtils.getInteger(page));
pageDelete.set(page, 0);
}
}
pageOwners.set(page, storageId);
}
......
......@@ -153,15 +153,14 @@ java org.h2.test.TestAll timer
/*
Extend tests that simulate power off (multiple connections, truncate table, drop table, rename objects,...)
Test space re-use
REUSE_SPACE_AFTER=20 or so
sourceDocs.html: move
Automate real power off tests
timer test
Test space re-use
enforce javadoc comments for constants
Can sometimes not delete log file? need test case
link to new changelog and roadmap, remove pages from google groups
......@@ -175,6 +174,7 @@ Adjust cache memory usage
Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes
History:
Empty space is re-used less agressively because this could cause database corruption in some cases.
CSV tool now support lineSeparator
......@@ -412,10 +412,7 @@ DROP TABLE MY_TEST;
new TestLinkedTable().runTest(this);
new TestListener().runTest(this);
new TestLob().runTest(this);
int todo;
// new TestLogFile().runTest(this);
new TestLogFile().runTest(this);
new TestMemoryUsage().runTest(this);
new TestMultiConn().runTest(this);
new TestMultiDimension().runTest(this);
......@@ -431,7 +428,7 @@ DROP TABLE MY_TEST;
new TestSequence().runTest(this);
int todo2;
// new TestSpaceReuse().runTest(this);
new TestSpaceReuse().runTest(this);
new TestSpeed().runTest(this);
new TestTempTables().runTest(this);
......@@ -472,6 +469,8 @@ DROP TABLE MY_TEST;
// synth
new TestCrashAPI().runTest(this);
new TestRandomSQL().runTest(this);
int test3;
new TestKillRestart().runTest(this);
new TestKillRestartMulti().runTest(this);
......
......@@ -53,7 +53,7 @@ public class TestLogFile extends TestBase {
long length = reconnect(maxFiles);
insert();
long l2 = reconnect(maxFiles);
trace("l2=" + l2);
trace("length:" + length + " l2:" + l2);
check(l2 <= length * 2);
}
conn.close();
......@@ -90,6 +90,7 @@ public class TestLogFile extends TestBase {
}
}
checkLogSize();
// stat.execute("TRUNCATE TABLE TEST");
}
}
......@@ -137,17 +137,20 @@ public class Doclet {
int fieldId = 0;
for (int i = 0; i < fields.length; i++) {
FieldDoc field = fields[i];
if (!field.isFinal() || !field.isStatic() || !field.isPublic()) {
if (skipField(clazz, field)) {
continue;
}
String name = field.name();
String text = field.commentText();
if (text == null || text.trim().length() == 0) {
throw new Error("undocumented field? " + clazz.name() + "." + name + " " + field);
}
if (text.startsWith("INTERNAL")) {
continue;
}
if (fieldId == 0) {
writer.println("<br /><table><tr><th colspan=\"2\">Fields</th></tr>");
}
String name = field.name();
String type = getTypeName(true, field.type());
writer.println("<tr><td class=\"return\">" + type + "</td><td class=\"method\">");
String constant = field.constantValueExpression();
......@@ -260,7 +263,7 @@ public class Doclet {
});
for (int i = 0; i < fields.length; i++) {
FieldDoc field = fields[i];
if (!field.isFinal() || !field.isStatic() || !field.isPublic()) {
if (skipField(clazz, field)) {
continue;
}
String text = field.commentText();
......@@ -314,6 +317,13 @@ public class Doclet {
return text;
}
private static boolean skipField(ClassDoc clazz, FieldDoc field) {
if (!field.isFinal() || !field.isStatic() || !field.isPublic() || field.containingClass() != clazz) {
return true;
}
return false;
}
private static boolean skipMethod(MethodDoc method) {
ClassDoc clazz = method.containingClass();
if (INTERFACES_ONLY && (!clazz.isAbstract() || !method.isAbstract()) && !clazz.isInterface()) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论