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

Operations that don't fit in memory are now faster. Temporary file handling was changed.

上级 1c9fa69f
...@@ -249,7 +249,6 @@ public class FileStore { ...@@ -249,7 +249,6 @@ public class FileStore {
public void closeAndDeleteSilently() { public void closeAndDeleteSilently() {
if (file != null) { if (file != null) {
closeSilently(); closeSilently();
tempFileDeleter.updateAutoDelete(autoDeleteReference);
tempFileDeleter.deleteFile(autoDeleteReference, name); tempFileDeleter.deleteFile(autoDeleteReference, name);
name = null; name = null;
} }
...@@ -462,8 +461,6 @@ public class FileStore { ...@@ -462,8 +461,6 @@ public class FileStore {
public void autoDelete() { public void autoDelete() {
if (autoDeleteReference == null) { if (autoDeleteReference == null) {
autoDeleteReference = tempFileDeleter.addFile(name, this); autoDeleteReference = tempFileDeleter.addFile(name, this);
} else {
tempFileDeleter.updateAutoDelete(autoDeleteReference);
} }
} }
......
...@@ -10,13 +10,21 @@ import java.io.IOException; ...@@ -10,13 +10,21 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Utils;
/** /**
* The file system is a storage abstraction. * The file system is a storage abstraction.
*/ */
public abstract class FileSystem { public abstract class FileSystem {
/**
* The prefix for temporary files. See also TestClearReferences.
*/
private static String tempRandom;
private static long tempSequence;
private static boolean defaultServicesRegistered; private static boolean defaultServicesRegistered;
private static final ArrayList<FileSystem> SERVICES = New.arrayList(); private static final ArrayList<FileSystem> SERVICES = New.arrayList();
...@@ -134,19 +142,6 @@ public abstract class FileSystem { ...@@ -134,19 +142,6 @@ public abstract class FileSystem {
*/ */
public abstract boolean tryDelete(String fileName); public abstract boolean tryDelete(String fileName);
/**
* Create a new temporary file.
*
* @param prefix the prefix of the file name (including directory name if
* required)
* @param suffix the suffix
* @param deleteOnExit if the file should be deleted when the virtual
* machine exists
* @param inTempDir if the file should be stored in the temporary directory
* @return the name of the created file
*/
public abstract String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException;
/** /**
* List the files in the given directory. * List the files in the given directory.
* *
...@@ -295,4 +290,43 @@ public abstract class FileSystem { ...@@ -295,4 +290,43 @@ public abstract class FileSystem {
*/ */
public abstract InputStream openFileInputStream(String fileName) throws IOException; public abstract InputStream openFileInputStream(String fileName) throws IOException;
/**
* Get the next temporary file name part (the part in the middle).
*
* @param newRandom if the random part of the filename should change
* @return the file name part
*/
protected synchronized String getNextTempFileNamePart(boolean newRandom) {
if (newRandom || tempRandom == null) {
byte[] prefix = new byte[8];
MathUtils.randomBytes(prefix);
tempRandom = Utils.convertBytesToString(prefix) + ".";
}
return tempRandom + tempSequence++;
}
/**
* Create a new temporary file.
*
* @param prefix the prefix of the file name (including directory name if
* required)
* @param suffix the suffix
* @param deleteOnExit if the file should be deleted when the virtual
* machine exists
* @param inTempDir if the file should be stored in the temporary directory
* @return the name of the created file
*/
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
while (true) {
String n = name + getNextTempFileNamePart(false) + suffix;
if (exists(n)) {
// in theory, the random number could collide
getNextTempFileNamePart(true);
}
// creates the file (not thread safe)
openFileObject(n, "rw").close();
return n;
}
}
} }
...@@ -183,10 +183,16 @@ public class FileSystemDisk extends FileSystem { ...@@ -183,10 +183,16 @@ public class FileSystemDisk extends FileSystem {
dir = new File(name).getAbsoluteFile().getParentFile(); dir = new File(name).getAbsoluteFile().getParentFile();
IOUtils.mkdirs(dir); IOUtils.mkdirs(dir);
} }
if (prefix.length() < 3) { File f;
prefix += "0"; while (true) {
f = new File(dir, prefix + getNextTempFileNamePart(false) + suffix);
if (f.exists()) {
// in theory, the random number could collide
getNextTempFileNamePart(true);
} else {
break;
}
} }
File f = File.createTempFile(prefix, suffix, dir);
if (deleteOnExit) { if (deleteOnExit) {
try { try {
f.deleteOnExit(); f.deleteOnExit();
......
...@@ -14,7 +14,6 @@ import java.util.Iterator; ...@@ -14,7 +14,6 @@ import java.util.Iterator;
import java.util.TreeMap; import java.util.TreeMap;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
/** /**
...@@ -88,19 +87,6 @@ public class FileSystemMemory extends FileSystem { ...@@ -88,19 +87,6 @@ public class FileSystemMemory extends FileSystem {
return true; return true;
} }
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) {
name += ".";
synchronized (MEMORY_FILES) {
for (int i = 0;; i++) {
String n = name + (MathUtils.secureRandomLong() >>> 1) + suffix;
if (!exists(n)) {
getMemoryFile(n);
return n;
}
}
}
}
public String[] listFiles(String path) { public String[] listFiles(String path) {
ArrayList<String> list = New.arrayList(); ArrayList<String> list = New.arrayList();
synchronized (MEMORY_FILES) { synchronized (MEMORY_FILES) {
......
...@@ -20,7 +20,7 @@ import org.h2.message.DbException; ...@@ -20,7 +20,7 @@ import org.h2.message.DbException;
public class TempFileDeleter { public class TempFileDeleter {
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
private final HashMap<PhantomReference< ? >, TempFile> refMap = New.hashMap(); private final HashMap<PhantomReference< ? >, String> refMap = New.hashMap();
private TempFileDeleter() { private TempFileDeleter() {
// utility class // utility class
...@@ -30,22 +30,6 @@ public class TempFileDeleter { ...@@ -30,22 +30,6 @@ public class TempFileDeleter {
return new TempFileDeleter(); return new TempFileDeleter();
} }
/**
* Contains information about a file.
*/
static class TempFile {
/**
* The file name.
*/
String fileName;
/**
* The last modified date of this file.
*/
long lastModified;
}
/** /**
* Add a file to the list of temp files to delete. The file is deleted once * Add a file to the list of temp files to delete. The file is deleted once
* the file object is garbage collected. * the file object is garbage collected.
...@@ -57,30 +41,11 @@ public class TempFileDeleter { ...@@ -57,30 +41,11 @@ public class TempFileDeleter {
public synchronized Reference< ? > addFile(String fileName, Object file) { public synchronized Reference< ? > addFile(String fileName, Object file) {
IOUtils.trace("TempFileDeleter.addFile", fileName, file); IOUtils.trace("TempFileDeleter.addFile", fileName, file);
PhantomReference< ? > ref = new PhantomReference<Object>(file, queue); PhantomReference< ? > ref = new PhantomReference<Object>(file, queue);
TempFile f = new TempFile(); refMap.put(ref, fileName);
f.fileName = fileName;
f.lastModified = IOUtils.getLastModified(fileName);
refMap.put(ref, f);
deleteUnused(); deleteUnused();
return ref; return ref;
} }
/**
* Update the last modified date of the auto-delete reference. If the file
* was modified after that, it will not be deleted (because it might have
* been deleted and then re-created).
*
* @param ref the reference
*/
public synchronized void updateAutoDelete(Reference< ? > ref) {
TempFile f2 = refMap.get(ref);
if (f2 != null) {
String fileName = f2.fileName;
long mod = IOUtils.getLastModified(fileName);
f2.lastModified = mod;
}
}
/** /**
* Delete the given file now. This will remove the reference from the list. * Delete the given file now. This will remove the reference from the list.
* *
...@@ -89,18 +54,12 @@ public class TempFileDeleter { ...@@ -89,18 +54,12 @@ public class TempFileDeleter {
*/ */
public synchronized void deleteFile(Reference< ? > ref, String fileName) { public synchronized void deleteFile(Reference< ? > ref, String fileName) {
if (ref != null) { if (ref != null) {
TempFile f2 = refMap.remove(ref); String f2 = refMap.remove(ref);
if (f2 != null) { if (f2 != null) {
if (SysProperties.CHECK && fileName != null && !f2.fileName.equals(fileName)) { if (SysProperties.CHECK && fileName != null && !f2.equals(fileName)) {
DbException.throwInternalError("f2:" + f2.fileName + " f:" + fileName); DbException.throwInternalError("f2:" + f2 + " f:" + fileName);
}
fileName = f2.fileName;
long mod = IOUtils.getLastModified(fileName);
if (mod != f2.lastModified) {
// the file has been deleted and a new one created
// or it has been modified afterwards
return;
} }
fileName = f2;
} }
} }
if (fileName != null && IOUtils.exists(fileName)) { if (fileName != null && IOUtils.exists(fileName)) {
...@@ -117,8 +76,8 @@ public class TempFileDeleter { ...@@ -117,8 +76,8 @@ public class TempFileDeleter {
* Delete all registered temp files. * Delete all registered temp files.
*/ */
public void deleteAll() { public void deleteAll() {
for (TempFile tempFile : refMap.values()) { for (String tempFile : refMap.values()) {
deleteFile(null, tempFile.fileName); deleteFile(null, tempFile);
} }
deleteUnused(); deleteUnused();
} }
...@@ -146,9 +105,9 @@ public class TempFileDeleter { ...@@ -146,9 +105,9 @@ public class TempFileDeleter {
public void stopAutoDelete(Reference< ? > ref, String fileName) { public void stopAutoDelete(Reference< ? > ref, String fileName) {
IOUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref); IOUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref);
if (ref != null) { if (ref != null) {
TempFile f2 = refMap.remove(ref); String f2 = refMap.remove(ref);
if (SysProperties.CHECK && (f2 == null || !f2.fileName.equals(fileName))) { if (SysProperties.CHECK && (f2 == null || !f2.equals(fileName))) {
DbException.throwInternalError("f2:" + f2 + " " + (f2 == null ? "" : f2.fileName) + " f:" + fileName); DbException.throwInternalError("f2:" + f2 + " " + (f2 == null ? "" : f2) + " f:" + fileName);
} }
} }
deleteUnused(); deleteUnused();
......
...@@ -240,18 +240,6 @@ public class FileSystemDatabase extends FileSystem { ...@@ -240,18 +240,6 @@ public class FileSystemDatabase extends FileSystem {
} }
} }
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
name += ".";
for (int i = 0;; i++) {
String n = name + i + suffix;
if (!exists(n)) {
// creates the file (not thread safe)
openFileObject(n, "rw").close();
return n;
}
}
}
public synchronized void delete(String fileName) { public synchronized void delete(String fileName) {
try { try {
long id = getId(fileName, false); long id = getId(fileName, false);
......
...@@ -33,7 +33,8 @@ public class TestClearReferences extends TestBase { ...@@ -33,7 +33,8 @@ public class TestClearReferences extends TestBase {
"org.h2.util.MemoryUtils.reserveMemory", "org.h2.util.MemoryUtils.reserveMemory",
"org.h2.util.NetUtils.cachedLocalAddress", "org.h2.util.NetUtils.cachedLocalAddress",
"org.h2.util.MathUtils.cachedSecureRandom", "org.h2.util.MathUtils.cachedSecureRandom",
"org.h2.value.CompareMode.lastUsed" "org.h2.value.CompareMode.lastUsed",
"org.h2.store.fs.FileSystem.tempRandom",
}; };
private boolean hasError; private boolean hasError;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论