提交 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 {
* The database name
*/
private String name;
private String nameNormalized;
private boolean remote;
private boolean ssl;
private boolean persistent;
......@@ -331,14 +332,16 @@ public class ConnectionInfo implements Cloneable {
*/
String getName() {
if (persistent) {
String suffix = Constants.SUFFIX_PAGE_FILE;
String n = IOUtils.normalize(name + suffix);
String fileName = IOUtils.getFileName(n);
if (fileName.length() < suffix.length() + 1) {
throw DbException.get(ErrorCode.INVALID_DATABASE_NAME_1, name);
if (nameNormalized == null) {
String suffix = Constants.SUFFIX_PAGE_FILE;
String n = IOUtils.normalize(name + suffix);
String fileName = IOUtils.getFileName(n);
if (fileName.length() < suffix.length() + 1) {
throw DbException.get(ErrorCode.INVALID_DATABASE_NAME_1, name);
}
nameNormalized = n.substring(0, n.length() - suffix.length());
}
n = n.substring(0, n.length() - suffix.length());
return IOUtils.normalize(n);
return nameNormalized;
}
return name;
}
......
......@@ -535,7 +535,6 @@ public class Database implements DataHandler {
starting = true;
getPageStore();
starting = false;
reserveLobFileObjectIds();
writer = WriterThread.create(this, writeDelay);
} else {
traceSystem = new TraceSystem(null);
......@@ -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() {
String path = IOUtils.getParent(databaseName);
String prefix = IOUtils.normalize(databaseName);
String[] list = IOUtils.listFiles(path);
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
IOUtils.tryDelete(name);
}
......
......@@ -78,16 +78,20 @@ public class FileStore {
tempFileDeleter = handler.getTempFileDeleter();
}
try {
fs.createDirs(name);
if (fs.exists(name) && !fs.canWrite(name)) {
boolean exists = fs.exists(name);
if (exists && !fs.canWrite(name)) {
mode = "r";
this.mode = mode;
} else {
fs.createDirs(name);
}
file = fs.openFileObject(name, mode);
if (mode.length() > 2) {
synchronousMode = true;
}
fileLength = file.length();
if (exists) {
fileLength = file.length();
}
} catch (IOException e) {
throw DbException.convertIOException(e, "name: " + name + " mode: " + mode);
}
......
......@@ -188,7 +188,12 @@ public class PageLog {
* Free up all pages allocated by the log.
*/
void free() {
if (trace.isDebugEnabled()) {
trace.debug("log free");
}
int currentDataPage = 0;
if (pageOut != null) {
currentDataPage = pageOut.getCurrentDataPageId();
pageOut.freeReserved();
}
PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator(store, firstTrunkPage);
......@@ -200,7 +205,7 @@ public class PageLog {
}
break;
}
t.free();
t.free(currentDataPage);
firstTrunkPage = t.getNextTrunk();
}
}
......
......@@ -191,7 +191,7 @@ public class PageOutputStream {
* @param t the trunk page
*/
void free(PageStreamTrunk t) {
pageCount -= t.free();
pageCount -= t.free(0);
}
/**
......
......@@ -402,6 +402,9 @@ public class PageStore implements CacheWriter {
// ensure the free list is backed up again
log.checkpoint();
if (trace.isDebugEnabled()) {
trace.debug("writeFree");
}
byte[] test = new byte[16];
byte[] empty = new byte[pageSize];
for (int i = PAGE_ID_FREE_LIST_ROOT; i < pageCount; i++) {
......@@ -444,13 +447,12 @@ public class PageStore implements CacheWriter {
// open a new log at the very end
// (to be truncated later)
writeBack();
log.free();
recoveryRunning = true;
try {
log.free();
logFirstTrunkPage = lastUsed + 1;
allocatePage(logFirstTrunkPage);
log.openForWriting(logFirstTrunkPage, true);
// ensure the free list is backed up again
log.checkpoint();
} finally {
......@@ -465,12 +467,6 @@ public class PageStore implements CacheWriter {
}
int blockSize = fully ? COMPACT_BLOCK_SIZE : 1;
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++) {
if (full > MIN_PAGE_COUNT) {
synchronized (database) {
......@@ -501,10 +497,10 @@ public class PageStore implements CacheWriter {
writeBack();
log.checkpoint();
log.free();
// truncate the log
recoveryRunning = true;
try {
log.free();
setLogFirstPage(0, 0, 0);
} finally {
recoveryRunning = false;
......@@ -1061,7 +1057,7 @@ public class PageStore implements CacheWriter {
*/
void free(int pageId, boolean undo) {
if (trace.isDebugEnabled()) {
// trace.debug("freePage " + pageId);
// trace.debug("free " + pageId + " " + undo);
}
synchronized (database) {
cache.remove(pageId);
......@@ -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.
*
......
......@@ -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
*/
int free() {
int free(int lastUsedPage) {
store.free(getPos(), false);
int freed = 1;
boolean notUsed = false;
for (int i = 0; i < pageCount; i++) {
int page = pageIds[i];
store.free(page, false);
if (notUsed) {
store.freeUnused(page);
} else {
store.free(page, false);
}
freed++;
if (page == lastUsedPage) {
notUsed = true;
}
}
return freed;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论