Package net.sf.hajdbc.sql

Source Code of net.sf.hajdbc.sql.LocalTransactionContext

/*
* HA-JDBC: High-Availability JDBC
* Copyright (C) 2012  Paul Ferraro
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.hajdbc.sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.SortedMap;
import java.util.concurrent.locks.Lock;

import net.sf.hajdbc.Database;
import net.sf.hajdbc.DatabaseCluster;
import net.sf.hajdbc.ExceptionType;
import net.sf.hajdbc.durability.Durability;
import net.sf.hajdbc.invocation.InvocationStrategy;
import net.sf.hajdbc.invocation.Invoker;
import net.sf.hajdbc.tx.TransactionIdentifierFactory;

/**
* @author Paul Ferraro
* @param <Z>
* @param <D>
*/
public class LocalTransactionContext<Z, D extends Database<Z>> implements TransactionContext<Z, D>
{
  final Durability<Z, D> durability;
  private final Lock lock;
  private final TransactionIdentifierFactory<? extends Object> transactionIdFactory;
  volatile Object transactionId;
 
  /**
   * @param cluster
   */
  public LocalTransactionContext(DatabaseCluster<Z, D> cluster)
  {
    this.lock = cluster.getLockManager().readLock(null);
    this.durability = cluster.getDurability();
    this.transactionIdFactory = cluster.getTransactionIdentifierFactory();
  }
 
  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.sql.TransactionContext#start(net.sf.hajdbc.invocation.InvocationStrategy, java.sql.Connection)
   */
  @Override
  public InvocationStrategy start(final InvocationStrategy strategy, final Connection connection) throws SQLException
  {
    if (this.transactionId != null) return strategy;
   
    if (connection.getAutoCommit())
    {
      return new InvocationStrategy()
      {
        @Override
        public <ZZ, DD extends Database<ZZ>, T, R, E extends Exception> SortedMap<DD, R> invoke(ProxyFactory<ZZ, DD, T, E> proxy, Invoker<ZZ, DD, T, R, E> invoker) throws E
        {
          LocalTransactionContext.this.lock();
         
          try
          {
            InvocationStrategy durabilityStrategy = LocalTransactionContext.this.durability.getInvocationStrategy(strategy, Durability.Phase.COMMIT, LocalTransactionContext.this.transactionId);
           
            return durabilityStrategy.invoke(proxy, invoker);
          }
          finally
          {
            LocalTransactionContext.this.unlock();
          }
        }
      };
    }
   
    return new InvocationStrategy()
    {
      @Override
      public <ZZ, DD extends Database<ZZ>, T, R, E extends Exception> SortedMap<DD, R> invoke(ProxyFactory<ZZ, DD, T, E> proxy, Invoker<ZZ, DD, T, R, E> invoker) throws E
      {
        LocalTransactionContext.this.lock();
       
        try
        {
          return strategy.invoke(proxy, invoker);
        }
        catch (Throwable e)
        {
          throw proxy.getExceptionFactory().createException(e);
        }
        finally
        {
          LocalTransactionContext.this.unlock();
        }
      }
    };
  }
 
  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.sql.TransactionContext#start(net.sf.hajdbc.invocation.Invoker, java.sql.Connection)
   */
  @Override
  public <T, R> Invoker<Z, D, T, R, SQLException> start(final Invoker<Z, D, T, R, SQLException> invoker, Connection connection) throws SQLException
  {
    if ((this.transactionId == null) || !connection.getAutoCommit()) return invoker;

    return new Invoker<Z, D, T, R, SQLException>()
    {
      @Override
      public R invoke(D database, T object) throws SQLException
      {
        return LocalTransactionContext.this.durability.getInvoker(invoker, Durability.Phase.COMMIT, LocalTransactionContext.this.transactionId, ExceptionType.SQL.<SQLException>getExceptionFactory()).invoke(database, object);
      }
    };
  }

  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.sql.TransactionContext#end(net.sf.hajdbc.invocation.InvocationStrategy, net.sf.hajdbc.durability.Durability.Phase)
   */
  @Override
  public InvocationStrategy end(final InvocationStrategy strategy, final Durability.Phase phase)
  {
    if (this.transactionId == null) return strategy;

    return new InvocationStrategy()
    {
      @Override
      public <ZZ, DD extends Database<ZZ>, T, R, E extends Exception> SortedMap<DD, R> invoke(ProxyFactory<ZZ, DD, T, E> proxy, Invoker<ZZ, DD, T, R, E> invoker) throws E
      {
        InvocationStrategy durabilityStrategy = LocalTransactionContext.this.durability.getInvocationStrategy(strategy, phase, LocalTransactionContext.this.transactionId);
       
        try
        {
          return durabilityStrategy.invoke(proxy, invoker);
        }
        finally
        {
          LocalTransactionContext.this.unlock();
        }
      }
    };
  }

  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.sql.TransactionContext#end(net.sf.hajdbc.invocation.Invoker, net.sf.hajdbc.durability.Durability.Phase)
   */
  @Override
  public <T, R> Invoker<Z, D, T, R, SQLException> end(final Invoker<Z, D, T, R, SQLException> invoker, Durability.Phase phase)
  {
    if (this.transactionId == null) return invoker;

    return this.durability.getInvoker(invoker, phase, this.transactionId, ExceptionType.SQL.<SQLException>getExceptionFactory());
  }

  /**
   * @see net.sf.hajdbc.sql.TransactionContext#close()
   */
  @Override
  public void close()
  {
    // Tsk, tsk... User neglected to commit/rollback transaction
    if (this.transactionId != null)
    {
      this.unlock();
    }
  }

  void lock()
  {
    this.lock.lock();
    this.transactionId = this.transactionIdFactory.createTransactionIdentifier();
  }
 
  void unlock()
  {
    this.lock.unlock();
    this.transactionId = null;
  }
}
TOP

Related Classes of net.sf.hajdbc.sql.LocalTransactionContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.