Unverified 提交 8a7aa9db authored 作者: Andrei Tokar's avatar Andrei Tokar 提交者: GitHub

Merge pull request #1194 from h2database/post-undo-split

TestKillRestartMulti: A map named undoLog-1 already exists
...@@ -808,7 +808,7 @@ public class Database implements DataHandler { ...@@ -808,7 +808,7 @@ public class Database implements DataHandler {
} }
systemSession.commit(true); systemSession.commit(true);
if (mvStore != null) { if (mvStore != null) {
mvStore.initTransactions(); mvStore.getTransactionStore().endLeftoverTransactions();
mvStore.removeTemporaryMaps(objectIds); mvStore.removeTemporaryMaps(objectIds);
} }
recompileInvalidViews(systemSession); recompileInvalidViews(systemSession);
...@@ -1014,6 +1014,7 @@ public class Database implements DataHandler { ...@@ -1014,6 +1014,7 @@ public class Database implements DataHandler {
SearchRow r = meta.getTemplateSimpleRow(false); SearchRow r = meta.getTemplateSimpleRow(false);
r.setValue(0, ValueInt.get(id)); r.setValue(0, ValueInt.get(id));
boolean wasLocked = lockMeta(session); boolean wasLocked = lockMeta(session);
try {
Cursor cursor = metaIdIndex.find(session, r, r); Cursor cursor = metaIdIndex.find(session, r, r);
if (cursor.next()) { if (cursor.next()) {
if (SysProperties.CHECK) { if (SysProperties.CHECK) {
...@@ -1031,12 +1032,13 @@ public class Database implements DataHandler { ...@@ -1031,12 +1032,13 @@ public class Database implements DataHandler {
if (SysProperties.CHECK) { if (SysProperties.CHECK) {
checkMetaFree(session, id); checkMetaFree(session, id);
} }
} else if (!wasLocked) { }
unlockMetaDebug(session); } finally {
if (!wasLocked) {
// must not keep the lock if it was not locked // must not keep the lock if it was not locked
// otherwise updating sequences may cause a deadlock // otherwise updating sequences may cause a deadlock
meta.unlock(session); unlockMeta(session);
session.unlock(meta); }
} }
objectIds.clear(id); objectIds.clear(id);
} }
...@@ -1333,10 +1335,10 @@ public class Database implements DataHandler { ...@@ -1333,10 +1335,10 @@ public class Database implements DataHandler {
} }
closing = true; closing = true;
} }
} if (!this.isReadOnly()) {
if(!this.isReadOnly()) {
removeOrphanedLobs(); removeOrphanedLobs();
} }
}
try { try {
if (systemSession != null) { if (systemSession != null) {
if (powerOffCount != -1) { if (powerOffCount != -1) {
...@@ -1427,6 +1429,7 @@ public class Database implements DataHandler { ...@@ -1427,6 +1429,7 @@ public class Database implements DataHandler {
* @param flush whether writing is allowed * @param flush whether writing is allowed
*/ */
private synchronized void closeOpenFilesAndUnlock(boolean flush) { private synchronized void closeOpenFilesAndUnlock(boolean flush) {
try {
stopWriter(); stopWriter();
if (pageStore != null) { if (pageStore != null) {
if (flush) { if (flush) {
...@@ -1456,7 +1459,7 @@ public class Database implements DataHandler { ...@@ -1456,7 +1459,7 @@ public class Database implements DataHandler {
} }
} }
reconnectModified(false); reconnectModified(false);
if (mvStore != null && !mvStore.getStore().isClosed()) { if (mvStore != null && mvStore.getStore() != null && !mvStore.getStore().isClosed()) {
long maxCompactTime = dbSettings.maxCompactTime; long maxCompactTime = dbSettings.maxCompactTime;
if (compactMode == CommandInterface.SHUTDOWN_COMPACT) { if (compactMode == CommandInterface.SHUTDOWN_COMPACT) {
mvStore.compactFile(dbSettings.maxCompactTime); mvStore.compactFile(dbSettings.maxCompactTime);
...@@ -1467,6 +1470,14 @@ public class Database implements DataHandler { ...@@ -1467,6 +1470,14 @@ public class Database implements DataHandler {
} }
mvStore.close(maxCompactTime); mvStore.close(maxCompactTime);
} }
if (systemSession != null) {
systemSession.close();
systemSession = null;
}
if (lobSession != null) {
lobSession.close();
lobSession = null;
}
closeFiles(); closeFiles();
if (persistent && lock == null && if (persistent && lock == null &&
fileLockMethod != FileLockMethod.NO && fileLockMethod != FileLockMethod.NO &&
...@@ -1479,14 +1490,7 @@ public class Database implements DataHandler { ...@@ -1479,14 +1490,7 @@ public class Database implements DataHandler {
if (persistent) { if (persistent) {
deleteOldTempFiles(); deleteOldTempFiles();
} }
if (systemSession != null) { } finally {
systemSession.close();
systemSession = null;
}
if (lobSession != null) {
lobSession.close();
lobSession = null;
}
if (lock != null) { if (lock != null) {
if (fileLockMethod == FileLockMethod.SERIALIZED) { if (fileLockMethod == FileLockMethod.SERIALIZED) {
// wait before deleting the .lock file, // wait before deleting the .lock file,
...@@ -1504,6 +1508,7 @@ public class Database implements DataHandler { ...@@ -1504,6 +1508,7 @@ public class Database implements DataHandler {
lock = null; lock = null;
} }
} }
}
private synchronized void closeFiles() { private synchronized void closeFiles() {
try { try {
...@@ -1946,7 +1951,6 @@ public class Database implements DataHandler { ...@@ -1946,7 +1951,6 @@ public class Database implements DataHandler {
t.getSQL()); t.getSQL());
} }
obj.removeChildrenAndResources(session); obj.removeChildrenAndResources(session);
} }
removeMeta(session, id); removeMeta(session, id);
} }
...@@ -2550,6 +2554,7 @@ public class Database implements DataHandler { ...@@ -2550,6 +2554,7 @@ public class Database implements DataHandler {
* Immediately close the database. * Immediately close the database.
*/ */
public void shutdownImmediately() { public void shutdownImmediately() {
closing = true;
setPowerOffCount(1); setPowerOffCount(1);
try { try {
checkPowerOff(); checkPowerOff();
......
...@@ -511,9 +511,12 @@ public class MVStore { ...@@ -511,9 +511,12 @@ public class MVStore {
M map = (M) getMap(id); M map = (M) getMap(id);
if (map == null) { if (map == null) {
String configAsString = meta.get(MVMap.getMapKey(id)); String configAsString = meta.get(MVMap.getMapKey(id));
if(configAsString != null) { HashMap<String, Object> config;
HashMap<String, Object> config = if (configAsString != null) {
new HashMap<String, Object>(DataUtils.parseMap(configAsString)); config = new HashMap<String, Object>(DataUtils.parseMap(configAsString));
} else {
config = new HashMap<>();
}
config.put("id", id); config.put("id", id);
map = builder.create(this, config); map = builder.create(this, config);
map.init(); map.init();
...@@ -521,7 +524,6 @@ public class MVStore { ...@@ -521,7 +524,6 @@ public class MVStore {
map.setRootPos(root, lastStoredVersion); map.setRootPos(root, lastStoredVersion);
maps.put(id, map); maps.put(id, map);
} }
}
return map; return map;
} finally { } finally {
storeLock.unlock(); storeLock.unlock();
......
...@@ -109,10 +109,7 @@ public class MVTableEngine implements TableEngine { ...@@ -109,10 +109,7 @@ public class MVTableEngine implements TableEngine {
public TableBase createTable(CreateTableData data) { public TableBase createTable(CreateTableData data) {
Database db = data.session.getDatabase(); Database db = data.session.getDatabase();
Store store = init(db); Store store = init(db);
MVTable table = new MVTable(data, store); return store.createTable(data);
table.init(data.session);
store.tableMap.put(table.getMapName(), table);
return table;
} }
/** /**
...@@ -124,7 +121,7 @@ public class MVTableEngine implements TableEngine { ...@@ -124,7 +121,7 @@ public class MVTableEngine implements TableEngine {
* The map of open tables. * The map of open tables.
* Key: the map name, value: the table. * Key: the map name, value: the table.
*/ */
final ConcurrentHashMap<String, MVTable> tableMap = private final ConcurrentHashMap<String, MVTable> tableMap =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
/** /**
...@@ -152,7 +149,7 @@ public class MVTableEngine implements TableEngine { ...@@ -152,7 +149,7 @@ public class MVTableEngine implements TableEngine {
* @param builder the builder * @param builder the builder
* @param encrypted whether the store is encrypted * @param encrypted whether the store is encrypted
*/ */
void open(Database db, MVStore.Builder builder, boolean encrypted) { private void open(Database db, MVStore.Builder builder, boolean encrypted) {
this.encrypted = encrypted; this.encrypted = encrypted;
try { try {
this.store = builder.open(); this.store = builder.open();
...@@ -166,7 +163,6 @@ public class MVTableEngine implements TableEngine { ...@@ -166,7 +163,6 @@ public class MVTableEngine implements TableEngine {
this.transactionStore = new TransactionStore( this.transactionStore = new TransactionStore(
store, store,
new ValueDataType(db.getCompareMode(), db, null), db.getLockTimeout()); new ValueDataType(db.getCompareMode(), db, null), db.getLockTimeout());
// transactionStore.init();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
throw convertIllegalStateException(e); throw convertIllegalStateException(e);
} }
...@@ -195,6 +191,10 @@ public class MVTableEngine implements TableEngine { ...@@ -195,6 +191,10 @@ public class MVTableEngine implements TableEngine {
throw DbException.get( throw DbException.get(
ErrorCode.IO_EXCEPTION_1, ErrorCode.IO_EXCEPTION_1,
e, fileName); e, fileName);
} else if (errorCode == DataUtils.ERROR_INTERNAL) {
throw DbException.get(
ErrorCode.GENERAL_ERROR_1,
e, fileName);
} }
throw DbException.get( throw DbException.get(
ErrorCode.FILE_CORRUPTED_1, ErrorCode.FILE_CORRUPTED_1,
...@@ -214,6 +214,19 @@ public class MVTableEngine implements TableEngine { ...@@ -214,6 +214,19 @@ public class MVTableEngine implements TableEngine {
return tableMap.get(tableName); return tableMap.get(tableName);
} }
/**
* Create a table.
*
* @param data CreateTableData
* @return table created
*/
public MVTable createTable(CreateTableData data) {
MVTable table = new MVTable(data, this);
table.init(data.session);
tableMap.put(table.getMapName(), table);
return table;
}
/** /**
* Remove a table. * Remove a table.
* *
...@@ -246,21 +259,6 @@ public class MVTableEngine implements TableEngine { ...@@ -246,21 +259,6 @@ public class MVTableEngine implements TableEngine {
store.closeImmediately(); store.closeImmediately();
} }
/**
* Commit all transactions that are in the committing state, and
* rollback all open transactions.
*/
public void initTransactions() {
List<Transaction> list = transactionStore.getOpenTransactions();
for (Transaction t : list) {
if (t.getStatus() == Transaction.STATUS_COMMITTED) {
t.commit();
} else if (t.getStatus() != Transaction.STATUS_PREPARED) {
t.rollback();
}
}
}
/** /**
* Remove all temporary maps. * Remove all temporary maps.
* *
......
...@@ -436,7 +436,7 @@ public class Transaction { ...@@ -436,7 +436,7 @@ public class Transaction {
return store.getChanges(this, getLogId(), savepointId); return store.getChanges(this, getLogId(), savepointId);
} }
long getLogId() { private long getLogId() {
return getLogId(statusAndLogId.get()); return getLogId(statusAndLogId.get());
} }
...@@ -454,7 +454,7 @@ public class Transaction { ...@@ -454,7 +454,7 @@ public class Transaction {
/** /**
* Check whether this transaction is open or prepared. * Check whether this transaction is open or prepared.
*/ */
void checkNotClosed() { private void checkNotClosed() {
if (getStatus() == STATUS_CLOSED) { if (getStatus() == STATUS_CLOSED) {
throw DataUtils.newIllegalStateException( throw DataUtils.newIllegalStateException(
DataUtils.ERROR_CLOSED, "Transaction {0} is closed", transactionId); DataUtils.ERROR_CLOSED, "Transaction {0} is closed", transactionId);
......
...@@ -89,11 +89,6 @@ public class TransactionStore { ...@@ -89,11 +89,6 @@ public class TransactionStore {
private final AtomicReferenceArray<Transaction> transactions = private final AtomicReferenceArray<Transaction> transactions =
new AtomicReferenceArray<>(MAX_OPEN_TRANSACTIONS + 1); new AtomicReferenceArray<>(MAX_OPEN_TRANSACTIONS + 1);
/**
* The next id of a temporary map.
*/
private int nextTempMapId;
private static final String UNDO_LOG_NAME_PEFIX = "undoLog"; private static final String UNDO_LOG_NAME_PEFIX = "undoLog";
private static final char UNDO_LOG_COMMITTED = '-'; // must come before open in lexicographical order private static final char UNDO_LOG_COMMITTED = '-'; // must come before open in lexicographical order
private static final char UNDO_LOG_OPEN = '.'; private static final char UNDO_LOG_OPEN = '.';
...@@ -147,14 +142,6 @@ public class TransactionStore { ...@@ -147,14 +142,6 @@ public class TransactionStore {
*/ */
public void init() { public void init() {
if (!init) { if (!init) {
// remove all temporary maps
for (String mapName : store.getMapNames()) {
if (mapName.startsWith("temp.")) {
MVMap<Object, Integer> temp = openTempMap(mapName);
store.removeMap(temp);
}
}
for (String mapName : store.getMapNames()) { for (String mapName : store.getMapNames()) {
if (mapName.startsWith(UNDO_LOG_NAME_PEFIX)) { if (mapName.startsWith(UNDO_LOG_NAME_PEFIX)) {
if (store.hasData(mapName)) { if (store.hasData(mapName)) {
...@@ -165,13 +152,15 @@ public class TransactionStore { ...@@ -165,13 +152,15 @@ public class TransactionStore {
int status; int status;
String name; String name;
if (data == null) { if (data == null) {
status = mapName.charAt(UNDO_LOG_NAME_PEFIX.length()) == UNDO_LOG_OPEN ? status = Transaction.STATUS_OPEN;
Transaction.STATUS_OPEN : Transaction.STATUS_COMMITTED;
name = null; name = null;
} else { } else {
status = (Integer) data[0]; status = (Integer) data[0];
name = (String) data[1]; name = (String) data[1];
} }
if (mapName.charAt(UNDO_LOG_NAME_PEFIX.length()) == UNDO_LOG_COMMITTED) {
status = Transaction.STATUS_COMMITTED;
}
MVMap<Long, Object[]> undoLog = store.openMap(mapName, undoLogBuilder); MVMap<Long, Object[]> undoLog = store.openMap(mapName, undoLogBuilder);
undoLogs[transactionId] = undoLog; undoLogs[transactionId] = undoLog;
Long lastUndoKey = undoLog.lastKey(); Long lastUndoKey = undoLog.lastKey();
...@@ -187,6 +176,21 @@ public class TransactionStore { ...@@ -187,6 +176,21 @@ public class TransactionStore {
} }
} }
/**
* Commit all transactions that are in the committed state, and
* rollback all open transactions.
*/
public void endLeftoverTransactions() {
List<Transaction> list = getOpenTransactions();
for (Transaction t : list) {
if (t.getStatus() == Transaction.STATUS_COMMITTED) {
t.commit();
} else if (t.getStatus() != Transaction.STATUS_PREPARED) {
t.rollback();
}
}
}
/** /**
* Set the maximum transaction id, after which ids are re-used. If the old * Set the maximum transaction id, after which ids are re-used. If the old
* transaction is still in use when re-using an old id, the new transaction * transaction is still in use when re-using an old id, the new transaction
...@@ -508,29 +512,6 @@ public class TransactionStore { ...@@ -508,29 +512,6 @@ public class TransactionStore {
return map; return map;
} }
/**
* Create a temporary map. Such maps are removed when opening the store.
*
* @return the map
*/
synchronized MVMap<Object, Integer> createTempMap() {
String mapName = "temp." + nextTempMapId++;
return openTempMap(mapName);
}
/**
* Open a temporary map.
*
* @param mapName the map name
* @return the map
*/
private MVMap<Object, Integer> openTempMap(String mapName) {
MVMap.Builder<Object, Integer> mapBuilder =
new MVMap.Builder<Object, Integer>().
keyType(dataType);
return store.openMap(mapName, mapBuilder);
}
/** /**
* End this transaction. Change status to CLOSED and vacate transaction slot. * End this transaction. Change status to CLOSED and vacate transaction slot.
* Will try to commit MVStore if autocommitDelay is 0 or if database is idle * Will try to commit MVStore if autocommitDelay is 0 or if database is idle
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论