[jbosscache-commits] JBoss Cache SVN: r6889 - in core/branches/flat/src/main/java/org/jboss/starobrno: commands and 3 other directories.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Wed Oct 8 13:13:48 EDT 2008
Author: mircea.markus
Date: 2008-10-08 13:13:48 -0400 (Wed, 08 Oct 2008)
New Revision: 6889
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/OrderedSynchronizationHandler.java
core/branches/flat/src/main/java/org/jboss/starobrno/ReplicationException.java
core/branches/flat/src/main/java/org/jboss/starobrno/TxInterceptor.java
core/branches/flat/src/main/java/org/jboss/starobrno/jmx/
core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/
core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/MBean.java
core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedAttribute.java
core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedOperation.java
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactory.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContext.java
core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContextImpl.java
Log:
work on progress
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/OrderedSynchronizationHandler.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/interceptors/OrderedSynchronizationHandler.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/OrderedSynchronizationHandler.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/OrderedSynchronizationHandler.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import java.util.LinkedList;
+
+/**
+ * Maintains a list of Synchronization handlers. Reason is that we have to
+ * invoke certain handlers <em>before</em> others. See the description in
+ * SyncTxUnitTestCase.testConcurrentPuts(). For example, for synchronous
+ * replication, we have to execute the ReplicationInterceptor's
+ * afterCompletion() <em>before</em> the TransactionInterceptor's.
+ *
+ * @author Bela Ban
+ * @version $Id$
+ */
+public class OrderedSynchronizationHandler implements Synchronization
+{
+ static final Log log = LogFactory.getLog(org.jboss.cache.interceptors.OrderedSynchronizationHandler.class);
+
+ private Transaction tx = null;
+ private final LinkedList<Synchronization> handlers = new LinkedList<Synchronization>();
+
+ public OrderedSynchronizationHandler(Transaction tx) throws SystemException, RollbackException
+ {
+ this.tx = tx;
+ tx.registerSynchronization(this);
+ }
+
+ public void registerAtHead(Synchronization handler)
+ {
+ register(handler, true);
+ }
+
+ public void registerAtTail(Synchronization handler)
+ {
+ register(handler, false);
+ }
+
+ void register(Synchronization handler, boolean head)
+ {
+ if (handler != null && !handlers.contains(handler))
+ {
+ if (head)
+ handlers.addFirst(handler);
+ else
+ handlers.addLast(handler);
+ }
+ }
+
+ public void beforeCompletion()
+ {
+ for (Synchronization sync : handlers)
+ {
+ sync.beforeCompletion();
+ }
+ }
+
+ public void afterCompletion(int status)
+ {
+ RuntimeException exceptionInAfterCompletion = null;
+ for (Synchronization sync : handlers)
+ {
+ try
+ {
+ sync.afterCompletion(status);
+ }
+ catch (Throwable t)
+ {
+ log.error("failed calling afterCompletion() on " + sync, t);
+ exceptionInAfterCompletion = (RuntimeException) t;
+ }
+ }
+
+ // throw the exception so the TM can deal with it.
+ if (exceptionInAfterCompletion != null) throw exceptionInAfterCompletion;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "tx=" + getTxAsString() + ", handlers=" + handlers;
+ }
+
+ private String getTxAsString()
+ {
+ // JBCACHE-1114 -- don't call toString() on tx or it can lead to stack overflow
+ if (tx == null)
+ return null;
+
+ return tx.getClass().getName() + "@" + System.identityHashCode(tx);
+ }
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/ReplicationException.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/ReplicationException.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/ReplicationException.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/ReplicationException.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno;
+
+import org.jboss.cache.*;
+import org.jboss.cache.CacheException;
+
+/**
+ * Thrown when a replication problem occurred
+ */
+public class ReplicationException extends CacheException
+{
+
+ private static final long serialVersionUID = 33172388691879866L;
+
+ public ReplicationException()
+ {
+ super();
+ }
+
+ public ReplicationException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ public ReplicationException(String msg)
+ {
+ super(msg);
+ }
+
+ public ReplicationException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString();
+ }
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/TxInterceptor.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/TxInterceptor.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/TxInterceptor.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,1040 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno;
+
+import org.jboss.cache.config.Option;
+import org.jboss.cache.factories.ComponentRegistry;
+import org.jboss.cache.util.concurrent.ConcurrentHashSet;
+import org.jboss.starobrno.commands.CommandsFactory;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.commands.VisitableCommand;
+import org.jboss.starobrno.commands.tx.CommitCommand;
+import org.jboss.starobrno.commands.tx.PrepareCommand;
+import org.jboss.starobrno.commands.tx.RollbackCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.context.TransactionContext;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.factories.context.ContextFactory;
+import org.jboss.starobrno.interceptors.BaseTransactionalContextInterceptor;
+import org.jboss.starobrno.invocation.InvocationContextContainer;
+import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.notifier.Notifier;
+import org.jboss.starobrno.transaction.GlobalTransaction;
+import org.jboss.starobrno.transaction.TransactionTable;
+import org.jboss.starobrno.jmx.annotations.ManagedOperation;
+import org.jboss.starobrno.jmx.annotations.ManagedAttribute;
+
+import javax.transaction.*;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This interceptor is the new default at the head of all interceptor chains,
+ * and makes transactional attributes available to all interceptors in the chain.
+ * This interceptor is also responsible for registering for synchronisation on
+ * transaction completion.
+ *
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
+ * @author <a href="mailto:stevew at jofti.com">Steve Woodcock (stevew at jofti.com)</a>
+ */
+public class TxInterceptor extends BaseTransactionalContextInterceptor
+{
+ protected CommandsFactory commandsFactory;
+ protected RPCManager rpcManager;
+ private Notifier notifier;
+ private InvocationContextContainer invocationContextContainer;
+ private ComponentRegistry componentRegistry;
+ private ContextFactory contextFactory;
+
+ /**
+ * List <Transaction>that we have registered for
+ */
+ private final Set<Transaction> transactions = new ConcurrentHashSet<Transaction>();
+ private final Map<Transaction, GlobalTransaction> rollbackTransactions = new ConcurrentHashMap<Transaction, GlobalTransaction>(16);
+ private long prepares = 0;
+ private long commits = 0;
+ private long rollbacks = 0;
+ protected boolean optimistic = false;
+ private LockManager lockManager;
+ private boolean statsEnabled;
+
+ @Inject
+ public void intialize(RPCManager rpcManager, ContextFactory contextFactory,
+ Notifier notifier, InvocationContextContainer icc,
+ CommandsFactory factory, ComponentRegistry componentRegistry, LockManager lockManager)
+ {
+ this.contextFactory = contextFactory;
+ this.commandsFactory = factory;
+ this.rpcManager = rpcManager;
+ this.notifier = notifier;
+ this.invocationContextContainer = icc;
+ this.componentRegistry = componentRegistry;
+ this.lockManager = lockManager;
+ setStatisticsEnabled(configuration.isExposeManagementStatistics());
+ }
+
+ @Override
+ public Object visitPrepareCommand(InvocationContext ctx, PrepareCommand command) throws Throwable
+ {
+ Object result = null;
+
+ // this is a prepare, commit, or rollback.
+ if (log.isDebugEnabled()) log.debug("Got gtx from invocation context " + ctx.getGlobalTransaction());
+ try
+ {
+ if (ctx.getGlobalTransaction().isRemote())
+ {
+ result = handleRemotePrepare(ctx, command);
+ if (getStatisticsEnabled()) prepares++;
+ }
+ else
+ {
+ if (trace) log.trace("received my own message (discarding it)");
+ result = null;
+ }
+ }
+ catch (Throwable e)
+ {
+ ctx.throwIfNeeded(e);
+ }
+
+ return result;
+ }
+
+ @Override
+ public Object visitCommitCommand(InvocationContext ctx, CommitCommand command) throws Throwable
+ {
+ if (!ctx.getGlobalTransaction().isRemote())
+ {
+ if (trace) log.trace("received my own message (discarding it)");
+ return null;
+ }
+ try
+ {
+ if (trace) log.trace("(" + rpcManager.getLocalAddress() + ") call on command [" + command + "]");
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+ Transaction ltx = txTable.getLocalTransaction(gtx, true);
+ // disconnect if we have a current tx associated
+ Transaction currentTx = txManager.getTransaction();
+ boolean resumeCurrentTxOnCompletion = false;
+ try
+ {
+ if (!ltx.equals(currentTx))
+ {
+ currentTx = txManager.suspend();
+ resumeCurrentTxOnCompletion = true;
+ txManager.resume(ltx);
+ // make sure we set this in the ctx
+ ctx.setTransaction(ltx);
+ }
+ if (log.isDebugEnabled()) log.debug(" executing commit() with local TX " + ltx + " under global tx " + gtx);
+ txManager.commit();
+ if (getStatisticsEnabled()) commits++;
+ }
+ finally
+ {
+ //resume the old transaction if we suspended it
+ if (resumeCurrentTxOnCompletion)
+ {
+ resumeTransactionOnCompletion(ctx, currentTx);
+ }
+ // remove from local lists.
+ transactions.remove(ltx);
+ // this tx has completed. Clean up in the tx table.
+ txTable.remove(gtx, ltx);
+ }
+ if (log.isDebugEnabled()) log.debug("Finished remote rollback method for " + gtx);
+ }
+ catch (Throwable throwable)
+ {
+ ctx.throwIfNeeded(throwable);
+ }
+ return null;
+ }
+
+ @Override
+ public Object visitRollbackCommand(InvocationContext ctx, RollbackCommand command) throws Throwable
+ {
+ if (!ctx.getGlobalTransaction().isRemote())
+ {
+ if (trace) log.trace("received my own message (discarding it)");
+ return null;
+ }
+ try
+ {
+ if (trace) log.trace("(" + rpcManager.getLocalAddress() + ") call on command [" + command + "]");
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+ Transaction ltx = txTable.getLocalTransaction(gtx);
+ if (ltx == null)
+ {
+ log.warn("No local transaction for this remotely originating rollback. Possibly rolling back before a prepare call was broadcast?");
+ txTable.remove(gtx);
+ return null;
+ }
+ // disconnect if we have a current tx associated
+ Transaction currentTx = txManager.getTransaction();
+ boolean resumeCurrentTxOnCompletion = false;
+ try
+ {
+ if (!ltx.equals(currentTx))
+ {
+ currentTx = txManager.suspend();
+ resumeCurrentTxOnCompletion = true;
+ txManager.resume(ltx);
+ // make sure we set this in the ctx
+ ctx.setTransaction(ltx);
+ }
+ if (log.isDebugEnabled()) log.debug("executing with local TX " + ltx + " under global tx " + gtx);
+ txManager.rollback();
+ if (getStatisticsEnabled()) rollbacks++;
+ }
+ finally
+ {
+ //resume the old transaction if we suspended it
+ if (resumeCurrentTxOnCompletion)
+ {
+ resumeTransactionOnCompletion(ctx, currentTx);
+ }
+
+ // remove from local lists.
+ transactions.remove(ltx);
+
+ // this tx has completed. Clean up in the tx table.
+ txTable.remove(gtx, ltx);
+ }
+ if (log.isDebugEnabled()) log.debug("Finished remote commit/rollback method for " + gtx);
+ }
+ catch (Throwable throwable)
+ {
+ ctx.throwIfNeeded(throwable);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable
+ {
+ try
+ {
+ return attachGtxAndPassUpChain(ctx, command);
+ }
+ catch (Throwable throwable)
+ {
+ ctx.throwIfNeeded(throwable);
+ return null;
+ }
+ }
+
+ protected Object attachGtxAndPassUpChain(InvocationContext ctx, VisitableCommand command) throws Throwable
+ {
+ Transaction tx = ctx.getTransaction();
+ if (tx != null) attachGlobalTransaction(ctx, tx, command);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ // ------------------------------------------------------------------------
+ // JMX statistics
+ // ------------------------------------------------------------------------
+
+ // --------------------------------------------------------------
+
+ /**
+ * Handles a remotely originating prepare call, by creating a local transaction for the remote global transaction
+ * and replaying modifications in this new local transaction.
+ *
+ * @param ctx invocation context
+ * @param command prepare command
+ * @return result of the prepare, typically a null.
+ * @throws Throwable in the event of problems.
+ */
+ private Object handleRemotePrepare(InvocationContext ctx, PrepareCommand command) throws Throwable
+ {
+ // the InvocationContextInterceptor would have set this for us
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+
+ // Is there a local transaction associated with GTX? (not the current tx associated with the thread, which may be
+ // in the invocation context
+ Transaction ltx = txTable.getLocalTransaction(gtx);
+ Transaction currentTx = txManager.getTransaction();
+
+ Object retval = null;
+ boolean success = false;
+ try
+ {
+ if (ltx == null)
+ {
+ if (currentTx != null) txManager.suspend();
+ // create a new local transaction
+ ltx = createLocalTx();
+ // associate this with a global tx
+ txTable.put(ltx, gtx);
+ if (trace) log.trace("Created new tx for gtx " + gtx);
+
+ if (log.isDebugEnabled())
+ log.debug("Started new local tx as result of remote prepare: local tx=" + ltx + " (status=" + ltx.getStatus() + "), gtx=" + gtx);
+ }
+ else
+ {
+ //this should be valid
+ if (!TransactionTable.isValid(ltx))
+ throw new CacheException("Transaction " + ltx + " not in correct state to be prepared");
+
+ //associate this thread with the local transaction associated with the global transaction, IF the localTx is NOT the current tx.
+ if (currentTx == null || !ltx.equals(currentTx))
+ {
+ if (trace) log.trace("Suspending current tx " + currentTx);
+ txManager.suspend();
+ txManager.resume(ltx);
+ }
+ }
+ if (trace) log.trace("Resuming existing tx " + ltx + ", global tx=" + gtx);
+
+ // at this point we have a non-null ltx
+
+ // Asssociate the local TX with the global TX. Create new
+ // transactionContext for TX in txTable, the modifications
+ // below will need this transactionContext to add their modifications
+ // under the GlobalTx key
+ TransactionContext transactionContext = txTable.get(gtx);
+ if (transactionContext == null)
+ {
+ // create a new transaction transactionContext
+ if (log.isDebugEnabled()) log.debug("creating new tx transactionContext");
+ transactionContext = contextFactory.createTransactionContext(ltx);
+ txTable.put(gtx, transactionContext);
+ }
+
+ setTransactionalContext(ltx, gtx, transactionContext, ctx);
+
+ // register a sync handler for this tx.
+ registerHandler(ltx, new RemoteSynchronizationHandler(gtx, ltx, transactionContext), ctx);
+
+ success = false;
+
+ // replay modifications
+ replayModifications(ctx, ltx, command);
+
+ success = true; // no exceptions were thrown above!!
+
+ // now pass the prepare command up the chain as well.
+ if (command.isOnePhaseCommit())
+ {
+ if (trace)
+ log.trace("Using one-phase prepare. Not propagating the prepare call up the stack until called to do so by the sync handler.");
+ }
+ else
+ {
+ // now pass up the prepare method itself.
+ invokeNextInterceptor(ctx, command);
+ }
+ // JBCACHE-361 Confirm that the transaction is ACTIVE
+ assertTxIsStillValid(ltx);
+ }
+ finally
+ {
+ // if we are running a one-phase commit, perform a commit or rollback now.
+ if (trace) log.trace("Are we running a 1-phase commit? " + command.isOnePhaseCommit());
+
+ if (command.isOnePhaseCommit())
+ {
+ try
+ {
+ if (success)
+ {
+ ltx.commit();
+ }
+ else
+ {
+ ltx.rollback();
+ }
+ }
+ catch (Throwable t)
+ {
+ log.error("Commit/rollback failed.", t);
+ if (success)
+ {
+ // try another rollback...
+ try
+ {
+ log.info("Attempting anotehr rollback");
+ //invokeOnePhaseCommitMethod(globalTransaction, modifications.size() > 0, false);
+ ltx.rollback();
+ }
+ catch (Throwable t2)
+ {
+ log.error("Unable to rollback", t2);
+ }
+ }
+ }
+ finally
+ {
+ transactions.remove(ltx);// JBAS-298
+ }
+ }
+
+ txManager.suspend();// suspends ltx - could be null
+ // resume whatever else we had going.
+ if (currentTx != null) txManager.resume(currentTx);
+ if (log.isDebugEnabled()) log.debug("Finished remote prepare " + gtx);
+ }
+
+ return retval;
+ }
+
+ private ReplicableCommand attachGlobalTransaction(InvocationContext ctx, Transaction tx, VisitableCommand command) throws Throwable
+ {
+ if (trace)
+ {
+ log.trace(" local transaction exists - registering global tx if not present for " + Thread.currentThread());
+ }
+ if (trace)
+ {
+ GlobalTransaction tempGtx = txTable.get(tx);
+ log.trace("Associated gtx in txTable is " + tempGtx);
+ }
+
+ // register a sync handler for this tx - only if the globalTransaction is not remotely initiated.
+ GlobalTransaction gtx = registerTransaction(tx, ctx);
+ if (gtx == null)
+ {
+ // get the current globalTransaction from the txTable.
+ gtx = txTable.get(tx);
+ }
+
+ // make sure we attach this globalTransaction to the invocation context.
+ ctx.setGlobalTransaction(gtx);
+
+ return command;
+ }
+
+ /**
+ * Replays modifications
+ */
+ protected void replayModifications(InvocationContext ctx, Transaction ltx, PrepareCommand command) throws Throwable
+ {
+ try
+ {
+ // replay modifications
+ for (VisitableCommand modification : command.getModifications())
+ {
+ invokeNextInterceptor(ctx, modification);
+ assertTxIsStillValid(ltx);
+ }
+ }
+ catch (Throwable th)
+ {
+ log.error("prepare failed!", th);
+ throw th;
+ }
+ }
+
+ private void resumeTransactionOnCompletion(InvocationContext ctx, Transaction currentTx)
+ throws SystemException, InvalidTransactionException
+ {
+ if (trace) log.trace("Resuming suspended transaction " + currentTx);
+ txManager.suspend();
+ if (currentTx != null)
+ {
+ txManager.resume(currentTx);
+ ctx.setTransaction(currentTx);
+ }
+ }
+
+ /**
+ * Handles a commit or a rollback. Called by the synch handler. Simply tests that we are in the correct tx and
+ * passes the meth call up the interceptor chain.
+ *
+ * @throws Throwable
+ */
+ @SuppressWarnings("deprecation")
+ private Object handleCommitRollback(InvocationContext ctx, VisitableCommand command) throws Throwable
+ {
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+ Object result;
+ VisitableCommand originalCommand = ctx.getCommand();
+ ctx.setCommand(command);
+ try
+ {
+ result = invokeNextInterceptor(ctx, command);
+ }
+ finally
+ {
+ ctx.setCommand(originalCommand);
+ }
+ if (log.isDebugEnabled()) log.debug("Finished local commit/rollback method for " + gtx);
+ return result;
+ }
+
+ // --------------------------------------------------------------
+ // Transaction phase runners
+ // --------------------------------------------------------------
+
+ protected PrepareCommand buildPrepareCommand(GlobalTransaction gtx, List modifications, boolean onePhaseCommit)
+ {
+ return commandsFactory.buildPrepareCommand(gtx, modifications, rpcManager.getLocalAddress(), onePhaseCommit);
+ }
+
+ /**
+ * creates a commit()
+ */
+ protected void runCommitPhase(InvocationContext ctx, GlobalTransaction gtx, List modifications, boolean onePhaseCommit)
+ {
+ try
+ {
+ VisitableCommand commitCommand = onePhaseCommit ? buildPrepareCommand(gtx, modifications, true) : commandsFactory.buildCommitCommand(gtx);
+
+ if (trace) log.trace("Running commit for " + gtx);
+
+ handleCommitRollback(ctx, commitCommand);
+ }
+ catch (Throwable e)
+ {
+ log.warn("Commit failed. Clearing stale locks.");
+ try
+ {
+ cleanupStaleLocks(ctx);
+ }
+ catch (RuntimeException re)
+ {
+ log.error("Unable to clear stale locks", re);
+ throw re;
+ }
+ catch (Throwable e2)
+ {
+ log.error("Unable to clear stale locks", e2);
+ throw new RuntimeException(e2);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Commit failed.", e);
+ }
+ }
+
+ protected void cleanupStaleLocks(InvocationContext ctx) throws Throwable
+ {
+ TransactionContext transactionContext = ctx.getTransactionContext();
+ if (transactionContext != null) lockManager.unlock(ctx);
+ }
+
+ /**
+ * creates a rollback()
+ */
+ protected void runRollbackPhase(InvocationContext ctx, GlobalTransaction gtx, Transaction tx)
+ {
+ try
+ {
+ // JBCACHE-457
+ VisitableCommand rollbackCommand = commandsFactory.buildRollbackCommand(gtx);
+ if (trace) log.trace(" running rollback for " + gtx);
+
+ //JBCACHE-359 Store a lookup for the globalTransaction so a listener
+ // callback can find it
+ rollbackTransactions.put(tx, gtx);
+
+ handleCommitRollback(ctx, rollbackCommand);
+ }
+ catch (Throwable e)
+ {
+ log.warn("Rollback had a problem", e);
+ }
+ finally
+ {
+ rollbackTransactions.remove(tx);
+ }
+ }
+
+ private boolean isOnePhaseCommit()
+ {
+ if (!configuration.getCacheMode().isSynchronous())
+ {
+ // this is a REPL_ASYNC call - do 1-phase commit. break!
+ if (trace) log.trace("This is a REPL_ASYNC call (1 phase commit) - do nothing for beforeCompletion()");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Handles a local prepare - invoked by the sync handler. Tests if the current tx matches the gtx passed in to the
+ * method call and passes the prepare() call up the chain.
+ */
+ @SuppressWarnings("deprecation")
+ public Object runPreparePhase(InvocationContext ctx, GlobalTransaction gtx, List<VisitableCommand> modifications) throws Throwable
+ {
+ // running a 2-phase commit.
+ VisitableCommand prepareCommand = buildPrepareCommand(gtx, modifications, false);
+
+ Object result;
+
+ // Is there a local transaction associated with GTX ?
+ Transaction ltx = ctx.getTransaction();
+
+ //if ltx is not null and it is already running
+ Transaction currentTransaction = txManager.getTransaction();
+ if (currentTransaction != null && ltx != null && currentTransaction.equals(ltx))
+ {
+ VisitableCommand originalCommand = ctx.getCommand();
+ ctx.setCommand(prepareCommand);
+ try
+ {
+ result = invokeNextInterceptor(ctx, prepareCommand);
+ }
+ finally
+ {
+ ctx.setCommand(originalCommand);
+ }
+ }
+ else
+ {
+ log.warn("Local transaction does not exist or does not match expected transaction " + gtx);
+ throw new CacheException(" local transaction " + ltx + " does not exist or does not match expected transaction " + gtx);
+ }
+ return result;
+ }
+
+ // --------------------------------------------------------------
+ // Private helper methods
+ // --------------------------------------------------------------
+
+ protected void assertTxIsStillValid(Transaction tx)
+ {
+ if (!TransactionTable.isActive(tx))
+ {
+ try
+ {
+ throw new ReplicationException("prepare() failed -- local transaction status is not STATUS_ACTIVE; is " + tx.getStatus());
+ }
+ catch (SystemException e)
+ {
+ throw new ReplicationException("prepare() failed -- local transaction status is not STATUS_ACTIVE; Unable to retrieve transaction status.");
+ }
+ }
+ }
+
+ /**
+ * Creates a gtx (if one doesnt exist), a sync handler, and registers the tx.
+ */
+ private GlobalTransaction registerTransaction(Transaction tx, InvocationContext ctx) throws Exception
+ {
+ GlobalTransaction gtx;
+
+ if (TransactionTable.isValid(tx) && transactions.add(tx))
+ {
+ gtx = txTable.getCurrentTransaction(tx, true);
+ TransactionContext transactionContext;
+ if (ctx.getGlobalTransaction() == null)
+ {
+ ctx.setGlobalTransaction(gtx);
+ transactionContext = txTable.get(gtx);
+ ctx.setTransactionContext(transactionContext);
+ }
+ else
+ {
+ transactionContext = ctx.getTransactionContext();
+ }
+ if (gtx.isRemote())
+ {
+ // should be no need to register a handler since this a remotely initiated globalTransaction
+ if (trace) log.trace("is a remotely initiated gtx so no need to register a tx for it");
+ }
+ else
+ {
+ if (trace) log.trace("Registering sync handler for tx " + tx + ", gtx " + gtx);
+
+ // see the comment in the LocalSyncHandler for the last isOriginLocal param.
+ LocalSynchronizationHandler myHandler = new LocalSynchronizationHandler(gtx, tx, transactionContext, !ctx.isOriginLocal());
+ registerHandler(tx, myHandler, ctx);
+ }
+ }
+ else if ((gtx = rollbackTransactions.get(tx)) != null)
+ {
+ if (trace) log.trace("Transaction " + tx + " is already registered and is rolling back.");
+ }
+ else
+ {
+ if (trace) log.trace("Transaction " + tx + " is already registered.");
+ }
+ return gtx;
+ }
+
+ /**
+ * Registers a sync hander against a tx.
+ */
+ private void registerHandler(Transaction tx, Synchronization handler, InvocationContext ctx) throws Exception
+ {
+ OrderedSynchronizationHandler orderedHandler = ctx.getTransactionContext().getOrderedSynchronizationHandler(); //OrderedSynchronizationHandler.getInstance(tx);
+
+ if (trace) log.trace("registering for TX completion: SynchronizationHandler(" + handler + ")");
+
+ orderedHandler.registerAtHead(handler);// needs to be invoked first on TX commit
+
+ notifier.notifyTransactionRegistered(tx, ctx);
+ }
+
+ /**
+ * Creates and starts a local tx
+ *
+ * @throws Exception
+ */
+ protected Transaction createLocalTx() throws Exception
+ {
+ if (trace)
+ {
+ log.trace("Creating transaction for thread " + Thread.currentThread());
+ }
+ Transaction localTx;
+ if (txManager == null) throw new Exception("Failed to create local transaction; TransactionManager is null");
+ txManager.begin();
+ localTx = txManager.getTransaction();
+ return localTx;
+ }
+
+ // ------------------------------------------------------------------------
+ // Synchronization classes
+ // ------------------------------------------------------------------------
+
+ // this controls the whole transaction
+
+ private class RemoteSynchronizationHandler implements Synchronization
+ {
+ Transaction tx = null;
+ GlobalTransaction gtx = null;
+ List<VisitableCommand> modifications = null;
+ TransactionContext transactionContext = null;
+ protected InvocationContext ctx; // the context for this call.
+
+ RemoteSynchronizationHandler(GlobalTransaction gtx, Transaction tx, TransactionContext entry)
+ {
+ this.gtx = gtx;
+ this.tx = tx;
+ this.transactionContext = entry;
+ }
+
+ public void beforeCompletion()
+ {
+ if (trace) log.trace("Running beforeCompletion on gtx " + gtx);
+
+ if (transactionContext == null)
+ {
+ log.error("Transaction has a null transaction entry - beforeCompletion() will fail.");
+ throw new IllegalStateException("cannot find transaction entry for " + gtx);
+ }
+
+ modifications = transactionContext.getModifications();
+ ctx = invocationContextContainer.get();
+ setTransactionalContext(tx, gtx, transactionContext, ctx);
+
+ if (ctx.isOptionsUninitialised() && transactionContext.getOption() != null)
+ ctx.setOptionOverrides(transactionContext.getOption());
+
+ assertCanContinue();
+
+ ctx.setOriginLocal(false);
+ }
+
+ // this should really not be done here -
+ // it is supposed to be post commit not actually run the commit
+ public void afterCompletion(int status)
+ {
+ // could happen if a rollback is called and beforeCompletion() doesn't get called.
+ if (ctx == null)
+ {
+ ctx = invocationContextContainer.get();
+ setTransactionalContext(tx, gtx, transactionContext, ctx);
+
+ if (ctx.isOptionsUninitialised() && transactionContext != null && transactionContext.getOption() != null)
+ {
+ // use the options from the transaction entry instead
+ ctx.setOptionOverrides(transactionContext.getOption());
+ }
+ }
+
+ try
+ {
+ assertCanContinue();
+
+ try
+ {
+ if (txManager.getTransaction() != null && !txManager.getTransaction().equals(tx)) txManager.resume(tx);
+ }
+ catch (Exception e)
+ {
+ log.error("afterCompletion error: " + status, e);
+ }
+
+ if (trace) log.trace("calling aftercompletion for " + gtx);
+
+ // set any transaction wide options as current for this thread.
+ if (transactionContext != null)
+ {
+ // this should ideally be set in beforeCompletion(), after compacting the list.
+ if (modifications == null) modifications = transactionContext.getModifications();
+ ctx.setOptionOverrides(transactionContext.getOption());
+ }
+ if (tx != null) transactions.remove(tx);
+
+ switch (status)
+ {
+ case Status.STATUS_COMMITTED:
+ boolean onePhaseCommit = isOnePhaseCommit();
+ if (log.isDebugEnabled()) log.debug("Running commit phase. One phase? " + onePhaseCommit);
+ runCommitPhase(ctx, gtx, modifications, onePhaseCommit);
+ log.debug("Finished commit phase");
+ break;
+ case Status.STATUS_UNKNOWN:
+ log.warn("Received JTA STATUS_UNKNOWN in afterCompletion()! XA resources may not be in sync. The app should manually clean up resources at this point.");
+ case Status.STATUS_MARKED_ROLLBACK:
+ case Status.STATUS_ROLLEDBACK:
+ log.debug("Running rollback phase");
+ runRollbackPhase(ctx, gtx, tx);
+ log.debug("Finished rollback phase");
+ break;
+
+ default:
+ throw new IllegalStateException("illegal status: " + status);
+ }
+ }
+ catch (Exception th)
+ {
+ log.trace("Caught exception ", th);
+
+ }
+ finally
+ {
+ // clean up the tx table
+ txTable.remove(gtx);
+ txTable.remove(tx);
+ setTransactionalContext(null, null, null, ctx);
+ cleanupInternalState();
+ }
+ }
+
+ private void assertCanContinue()
+ {
+ if (!componentRegistry.invocationsAllowed(true) && (ctx.getOptionOverrides() == null || !ctx.getOptionOverrides().isSkipCacheStatusCheck()))
+ throw new IllegalStateException("Cache not in STARTED state!");
+ }
+
+ /**
+ * Cleans out (nullifies) member variables held by the sync object for easier gc. Could be (falsely) seen as a mem
+ * leak if the TM implementation hangs on to the synchronizations for an unnecessarily long time even after the tx
+ * completes. See JBCACHE-1007.
+ */
+ private void cleanupInternalState()
+ {
+ tx = null;
+ gtx = null;
+ modifications = null;
+ if (transactionContext != null) transactionContext.reset();
+ transactionContext = null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "TxInterceptor.RemoteSynchronizationHandler(gtx=" + gtx + ", tx=" + getTxAsString() + ")";
+ }
+
+ protected String getTxAsString()
+ {
+ // JBCACHE-1114 -- don't call toString() on tx or it can lead to stack overflow
+ if (tx == null)
+ return null;
+
+ return tx.getClass().getName() + "@" + System.identityHashCode(tx);
+ }
+ }
+
+ private class LocalSynchronizationHandler extends RemoteSynchronizationHandler
+ {
+ private boolean localRollbackOnly = true;
+ // a VERY strange situation where a tx has remote origins, but since certain buddy group org methods perform local
+ // cleanups even when remotely triggered, and optimistic locking is used, you end up with an implicit local tx.
+ // This is STILL remotely originating though and this needs to be made explicit here.
+ // this can be checked by inspecting the InvocationContext.isOriginLocal() at the time of registering the sync.
+ private boolean remoteLocal = false;
+ private Option originalOptions, transactionalOptions;
+
+ /**
+ * A Synchronization for locally originating txs.
+ * <p/>
+ * a VERY strange situation where a tx has remote origins, but since certain buddy group org methods perform local
+ * cleanups even when remotely triggered, and optimistic locking is used, you end up with an implicit local tx.
+ * This is STILL remotely originating though and this needs to be made explicit here.
+ * this can be checked by inspecting the InvocationContext.isOriginLocal() at the time of registering the sync.
+ *
+ * @param gtx
+ * @param tx
+ * @param remoteLocal
+ */
+ LocalSynchronizationHandler(GlobalTransaction gtx, Transaction tx, TransactionContext transactionContext, boolean remoteLocal)
+ {
+ super(gtx, tx, transactionContext);
+ this.remoteLocal = remoteLocal;
+ }
+
+ @Override
+ public void beforeCompletion()
+ {
+ super.beforeCompletion();
+ ctx.setOriginLocal(!remoteLocal); // this is the LOCAL sync handler after all!
+ // fetch the modifications before the transaction is committed
+ // (and thus removed from the txTable)
+ setTransactionalContext(tx, gtx, transactionContext, ctx);
+ if (!transactionContext.hasModifications())
+ {
+ if (trace) log.trace("No modifications in this tx. Skipping beforeCompletion()");
+ modifications = Collections.emptyList();
+ return;
+ }
+ else
+ {
+ modifications = transactionContext.getModifications();
+ }
+
+ // set any transaction wide options as current for this thread, caching original options that would then be reset
+ originalOptions = ctx.getOptionOverrides();
+ transactionalOptions = transactionContext.getOption();
+ ctx.setOptionOverrides(transactionalOptions);
+
+ try
+ {
+ switch (tx.getStatus())
+ {
+ // if we are active or preparing then we can go ahead
+ case Status.STATUS_ACTIVE:
+ case Status.STATUS_PREPARING:
+ // run a prepare call.
+
+ Object result = isOnePhaseCommit() ? null : runPreparePhase(ctx, gtx, modifications);
+
+ if (result instanceof Throwable)
+ {
+ if (log.isDebugEnabled())
+ log.debug("Transaction needs to be rolled back - the cache returned an instance of Throwable for this prepare call (tx=" + tx + " and gtx=" + gtx + ")", (Throwable) result);
+ tx.setRollbackOnly();
+ throw (Throwable) result;
+ }
+ break;
+ default:
+ throw new CacheException("transaction " + tx + " in status " + tx.getStatus() + " unable to start transaction");
+ }
+ }
+ catch (Throwable t)
+ {
+ if (log.isWarnEnabled()) log.warn("Caught exception, will now set transaction to roll back", t);
+ try
+ {
+ tx.setRollbackOnly();
+ }
+ catch (SystemException se)
+ {
+ throw new RuntimeException("setting tx rollback failed ", se);
+ }
+ if (t instanceof RuntimeException)
+ throw (RuntimeException) t;
+ else
+ throw new RuntimeException("", t);
+ }
+ finally
+ {
+ localRollbackOnly = false;
+ setTransactionalContext(null, null, null, ctx);
+ ctx.setOptionOverrides(originalOptions);
+ }
+ }
+
+ @Override
+ public void afterCompletion(int status)
+ {
+ // could happen if a rollback is called and beforeCompletion() doesn't get called.
+ if (ctx == null) ctx = invocationContextContainer.get();
+ ctx.setLocalRollbackOnly(localRollbackOnly);
+ setTransactionalContext(tx, gtx, transactionContext, ctx);
+ if (transactionalOptions != null) ctx.setOptionOverrides(transactionalOptions);
+ try
+ {
+ super.afterCompletion(status);
+ }
+ finally
+ {
+ ctx.setOptionOverrides(originalOptions);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "TxInterceptor.LocalSynchronizationHandler(gtx=" + gtx + ", tx=" + getTxAsString() + ")";
+ }
+ }
+
+ @ManagedOperation
+ public void resetStatistics()
+ {
+ prepares = 0;
+ commits = 0;
+ rollbacks = 0;
+ }
+
+ @ManagedOperation
+ public Map<String, Object> dumpStatistics()
+ {
+ Map<String, Object> retval = new HashMap<String, Object>(3);
+ retval.put("Prepares", prepares);
+ retval.put("Commits", commits);
+ retval.put("Rollbacks", rollbacks);
+ return retval;
+ }
+
+ @ManagedAttribute
+ public boolean getStatisticsEnabled()
+ {
+ return this.statsEnabled;
+ }
+
+ @ManagedAttribute
+ public void setStatisticsEnabled(boolean enabled)
+ {
+ this.statsEnabled = enabled;
+ }
+
+ @ManagedAttribute(description = "number of transaction prepares")
+ public long getPrepares()
+ {
+ return prepares;
+ }
+
+ @ManagedAttribute(description = "number of transaction commits")
+ public long getCommits()
+ {
+ return commits;
+ }
+
+ @ManagedAttribute(description = "number of transaction rollbacks")
+ public long getRollbacks()
+ {
+ return rollbacks;
+ }
+}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactory.java 2008-10-08 16:37:44 UTC (rev 6888)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactory.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -24,8 +24,14 @@
import org.jboss.starobrno.commands.write.*;
import org.jboss.starobrno.commands.read.SizeCommand;
import org.jboss.starobrno.commands.read.GetKeyValueCommand;
+import org.jboss.starobrno.commands.tx.PrepareCommand;
+import org.jboss.starobrno.commands.tx.RollbackCommand;
+import org.jboss.starobrno.commands.tx.CommitCommand;
+import org.jboss.starobrno.transaction.GlobalTransaction;
+import org.jgroups.Address;
import java.util.Map;
+import java.util.List;
/**
* @author Mircea.Markus at jboss.com
@@ -47,4 +53,10 @@
ClearCommand buildClearCommand();
EvictCommand buildEvictCommand(Object key);
+
+ PrepareCommand buildPrepareCommand(GlobalTransaction gtx, List modifications, Address localAddress, boolean onePhaseCommit);
+
+ CommitCommand buildCommitCommand(GlobalTransaction gtx);
+
+ RollbackCommand buildRollbackCommand(GlobalTransaction gtx);
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java 2008-10-08 16:37:44 UTC (rev 6888)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -24,10 +24,16 @@
import org.jboss.starobrno.commands.write.*;
import org.jboss.starobrno.commands.read.SizeCommand;
import org.jboss.starobrno.commands.read.GetKeyValueCommand;
+import org.jboss.starobrno.commands.tx.PrepareCommand;
+import org.jboss.starobrno.commands.tx.RollbackCommand;
+import org.jboss.starobrno.commands.tx.CommitCommand;
import org.jboss.starobrno.DataContainer;
+import org.jboss.starobrno.transaction.GlobalTransaction;
import org.jboss.starobrno.notifier.Notifier;
+import org.jgroups.Address;
import java.util.Map;
+import java.util.List;
/**
* @author Mircea.Markus at jboss.com
@@ -76,4 +82,19 @@
{
return new EvictCommand();
}
+
+ public PrepareCommand buildPrepareCommand(GlobalTransaction gtx, List modifications, Address localAddress, boolean onePhaseCommit)
+ {
+ return new PrepareCommand(gtx, modifications, localAddress, onePhaseCommit);
+ }
+
+ public CommitCommand buildCommitCommand(GlobalTransaction gtx)
+ {
+ return new CommitCommand(gtx);
+ }
+
+ public RollbackCommand buildRollbackCommand(GlobalTransaction gtx)
+ {
+ return new RollbackCommand(gtx);
+ }
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContext.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContext.java 2008-10-08 16:37:44 UTC (rev 6888)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContext.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -21,8 +21,8 @@
*/
package org.jboss.starobrno.context;
-import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
import org.jboss.starobrno.commands.VisitableCommand;
+import org.jboss.starobrno.OrderedSynchronizationHandler;
import org.jboss.starobrno.config.Option;
import javax.transaction.Transaction;
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContextImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContextImpl.java 2008-10-08 16:37:44 UTC (rev 6888)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContextImpl.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -21,11 +21,11 @@
*/
package org.jboss.starobrno.context;
-import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
import org.jboss.cache.util.Immutables;
import org.jboss.starobrno.commands.VisitableCommand;
import org.jboss.starobrno.config.Option;
import org.jboss.starobrno.mvcc.MVCCEntry;
+import org.jboss.starobrno.OrderedSynchronizationHandler;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/MBean.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/jmx/annotations/MBean.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/MBean.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/MBean.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.jmx.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Classes anotaded with this will be exposed as MBeans.
+ * If you are looking for more fined grained way of exposing jmx attributes/operations, take a look at
+ * {@link org.jboss.cache.jmx.annotations.ManagedAttribute} and {@link org.jboss.cache.jmx.annotations.ManagedOperation}
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE})
+ at Inherited
+public @interface MBean
+{
+ public abstract String objectName() default "";
+
+ public abstract boolean exposeAll() default false;
+
+ public abstract String description() default "";
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedAttribute.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/jmx/annotations/ManagedAttribute.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedAttribute.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedAttribute.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.jmx.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a public method or a field (any visibility) in
+ * an MBean class defines an MBean attribute. This annotation can
+ * be applied to either a field or a public setter and/or getter
+ * method of a public class that is itself is optionally annotated
+ * with an @MBean annotation, or inherits such an annotation from
+ * a superclass.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.FIELD})
+public @interface ManagedAttribute
+{
+ public abstract String description() default "";
+
+ public abstract String name() default "";
+
+ public abstract boolean writable() default false;
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedOperation.java (from rev 6858, core/branches/flat/src/main/java/org/jboss/cache/jmx/annotations/ManagedOperation.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedOperation.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/jmx/annotations/ManagedOperation.java 2008-10-08 17:13:48 UTC (rev 6889)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.jmx.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a method in an MBean class defines an MBean
+ * operation. @ManagedOperation annotation can be applied to a
+ * public method of a public class that is itself optionally
+ * annotated with an @MBean annotation, or inherits such an
+ * annotation from a superclass.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD})
+public @interface ManagedOperation
+{
+ public abstract String description() default "";
+}
\ No newline at end of file
More information about the jbosscache-commits
mailing list