/*
* 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) 2002,
*
* Arjuna Technologies Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: ParticipantRecord.java,v 1.11 2005/06/09 09:41:27 nmcl Exp $
*/
package com.arjuna.mwlabs.wscf.model.twophase.arjunacore;
import com.arjuna.mw.wscf.logging.wscfLogger;
import com.arjuna.ats.arjuna.ObjectType;
import com.arjuna.ats.arjuna.coordinator.*;
import com.arjuna.ats.arjuna.common.*;
import com.arjuna.ats.arjuna.state.*;
import com.arjuna.mw.wscf.model.twophase.vote.*;
import com.arjuna.mw.wscf.model.twophase.participants.Participant;
import com.arjuna.mw.wscf.model.twophase.exceptions.*;
import com.arjuna.mw.wsas.exceptions.*;
import com.arjuna.mw.wscf.exceptions.*;
import com.arjuna.webservices.util.ClassLoaderHelper;
import java.io.PrintWriter;
/**
* Arjuna abstract record to handle two-phase participants.
*
* @author Mark Little (mark.little@arjuna.com)
* @version $Id: ParticipantRecord.java,v 1.11 2005/06/09 09:41:27 nmcl Exp $
*/
public class ParticipantRecord extends
com.arjuna.ats.arjuna.coordinator.AbstractRecord
{
/**
* Constructor.
*
* @param theResource
* is the proxy that allows us to call out to the object.
*
*/
public ParticipantRecord (Participant theResource, Uid id)
{
super(id, null, ObjectType.ANDPERSISTENT);
_resourceHandle = theResource;
_timeout = 0;
_coordId = new CoordinatorIdImple(id);
if (theResource == null)
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_1(order());
}
/**
* Override AbstractRecord.propagateOnCommit
*/
public boolean propagateOnCommit ()
{
return true;
}
/**
* The type of this abstract record.
*/
public int typeIs ()
{
// TODO add specific record type.
return RecordType.XTS_WSAT_RECORD;
}
/**
* The internal value.
*/
public Object value ()
{
return _resourceHandle;
}
/**
* Set the internal value. Not allowed for this class.
*
*/
public void setValue (Object o)
{
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_2();
}
/**
* The record is being driven through nested rollback.
*
*/
// TODO
public int nestedAbort ()
{
try
{
if (_resourceHandle != null)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
else
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_3(order(), ex6);
ex6.printStackTrace();
return TwoPhaseOutcome.FINISH_ERROR;
}
}
/**
* The record is being driven through nested commit.
*
*/
public int nestedCommit ()
{
try
{
if (_resourceHandle != null)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
else
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_4(order(), ex6);
return TwoPhaseOutcome.FINISH_ERROR;
}
}
/**
* The record is being driven through nested prepare.
*
*/
public int nestedPrepare ()
{
try
{
if (_resourceHandle != null)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
else
return TwoPhaseOutcome.PREPARE_NOTOK;
}
catch (Exception e6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_5(order(), e6);
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
}
/**
* The record is being driven through top-level rollback.
*
*/
public int topLevelAbort ()
{
try
{
if (_resourceHandle != null)
{
try
{
if (!_rolledback)
_resourceHandle.cancel();
}
catch (InvalidParticipantException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (WrongStateException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (HeuristicHazardException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
catch (HeuristicMixedException ex)
{
return TwoPhaseOutcome.HEURISTIC_MIXED;
}
catch (HeuristicConfirmException ex)
{
return TwoPhaseOutcome.HEURISTIC_COMMIT;
}
catch (SystemException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
return TwoPhaseOutcome.FINISH_OK;
}
else
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_6(order(), ex6);
return TwoPhaseOutcome.FINISH_ERROR;
}
}
/**
* The record is being driven through top-level commit.
*
*/
public int topLevelCommit ()
{
try
{
if (_resourceHandle != null)
{
try
{
if (!_rolledback && !_readonly)
_resourceHandle.confirm();
if (_rolledback)
throw new HeuristicHazardException();
}
catch (InvalidParticipantException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (WrongStateException ex)
{
return TwoPhaseOutcome.NOT_PREPARED; // should be HEURISTIC_HAZARD?
}
catch (HeuristicHazardException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
catch (HeuristicMixedException ex)
{
return TwoPhaseOutcome.HEURISTIC_MIXED;
}
catch (HeuristicCancelException ex)
{
return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
}
catch(SystemCommunicationException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (SystemException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
return TwoPhaseOutcome.FINISH_OK;
}
else
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_7(order(), ex6);
return TwoPhaseOutcome.FINISH_ERROR;
}
}
/**
* The record is being driven through top-level prepare.
*
*/
public int topLevelPrepare ()
{
try
{
if (_resourceHandle != null)
{
if (_rolledback)
return TwoPhaseOutcome.PREPARE_NOTOK;
if (_readonly)
return TwoPhaseOutcome.PREPARE_READONLY;
try
{
Vote res = _resourceHandle.prepare();
if (res instanceof VoteConfirm)
{
return TwoPhaseOutcome.PREPARE_OK;
}
else
{
if (res instanceof VoteReadOnly)
{
_readonly = true;
return TwoPhaseOutcome.PREPARE_READONLY;
}
else
{
_rolledback = true;
return TwoPhaseOutcome.PREPARE_NOTOK;
}
}
}
catch (InvalidParticipantException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (WrongStateException ex)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (HeuristicHazardException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
catch (HeuristicMixedException ex)
{
return TwoPhaseOutcome.HEURISTIC_MIXED;
}
catch(SystemCommunicationException ex)
{
// if prepare timed out then we return error so it goes back on the
// prepare list and is rolled back
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (SystemException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
}
else
return TwoPhaseOutcome.PREPARE_NOTOK;
}
catch (Exception e6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_8(order(), e6);
return TwoPhaseOutcome.PREPARE_NOTOK;
}
}
/**
* The record is being driven through nested commit and is the only
* resource.
*
*/
public int nestedOnePhaseCommit ()
{
try
{
if (_resourceHandle != null)
{
return TwoPhaseOutcome.FINISH_ERROR;
}
else
return TwoPhaseOutcome.FINISH_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_9(order(), ex6);
return TwoPhaseOutcome.FINISH_ERROR;
}
}
/**
* The record is being driven through top-level commit and is the only
* resource.
*
*/
public int topLevelOnePhaseCommit ()
{
try
{
if (_resourceHandle != null)
{
if (_rolledback)
return TwoPhaseOutcome.ONE_PHASE_ERROR;
if (_readonly)
return TwoPhaseOutcome.FINISH_OK;
try
{
_resourceHandle.confirmOnePhase();
}
catch (InvalidParticipantException ex)
{
return TwoPhaseOutcome.ONE_PHASE_ERROR;
}
catch (WrongStateException ex)
{
return TwoPhaseOutcome.ONE_PHASE_ERROR;
}
catch (HeuristicHazardException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
catch (HeuristicMixedException ex)
{
return TwoPhaseOutcome.HEURISTIC_MIXED;
}
catch (HeuristicCancelException ex)
{
return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
}
// TODO explicit in the signature
catch (ParticipantCancelledException ex) // a type of SystemException
{
return TwoPhaseOutcome.ONE_PHASE_ERROR;
}
catch (SystemException ex)
{
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
return TwoPhaseOutcome.FINISH_OK;
}
else
return TwoPhaseOutcome.ONE_PHASE_ERROR;
}
catch (Exception ex6) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_10(order(), ex6);
return TwoPhaseOutcome.ONE_PHASE_ERROR;
}
}
/**
* The record generated a heuristic and can now forget about it.
*
*/
public boolean forgetHeuristic ()
{
try
{
if (_resourceHandle != null)
{
try
{
_resourceHandle.forget();
}
catch (InvalidParticipantException ex)
{
return false;
}
catch (WrongStateException ex)
{
return false;
}
catch (SystemException ex)
{
return false;
}
return true;
}
else {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_11(order());
}
}
catch (Exception e) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_12(order(), e);
e.printStackTrace();
}
return false;
}
public static AbstractRecord create ()
{
return new ParticipantRecord();
}
public void print (PrintWriter strm)
{
super.print(strm);
strm.print("ParticipantRecord");
strm.print(_resourceHandle);
}
public boolean restore_state (InputObjectState os, int t)
{
boolean result = super.restore_state(os, t);
if (result)
{
try
{
String resourcehandleImplClassName = os.unpackString();
Class clazz = ClassLoaderHelper.forName(ParticipantRecord.class, resourcehandleImplClassName);
_resourceHandle = (Participant)clazz.newInstance();
result = _resourceHandle.restore_state(os);
if (result)
_timeout = os.unpackLong();
/*
* TODO: unpack qualifiers and coord id.
*/
}
catch (Exception ex) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_13(ex);
result = false;
}
}
return result;
}
public boolean save_state (OutputObjectState os, int t)
{
boolean result = super.save_state(os, t);
if (result)
{
try
{
os.packString(_resourceHandle.getClass().getName()); // TODO: a shorter value whould be more efficient.
result = _resourceHandle.save_state(os);
if (result)
os.packLong(_timeout);
/*
* TODO: pack qualifiers and coord id.
*/
}
catch (Exception ex) {
wscfLogger.i18NLogger.warn_model_twophase_arjunacore_ParticipantRecord_14(ex);
result = false;
}
}
return result;
}
public String type ()
{
return "/StateManager/AbstractRecord/WSCF/ArjunaCore/ParticipantRecord";
}
public boolean doSave ()
{
return true;
}
public void merge (AbstractRecord a)
{
}
public void alter (AbstractRecord a)
{
}
public boolean shouldAdd (AbstractRecord a)
{
return false;
}
public boolean shouldAlter (AbstractRecord a)
{
return false;
}
public boolean shouldMerge (AbstractRecord a)
{
return false;
}
public boolean shouldReplace (AbstractRecord rec)
{
return false;
}
public final void rolledback ()
{
_rolledback = true;
}
public final void readonly ()
{
_readonly = true;
}
/*
* Protected constructor used by crash recovery.
*/
public ParticipantRecord ()
{
super();
_resourceHandle = null;
_timeout = 0;
_coordId = null;
}
private Participant _resourceHandle;
private long _timeout;
private CoordinatorIdImple _coordId;
private boolean _rolledback = false;
private boolean _readonly = false;
}