/** * Copyright 2014 Duan Bingnan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.pinus4j.transaction.impl; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.xa.XAResource; import org.pinus4j.cluster.resources.IDBResource; import org.pinus4j.cluster.resources.IResourceId; import org.pinus4j.transaction.ITransaction; import org.pinus4j.transaction.enums.EnumTransactionIsolationLevel; /** * local transaction impelemnt. * * @author duanbn * @since 1.1.0 */ public class BestEffortsOnePCJtaTransaction implements ITransaction { /** * db resource will do commit or rollback. */ private Map<IResourceId, IDBResource> txRes = new LinkedHashMap<IResourceId, IDBResource>(); /** * isolation level of transaction. */ private EnumTransactionIsolationLevel txLevel; private AtomicInteger status = new AtomicInteger(Status.STATUS_ACTIVE); @Override public boolean isContain(IResourceId resId) { return this.txRes.containsKey(resId); } @Override public IDBResource getDBResource(IResourceId resId) { return this.txRes.get(resId); } @Override public void flush() { commit(true); } @Override public void setIsolationLevel(EnumTransactionIsolationLevel txLevel) { this.txLevel = txLevel; } /** * do commit. */ @Override public void commit() { commit(false); } private void commit(boolean isFlush) { // do flush if (isFlush) { for (IDBResource dbResource : txRes.values()) { dbResource.commit(); } return; } status.set(Status.STATUS_COMMITTING); // do commit for (IDBResource dbResource : txRes.values()) { dbResource.commit(); dbResource.close(); } status.set(Status.STATUS_NO_TRANSACTION); } /** * do rollback. */ @Override public void rollback() { status.set(Status.STATUS_ROLLING_BACK); // do rollback. for (IDBResource dbResource : txRes.values()) { dbResource.rollback(); if (!dbResource.isClosed()) dbResource.close(); } status.set(Status.STATUS_NO_TRANSACTION); } // jta implements. @Override public boolean delistResource(XAResource xaResource, int arg1) throws IllegalStateException, SystemException { IDBResource dbResource = (IDBResource) xaResource; IResourceId resId = dbResource.getId(); txRes.remove(resId); return true; } @Override public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException { IDBResource dbResource = (IDBResource) xaResource; IResourceId resId = dbResource.getId(); if (txRes.get(resId) == null) { synchronized (txRes) { if (txRes.get(resId) == null) { dbResource.setTransactionIsolationLevel(txLevel); txRes.put(resId, dbResource); } } } return true; } @Override public int getStatus() throws SystemException { return status.get(); } @Override public void registerSynchronization(Synchronization arg0) throws RollbackException, IllegalStateException, SystemException { throw new UnsupportedOperationException(); } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { // do nothing... } }