提交 5a84a557 authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental system property "h2.modifyOnWrite".

上级 d744354c
......@@ -174,7 +174,9 @@ public abstract class Command implements CommandInterface {
session.waitIfExclusiveModeEnabled();
boolean writing = !isReadOnly();
if (writing) {
database.beforeWriting();
while (!database.beforeWriting()) {
// wait
}
}
synchronized (sync) {
session.setCurrentCommand(this);
......@@ -208,9 +210,14 @@ public abstract class Command implements CommandInterface {
Object sync = database.isMultiThreaded() ? (Object) session : (Object) database;
session.waitIfExclusiveModeEnabled();
boolean callStop = true;
database.beforeWriting();
boolean writing = !isReadOnly();
if (writing) {
while (!database.beforeWriting()) {
// wait
}
}
synchronized (sync) {
int rollback = session.getLogId();
int rollback = session.getUndoLogPos();
session.setCurrentCommand(this);
try {
while (true) {
......@@ -248,11 +255,13 @@ public abstract class Command implements CommandInterface {
stop();
}
} finally {
if (writing) {
database.afterWriting();
}
}
}
}
}
private long filterConcurrentUpdate(DbException e, long start) {
if (e.getErrorCode() != ErrorCode.CONCURRENT_UPDATE_1) {
......
......@@ -61,6 +61,11 @@ public class Constants {
*/
public static final int TCP_PROTOCOL_VERSION_9 = 9;
/**
* The TCP protocol version number 10.
*/
public static final int TCP_PROTOCOL_VERSION_10 = 10;
/**
* The major version of this database.
*/
......
......@@ -542,7 +542,7 @@ public class Session extends SessionWithState {
}
}
public int getLogId() {
public int getUndoLogPos() {
return undoLog.size();
}
......@@ -755,7 +755,7 @@ public class Session extends SessionWithState {
if (savepoints == null) {
savepoints = database.newStringMap();
}
savepoints.put(name, getLogId());
savepoints.put(name, getUndoLogPos());
}
/**
......
......@@ -67,6 +67,13 @@ public interface SessionInterface extends Closeable {
*/
DataHandler getDataHandler();
/**
* Get the undo log position.
*
* @return the position (0 means no pending transaction)
*/
int getUndoLogPos();
/**
* Cancel the current or next command (called when closing a connection).
*/
......
......@@ -55,6 +55,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
public static final int SESSION_CANCEL_STATEMENT = 13;
public static final int SESSION_CHECK_KEY = 14;
public static final int SESSION_SET_AUTOCOMMIT = 15;
public static final int SESSION_UNDO_LOG_POS = 16;
public static final int STATUS_ERROR = 0;
public static final int STATUS_OK = 1;
......@@ -94,7 +95,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
trans.setSSL(ci.isSSL());
trans.init();
trans.writeInt(Constants.TCP_PROTOCOL_VERSION_6);
trans.writeInt(Constants.TCP_PROTOCOL_VERSION_9);
trans.writeInt(Constants.TCP_PROTOCOL_VERSION_10);
trans.writeString(db);
trans.writeString(ci.getOriginalURL());
trans.writeString(ci.getUserName());
......@@ -120,6 +121,24 @@ public class SessionRemote extends SessionWithState implements DataHandler {
return trans;
}
public int getUndoLogPos() {
if (clientVersion < Constants.TCP_PROTOCOL_VERSION_10) {
return 1;
}
for (int i = 0, count = 0; i < transferList.size(); i++) {
Transfer transfer = transferList.get(i);
try {
traceOperation("SESSION_UNDO_LOG_POS", 0);
transfer.writeInt(SessionRemote.SESSION_UNDO_LOG_POS);
done(transfer);
return transfer.readInt();
} catch (IOException e) {
removeServer(e, i--, ++count);
}
}
return 1;
}
public void cancel() {
// this method is called when closing the connection
// the statement that is currently running is not canceled in this case
......@@ -482,6 +501,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
}
public void close() {
RuntimeException closeError = null;
if (transferList != null) {
synchronized (this) {
for (Transfer transfer : transferList) {
......@@ -490,6 +510,9 @@ public class SessionRemote extends SessionWithState implements DataHandler {
transfer.writeInt(SessionRemote.SESSION_CLOSE);
done(transfer);
transfer.close();
} catch (RuntimeException e) {
trace.error(e, "close");
closeError = e;
} catch (Exception e) {
trace.error(e, "close");
}
......@@ -502,6 +525,9 @@ public class SessionRemote extends SessionWithState implements DataHandler {
embedded.close();
embedded = null;
}
if (closeError != null) {
throw closeError;
}
}
public Trace getTrace() {
......
......@@ -345,6 +345,7 @@ public class JdbcConnection extends TraceObject implements Connection {
try {
if (!session.isClosed()) {
try {
if (session.getUndoLogPos() != 0) {
// roll back unless that would require to re-connect
// (the transaction can't be rolled back after re-connecting)
if (!session.isReconnectNeeded(true)) {
......@@ -356,6 +357,7 @@ public class JdbcConnection extends TraceObject implements Connection {
throw e;
}
}
}
session.afterWriting();
}
closePreparedCommands();
......
......@@ -71,12 +71,12 @@ public class TcpServerThread implements Runnable {
int minClientVersion = transfer.readInt();
if (minClientVersion < Constants.TCP_PROTOCOL_VERSION_6) {
throw DbException.get(ErrorCode.DRIVER_VERSION_ERROR_2, "" + clientVersion, "" + Constants.TCP_PROTOCOL_VERSION_6);
} else if (minClientVersion > Constants.TCP_PROTOCOL_VERSION_9) {
throw DbException.get(ErrorCode.DRIVER_VERSION_ERROR_2, "" + clientVersion, "" + Constants.TCP_PROTOCOL_VERSION_9);
} else if (minClientVersion > Constants.TCP_PROTOCOL_VERSION_10) {
throw DbException.get(ErrorCode.DRIVER_VERSION_ERROR_2, "" + clientVersion, "" + Constants.TCP_PROTOCOL_VERSION_10);
}
int maxClientVersion = transfer.readInt();
if (maxClientVersion >= Constants.TCP_PROTOCOL_VERSION_9) {
clientVersion = Constants.TCP_PROTOCOL_VERSION_9;
if (maxClientVersion >= Constants.TCP_PROTOCOL_VERSION_10) {
clientVersion = Constants.TCP_PROTOCOL_VERSION_10;
} else {
clientVersion = minClientVersion;
}
......@@ -149,20 +149,32 @@ public class TcpServerThread implements Runnable {
private void closeSession() {
if (session != null) {
RuntimeException closeError = null;
try {
Command rollback = session.prepareLocal("ROLLBACK");
rollback.executeUpdate();
} catch (RuntimeException e) {
closeError = e;
server.traceError(e);
} catch (Exception e) {
server.traceError(e);
}
try {
session.close();
server.removeConnection(threadId);
} catch (RuntimeException e) {
if (closeError == null) {
closeError = e;
server.traceError(e);
}
} catch (Exception e) {
server.traceError(e);
} finally {
session = null;
}
if (closeError != null) {
throw closeError;
}
}
}
......@@ -173,13 +185,14 @@ public class TcpServerThread implements Runnable {
try {
stop = true;
closeSession();
transfer.close();
trace("Close");
} catch (Exception e) {
server.traceError(e);
}
} finally {
transfer.close();
trace("Close");
server.remove(this);
}
}
private void sendError(Throwable t) {
try {
......@@ -241,6 +254,7 @@ public class TcpServerThread implements Runnable {
break;
}
case SessionRemote.SESSION_CLOSE: {
stop = true;
closeSession();
transfer.writeInt(SessionRemote.STATUS_OK).flush();
close();
......@@ -364,6 +378,11 @@ public class TcpServerThread implements Runnable {
transfer.writeInt(SessionRemote.STATUS_OK).flush();
break;
}
case SessionRemote.SESSION_UNDO_LOG_POS: {
transfer.writeInt(SessionRemote.STATUS_OK).
writeInt(session.getUndoLogPos()).flush();
break;
}
default:
trace("Unknown operation: " + operation);
closeSession();
......
......@@ -224,7 +224,7 @@ public class FileLock implements Runnable {
transfer.setSocket(socket);
transfer.init();
transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_6);
transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_9);
transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_10);
transfer.writeString(null);
transfer.writeString(null);
transfer.writeString(id);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论