001: /*
002: * HA-JDBC: High-Availability JDBC
003: * Copyright (c) 2004-2008 Paul Ferraro
004: *
005: * This library is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU Lesser General Public License as published by the
007: * Free Software Foundation; either version 2.1 of the License, or (at your
008: * option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
013: * for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software Foundation,
017: * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: ferraro@users.sourceforge.net
020: */
021: package net.sf.hajdbc.sql;
022:
023: import java.sql.Connection;
024: import java.sql.SQLException;
025: import java.util.Collections;
026: import java.util.concurrent.locks.Lock;
027:
028: import net.sf.hajdbc.DatabaseCluster;
029: import net.sf.hajdbc.LockManager;
030:
031: /**
032: * @author Paul Ferraro
033: * @param <D>
034: */
035: public class LocalTransactionContext<D> implements
036: TransactionContext<D> {
037: private Lock lock;
038: private boolean locked = false;
039:
040: /**
041: * @param cluster
042: */
043: public LocalTransactionContext(DatabaseCluster<D> cluster) {
044: this .lock = cluster.getLockManager().readLock(
045: LockManager.GLOBAL);
046: }
047:
048: /**
049: * @see net.sf.hajdbc.sql.TransactionContext#start(net.sf.hajdbc.sql.InvocationStrategy, java.sql.Connection)
050: */
051: public <T, R> InvocationStrategy<D, T, R> start(
052: final InvocationStrategy<D, T, R> strategy,
053: Connection connection) throws SQLException {
054: if (this .locked)
055: return strategy;
056:
057: if (connection.getAutoCommit()) {
058: return new LockingInvocationStrategy<D, T, R>(strategy,
059: Collections.singletonList(this .lock));
060: }
061:
062: return new InvocationStrategy<D, T, R>() {
063: @Override
064: public R invoke(SQLProxy<D, T> proxy,
065: Invoker<D, T, R> invoker) throws Exception {
066: LocalTransactionContext.this .lock();
067:
068: try {
069: return strategy.invoke(proxy, invoker);
070: } catch (Exception e) {
071: LocalTransactionContext.this .unlock();
072:
073: throw e;
074: }
075: }
076: };
077: }
078:
079: /**
080: * @see net.sf.hajdbc.sql.TransactionContext#end(net.sf.hajdbc.sql.InvocationStrategy)
081: */
082: public <T, R> InvocationStrategy<D, T, R> end(
083: final InvocationStrategy<D, T, R> strategy) {
084: if (!this .locked)
085: return strategy;
086:
087: return new InvocationStrategy<D, T, R>() {
088: @Override
089: public R invoke(SQLProxy<D, T> proxy,
090: Invoker<D, T, R> invoker) throws Exception {
091: try {
092: return strategy.invoke(proxy, invoker);
093: } finally {
094: LocalTransactionContext.this .unlock();
095: }
096: }
097: };
098: }
099:
100: /**
101: * @see net.sf.hajdbc.sql.TransactionContext#close()
102: */
103: @Override
104: public void close() {
105: // Tsk, tsk... User neglected to commit/rollback transaction
106: if (this .locked) {
107: this .unlock();
108: }
109: }
110:
111: void lock() {
112: this .lock.lock();
113: this .locked = true;
114: }
115:
116: void unlock() {
117: this .lock.unlock();
118: this .locked = false;
119: }
120: }
|