提交 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 {
public void closeAndDeleteSilently() {
if (file != null) {
closeSilently();
tempFileDeleter.updateAutoDelete(autoDeleteReference);
tempFileDeleter.deleteFile(autoDeleteReference, name);
name = null;
}
......@@ -462,8 +461,6 @@ public class FileStore {
public void autoDelete() {
if (autoDeleteReference == null) {
autoDeleteReference = tempFileDeleter.addFile(name, this);
} else {
tempFileDeleter.updateAutoDelete(autoDeleteReference);
}
}
......
......@@ -10,13 +10,21 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.util.Utils;
/**
* The file system is a storage abstraction.
*/
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 final ArrayList<FileSystem> SERVICES = New.arrayList();
......@@ -134,19 +142,6 @@ public abstract class FileSystem {
*/
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.
*
......@@ -295,4 +290,43 @@ public abstract class FileSystem {
*/
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 {
dir = new File(name).getAbsoluteFile().getParentFile();
IOUtils.mkdirs(dir);
}
if (prefix.length() < 3) {
prefix += "0";
File f;
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) {
try {
f.deleteOnExit();
......
......@@ -14,7 +14,6 @@ import java.util.Iterator;
import java.util.TreeMap;
import org.h2.message.DbException;
import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
import org.h2.util.New;
/**
......@@ -88,19 +87,6 @@ public class FileSystemMemory extends FileSystem {
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) {
ArrayList<String> list = New.arrayList();
synchronized (MEMORY_FILES) {
......
......@@ -20,7 +20,7 @@ import org.h2.message.DbException;
public class TempFileDeleter {
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() {
// utility class
......@@ -30,22 +30,6 @@ public class 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
* the file object is garbage collected.
......@@ -57,30 +41,11 @@ public class TempFileDeleter {
public synchronized Reference< ? > addFile(String fileName, Object file) {
IOUtils.trace("TempFileDeleter.addFile", fileName, file);
PhantomReference< ? > ref = new PhantomReference<Object>(file, queue);
TempFile f = new TempFile();
f.fileName = fileName;
f.lastModified = IOUtils.getLastModified(fileName);
refMap.put(ref, f);
refMap.put(ref, fileName);
deleteUnused();
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.
*
......@@ -89,18 +54,12 @@ public class TempFileDeleter {
*/
public synchronized void deleteFile(Reference< ? > ref, String fileName) {
if (ref != null) {
TempFile f2 = refMap.remove(ref);
String f2 = refMap.remove(ref);
if (f2 != null) {
if (SysProperties.CHECK && fileName != null && !f2.fileName.equals(fileName)) {
DbException.throwInternalError("f2:" + f2.fileName + " 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;
if (SysProperties.CHECK && fileName != null && !f2.equals(fileName)) {
DbException.throwInternalError("f2:" + f2 + " f:" + fileName);
}
fileName = f2;
}
}
if (fileName != null && IOUtils.exists(fileName)) {
......@@ -117,8 +76,8 @@ public class TempFileDeleter {
* Delete all registered temp files.
*/
public void deleteAll() {
for (TempFile tempFile : refMap.values()) {
deleteFile(null, tempFile.fileName);
for (String tempFile : refMap.values()) {
deleteFile(null, tempFile);
}
deleteUnused();
}
......@@ -146,9 +105,9 @@ public class TempFileDeleter {
public void stopAutoDelete(Reference< ? > ref, String fileName) {
IOUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref);
if (ref != null) {
TempFile f2 = refMap.remove(ref);
if (SysProperties.CHECK && (f2 == null || !f2.fileName.equals(fileName))) {
DbException.throwInternalError("f2:" + f2 + " " + (f2 == null ? "" : f2.fileName) + " f:" + fileName);
String f2 = refMap.remove(ref);
if (SysProperties.CHECK && (f2 == null || !f2.equals(fileName))) {
DbException.throwInternalError("f2:" + f2 + " " + (f2 == null ? "" : f2) + " f:" + fileName);
}
}
deleteUnused();
......
......@@ -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) {
try {
long id = getId(fileName, false);
......
......@@ -33,7 +33,8 @@ public class TestClearReferences extends TestBase {
"org.h2.util.MemoryUtils.reserveMemory",
"org.h2.util.NetUtils.cachedLocalAddress",
"org.h2.util.MathUtils.cachedSecureRandom",
"org.h2.value.CompareMode.lastUsed"
"org.h2.value.CompareMode.lastUsed",
"org.h2.store.fs.FileSystem.tempRandom",
};
private boolean hasError;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论