Permalink
Browse files

refactor: state of PGXAConnection as enum (#966)

make state of PGXAConnection as enum
  • Loading branch information...
AlexElin authored and davecramer committed Oct 24, 2017
1 parent bdfc1db commit 76188228ddb412db74959fbe59b5c2d6ef5eddfc
@@ -62,13 +62,15 @@ public PGPooledConnection(Connection con, boolean autoCommit) {
/**
* Adds a listener for close or fatal error events on the connection handed out to a client.
*/
@Override
public void addConnectionEventListener(ConnectionEventListener connectionEventListener) {
listeners.add(connectionEventListener);
}
/**
* Removes a listener for close or fatal error events on the connection handed out to a client.
*/
@Override
public void removeConnectionEventListener(ConnectionEventListener connectionEventListener) {
listeners.remove(connectionEventListener);
}
@@ -77,6 +79,7 @@ public void removeConnectionEventListener(ConnectionEventListener connectionEven
* Closes the physical database connection represented by this PooledConnection. If any client has
* a connection based on this PooledConnection, it is forcibly closed as well.
*/
@Override
public void close() throws SQLException {
if (last != null) {
last.close();
@@ -107,6 +110,7 @@ public void close() throws SQLException {
* called, the previous one is forcibly closed and its work rolled back.
* </p>
*/
@Override
public Connection getConnection() throws SQLException {
if (con == null) {
// Before throwing the exception, let's notify the registered listeners about the error
@@ -432,9 +436,11 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
}
}
@Override
public void removeStatementEventListener(StatementEventListener listener) {
}
@Override
public void addStatementEventListener(StatementEventListener listener) {
}
@@ -50,29 +50,9 @@
*/
private final BaseConnection conn;
/*
* PGXAConnection-object can be in one of three states:
*
* IDLE Not associated with a XA-transaction. You can still call getConnection and use the
* connection outside XA. currentXid is null. autoCommit is true on a connection by getConnection,
* per normal JDBC rules, though the caller can change it to false and manage transactions itself
* using Connection.commit and rollback.
*
* ACTIVE start has been called, and we're associated with an XA transaction. currentXid is valid.
* autoCommit is false on a connection returned by getConnection, and should not be messed with by
* the caller or the XA transaction will be broken.
*
* ENDED end has been called, but the transaction has not yet been prepared. currentXid is still
* valid. You shouldn't use the connection for anything else than issuing a XAResource.commit or
* rollback.
*/
private Xid currentXid;
private int state;
private static final int STATE_IDLE = 0;
private static final int STATE_ACTIVE = 1;
private static final int STATE_ENDED = 2;
private State state;
/*
* When an XA transaction is started, we put the underlying connection into non-autocommit mode.
@@ -90,20 +70,21 @@ private void debug(String s) {
public PGXAConnection(BaseConnection conn) throws SQLException {
super(conn, true, true);
this.conn = conn;
this.state = STATE_IDLE;
this.state = State.IDLE;
}
/**
* XAConnection interface
*/
@Override
public Connection getConnection() throws SQLException {
Connection conn = super.getConnection();
// When we're outside an XA transaction, autocommit
// is supposed to be true, per usual JDBC convention.
// When an XA transaction is in progress, it should be
// false.
if (state == STATE_IDLE) {
if (state == State.IDLE) {
conn.setAutoCommit(true);
}
@@ -116,6 +97,7 @@ public Connection getConnection() throws SQLException {
new Class[]{Connection.class, PGConnection.class}, handler);
}
@Override
public XAResource getXAResource() {
return this;
}
@@ -133,7 +115,7 @@ public XAResource getXAResource() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (state != STATE_IDLE) {
if (state != State.IDLE) {
String methodName = method.getName();
if (methodName.equals("commit")
|| methodName.equals("rollback")
@@ -181,6 +163,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
*
* Postconditions: 1. Connection is associated with the transaction
*/
@Override
public void start(Xid xid, int flags) throws XAException {
if (LOGGER.isLoggable(Level.FINEST)) {
debug("starting transaction xid = " + xid);
@@ -196,7 +179,7 @@ public void start(Xid xid, int flags) throws XAException {
throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);
}
if (state == STATE_ACTIVE) {
if (state == State.ACTIVE) {
throw new PGXAException(GT.tr("Connection is busy with another transaction"),
XAException.XAER_PROTO);
}
@@ -211,7 +194,7 @@ public void start(Xid xid, int flags) throws XAException {
// It's ok to join an ended transaction. WebLogic does that.
if (flags == TMJOIN) {
if (state != STATE_ENDED) {
if (state != State.ENDED) {
throw new PGXAException(GT.tr("Transaction interleaving not implemented"),
XAException.XAER_RMERR);
}
@@ -220,7 +203,7 @@ public void start(Xid xid, int flags) throws XAException {
throw new PGXAException(GT.tr("Transaction interleaving not implemented"),
XAException.XAER_RMERR);
}
} else if (state == STATE_ENDED) {
} else if (state == State.ENDED) {
throw new PGXAException(GT.tr("Transaction interleaving not implemented"),
XAException.XAER_RMERR);
}
@@ -237,7 +220,7 @@ public void start(Xid xid, int flags) throws XAException {
}
// Preconditions are met, Associate connection with the transaction
state = STATE_ACTIVE;
state = State.ACTIVE;
currentXid = xid;
}
@@ -249,6 +232,7 @@ public void start(Xid xid, int flags) throws XAException {
*
* Postconditions: 1. connection is disassociated from the transaction.
*/
@Override
public void end(Xid xid, int flags) throws XAException {
if (LOGGER.isLoggable(Level.FINEST)) {
debug("ending transaction xid = " + xid);
@@ -265,7 +249,7 @@ public void end(Xid xid, int flags) throws XAException {
throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);
}
if (state != STATE_ACTIVE || !currentXid.equals(xid)) {
if (state != State.ACTIVE || !currentXid.equals(xid)) {
throw new PGXAException(GT.tr("tried to call end without corresponding start call"),
XAException.XAER_PROTO);
}
@@ -279,7 +263,7 @@ public void end(Xid xid, int flags) throws XAException {
// if TMFAIL was given.
// All clear. We don't have any real work to do.
state = STATE_ENDED;
state = State.ENDED;
}
/**
@@ -289,6 +273,7 @@ public void end(Xid xid, int flags) throws XAException {
*
* Postconditions: 1. Transaction is prepared
*/
@Override
public int prepare(Xid xid) throws XAException {
if (LOGGER.isLoggable(Level.FINEST)) {
debug("preparing transaction xid = " + xid);
@@ -301,11 +286,11 @@ public int prepare(Xid xid) throws XAException {
"Not implemented: Prepare must be issued using the same connection that started the transaction"),
XAException.XAER_RMERR);
}
if (state != STATE_ENDED) {
if (state != State.ENDED) {
throw new PGXAException(GT.tr("Prepare called before end"), XAException.XAER_INVAL);
}
state = STATE_IDLE;
state = State.IDLE;
currentXid = null;
try {
@@ -332,6 +317,7 @@ public int prepare(Xid xid) throws XAException {
*
* Postconditions: 1. list of prepared xids is returned
*/
@Override
public Xid[] recover(int flag) throws XAException {
// Check preconditions
if (flag != TMSTARTRSCAN && flag != TMENDRSCAN && flag != TMNOFLAGS
@@ -384,6 +370,7 @@ public int prepare(Xid xid) throws XAException {
*
* Postconditions: 1. Transaction is rolled back and disassociated from connection
*/
@Override
public void rollback(Xid xid) throws XAException {
if (LOGGER.isLoggable(Level.FINEST)) {
debug("rolling back xid = " + xid);
@@ -393,7 +380,7 @@ public void rollback(Xid xid) throws XAException {
try {
if (currentXid != null && xid.equals(currentXid)) {
state = STATE_IDLE;
state = State.IDLE;
currentXid = null;
conn.rollback();
conn.setAutoCommit(localAutoCommitMode);
@@ -418,6 +405,7 @@ public void rollback(Xid xid) throws XAException {
}
}
@Override
public void commit(Xid xid, boolean onePhase) throws XAException {
if (LOGGER.isLoggable(Level.FINEST)) {
debug("committing xid = " + xid + (onePhase ? " (one phase) " : " (two phase)"));
@@ -454,12 +442,12 @@ private void commitOnePhase(Xid xid) throws XAException {
"Not implemented: one-phase commit must be issued using the same connection that was used to start it"),
XAException.XAER_RMERR);
}
if (state != STATE_ENDED) {
if (state != State.ENDED) {
throw new PGXAException(GT.tr("commit called before end"), XAException.XAER_PROTO);
}
// Preconditions are met. Commit
state = STATE_IDLE;
state = State.IDLE;
currentXid = null;
conn.commit();
@@ -481,7 +469,7 @@ private void commitPrepared(Xid xid) throws XAException {
// Check preconditions. The connection mustn't be used for another
// other XA or local transaction, or the COMMIT PREPARED command
// would mess it up.
if (state != STATE_IDLE
if (state != State.IDLE
|| conn.getTransactionState() != TransactionState.IDLE) {
throw new PGXAException(
GT.tr("Not implemented: 2nd phase commit must be issued using an idle connection"),
@@ -505,6 +493,7 @@ private void commitPrepared(Xid xid) throws XAException {
}
}
@Override
public boolean isSameRM(XAResource xares) throws XAException {
// This trivial implementation makes sure that the
// application server doesn't try to use another connection
@@ -515,6 +504,7 @@ public boolean isSameRM(XAResource xares) throws XAException {
/**
* Does nothing, since we don't do heuristics,
*/
@Override
public void forget(Xid xid) throws XAException {
throw new PGXAException(GT.tr("Heuristic commit/rollback not supported"),
XAException.XAER_NOTA);
@@ -523,14 +513,39 @@ public void forget(Xid xid) throws XAException {
/**
* We don't do transaction timeouts. Just returns 0.
*/
@Override
public int getTransactionTimeout() {
return 0;
}
/**
* We don't do transaction timeouts. Returns false.
*/
@Override
public boolean setTransactionTimeout(int seconds) {
return false;
}
private enum State {
/**
* {@code PGXAConnection} not associated with a XA-transaction. You can still call {@link #getConnection()} and
* use the connection outside XA. {@code currentXid} is {@code null}. autoCommit is {@code true} on a connection
* by getConnection, per normal JDBC rules, though the caller can change it to {@code false} and manage
* transactions itself using Connection.commit and rollback.
*/
IDLE,
/**
* {@link #start(Xid, int)} has been called, and we're associated with an XA transaction. {@code currentXid}
* is valid. autoCommit is false on a connection returned by getConnection, and should not be messed with by
* the caller or the XA transaction will be broken.
*/
ACTIVE,
/**
* {@link #end(Xid, int)} has been called, but the transaction has not yet been prepared. {@code currentXid}
* is still valid. You shouldn't use the connection for anything else than issuing a {@link XAResource#commit(Xid, boolean)} or
* rollback.
*/
ENDED
}
}

0 comments on commit 7618822

Please sign in to comment.