[jboss-svn-commits] JBL Code SVN: r37814 - in labs/jbosstm/branches/JBOSSTS_4_16: ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Dec 15 16:43:39 EST 2011
Author: mmusgrov
Date: 2011-12-15 16:43:39 -0500 (Thu, 15 Dec 2011)
New Revision: 37814
Added:
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBean.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBeanMBean.java
Modified:
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java
labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java
Log:
JBTM-1000 and JBTM-995 (the new system property is ObjStoreBrowserHandlers.OBJ_STORE_BROWSER_HANDLERS)
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -1,308 +1,417 @@
package com.arjuna.ats.arjuna.tools.osb.mbean;
+import com.arjuna.ats.arjuna.coordinator.BasicAction;
import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
import com.arjuna.ats.arjuna.logging.tsLogger;
-import com.arjuna.ats.arjuna.AtomicAction;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
import com.arjuna.ats.arjuna.coordinator.RecordList;
-import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import com.arjuna.ats.arjuna.objectstore.StoreManager;
import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
/**
* 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<LogRecordWrapper> participants = new ArrayList<LogRecordWrapper>();
- // wrapper around the real AtomicAction
- private ActionBeanWrapperInterface ra;
+ // Basic properties this enty
+ private StateManagerWrapper sminfo;
+ // collection of participants belonging to this BasicAction
+ private Collection<LogRecordWrapper> participants = new ArrayList<LogRecordWrapper>();
+ // wrapper around the real AtomicAction
+ protected ActionBeanWrapperInterface ra;
- public ActionBean(UidWrapper w) {
- super(w);
+ 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<UidWrapper> recuids = null;
+ boolean isJTS = JMXServer.isJTS() && w.getType().endsWith("ArjunaTransactionImple");
+ // Participants in a JTS transaction are represented by entries in the ObjectStore
+ List<UidWrapper> recuids = null;
- if (isJTS) {
- try {
- Class<ActionBeanWrapperInterface> cl = (Class<ActionBeanWrapperInterface>) Class.forName(JMXServer.AJT_WRAPPER_TYPE);
- Constructor<ActionBeanWrapperInterface> constructor = cl.getConstructor(ActionBean.class, UidWrapper.class);
- ra = constructor.newInstance(this, w);
- } catch (Exception e) { // ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
- if (tsLogger.logger.isTraceEnabled())
- tsLogger.logger.trace("Error constructing " + JMXServer.AJT_WRAPPER_TYPE + ": " + e);
- ra = new AtomicActionWrapper(w);
- }
- } else {
- ra = new AtomicActionWrapper(w);
- }
+ if (isJTS) {
+ try {
+ Class<ActionBeanWrapperInterface> cl = (Class<ActionBeanWrapperInterface>) Class.forName(JMXServer.AJT_WRAPPER_TYPE);
+ Constructor<ActionBeanWrapperInterface> 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);
+ }
- ra.activate();
- sminfo = new StateManagerWrapper(StoreManager.getRecoveryStore(), getUid(), getType());
+ /*
+ * 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()
+ }
- if (isJTS) {
- /*
- * 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);
- }
+ sminfo = new StateManagerWrapper(StoreManager.getRecoveryStore(), getUid(), getType());
- for (ParticipantStatus lt : ParticipantStatus.values()) {
- findParticipants(recuids, ra.getRecords(lt), lt);
- }
- }
+ for (ParticipantStatus lt : ParticipantStatus.values()) {
+ findParticipants(recuids, ra.getRecords(lt), lt);
+ }
+ }
- 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());
+ protected ActionBeanWrapperInterface createWrapper(UidWrapper w, boolean activate) {
+ GenericAtomicActionWrapper action = new GenericAtomicActionWrapper(w.getClassName(), w);
- for (LogRecordWrapper p : participants) {
- p.toString(prefix, sb);
- }
+ if (activate)
+ action.activate();
- return sb;
- }
+ return action;
+ }
- /**
- * 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 "remove committed failed"; // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_1
- else
- w.probe();
+ 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());
- return "remove ok"; // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_2
- } catch (ObjectStoreException e) {
- return "remove committed exception: " + e.getMessage(); // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_3
- }
- }
+ for (LogRecordWrapper p : participants) {
+ p.toString(prefix, sb);
+ }
- /**
- * 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<UidWrapper> 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)));
+ return sb;
+ }
- if (i != -1) {
- OSEntryBean p = recuids.get(i).getMBean();
+ /**
+ * 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);
+ }
- 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);
- }
+ /**
+ * 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();
- lw.activate();
- participants.add(lw);
- }
- }
- }
+ return "Transaction successfully removed";
+ } catch (ObjectStoreException e) {
+ return "Unable to remove transaction: " + e.getMessage();
+ }
+ }
- /**
- * 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);
- }
+ /**
+ * 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<UidWrapper> 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)));
- /**
- * 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;
+ if (i != -1) {
+ OSEntryBean p = recuids.get(i).getMBean();
- return null;
- }
+ 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);
+ }
- /**
- * register this bean (and its participants) with the MBeanServer
- */
- public void register() {
- super.register();
+ lw.activate();
+ participants.add(lw);
+ }
+ }
+ }
- for (LogRecordWrapper p : participants)
- JMXServer.getAgent().registerMBean(p.getName(), p);
- }
+ /**
+ * 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);
+ }
- /**
- * unregister this bean (and its participants) with the MBeanServer
- */
- public void unregister() {
- for (LogRecordWrapper p : participants)
- JMXServer.getAgent().unregisterMBean(p.getName());
+ /**
+ * 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;
- super.unregister();
- }
+ return null;
+ }
- public long getAgeInSeconds() {
- return sminfo.getAgeInSeconds();
- }
+ /**
+ * register this bean (and its participants) with the MBeanServer
+ */
+ public void register() {
+ super.register();
- public String getCreationTime() {
- return sminfo.getCreationTime();
- }
+ for (LogRecordWrapper p : participants)
+ JMXServer.getAgent().registerMBean(p.getName(), p);
+ }
- public boolean isParticipant() {
- return false;
- }
+ /**
+ * unregister this bean (and its participants) with the MBeanServer
+ */
+ public void unregister() {
+ for (LogRecordWrapper p : participants)
+ JMXServer.getAgent().unregisterMBean(p.getName());
- /**
- * 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
- * committment 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();
+ super.unregister();
+ }
- RecordList oldList = ra.getRecords(lt);
- RecordList newList = ra.getRecords(newStatus);
+ public long getAgeInSeconds() {
+ return sminfo.getAgeInSeconds();
+ }
- if (lt.equals(ParticipantStatus.HEURISTIC) && !targRecord.forgetHeuristic()) {
- return false;
- }
+ public String getCreationTime() {
+ return sminfo.getCreationTime();
+ }
- // 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;
- }
- }
+ public boolean isParticipant() {
+ return false;
+ }
- ra.doUpdateState();
-
- return true;
- }
- }
+ /**
+ * 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();
- return false;
- }
+ RecordList oldList = ra.getRecords(lt);
+ RecordList newList = ra.getRecords(newStatus);
- /**
- *
- * @return the MBeans corresponding to the participants within this action
- */
- public Collection<LogRecordWrapper> getParticipants() {
- return Collections.unmodifiableCollection(participants);
- }
+ if (lt.equals(ParticipantStatus.HEURISTIC) && !targRecord.forgetHeuristic()) {
+ return false;
+ }
- /**
- * 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:
- */
- class AtomicActionWrapper extends AtomicAction implements ActionBeanWrapperInterface {
- boolean activated;
+ // move the record from currList to targList
+ if (oldList.remove(targRecord)) {
- public AtomicActionWrapper(UidWrapper w) {
- super(w.getUid());
- }
+ 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;
+ }
+ }
- public boolean activate() {
- if (!activated)
- activated = super.activate();
+ ra.doUpdateState();
- return activated;
- }
+ return true;
+ }
+ }
- public void doUpdateState() {
- updateState();
- }
+ return false;
+ }
- public Uid getUid(AbstractRecord rec) {
- return get_uid();
- }
-
- public StringBuilder toString(String prefix, StringBuilder sb) {
- prefix += '\t';
- return sb.append('\n').append(prefix).append(get_uid());
- }
+ /**
+ *
+ * @return the MBeans corresponding to the participants within this action
+ */
+ public Collection<LogRecordWrapper> getParticipants() {
+ return Collections.unmodifiableCollection(participants);
+ }
- public void clearHeuristicDecision(int newDecision) {
- if (super.heuristicList.size() == 0)
- setHeuristicDecision(newDecision);
- }
+ /**
+ * 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<String, RecordList> recs;
+ Method setHeuristicDecision;
+ Method updateState = null;
+ UidWrapper uidWrapper;
- public RecordList getRecords(ParticipantStatus type) {
- switch (type) {
- default:
- case PREPARED: return preparedList;
- case FAILED: return failedList;
- case HEURISTIC: return heuristicList;
- case PENDING: return pendingList;
- case READONLY: return readonlyList;
- }
- }
- }
+ public GenericAtomicActionWrapper(String classType, UidWrapper w) {
+ uidWrapper = w;
+ recs = new HashMap<String, RecordList>();
+ 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");
+ }
+ }
+ }
}
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -2,6 +2,7 @@
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;
/**
@@ -14,6 +15,7 @@
Uid get_uid();
Uid getUid(AbstractRecord rec);
StringBuilder toString(String prefix, StringBuilder sb);
+ BasicAction getAction();
void clearHeuristicDecision(int newDecision);
}
\ No newline at end of file
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -65,11 +65,18 @@
}
public String setStatus(ParticipantStatus newState) {
+ if (getListType().equals(newState))
+ return "participant is prepared for recovery";
+
if (parent != null && parent.setStatus(this, newState)) {
listType = newState;
- return "status change was successful";
+
+ if (newState == ParticipantStatus.PREPARED )
+ return "participant recovery will be attempted during the next recovery pass";
+
+ return "participant status change was successful";
} else {
- return "failed";
+ return "participant status change failed";
}
}
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -4,28 +4,34 @@
import java.net.URL;
import java.util.*;
+import com.arjuna.ats.arjuna.StateManager;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
import com.arjuna.ats.arjuna.logging.tsLogger;
import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import com.arjuna.ats.arjuna.objectstore.ObjectStoreIterator;
import com.arjuna.ats.arjuna.objectstore.StoreManager;
import com.arjuna.ats.arjuna.state.InputObjectState;
import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
-import com.arjuna.ats.arjuna.common.*;
-
/**
* An MBean implementation for walking an ObjectStore and creating/deleting MBeans
* that represent completing transactions (ie ones on which the user has called commit)
*/
public class ObjStoreBrowser implements ObjStoreBrowserMBean {
+ public static final String OBJ_STORE_BROWSER_HANDLERS = "com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowserHandlers";
private static final String STORE_MBEAN_NAME = "jboss.jta:type=ObjectStore";
- private static final String OS_BEAN_PROPFILE = "osmbean.properties";
- // define which object store types can be represented by mbeans
- private Properties typeHandlers;
+ // defines a (default) map of object store types to the corresponding MBean for instrumentation.
+ // The format is OSType1=BeanType1,OSType2=BeanType2,etc
+ // Can be over-ridden by setting a system property called com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowserHandlers
+ private static final String defaultStateHandlers =
+ "com.arjuna.ats.arjuna.AtomicAction=com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean"
+// + ",com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.SubordinateAtomicAction=com.arjuna.ats.internal.jta.tools.osb.mbean.jta.SubordinateActionBean"
+ + ",com.arjuna.ats.internal.jta.tools.osb.mbean.jts.ArjunaTransactionImpleWrapper=com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean";
+ private Map<String, String> stateTypes = null; // defines which object store types will be instrumented
+ private Map<String, String> beanTypes = null; // defines which bean types are used to represent object store types
private Map<String, List<UidWrapper>> allUids;
public static void main(String[] args) throws Exception {
@@ -106,13 +112,26 @@
* as MBeans
*/
public void setTypes(Map<String, String> types) {
- for (Map.Entry<String, String> entry : types.entrySet()) {
- if (tsLogger.logger.isTraceEnabled())
- tsLogger.logger.trace("ObjStoreBrowser: adding type handler " + entry.getKey() + "," + entry.getValue());
- typeHandlers.put(entry.getKey(), entry.getValue());
- }
}
+ private void initTypeHandlers(String handlers) {
+ for (String h : handlers.split(",")) {
+ String[] handler = h.split("=");
+
+ if (handler.length == 2) {
+ String typeName = getOSType(handler[0]);
+ if (typeName != null) {
+
+ if (typeName.startsWith("/"))
+ typeName = typeName.substring(1);
+
+ stateTypes.put(typeName, handler[0]);
+ beanTypes.put(typeName, handler[1]);
+ }
+ }
+ }
+ }
+
private void init(String logDir) {
if (logDir != null)
arjPropertyManager.getObjectStoreEnvironmentBean().setObjectStoreDir(logDir);
@@ -121,10 +140,11 @@
tsLogger.logger.trace("ObjectStoreDir: " + arjPropertyManager.getObjectStoreEnvironmentBean().getObjectStoreDir());
allUids = new HashMap<String, List<UidWrapper>> ();
- typeHandlers = loadProperties(OS_BEAN_PROPFILE);
-
- if (typeHandlers.size() == 0)
- typeHandlers = loadProperties("META-INF/" + OS_BEAN_PROPFILE);
+ stateTypes = new HashMap<String, String>();
+ beanTypes = new HashMap<String, String>();
+
+ initTypeHandlers(defaultStateHandlers);
+ initTypeHandlers(System.getProperty(OBJ_STORE_BROWSER_HANDLERS, ""));
}
public ObjStoreBrowser() {
@@ -164,7 +184,20 @@
return null;
}
+;
+ private String getOSType(String classType) {
+ try {
+ Class cls = Class.forName(classType);
+ StateManager sm = (StateManager) cls.getConstructor().newInstance();
+ return sm.type();
+ } catch (Exception e) {
+ if (tsLogger.logger.isDebugEnabled())
+ tsLogger.logger.debug("Invalid class type in system property ObjStoreBrowserHandlers: " + classType);
+ }
+
+ return null;
+ }
/**
* See if any new MBeans need to be registered or if any existing MBeans no longer exist
* as ObjectStore entries.
@@ -187,8 +220,8 @@
allUids.put(tname, uids);
}
- if (typeHandlers.containsKey(tname))
- updateMBeans(uids, System.currentTimeMillis(), true, tname, typeHandlers.getProperty(tname));
+ if (beanTypes.containsKey(tname))
+ updateMBeans2(uids, System.currentTimeMillis(), true, tname);
}
} catch (IOException e1) {
tname = "";
@@ -215,20 +248,21 @@
List<UidWrapper> uids = allUids.get(type);
- updateMBeans(uids, System.currentTimeMillis(), false, type, beantype);
+ updateMBeans2(uids, System.currentTimeMillis(), false, type);
return uids;
}
- private void updateMBeans(List<UidWrapper> uids, long tstamp, boolean register, String type, String thandler) {
+ private void updateMBeans2(List<UidWrapper> uids, long tstamp, boolean register, String type) {
ObjectStoreIterator iter = new ObjectStoreIterator(StoreManager.getRecoveryStore(), type);
while (true) {
Uid u = iter.iterate();
- if (Uid.nullUid().equals(u))
+ if (u == null || Uid.nullUid().equals(u))
break;
- UidWrapper w = new UidWrapper(this, thandler, type, u);
+
+ UidWrapper w = new UidWrapper(this, beanTypes.get(type), type, stateTypes.get(type), u);
int i = uids.indexOf(w);
if (i == -1) {
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -13,6 +13,7 @@
private String name;
private ObjStoreBrowser browser;
private String beantype;
+ private String className;
private String ostype;
private Uid uid;
private long tstamp;
@@ -23,19 +24,22 @@
this.name = "";
this.beantype = "";
this.ostype = "";
+ this.className = null;
}
public OSEntryBean getMBean() {
return mbean;
}
- public UidWrapper(ObjStoreBrowser browser, String beantype, String ostype, Uid uid) {
+ public UidWrapper(ObjStoreBrowser browser, String beantype, String ostype, String className, Uid uid) {
this.browser = browser;
this.ostype = ostype;
this.beantype = beantype;
+ this.className = className;
this.uid = uid;
this.tstamp = 0L;
this.name = "jboss.jta:type=ObjectStore,itype=" + ostype + ",uid=" + uid.fileStringForm(); // + ",participant=false";
+
}
/**
@@ -53,6 +57,10 @@
return name;
}
+ public String getClassName() {
+ return className;
+ }
+
void register() {
mbean.register();
}
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -73,14 +73,10 @@
* @return An object that maintains MBeans representing completing transactions
*/
private ObjStoreBrowser createObjStoreBrowser() {
- ObjStoreBrowser osb = new ObjStoreBrowser();
-
// define which object store types we are prepared to represent by mbeans
- osb.setTypes( new HashMap<String, String>() {{
- put("StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
- }});
+ System.setProperty("ObjStoreBrowserHandlers", "com.arjuna.ats.arjuna.AtomicAction=com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
- return osb;
+ return new ObjStoreBrowser();
}
@Test
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -1,10 +1,11 @@
package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
-import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean;
-import com.arjuna.ats.arjuna.tools.osb.mbean.ParticipantStatus;
-import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
-import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
+import com.arjuna.ats.arjuna.coordinator.BasicAction;
+import com.arjuna.ats.arjuna.coordinator.RecordList;
+import com.arjuna.ats.arjuna.tools.osb.mbean.*;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.SubordinateAtomicAction;
/**
* JTA specific version of an ActionBean that knows when a participant record
@@ -23,4 +24,56 @@
else
return super.createParticipant(rec, listType);
}
+/*
+ protected ActionBeanWrapperInterface createWrapper(UidWrapper w) {
+ String cn = SubordinateAtomicAction.class.getCanonicalName();
+ return new GenericAtomicActionWrapper("com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.SubordinateAtomicAction", w);
+ }
+
+
+
+ class SubordinateAtomicActionWrapper extends SubordinateAtomicAction implements ActionBeanWrapperInterface {
+ boolean activated;
+
+ public SubordinateAtomicActionWrapper(UidWrapper w) {
+ super(w.getUid());
+ }
+
+ public boolean activate() {
+ if (!activated)
+ activated = super.activate();
+
+ return activated;
+ }
+
+ public void doUpdateState() {
+ updateState();
+ }
+
+ public Uid getUid(AbstractRecord rec) {
+ return 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) {
+ if (super.heuristicList.size() == 0)
+ setHeuristicDecision(newDecision);
+ }
+
+ public RecordList getRecords(ParticipantStatus type) {
+ switch (type) {
+ default:
+ case PREPARED: return preparedList;
+ case FAILED: return failedList;
+ case HEURISTIC: return heuristicList;
+ case PENDING: return pendingList;
+ case READONLY: return readonlyList;
+ }
+ }
+
+ }*/
}
Added: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBean.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBean.java (rev 0)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBean.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -0,0 +1,44 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.coordinator.BasicAction;
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.SubordinateAtomicAction;
+
+public class SubordinateActionBean extends JTAActionBean implements SubordinateActionBeanMBean {
+ public SubordinateActionBean(UidWrapper w) {
+ super(w);
+ }
+
+ public String getXid() {
+ try {
+ SubordinateAtomicAction sub = (SubordinateAtomicAction) ra.getAction();
+
+ return sub.getXid().toString();
+ } catch (ClassCastException e) {
+ if (tsLogger.logger.isDebugEnabled()) {
+ BasicAction ba = ra.getAction();
+
+ tsLogger.logger.debug("unable to cast " + ba.toString() + e.getMessage());
+ }
+
+ return e.getMessage();
+ }
+ }
+
+ public String getParentNodeName() {
+ try {
+ SubordinateAtomicAction sub = (SubordinateAtomicAction) ra.getAction();
+
+ return sub.getParentNodeName();
+ } catch (ClassCastException e) {
+ if (tsLogger.logger.isDebugEnabled()) {
+ BasicAction ba = ra.getAction();
+
+ tsLogger.logger.debug("unable to cast " + (ba == null ? "null" : ba.toString()) + ": " + e.getMessage());
+ }
+
+ return e.getMessage();
+ }
+ }
+}
Added: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBeanMBean.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBeanMBean.java (rev 0)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/SubordinateActionBeanMBean.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -0,0 +1,13 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBeanMBean;
+
+ at MXBeanDescription("Management view of a subordinate transaction")
+public interface SubordinateActionBeanMBean extends ActionBeanMBean {
+ @MXBeanPropertyDescription("A unique id for this transaction")
+ String getXid();
+ @MXBeanPropertyDescription("The (XA) node name assigned by the administrator of the server from which this transaction was propagated")
+ String getParentNodeName();
+}
\ No newline at end of file
Modified: labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java 2011-12-15 16:56:59 UTC (rev 37813)
+++ labs/jbosstm/branches/JBOSSTS_4_16/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java 2011-12-15 21:43:39 UTC (rev 37814)
@@ -2,6 +2,7 @@
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.tools.osb.mbean.*;
import com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple;
@@ -16,6 +17,9 @@
ActionBean action;
boolean activated;
+ public ArjunaTransactionImpleWrapper () {
+ super(Uid.nullUid());
+ }
public ArjunaTransactionImpleWrapper (ActionBean action, UidWrapper w) {
super(w.getUid());
this.action = action;
@@ -60,6 +64,10 @@
return sb.append('\n').append(prefix).append(get_uid());
}
+ public BasicAction getAction() {
+ return null;
+ }
+
public void clearHeuristicDecision(int newDecision) {
if (super.heuristicList.size() == 0)
setHeuristicDecision(newDecision);
More information about the jboss-svn-commits
mailing list