Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.arjuna.ats.arjuna.tools.osb.mbean;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.RecordList;
import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import com.arjuna.ats.arjuna.logging.tsLogger;
import com.arjuna.ats.arjuna.objectstore.StoreManager;
import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
/**
* MBean implementation of an ObjectStore entry that represents an AtomicAction
*/
public class ActionBean extends OSEntryBean implements ActionBeanMBean {
// Basic properties this enty
private StateManagerWrapper sminfo;
// collection of participants belonging to this BasicAction
private Collection participants = new ArrayList();
// wrapper around the real AtomicAction
protected ActionBeanWrapperInterface ra;
public ActionBean(UidWrapper w) {
super(w);
boolean isJTS = JMXServer.isJTS() && w.getType().endsWith("ArjunaTransactionImple");
// Participants in a JTS transaction are represented by entries in the ObjectStore
List recuids = null;
if (isJTS) {
try {
Class cl = (Class) Class.forName(JMXServer.AJT_WRAPPER_TYPE);
Constructor constructor = cl.getConstructor(ActionBean.class, UidWrapper.class);
ra = constructor.newInstance(this, w);
ra.activate();
} catch (Exception e) { // ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
if (tsLogger.logger.isTraceEnabled())
tsLogger.logger.trace("Error constructing " + JMXServer.AJT_WRAPPER_TYPE + ": " + e);
ra = createWrapper(w, true);
}
/*
* for JTS actions the participants will have entries in the ObjectStore.
* these entries will be associated with the current MBean (refer to
* the method findParticipants below for details)
*/
recuids = w.probe(JMXServer.AJT_RECORD_TYPE, JMXServer.AJT_XAREC_TYPE);
} else {
ra = createWrapper(w, true); // com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeManager.manager()
}
sminfo = new StateManagerWrapper(StoreManager.getRecoveryStore(), getUid(), getType());
for (ParticipantStatus lt : ParticipantStatus.values()) {
findParticipants(recuids, ra.getRecords(lt), lt);
}
}
protected ActionBeanWrapperInterface createWrapper(UidWrapper w, boolean activate) {
GenericAtomicActionWrapper action = new GenericAtomicActionWrapper(w.getClassName(), w);
if (activate)
action.activate();
return action;
}
public StringBuilder toString(String prefix, StringBuilder sb) {
ra.toString(prefix, sb);
prefix += '\t';
sb.append('\n').append(prefix).append(sminfo.getCreationTime());
sb.append('\n').append(prefix).append(sminfo.getAgeInSeconds());
for (LogRecordWrapper p : participants) {
p.toString(prefix, sb);
}
return sb;
}
/**
* return the Uid for given AbstractRecord
* @param rec the record whose Uid is required
* @return the Uid of the requested record
*/
public Uid getUid(AbstractRecord rec) {
return ra.getUid(rec);
}
/**
* Remove this AtomicAction from the ObjectStore
* @return a textual indication of whether the remove operation succeeded
*/
public String remove() {
try {
if (!StoreManager.getRecoveryStore().remove_committed(getUid(), getType()))
return "Attempt to remove transaction failed";
else
w.probe();
return "Transaction successfully removed";
} catch (ObjectStoreException e) {
return "Unable to remove transaction: " + e.getMessage();
}
}
/**
* create MBean representations of the participants of this transaction
* @param recuids some transaction participants are represented in the ObjectStore
* - if this is the case then recuids contains a list of MBean wrappers representing them.
* Otherwise this list will be empty.
* @param list the records representing the participants
* @param listType indicates the type of the records in list (PREPARED, PENDING, FAILED, READONLY, HEURISTIC)
*/
private void findParticipants(List recuids, RecordList list, ParticipantStatus listType) {
if (list != null) {
for (AbstractRecord rec = list.peekFront(); rec != null; rec = list.peekNext(rec)) {
LogRecordWrapper lw;
int i = recuids == null ? -1 : recuids.indexOf(new UidWrapper(ra.getUid(rec)));
if (i != -1) {
OSEntryBean p = recuids.get(i).getMBean();
if (p instanceof LogRecordWrapper) {
lw = (LogRecordWrapper) p;
lw.init(this, rec, listType);
} else {
if (tsLogger.logger.isTraceEnabled())
tsLogger.logger.trace("participant record is not a LogRecordWrapper");
lw = createParticipant(rec, listType);
}
} else {
lw = createParticipant(rec, listType);
}
lw.activate();
participants.add(lw);
}
}
}
/**
* Extension point for other Bean implementations to provide an implementation bean for its participants.
* For example @see com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean
* @param rec the record that should be represented by an MBean
* @param listType the status of the record
* @return the MBean implementation of the participant
*/
protected LogRecordWrapper createParticipant(AbstractRecord rec, ParticipantStatus listType) {
return new LogRecordWrapper(this, rec, listType);
}
/**
* See if there is participant Bean corresponding to the given record
* @param rec the record for the target participant
* @return the bean corresponding to the requested record
*/
public LogRecordWrapper getParticipant(AbstractRecord rec) {
for (LogRecordWrapper w : participants)
if (w.getRecord().equals(rec))
return w;
return null;
}
/**
* register this bean (and its participants) with the MBeanServer
*/
public void register() {
super.register();
for (LogRecordWrapper p : participants)
JMXServer.getAgent().registerMBean(p.getName(), p);
}
/**
* unregister this bean (and its participants) with the MBeanServer
*/
public void unregister() {
for (LogRecordWrapper p : participants)
JMXServer.getAgent().unregisterMBean(p.getName());
super.unregister();
}
public long getAgeInSeconds() {
return sminfo.getAgeInSeconds();
}
public String getCreationTime() {
return sminfo.getCreationTime();
}
public boolean isParticipant() {
return false;
}
/**
* Request a change in status of a participant. For example if a record has a
* heuristic status then this method could be used to move it back into the
* prepared state so that the recovery system can replay phase 2 of the
* commitment protocol
* @param logrec the record whose status is to be changed
* @param newStatus the desired status
* @return true if the status was changed
*/
public boolean setStatus(LogRecordWrapper logrec, ParticipantStatus newStatus) {
ParticipantStatus lt = logrec.getListType();
AbstractRecord targRecord = logrec.getRecord();
RecordList oldList = ra.getRecords(lt);
RecordList newList = ra.getRecords(newStatus);
if (lt.equals(ParticipantStatus.HEURISTIC) && !targRecord.forgetHeuristic()) {
return false;
}
// move the record from currList to targList
if (oldList.remove(targRecord)) {
if (newList.insert(targRecord)) {
if (lt.equals(ParticipantStatus.HEURISTIC)) {
switch (newStatus) {
case FAILED:
ra.clearHeuristicDecision(TwoPhaseOutcome.FINISH_ERROR);
break;
case PENDING:
ra.clearHeuristicDecision(TwoPhaseOutcome.NOT_PREPARED);
break;
case PREPARED:
ra.clearHeuristicDecision(TwoPhaseOutcome.PREPARE_OK);
break;
case READONLY:
ra.clearHeuristicDecision(TwoPhaseOutcome.PREPARE_READONLY);
break;
default:
break;
}
}
ra.doUpdateState();
return true;
}
}
return false;
}
/**
*
* @return the MBeans corresponding to the participants within this action
*/
public Collection getParticipants() {
return Collections.unmodifiableCollection(participants);
}
/**
* The ActionBean needs access to the participant lists maintained by an AtomicAction but these
* lists are protected. Therefore define a simple extension class to get at these records:
*/
public class GenericAtomicActionWrapper implements ActionBeanWrapperInterface {
boolean activated;
BasicAction action;
Map recs;
Method setHeuristicDecision;
Method updateState = null;
UidWrapper uidWrapper;
public GenericAtomicActionWrapper(String classType, UidWrapper w) {
uidWrapper = w;
recs = new HashMap();
if (classType == null)
classType = "com.arjuna.ats.arjuna.AtomicAction";
try {
Class cls = Class.forName(classType);
Class pTypes[] = new Class[1];
pTypes[0] = Uid.class;
Constructor ctor = cls.getConstructor(pTypes);
Object args[] = new Object[1];
args[0] = w.getUid();
action = (BasicAction) ctor.newInstance(args);
setHeuristicDecision = getMethod(action.getClass(), "setHeuristicDecision", int.class);
updateState = getMethod(action.getClass(), "updateState");
if (setHeuristicDecision != null)
setHeuristicDecision.setAccessible(true);
if (updateState != null)
updateState.setAccessible(true);
} catch (Exception e) {
action = null;
if (tsLogger.logger.isDebugEnabled())
tsLogger.logger.debug("unable to create log wrapper for type " + w.getType() + ": error: " + e.getMessage());
}
}
public BasicAction getAction() {
return action;
}
public boolean activate() {
if (!activated && action != null) {
activated = action.activate();
}
return activated;
}
public void doUpdateState() {
if (updateState != null && action != null) {
try {
updateState.invoke(action);
} catch (IllegalAccessException e) {
if (tsLogger.logger.isDebugEnabled())
tsLogger.logger.debug("failed to update heuristic for " + action.toString() + ": error: " + e.getMessage());
} catch (InvocationTargetException e) {
if (tsLogger.logger.isDebugEnabled())
tsLogger.logger.debug("failed to update heuristic for " + action.toString() + ": error: " + e.getMessage());
}
}
}
public Uid get_uid() {
return action != null ? action.get_uid() : uidWrapper.getUid();
}
public Uid getUid(AbstractRecord rec) {
return rec.order(); //get_uid();
}
public StringBuilder toString(String prefix, StringBuilder sb) {
prefix += '\t';
return sb.append('\n').append(prefix).append(get_uid());
}
public void clearHeuristicDecision(int newDecision) {
RecordList rl = getRecords("heuristicList");
if (setHeuristicDecision != null && rl != null && rl.size() == 0)
try {
setHeuristicDecision.invoke(action, newDecision);
} catch (IllegalAccessException e) {
if (tsLogger.logger.isDebugEnabled())
tsLogger.logger.debug("failed to update heuristic for " + action.toString() + ": error: " + e.getMessage());
} catch (InvocationTargetException e) {
if (tsLogger.logger.isDebugEnabled())
tsLogger.logger.debug("failed to update heuristic for " + action.toString() + ": error: " + e.getMessage());
}
}
private Field getField(Class cl, String fn) {
try {
return cl.getDeclaredField(fn);
} catch (NoSuchFieldException e) {
return getField(cl.getSuperclass(), fn);
}
}
private Method getMethod(Class cl, String mn, Class>... parameterTypes) {
try {
if (cl == null)
return null;
return cl.getDeclaredMethod(mn, parameterTypes);
} catch (NoSuchMethodException e) {
return getMethod(cl.getSuperclass(), mn, parameterTypes);
}
}
public RecordList getRecords(String ln) {
if (action == null)
return null;
if (recs.containsKey(ln))
return recs.get(ln);
Field f = getField(action.getClass(), ln);
f.setAccessible(true);
try {
RecordList rl = (RecordList) f.get(action);
if (rl != null)
recs.put(ln, rl);
return rl;
} catch (IllegalAccessException e) {
return null;
}
}
public RecordList getRecords(ParticipantStatus type) {
switch (type) {
default:
case PREPARED: return getRecords("preparedList");
case FAILED: return getRecords("failedList");
case HEURISTIC: return getRecords("heuristicList");
case PENDING: return getRecords("pendingList");
case READONLY: return getRecords("readonlyList");
}
}
}
}