提交 67bed1a9 authored 作者: Thomas Mueller's avatar Thomas Mueller

Opening an closing a database is now faster.

上级 7b65f2a3
...@@ -37,6 +37,7 @@ public class ConnectionInfo implements Cloneable { ...@@ -37,6 +37,7 @@ public class ConnectionInfo implements Cloneable {
* The database name * The database name
*/ */
private String name; private String name;
private String nameNormalized;
private boolean remote; private boolean remote;
private boolean ssl; private boolean ssl;
private boolean persistent; private boolean persistent;
...@@ -331,14 +332,16 @@ public class ConnectionInfo implements Cloneable { ...@@ -331,14 +332,16 @@ public class ConnectionInfo implements Cloneable {
*/ */
String getName() { String getName() {
if (persistent) { if (persistent) {
if (nameNormalized == null) {
String suffix = Constants.SUFFIX_PAGE_FILE; String suffix = Constants.SUFFIX_PAGE_FILE;
String n = IOUtils.normalize(name + suffix); String n = IOUtils.normalize(name + suffix);
String fileName = IOUtils.getFileName(n); String fileName = IOUtils.getFileName(n);
if (fileName.length() < suffix.length() + 1) { if (fileName.length() < suffix.length() + 1) {
throw DbException.get(ErrorCode.INVALID_DATABASE_NAME_1, name); throw DbException.get(ErrorCode.INVALID_DATABASE_NAME_1, name);
} }
n = n.substring(0, n.length() - suffix.length()); nameNormalized = n.substring(0, n.length() - suffix.length());
return IOUtils.normalize(n); }
return nameNormalized;
} }
return name; return name;
} }
......
...@@ -535,7 +535,6 @@ public class Database implements DataHandler { ...@@ -535,7 +535,6 @@ public class Database implements DataHandler {
starting = true; starting = true;
getPageStore(); getPageStore();
starting = false; starting = false;
reserveLobFileObjectIds();
writer = WriterThread.create(this, writeDelay); writer = WriterThread.create(this, writeDelay);
} else { } else {
traceSystem = new TraceSystem(null); traceSystem = new TraceSystem(null);
...@@ -1431,30 +1430,11 @@ public class Database implements DataHandler { ...@@ -1431,30 +1430,11 @@ public class Database implements DataHandler {
} }
} }
private void reserveLobFileObjectIds() {
String prefix = IOUtils.normalize(databaseName) + ".";
String path = IOUtils.getParent(databaseName);
String[] list = IOUtils.listFiles(path);
for (String name : list) {
if (name.endsWith(Constants.SUFFIX_LOB_FILE) && IOUtils.fileStartsWith(name, prefix)) {
name = name.substring(prefix.length());
name = name.substring(0, name.length() - Constants.SUFFIX_LOB_FILE.length());
int dot = name.indexOf('.');
if (dot >= 0) {
String id = name.substring(dot + 1);
int objectId = Integer.parseInt(id);
objectIds.set(objectId);
}
}
}
}
private void deleteOldTempFiles() { private void deleteOldTempFiles() {
String path = IOUtils.getParent(databaseName); String path = IOUtils.getParent(databaseName);
String prefix = IOUtils.normalize(databaseName);
String[] list = IOUtils.listFiles(path); String[] list = IOUtils.listFiles(path);
for (String name : list) { for (String name : list) {
if (name.endsWith(Constants.SUFFIX_TEMP_FILE) && IOUtils.fileStartsWith(name, prefix)) { if (name.endsWith(Constants.SUFFIX_TEMP_FILE) && IOUtils.fileStartsWith(name, databaseName)) {
// can't always delete the files, they may still be open // can't always delete the files, they may still be open
IOUtils.tryDelete(name); IOUtils.tryDelete(name);
} }
......
...@@ -78,16 +78,20 @@ public class FileStore { ...@@ -78,16 +78,20 @@ public class FileStore {
tempFileDeleter = handler.getTempFileDeleter(); tempFileDeleter = handler.getTempFileDeleter();
} }
try { try {
fs.createDirs(name); boolean exists = fs.exists(name);
if (fs.exists(name) && !fs.canWrite(name)) { if (exists && !fs.canWrite(name)) {
mode = "r"; mode = "r";
this.mode = mode; this.mode = mode;
} else {
fs.createDirs(name);
} }
file = fs.openFileObject(name, mode); file = fs.openFileObject(name, mode);
if (mode.length() > 2) { if (mode.length() > 2) {
synchronousMode = true; synchronousMode = true;
} }
if (exists) {
fileLength = file.length(); fileLength = file.length();
}
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, "name: " + name + " mode: " + mode); throw DbException.convertIOException(e, "name: " + name + " mode: " + mode);
} }
......
...@@ -188,7 +188,12 @@ public class PageLog { ...@@ -188,7 +188,12 @@ public class PageLog {
* Free up all pages allocated by the log. * Free up all pages allocated by the log.
*/ */
void free() { void free() {
if (trace.isDebugEnabled()) {
trace.debug("log free");
}
int currentDataPage = 0;
if (pageOut != null) { if (pageOut != null) {
currentDataPage = pageOut.getCurrentDataPageId();
pageOut.freeReserved(); pageOut.freeReserved();
} }
PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator(store, firstTrunkPage); PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator(store, firstTrunkPage);
...@@ -200,7 +205,7 @@ public class PageLog { ...@@ -200,7 +205,7 @@ public class PageLog {
} }
break; break;
} }
t.free(); t.free(currentDataPage);
firstTrunkPage = t.getNextTrunk(); firstTrunkPage = t.getNextTrunk();
} }
} }
......
...@@ -191,7 +191,7 @@ public class PageOutputStream { ...@@ -191,7 +191,7 @@ public class PageOutputStream {
* @param t the trunk page * @param t the trunk page
*/ */
void free(PageStreamTrunk t) { void free(PageStreamTrunk t) {
pageCount -= t.free(); pageCount -= t.free(0);
} }
/** /**
......
...@@ -402,6 +402,9 @@ public class PageStore implements CacheWriter { ...@@ -402,6 +402,9 @@ public class PageStore implements CacheWriter {
// ensure the free list is backed up again // ensure the free list is backed up again
log.checkpoint(); log.checkpoint();
if (trace.isDebugEnabled()) {
trace.debug("writeFree");
}
byte[] test = new byte[16]; byte[] test = new byte[16];
byte[] empty = new byte[pageSize]; byte[] empty = new byte[pageSize];
for (int i = PAGE_ID_FREE_LIST_ROOT; i < pageCount; i++) { for (int i = PAGE_ID_FREE_LIST_ROOT; i < pageCount; i++) {
...@@ -444,13 +447,12 @@ public class PageStore implements CacheWriter { ...@@ -444,13 +447,12 @@ public class PageStore implements CacheWriter {
// open a new log at the very end // open a new log at the very end
// (to be truncated later) // (to be truncated later)
writeBack(); writeBack();
log.free();
recoveryRunning = true; recoveryRunning = true;
try { try {
log.free();
logFirstTrunkPage = lastUsed + 1; logFirstTrunkPage = lastUsed + 1;
allocatePage(logFirstTrunkPage); allocatePage(logFirstTrunkPage);
log.openForWriting(logFirstTrunkPage, true); log.openForWriting(logFirstTrunkPage, true);
// ensure the free list is backed up again // ensure the free list is backed up again
log.checkpoint(); log.checkpoint();
} finally { } finally {
...@@ -465,12 +467,6 @@ public class PageStore implements CacheWriter { ...@@ -465,12 +467,6 @@ public class PageStore implements CacheWriter {
} }
int blockSize = fully ? COMPACT_BLOCK_SIZE : 1; int blockSize = fully ? COMPACT_BLOCK_SIZE : 1;
for (int x = lastUsed, j = 0; x > MIN_PAGE_COUNT && j < maxMove; x -= blockSize) { for (int x = lastUsed, j = 0; x > MIN_PAGE_COUNT && j < maxMove; x -= blockSize) {
for (int full = x - blockSize + 1; full <= x; full++) {
if (full > MIN_PAGE_COUNT) {
// ensure the page is in the disk buffer
readPage(full);
}
}
for (int full = x - blockSize + 1; full <= x; full++) { for (int full = x - blockSize + 1; full <= x; full++) {
if (full > MIN_PAGE_COUNT) { if (full > MIN_PAGE_COUNT) {
synchronized (database) { synchronized (database) {
...@@ -501,10 +497,10 @@ public class PageStore implements CacheWriter { ...@@ -501,10 +497,10 @@ public class PageStore implements CacheWriter {
writeBack(); writeBack();
log.checkpoint(); log.checkpoint();
log.free();
// truncate the log // truncate the log
recoveryRunning = true; recoveryRunning = true;
try { try {
log.free();
setLogFirstPage(0, 0, 0); setLogFirstPage(0, 0, 0);
} finally { } finally {
recoveryRunning = false; recoveryRunning = false;
...@@ -1061,7 +1057,7 @@ public class PageStore implements CacheWriter { ...@@ -1061,7 +1057,7 @@ public class PageStore implements CacheWriter {
*/ */
void free(int pageId, boolean undo) { void free(int pageId, boolean undo) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
// trace.debug("freePage " + pageId); // trace.debug("free " + pageId + " " + undo);
} }
synchronized (database) { synchronized (database) {
cache.remove(pageId); cache.remove(pageId);
...@@ -1085,6 +1081,22 @@ public class PageStore implements CacheWriter { ...@@ -1085,6 +1081,22 @@ public class PageStore implements CacheWriter {
} }
} }
/**
* Add a page to the free list. The page is not used, therefore doesn't need to be overwritten.
*
* @param pageId the page id
*/
void freeUnused(int pageId) {
if (trace.isDebugEnabled()) {
trace.debug("freeUnused " + pageId);
}
synchronized (database) {
cache.remove(pageId);
freePage(pageId);
freed.set(pageId);
}
}
/** /**
* Create a data object. * Create a data object.
* *
......
...@@ -158,17 +158,28 @@ public class PageStreamTrunk extends Page { ...@@ -158,17 +158,28 @@ public class PageStreamTrunk extends Page {
} }
/** /**
* Free this page and all data pages. * Free this page and all data pages. Pages after the last used data page
* (if within this list) are empty and therefore not just freed, but marked
* as not used.
* *
* @param lastUsedPage the last used data page
* @return the number of pages freed * @return the number of pages freed
*/ */
int free() { int free(int lastUsedPage) {
store.free(getPos(), false); store.free(getPos(), false);
int freed = 1; int freed = 1;
boolean notUsed = false;
for (int i = 0; i < pageCount; i++) { for (int i = 0; i < pageCount; i++) {
int page = pageIds[i]; int page = pageIds[i];
if (notUsed) {
store.freeUnused(page);
} else {
store.free(page, false); store.free(page, false);
}
freed++; freed++;
if (page == lastUsedPage) {
notUsed = true;
}
} }
return freed; return freed;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论