提交 239baa66 authored 作者: Andrei Tokar's avatar Andrei Tokar

double commit

上级 36350d2e
...@@ -1391,10 +1391,7 @@ public class Database implements DataHandler { ...@@ -1391,10 +1391,7 @@ public class Database implements DataHandler {
for (Session s : all) { for (Session s : all) {
if (s != except) { if (s != except) {
try { try {
// must roll back, otherwise the session is removed and // this will rollback outstanding transaction
// the transaction log that contains its uncommitted
// operations as well
s.rollback();
s.close(); s.close();
} catch (DbException e) { } catch (DbException e) {
trace.error(e, "disconnecting session #{0}", s.getId()); trace.error(e, "disconnecting session #{0}", s.getId());
......
...@@ -15,6 +15,7 @@ import java.util.LinkedList; ...@@ -15,6 +15,7 @@ import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Command; import org.h2.command.Command;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
...@@ -114,7 +115,6 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -114,7 +115,6 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
private boolean autoCommitAtTransactionEnd; private boolean autoCommitAtTransactionEnd;
private String currentTransactionName; private String currentTransactionName;
private volatile long cancelAtNs; private volatile long cancelAtNs;
private boolean closed;
private final long sessionStart = System.currentTimeMillis(); private final long sessionStart = System.currentTimeMillis();
private ValueTimestampTimeZone transactionStart; private ValueTimestampTimeZone transactionStart;
private ValueTimestampTimeZone currentCommandStart; private ValueTimestampTimeZone currentCommandStart;
...@@ -160,7 +160,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -160,7 +160,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
private ArrayList<Value> temporaryLobs; private ArrayList<Value> temporaryLobs;
private Transaction transaction; private Transaction transaction;
private State state = State.INIT; private final AtomicReference<State> state = new AtomicReference<>(State.INIT);
private long startStatement = -1; private long startStatement = -1;
/** /**
...@@ -598,7 +598,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -598,7 +598,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
* @return the prepared statement * @return the prepared statement
*/ */
public Command prepareLocal(String sql) { public Command prepareLocal(String sql) {
if (closed) { if (isClosed()) {
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, throw DbException.get(ErrorCode.CONNECTION_BROKEN_1,
"session closed"); "session closed");
} }
...@@ -879,8 +879,9 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -879,8 +879,9 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
@Override @Override
public void close() { public void close() {
if (!closed) { // this is the only operation that can be invoked concurrently
state = State.CLOSED; // so, we should prevent double-closure
if (state.getAndSet(State.CLOSED) != State.CLOSED) {
try { try {
database.checkPowerOff(); database.checkPowerOff();
...@@ -898,7 +899,6 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -898,7 +899,6 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
// want to take the meta lock using the system session. // want to take the meta lock using the system session.
database.unlockMeta(this); database.unlockMeta(this);
} finally { } finally {
closed = true;
database.removeSession(this); database.removeSession(this);
} }
} }
...@@ -1038,11 +1038,11 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1038,11 +1038,11 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
@Override @Override
public Trace getTrace() { public Trace getTrace() {
if (trace != null && !closed) { if (trace != null && !isClosed()) {
return trace; return trace;
} }
String traceModuleName = "jdbc[" + id + "]"; String traceModuleName = "jdbc[" + id + "]";
if (closed) { if (isClosed()) {
return new TraceSystem(null).getTrace(traceModuleName); return new TraceSystem(null).getTrace(traceModuleName);
} }
trace = database.getTraceSystem().getTrace(traceModuleName); trace = database.getTraceSystem().getTrace(traceModuleName);
...@@ -1204,7 +1204,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1204,7 +1204,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
@Override @Override
public boolean isClosed() { public boolean isClosed() {
return closed; return state.get() == State.CLOSED;
} }
public void setThrottle(int throttle) { public void setThrottle(int throttle) {
...@@ -1225,15 +1225,15 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1225,15 +1225,15 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
if (lastThrottle + TimeUnit.MILLISECONDS.toNanos(Constants.THROTTLE_DELAY) > time) { if (lastThrottle + TimeUnit.MILLISECONDS.toNanos(Constants.THROTTLE_DELAY) > time) {
return; return;
} }
State prevState = this.state; State prevState = this.state.get();
lastThrottle = time + throttleNs; lastThrottle = time + throttleNs;
try { try {
this.state = State.SLEEP; state.set(State.SLEEP);
Thread.sleep(TimeUnit.NANOSECONDS.toMillis(throttleNs)); Thread.sleep(TimeUnit.NANOSECONDS.toMillis(throttleNs));
} catch (Exception e) { } catch (Exception e) {
// ignore InterruptedException // ignore InterruptedException
} finally { } finally {
this.state = prevState; state.set(prevState);
} }
} }
...@@ -1265,7 +1265,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1265,7 +1265,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
currentCommandStart = null; currentCommandStart = null;
} }
} }
state = command == null ? State.SLEEP : State.RUNNING; state.set(command == null ? State.SLEEP : State.RUNNING);
} }
/** /**
...@@ -1782,11 +1782,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1782,11 +1782,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
} }
public State getState() { public State getState() {
return getBlockingSessionId() != 0 ? State.BLOCKED : state; return getBlockingSessionId() != 0 ? State.BLOCKED : state.get();
}
public void setState(State state) {
this.state = state;
} }
public int getBlockingSessionId() { public int getBlockingSessionId() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论