提交 6acd8d14 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 7b88d790
...@@ -395,6 +395,8 @@ private int test; ...@@ -395,6 +395,8 @@ private int test;
* INTERNAL * INTERNAL
*/ */
public static int getLogFileDeleteDelay() { public static int getLogFileDeleteDelay() {
return getIntSetting(H2_LOG_DELETE_DELAY, 2000); int test;
return getIntSetting(H2_LOG_DELETE_DELAY, 0);
// return getIntSetting(H2_LOG_DELETE_DELAY, 2000);
} }
} }
...@@ -51,6 +51,7 @@ import org.h2.util.BitField; ...@@ -51,6 +51,7 @@ import org.h2.util.BitField;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.CacheLRU; import org.h2.util.CacheLRU;
import org.h2.util.ClassUtils; import org.h2.util.ClassUtils;
import org.h2.util.DelayedFileDeleter;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.IntHashMap; import org.h2.util.IntHashMap;
...@@ -1344,11 +1345,7 @@ public class Database implements DataHandler { ...@@ -1344,11 +1345,7 @@ public class Database implements DataHandler {
} }
public void deleteLogFileLater(String fileName) throws SQLException { public void deleteLogFileLater(String fileName) throws SQLException {
if (writer == null) { DelayedFileDeleter.getInstance().deleteLater(fileName);
FileUtils.delete(fileName);
} else {
writer.deleteLater(fileName);
}
} }
public Class loadUserClass(String className) throws SQLException { public Class loadUserClass(String className) throws SQLException {
......
...@@ -34,7 +34,6 @@ import org.h2.message.TraceObject; ...@@ -34,7 +34,6 @@ import org.h2.message.TraceObject;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.util.ClassUtils; import org.h2.util.ClassUtils;
import org.h2.util.JdbcConnectionListener; import org.h2.util.JdbcConnectionListener;
import org.h2.util.TempFileDeleter;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLob; import org.h2.value.ValueLob;
...@@ -214,7 +213,6 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -214,7 +213,6 @@ public class JdbcConnection extends TraceObject implements Connection {
* rolled back. * rolled back.
*/ */
public void close() throws SQLException { public void close() throws SQLException {
TempFileDeleter.deleteUnused();
synchronized (this) { synchronized (this) {
if (listener == null) { if (listener == null) {
closeConnection(); closeConnection();
......
...@@ -312,6 +312,8 @@ public class LogFile { ...@@ -312,6 +312,8 @@ public class LogFile {
} }
public void redoAllGoEnd() throws SQLException { public void redoAllGoEnd() throws SQLException {
int test;
//System.out.println("redo log " + fileName);
boolean readOnly = logSystem.getDatabase().getReadOnly(); boolean readOnly = logSystem.getDatabase().getReadOnly();
long length = file.length(); long length = file.length();
if (length <= FileStore.HEADER_LENGTH) { if (length <= FileStore.HEADER_LENGTH) {
......
...@@ -213,6 +213,10 @@ public class DiskFile implements CacheWriter { ...@@ -213,6 +213,10 @@ public class DiskFile implements CacheWriter {
} }
public void initFromSummary(byte[] summary) { public void initFromSummary(byte[] summary) {
int test;
//System.out.println("init from summary: " + this);
synchronized (database) { synchronized (database) {
if (summary == null || summary.length == 0) { if (summary == null || summary.length == 0) {
ObjectArray list = database.getAllStorages(); ObjectArray list = database.getAllStorages();
......
...@@ -16,7 +16,7 @@ import org.h2.security.SecureFileStore; ...@@ -16,7 +16,7 @@ import org.h2.security.SecureFileStore;
import org.h2.store.fs.FileObject; import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.TempFileDeleter; import org.h2.util.DelayedFileDeleter;
/** /**
* This class is an abstraction of a random access file. * This class is an abstraction of a random access file.
...@@ -163,7 +163,7 @@ public class FileStore { ...@@ -163,7 +163,7 @@ public class FileStore {
public void closeAndDeleteSilently() { public void closeAndDeleteSilently() {
if (file != null) { if (file != null) {
closeSilently(); closeSilently();
TempFileDeleter.deleteFile(autoDeleteReference, name); DelayedFileDeleter.getInstance().autoDeleteFile(autoDeleteReference, name);
name = null; name = null;
} }
} }
...@@ -324,11 +324,11 @@ public class FileStore { ...@@ -324,11 +324,11 @@ public class FileStore {
} }
public void autoDelete() { public void autoDelete() {
autoDeleteReference = TempFileDeleter.addFile(name, this); autoDeleteReference = DelayedFileDeleter.getInstance().addTempFile(name, this);
} }
public void stopAutoDelete() { public void stopAutoDelete() {
TempFileDeleter.stopAutoDelete(autoDeleteReference, name); DelayedFileDeleter.getInstance().stopAutoDelete(autoDeleteReference, name);
autoDeleteReference = null; autoDeleteReference = null;
} }
......
...@@ -201,7 +201,9 @@ public class Storage { ...@@ -201,7 +201,9 @@ public class Storage {
public void delete(Session session) throws SQLException { public void delete(Session session) throws SQLException {
truncate(session); truncate(session);
database.removeStorage(id, file);
int test;
// database.removeStorage(id, file);
} }
// private int allocateBest(int start, int blocks) { // private int allocateBest(int start, int blocks) {
......
...@@ -6,9 +6,6 @@ package org.h2.store; ...@@ -6,9 +6,6 @@ package org.h2.store;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -19,10 +16,7 @@ import org.h2.log.LogSystem; ...@@ -19,10 +16,7 @@ import org.h2.log.LogSystem;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.util.FileUtils;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
import org.h2.util.TempFileDeleter;
/** /**
* The writer thread is responsible to flush the transaction log file from time to time. * The writer thread is responsible to flush the transaction log file from time to time.
...@@ -44,55 +38,6 @@ public class WriterThread extends Thread { ...@@ -44,55 +38,6 @@ public class WriterThread extends Thread {
private int writeDelay; private int writeDelay;
private long lastIndexFlush; private long lastIndexFlush;
private volatile boolean stop; private volatile boolean stop;
private HashMap deleteLater = new HashMap();
private volatile long deleteNext;
public void deleteLater(String fileName) {
long at = System.currentTimeMillis() + SysProperties.getLogFileDeleteDelay();
if (at < deleteNext || deleteNext == 0) {
deleteNext = at;
}
synchronized (deleteLater) {
deleteLater.put(fileName, ObjectUtils.getLong(at));
}
}
private void delete(boolean now) {
if (!now && (deleteNext == 0 || System.currentTimeMillis() < deleteNext)) {
return;
}
long time = System.currentTimeMillis();
ObjectArray delete = new ObjectArray();
synchronized (deleteLater) {
deleteNext = 0;
for (Iterator it = deleteLater.entrySet().iterator(); it.hasNext();) {
Entry entry = (Entry) it.next();
long at = ((Long) entry.getValue()).longValue();
if (now || time >= at) {
String fileName = (String) entry.getKey();
delete.add(fileName);
} else {
if (at < deleteNext || deleteNext == 0) {
deleteNext = at;
}
}
}
}
for (int i = 0; i < delete.size(); i++) {
String fileName = (String) delete.get(i);
try {
FileUtils.delete(fileName);
synchronized (deleteLater) {
deleteLater.remove(fileName);
}
} catch (SQLException e) {
Database database = (Database) databaseRef.get();
if (database != null) {
database.getTrace(Trace.DATABASE).error("delete " + fileName, e);
}
}
}
}
private WriterThread(Database database, int writeDelay) { private WriterThread(Database database, int writeDelay) {
this.databaseRef = new WeakReference(database); this.databaseRef = new WeakReference(database);
...@@ -161,8 +106,6 @@ public class WriterThread extends Thread { ...@@ -161,8 +106,6 @@ public class WriterThread extends Thread {
public void run() { public void run() {
while (!stop) { while (!stop) {
delete(false);
TempFileDeleter.deleteUnused();
Database database = (Database) databaseRef.get(); Database database = (Database) databaseRef.get();
if (database == null) { if (database == null) {
break; break;
...@@ -196,9 +139,6 @@ public class WriterThread extends Thread { ...@@ -196,9 +139,6 @@ public class WriterThread extends Thread {
} }
public void stopThread() { public void stopThread() {
int testing;
delete(false);
stop = true; stop = true;
} }
......
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import org.h2.constant.SysProperties;
import org.h2.message.Message;
/**
* Deletes files later on or if they are not used.
* This class deletes temporary files when they are not used any longer.
*/
public class DelayedFileDeleter extends Thread {
private static DelayedFileDeleter instance;
private final ReferenceQueue queue = new ReferenceQueue();
private final HashMap refMap = new HashMap();
private final HashMap deleteLater = new HashMap();
private long deleteNext;
public synchronized void deleteLater(String fileName) throws SQLException {
int delay = SysProperties.getLogFileDeleteDelay();
if (delay == 0 && deleteLater.size() == 0) {
// shortcut if delay is 0
FileUtils.delete(fileName);
return;
}
long at = System.currentTimeMillis() + delay;
if (deleteNext != 0 && at <= deleteNext) {
// make sure files are deleted in the correct order
at = deleteNext + 1;
}
deleteNext = at;
deleteLater.put(fileName, ObjectUtils.getLong(at));
}
/**
* Delete at most one old file (after the delay)
*/
private void deleteOld() {
long now = System.currentTimeMillis();
if (deleteNext == 0 || now < deleteNext) {
return;
}
String delete = null;
long oldest = 0;
for (Iterator it = deleteLater.entrySet().iterator(); it.hasNext();) {
Entry entry = (Entry) it.next();
long at = ((Long) entry.getValue()).longValue();
if (at < now && (delete == null || at < oldest)) {
delete = (String) entry.getKey();
oldest = at;
}
}
if (delete == null) {
return;
}
try {
FileUtils.delete(delete);
} catch (SQLException e) {
// ignore
}
deleteLater.remove(delete);
}
public static synchronized DelayedFileDeleter getInstance() {
if (instance == null) {
int test;
//System.out.println("DelayerFileDeleter.getInstance()");
instance = new DelayedFileDeleter();
instance.setDaemon(true);
instance.setPriority(Thread.MIN_PRIORITY);
instance.start();
}
return instance;
}
private DelayedFileDeleter() {
setName("H2 FileDeleter");
}
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
synchronized (this) {
if (refMap.size() != 0) {
deleteUnused();
} else if (deleteLater.size() != 0) {
deleteOld();
} else {
break;
}
}
}
int test;
//System.out.println("DelayerFileDeleter.stop()");
}
/**
* Add a temp file to the queue and delete it if it is no longer referenced.
*
* @param fileName the file name
* @param file the object to track
* @return the reference
*/
public synchronized Reference addTempFile(String fileName, Object file) {
FileUtils.trace("FileDeleter.addFile", fileName, file);
PhantomReference ref = new PhantomReference(file, queue);
refMap.put(ref, fileName);
return ref;
}
/**
* Delete a file now and remove it from the queue.
*
* @param the reference in the queue
* @param fileName the file name
*/
public synchronized void autoDeleteFile(Reference ref, String fileName) {
if (ref != null) {
String f2 = (String) refMap.remove(ref);
if (SysProperties.CHECK && f2 != null && fileName != null && !f2.equals(fileName)) {
throw Message.getInternalError("f2:" + f2 + " f:" + fileName);
}
}
if (fileName != null && FileUtils.exists(fileName)) {
try {
FileUtils.trace("FileDeleter.deleteFile", fileName, null);
FileUtils.delete(fileName);
} catch (Exception e) {
// TODO log such errors?
}
deleteUnused();
}
}
/**
* Delete all unreferenced files that have been garbage collected now.
* This method is called from time to time by the application.
*/
private void deleteUnused() {
while (true) {
Reference ref = queue.poll();
if (ref == null) {
break;
}
autoDeleteFile(ref, null);
}
}
/**
* Remove a file from the list of files to be deleted.
*
* @param ref the reference
* @param fileName the file name
*/
public synchronized void stopAutoDelete(Reference ref, String fileName) {
FileUtils.trace("FileDeleter.stopAutoDelete", fileName, ref);
if (ref != null) {
String f2 = (String) refMap.remove(ref);
if (SysProperties.CHECK && (f2 == null || !f2.equals(fileName))) {
throw Message.getInternalError("f2:" + f2 + " f:" + fileName);
}
}
}
}
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import org.h2.constant.SysProperties;
import org.h2.message.Message;
/**
* This class deletes temporary files when they are not used any longer.
*/
public class TempFileDeleter {
private static final ReferenceQueue QUEUE = new ReferenceQueue();
private static final HashMap REF_MAP = new HashMap();
public static synchronized Reference addFile(String fileName, Object file) {
FileUtils.trace("TempFileDeleter.addFile", fileName, file);
PhantomReference ref = new PhantomReference(file, QUEUE);
REF_MAP.put(ref, fileName);
deleteUnused();
return ref;
}
public static synchronized void deleteFile(Reference ref, String fileName) {
if (ref != null) {
String f2 = (String) REF_MAP.remove(ref);
if (SysProperties.CHECK && f2 != null && fileName != null && !f2.equals(fileName)) {
throw Message.getInternalError("f2:" + f2 + " f:" + fileName);
}
}
if (fileName != null && FileUtils.exists(fileName)) {
try {
FileUtils.trace("TempFileDeleter.deleteFile", fileName, null);
FileUtils.delete(fileName);
} catch (Exception e) {
// TODO log such errors?
}
deleteUnused();
}
}
public static void deleteUnused() {
// Mystery: I don't know how QUEUE could get null, but two independent
// people reported NullPointerException here - if somebody understands
// how it could happen please report it!
// Environment: web application under Tomcat, exception occurs during undeploy
while (QUEUE != null) {
Reference ref = QUEUE.poll();
if (ref == null) {
break;
}
deleteFile(ref, null);
}
}
public static void stopAutoDelete(Reference ref, String fileName) {
FileUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref);
if (ref != null) {
String f2 = (String) REF_MAP.remove(ref);
if (SysProperties.CHECK && (f2 == null || !f2.equals(fileName))) {
throw Message.getInternalError("f2:" + f2 + " f:" + fileName);
}
}
deleteUnused();
}
}
...@@ -179,6 +179,8 @@ conn3: ...@@ -179,6 +179,8 @@ conn3:
4) insert into bla 4) insert into bla
5) commit 5) commit
after init, scan all storages and return those that don't belong to a live database object!!
Automate real power off tests Automate real power off tests
Extend tests that simulate power off Extend tests that simulate power off
timer test timer test
......
...@@ -146,6 +146,10 @@ public abstract class TestBase { ...@@ -146,6 +146,10 @@ public abstract class TestBase {
} }
private Connection getConnectionInternal(String url, String user, String password) throws Exception { private Connection getConnectionInternal(String url, String user, String password) throws Exception {
int test;
//System.out.println();
//System.out.println("connect to " + url);
Class.forName("org.h2.Driver"); Class.forName("org.h2.Driver");
// url += ";DEFAULT_TABLE_TYPE=1"; // url += ";DEFAULT_TABLE_TYPE=1";
// Class.forName("org.hsqldb.jdbcDriver"); // Class.forName("org.hsqldb.jdbcDriver");
......
...@@ -32,46 +32,58 @@ public class TestIndex extends TestBase { ...@@ -32,46 +32,58 @@ public class TestIndex extends TestBase {
} }
public void test() throws Exception { public void test() throws Exception {
testDescIndex(); int teting;
// testDescIndex();
//
if (config.networked && config.big) { if (config.networked && config.big) {
return; return;
} }
random.setSeed(100); int teting2;
//
deleteDb("index"); // random.setSeed(100);
testWideIndex(147); //
testWideIndex(313); // deleteDb("index");
testWideIndex(979); // testWideIndex(147);
testWideIndex(1200); // testWideIndex(313);
testWideIndex(2400); // testWideIndex(979);
if (config.big && config.logMode == 2) { // testWideIndex(1200);
for (int i = 0; i < 2000; i++) { // testWideIndex(2400);
if ((i % 100) == 0) { // if (config.big && config.logMode == 2) {
System.out.println("width: " + i); // for (int i = 0; i < 2000; i++) {
} // if ((i % 100) == 0) {
testWideIndex(i); // System.out.println("width: " + i);
} // }
} // testWideIndex(i);
// }
// }
//
// testLike();
// reconnect();
// testConstraint();
// testLargeIndex();
// testMultiColumnIndex();
// // long time;
// // time = System.currentTimeMillis();
// testHashIndex(true, false);
System.setProperty("h2.logDeleteDelay", "999999999");
int testx;
if(config.logMode != 2) {
return;
}
testLike();
reconnect();
testConstraint();
testLargeIndex();
testMultiColumnIndex();
// long time;
// time = System.currentTimeMillis();
testHashIndex(true, false);
testHashIndex(false, false); testHashIndex(false, false);
// System.out.println("btree="+(System.currentTimeMillis()-time)); // // System.out.println("btree="+(System.currentTimeMillis()-time));
// time = System.currentTimeMillis(); // // time = System.currentTimeMillis();
testHashIndex(true, true); testHashIndex(true, true);
testHashIndex(false, true); testHashIndex(false, true);
// System.out.println("hash="+(System.currentTimeMillis()-time)); // System.out.println("hash="+(System.currentTimeMillis()-time));
testMultiColumnHashIndex();
conn.close(); int te3;
// testMultiColumnHashIndex();
//
// conn.close();
} }
void testDescIndex() throws Exception { void testDescIndex() throws Exception {
...@@ -217,6 +229,8 @@ public class TestIndex extends TestBase { ...@@ -217,6 +229,8 @@ public class TestIndex extends TestBase {
check(1, prep.executeUpdate()); check(1, prep.executeUpdate());
} }
check(0, getValue(stat, "SELECT COUNT(*) FROM TEST")); check(0, getValue(stat, "SELECT COUNT(*) FROM TEST"));
conn.close();
conn = null;
} }
void testMultiColumnIndex() throws Exception { void testMultiColumnIndex() throws Exception {
......
...@@ -34,9 +34,10 @@ public class TestLob extends TestBase { ...@@ -34,9 +34,10 @@ public class TestLob extends TestBase {
if (config.memory) { if (config.memory) {
return; return;
} }
testLobVariable(); int test;
testLobDrop(); // testLobVariable();
testLobNoClose(); // testLobDrop();
// testLobNoClose();
testLobTransactions(10); testLobTransactions(10);
testLobTransactions(10000); testLobTransactions(10000);
testLobRollbackStop(); testLobRollbackStop();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论