/* * JBoss, Home of Professional Open Source * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * 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, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * (C) 2005-2006, * @author JBoss Inc. */ /* * Copyright (C) 1998, 1999, 2000, 2001, * * Arjuna Solutions Limited, * Newcastle upon Tyne, * Tyne and Wear, * UK. * * $Id: CadaverLockRecord.java 2342 2006-03-30 13:06:17Z $ */ package com.arjuna.ats.internal.txoj.abstractrecords; import java.io.PrintWriter; import com.arjuna.ats.arjuna.ObjectModel; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.ats.arjuna.coordinator.AbstractRecord; import com.arjuna.ats.arjuna.coordinator.BasicAction; import com.arjuna.ats.arjuna.coordinator.RecordType; import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome; import com.arjuna.ats.arjuna.exceptions.FatalError; import com.arjuna.ats.txoj.LockManager; import com.arjuna.ats.txoj.lockstore.LockStore; import com.arjuna.ats.txoj.logging.txojLogger; /* * * Cadaver Lock Record Class Implementation * * Instances of this record class are created by LockManager if the * object goes out of scope prior to the end of a manipulating action. * The intention is that the operations of this class will clean up * those locks that get left set as the object goes out of scope but * which must remain held until the action ends otherwise serialisability * is compromised * */ public class CadaverLockRecord extends LockRecord { public CadaverLockRecord (LockStore store, LockManager lm, BasicAction currAct) { super(lm, currAct); cadaverLockStore = store; objectTypeName = new String(lm.type()); if (lm.getObjectModel() == ObjectModel.SINGLE) { doRelease = false; } else doRelease = true; if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::CadaverLockRecord("+store+ ", "+lm.get_uid()+")"); } } /* * Public virtual functions. These are all re-implementations of inherited * functions */ public boolean propagateOnAbort () { return true; } /* * Atomic action controlled functions. These functions create an instance * of CadaverLockManager to handle the lock manipulation that is needed and * then throw it away when done. */ public int nestedAbort () { if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::nestedAbort() for "+order()); } if (doRelease) { CadaverLockManager manager = new CadaverLockManager(order(), objectTypeName); if (super.actionHandle == null) { throw new FatalError(txojLogger.i18NLogger.get_CadaverLockRecord_1()); } return (manager.releaseAll(super.actionHandle.get_uid()) ? TwoPhaseOutcome.FINISH_OK : TwoPhaseOutcome.FINISH_ERROR); } else return TwoPhaseOutcome.FINISH_OK; } public int nestedCommit () { if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::nestedCommit() for "+order()); } if (doRelease) { /* * Need to change the owner of the locks from the current * committing action to its parent. Since no genuine LockManager * exists at this time create one to take care of this. */ if (super.actionHandle == null) { throw new FatalError(txojLogger.i18NLogger.get_CadaverLockRecord_2()); } CadaverLockManager manager = new CadaverLockManager(order(), objectTypeName); return (manager.propagate(super.actionHandle.get_uid(), super.actionHandle.parent().get_uid()) ? TwoPhaseOutcome.FINISH_OK : TwoPhaseOutcome.FINISH_ERROR); } else return TwoPhaseOutcome.FINISH_OK; } public int topLevelAbort () { if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::topLevelAbort() for "+order()); } if (doRelease) { if (super.actionHandle == null) { throw new FatalError(txojLogger.i18NLogger.get_CadaverLockRecord_3()); } CadaverLockManager manager = new CadaverLockManager(order(), objectTypeName); return (manager.releaseAll(super.actionHandle.get_uid()) ? TwoPhaseOutcome.FINISH_OK : TwoPhaseOutcome.FINISH_ERROR); } else return TwoPhaseOutcome.FINISH_OK; } public int topLevelCommit () { if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::topLevelCommit() for "+order()); } if (doRelease) { if (super.actionHandle == null) { throw new FatalError(txojLogger.i18NLogger.get_CadaverLockRecord_4()); } CadaverLockManager manager = new CadaverLockManager(order(), objectTypeName); return (manager.releaseAll(super.actionHandle.get_uid()) ? TwoPhaseOutcome.FINISH_OK : TwoPhaseOutcome.FINISH_ERROR); } else return TwoPhaseOutcome.FINISH_OK; } public void print (PrintWriter strm) { strm.println("CadaverLockRecord : "); super.print(strm); } public String type () { return "/StateManager/AbstractRecord/LockRecord/CadaverLockRecord"; } public boolean shouldReplace (AbstractRecord ar) { return (((order().equals(ar.order())) && ar.typeIs() == RecordType.LOCK ) ? true : false); } /* * Already determined that ar is a LockRecord, otherwise replace would * not have been called. * So, get the type from it before it is deleted! */ public void replace (AbstractRecord ar) { LockRecord lr = (LockRecord) ar; objectTypeName = lr.lockType(); } protected CadaverLockRecord () { super(); cadaverLockStore = null; objectTypeName = null; doRelease = false; if (txojLogger.logger.isTraceEnabled()) { txojLogger.logger.trace("CadaverLockRecord::CadaverLockRecord ()"); } } private LockStore cadaverLockStore; private String objectTypeName; private boolean doRelease; }