[jbosscache-commits] JBoss Cache SVN: r6869 - in core/branches/flat/src/main/java/org/jboss/starobrno: commands and 6 other directories.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Wed Oct 8 07:53:03 EDT 2008
Author: manik.surtani at jboss.com
Date: 2008-10-08 07:53:03 -0400 (Wed, 08 Oct 2008)
New Revision: 6869
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GravitateDataCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AnnounceBuddyPoolNameCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AssignToBuddyGroupCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ClusteredGetCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/DataGravitationCleanupCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/RemoveFromBuddyGroupCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ReplicateCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java
Removed:
core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionContext.java
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java
core/branches/flat/src/main/java/org/jboss/starobrno/CacheImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/TransactionBoundaryCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/AbstractTransactionBoundaryCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/CommitCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/PrepareCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/RollbackCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.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
core/branches/flat/src/main/java/org/jboss/starobrno/factories/context/ContextFactory.java
Log:
Fixed stuff
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,8 +21,8 @@
*/
package org.jboss.starobrno;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.config.Configuration;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.context.InvocationContext;
import org.jboss.starobrno.lifecycle.Lifecycle;
import java.util.Set;
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheImpl.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheImpl.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,14 +21,15 @@
*/
package org.jboss.starobrno;
+import org.jboss.starobrno.config.CacheConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.context.InvocationContext;
import org.jboss.util.NotImplementedException;
-import org.jboss.starobrno.config.CacheConfig;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
-import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
/**
* @author Mircea.Markus at jboss.com
@@ -36,7 +37,7 @@
public class CacheImpl implements Cache
{
private ConcurrentHashMap data = new ConcurrentHashMap();
- private Map<String, AtomicGroup> atomicGroups = new ConcurrentHashMap<String, AtomicGroup>();
+ private Map<String, AtomicGroup> atomicGroups = new ConcurrentHashMap<String, AtomicGroup>();
private CacheConfig cacheConfig;
@@ -141,4 +142,49 @@
{
return (data != null ? data.hashCode() : 0);
}
+
+ public void evict(Object key)
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
+
+ public Configuration getConfiguration()
+ {
+ return null; //TODO: Autogenerated. Implement me properly
+ }
+
+ public void addCacheListener(Object listener)
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
+
+ public void removeCacheListener(Object listener)
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
+
+ public Set getCacheListeners()
+ {
+ return null; //TODO: Autogenerated. Implement me properly
+ }
+
+ public InvocationContext getInvocationContext()
+ {
+ return null; //TODO: Autogenerated. Implement me properly
+ }
+
+ public void setInvocationContext(InvocationContext ctx)
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
+
+ public void start()
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
+
+ public void stop()
+ {
+ //TODO: Autogenerated. Implement me properly
+ }
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/TransactionBoundaryCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/TransactionBoundaryCommand.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/TransactionBoundaryCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,7 +21,7 @@
*/
package org.jboss.starobrno.commands;
-import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.starobrno.transaction.GlobalTransaction;
/**
* // TODO: MANIK: Document this
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GravitateDataCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GravitateDataCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GravitateDataCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,265 @@
+/*
+ * 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.commands.read;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.starobrno.DataContainer;
+import org.jboss.starobrno.commands.DataCommand;
+import org.jboss.starobrno.commands.Visitor;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jgroups.Address;
+
+/**
+ * Used with buddy replication's {@link org.jboss.cache.interceptors.DataGravitatorInterceptor}.
+ * <p/>
+ * This is the equivalent of the old MethodCallDefinitions.dataGravitationMethod method call from 2.1.x.
+ * <p/>
+ *
+ * @author Manik Surtani
+ * @since 2.2.0
+ */
+public class GravitateDataCommand implements DataCommand
+{
+ public static final int METHOD_ID = 35;
+
+ /* dependencies */
+ private CacheSPI spi;
+
+ /* parametres */
+ protected boolean searchSubtrees;
+ private Address localAddress;
+
+ private static final Log log = LogFactory.getLog(GravitateDataCommand.class);
+ private static final boolean trace = log.isTraceEnabled();
+ private BuddyFqnTransformer buddyFqnTransformer;
+ private Object key;
+ private DataContainer dataContainer;
+
+ public GravitateDataCommand(Object key, boolean searchSubtrees, Address localAddress)
+ {
+ this.key = key;
+ this.searchSubtrees = searchSubtrees;
+ this.localAddress = localAddress;
+ }
+
+ public GravitateDataCommand(Address localAddress)
+ {
+ this.localAddress = localAddress;
+ }
+
+ public void initialize(DataContainer dataContainer, CacheSPI spi, BuddyFqnTransformer transformer)
+ {
+ this.dataContainer = dataContainer;
+ this.spi = spi;
+ buddyFqnTransformer = transformer;
+ }
+
+ /**
+ * Searches for data to gravitate given an Fqn and whether buddy backup subtrees are to be searched as well. Note that
+ * data stored under the Fqn, along with all children, are retrieved.
+ *
+ * @param ctx invocation context
+ * @return a {@link org.jboss.cache.buddyreplication.GravitateResult} containing node data, as well as information on whether this was found in a primary or backup tree.
+ */
+ @SuppressWarnings("unchecked")
+ public Object perform(InvocationContext ctx)
+ {
+ /*
+ // TODO: Test this with MVCC.
+
+ // for now, perform a very simple series of getData calls.
+ if (trace) log.trace("Caller is asking for " + key);
+ try
+ {
+ ctx.setOriginLocal(false);
+ // use a get() call into the cache to make sure cache loading takes place.
+ // no need to cache the original skipDataGravitation setting here - it will always be false of we got here!!
+ //todo 2.2 use dataContainer for peek and load the data in the CLInterceptor rather than using the SPI for than!!!
+ ctx.getOptionOverrides().setSkipDataGravitation(true);
+ Node actualNode = spi.getNode(fqn);
+ ctx.getOptionOverrides().setSkipDataGravitation(false);
+
+ if (trace) log.trace("In local tree, this is " + actualNode);
+
+ Fqn backupNodeFqn = null;
+ if (actualNode == null && searchSubtrees)
+ {
+ log.trace("Looking at backup trees.");
+
+ // need to loop through backupSubtree's children
+ Set allGroupNames = getBackupRoots();
+ if (allGroupNames != null)
+ {
+ for (Object groupName : allGroupNames)
+ {
+ // groupName is the name of a buddy group since all child names in this
+ // collection are direct children of BUDDY_BACKUP_SUBTREE_FQN
+ Fqn backupRoot = Fqn.fromRelativeElements(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, (String) groupName);
+ if (buddyFqnTransformer.isDeadBackupRoot(backupRoot))
+ {
+ Set<Integer> deadChildNames = new TreeSet<Integer>(spi.getChildrenNames(backupRoot));
+ Integer[] elems = deadChildNames.toArray(new Integer[deadChildNames.size()]);
+
+ // these are integers. we need to start with the highest/most recent.
+ for (int i = elems.length - 1; i > -1; i--)
+ {
+ Integer versionOfDefunctData = elems[i];
+ backupNodeFqn = Fqn.fromRelativeFqn(Fqn.fromRelativeElements(backupRoot, versionOfDefunctData), fqn);
+
+ // use a get() call into the cache to make sure cache loading takes place.
+ ctx.getOptionOverrides().setSkipDataGravitation(true);
+ actualNode = spi.peek(backupNodeFqn, false);
+ ctx.getOptionOverrides().setSkipDataGravitation(false);
+
+ // break out of the inner loop searching through the dead node's various backups
+ if (actualNode != null) break;
+ }
+ }
+ else
+ {
+ backupNodeFqn = Fqn.fromRelativeFqn(backupRoot, fqn);
+ // use a get() call into the cache to make sure cache loading takes place.
+ ctx.getOptionOverrides().setSkipDataGravitation(true);
+ actualNode = spi.getNode(backupNodeFqn);
+ ctx.getOptionOverrides().setSkipDataGravitation(false);
+ }
+
+ if (trace)
+ log.trace("Looking for " + backupNodeFqn + ". Search result: " + actualNode);
+
+ // break out of outer loop searching through all available backups.
+ if (actualNode != null) break;
+ }
+ }
+
+ }
+
+ if (actualNode == null)
+ {
+ return GravitateResult.noDataFound();
+ }
+ else
+ {
+ // make sure we LOAD data for this node!!
+ actualNode.getData();
+ }
+
+ if (backupNodeFqn == null && searchSubtrees)
+ {
+ backupNodeFqn = buddyFqnTransformer.getBackupFqn(buddyFqnTransformer.getGroupNameFromAddress(localAddress), fqn);
+ }
+
+ List<NodeData> list = dataContainer.buildNodeData(new LinkedList<NodeData>(), (NodeSPI) actualNode, false);
+
+ return GravitateResult.subtreeResult(list, backupNodeFqn);
+ }
+ catch (RuntimeException re)
+ {
+ if (trace) log.trace("Caught throwable", re);
+ throw re;
+ }
+ finally
+ {
+ ctx.setOriginLocal(true);
+ }
+ */
+
+ throw new UnsupportedOperationException("FIX ME");
+ // TODO: implement BR on flat cache
+ }
+
+ /**
+ * @return a Set of child node names that hang directly off the backup tree root, or null if the backup tree root doesn't exist.
+ */
+// protected Set<Object> getBackupRoots()
+// {
+// InternalNode backupSubtree = dataContainer.peekInternalNode(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, false);
+// if (backupSubtree == null) return null;
+// return backupSubtree.getChildrenNames();
+// }
+ public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
+ {
+ // TODO implement me
+ return null;
+// return visitor.visitGravitateDataCommand(ctx, this);
+ }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ public boolean isSearchSubtrees()
+ {
+ return searchSubtrees;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{key, searchSubtrees};
+ }
+
+ public void setParameters(int commandId, Object[] args)
+ {
+ key = args[0];
+ searchSubtrees = (Boolean) args[1];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ GravitateDataCommand that = (GravitateDataCommand) o;
+
+ if (searchSubtrees != that.searchSubtrees) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = super.hashCode();
+ result = 31 * result + (searchSubtrees ? 1 : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "GravitateDataCommand{" +
+ "key=" + key +
+ ", searchSubtrees=" + searchSubtrees +
+ '}';
+ }
+
+ public Object getKey()
+ {
+ return null; //TODO: Autogenerated. Implement me properly
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AnnounceBuddyPoolNameCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AnnounceBuddyPoolNameCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AnnounceBuddyPoolNameCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,140 @@
+/*
+ * 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.commands.remote;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jgroups.Address;
+
+/**
+ * Announces a buddy pool name to the cluster. This is not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2.0
+ */
+public class AnnounceBuddyPoolNameCommand implements ReplicableCommand
+{
+ public static final int METHOD_ID = 28;
+ private static final Log log = LogFactory.getLog(AnnounceBuddyPoolNameCommand.class);
+
+ /* dependencies*/
+ private BuddyManager buddyManager;
+
+ /*parameters */
+ private Address address;
+ private String buddyPoolName;
+
+ public AnnounceBuddyPoolNameCommand()
+ {
+ }
+
+ public AnnounceBuddyPoolNameCommand(Address address, String buddyPoolName)
+ {
+ this.address = address;
+ this.buddyPoolName = buddyPoolName;
+ }
+
+ public void initialize(BuddyManager buddyManager)
+ {
+ this.buddyManager = buddyManager;
+ }
+
+ /**
+ * This method calls the relevant handler on the buddy manager to deal with this pool broadcast.
+ *
+ * @param ctx invocation context, ignored.
+ * @return null
+ * @throws Throwable in the event of problems
+ */
+ public Object perform(InvocationContext ctx) throws Throwable
+ {
+ if (buddyManager != null)
+ buddyManager.handlePoolNameBroadcast(address, buddyPoolName);
+ else if (log.isWarnEnabled())
+ log.warn("Received annouceBuddyPoolName call from [" + address + "] but buddy replication is not enabled on this node!");
+ return null;
+ }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ public Address getAddress()
+ {
+ return address;
+ }
+
+ public String getBuddyPoolName()
+ {
+ return buddyPoolName;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{address, buddyPoolName};
+ }
+
+ public void setParameters(int commandId, Object[] args)
+ {
+ address = (Address) args[0];
+ buddyPoolName = (String) args[1];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AnnounceBuddyPoolNameCommand that = (AnnounceBuddyPoolNameCommand) o;
+
+ if (address != null ? !address.equals(that.address) : that.address != null) return false;
+ if (buddyPoolName != null ? !buddyPoolName.equals(that.buddyPoolName) : that.buddyPoolName != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result;
+ result = (address != null ? address.hashCode() : 0);
+ result = 31 * result + (buddyPoolName != null ? buddyPoolName.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "AnnounceBuddyPoolNameCommand{" +
+ "buddyManager=" + buddyManager +
+ ", address=" + address +
+ ", buddyPoolName='" + buddyPoolName + '\'' +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AssignToBuddyGroupCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AssignToBuddyGroupCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/AssignToBuddyGroupCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,140 @@
+/*
+ * 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.commands.remote;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.buddyreplication.BuddyGroup;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Assigns a buddy to a group. This is not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2.0
+ */
+public class AssignToBuddyGroupCommand implements ReplicableCommand
+{
+ public static final int METHOD_ID = 29;
+
+ /* dependencies */
+ private BuddyManager buddyManager;
+
+ /* parameters */
+ private BuddyGroup group;
+ private Map<Fqn, byte[]> state;
+
+ public AssignToBuddyGroupCommand(BuddyGroup group, Map<Fqn, byte[]> state)
+ {
+ this.group = group;
+ this.state = state;
+ }
+
+ public AssignToBuddyGroupCommand()
+ {
+ }
+
+ public void initialize(BuddyManager manager)
+ {
+ this.buddyManager = manager;
+ }
+
+ /**
+ * This method calls the relevant handler on the buddy manager to deal with being assigned to a buddy group
+ *
+ * @param ctx invocation context, ignored.
+ * @return null
+ * @throws Throwable in the event of problems
+ */
+ public Object perform(InvocationContext ctx) throws Throwable
+ {
+ if (buddyManager != null)
+ buddyManager.handleAssignToBuddyGroup(group, state);
+ return null;
+ }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ public BuddyGroup getGroup()
+ {
+ return group;
+ }
+
+ public Map<Fqn, byte[]> getState()
+ {
+ return state;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{group, state};
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setParameters(int commandId, Object[] args)
+ {
+ group = (BuddyGroup) args[0];
+ state = (Map<Fqn, byte[]>) args[1];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AssignToBuddyGroupCommand that = (AssignToBuddyGroupCommand) o;
+
+ if (group != null ? !group.equals(that.group) : that.group != null) return false;
+ if (state != null ? !state.equals(that.state) : that.state != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result;
+ result = (group != null ? group.hashCode() : 0);
+ result = 31 * result + (state != null ? state.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "AssignToBuddyGroupCommand{" +
+ "buddyManager=" + buddyManager +
+ ", group=" + group +
+ ", state=" + (state == null ? null : Arrays.asList(state)) +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ClusteredGetCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ClusteredGetCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ClusteredGetCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,177 @@
+/*
+ * 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.commands.remote;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.starobrno.DataContainer;
+import org.jboss.starobrno.commands.DataCommand;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.interceptors.InterceptorChain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Issues a clustered get call, for use primarily by the {@link org.jboss.cache.loader.ClusteredCacheLoader}. This is
+ * not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2.0
+ */
+public class ClusteredGetCommand implements ReplicableCommand
+{
+ public static final int METHOD_ID = 22;
+
+ private DataCommand dataCommand;
+ private boolean searchBackupSubtrees;
+ private DataContainer dataContainer;
+ private InterceptorChain interceptorChain;
+
+ private static final Log log = LogFactory.getLog(ClusteredGetCommand.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ public ClusteredGetCommand(boolean searchBackupSubtrees, DataCommand dataCommand)
+ {
+ this.searchBackupSubtrees = searchBackupSubtrees;
+ this.dataCommand = dataCommand;
+ }
+
+ public ClusteredGetCommand()
+ {
+ }
+
+ public void initialize(DataContainer dataContainer, InterceptorChain interceptorChain)
+ {
+ this.dataContainer = dataContainer;
+ this.interceptorChain = interceptorChain;
+ }
+
+ /**
+ * Invokes a {@link org.jboss.cache.commands.DataCommand} on a remote cache and returns results.
+ *
+ * @param context invocation context, ignored.
+ * @return a List containing 2 elements: a boolean, (true or false) and a value (Object) which is the result of invoking a remote get specified by {@link #getDataCommand()}. If buddy replication is used one further element is added - an Fqn of the backup subtree in which this node may be found.
+ */
+ public Object perform(InvocationContext context) throws Throwable
+ {
+ if (trace)
+ log.trace("Clustered Get called with params: " + dataCommand + ", " + searchBackupSubtrees);
+
+ Object callResults = null;
+ try
+ {
+ InvocationContext ctx = interceptorChain.getInvocationContext();
+ ctx.setOriginLocal(false);
+ // very hacky to be calling this command directly.
+ callResults = dataCommand.perform(ctx);
+ boolean found = true; // TODO: Revisit this!!
+ if (trace) log.trace("Got result " + callResults + ", found=" + found);
+ if (found && callResults == null) callResults = createEmptyResults();
+ }
+ catch (Exception e)
+ {
+ log.warn("Problems processing clusteredGet call", e);
+ }
+
+ List<Object> results = new ArrayList<Object>(2);
+ if (callResults != null)
+ {
+ results.add(true);
+ results.add(callResults);
+ }
+ else
+ {
+ results.add(false);
+ results.add(null);
+ }
+ return results;
+ }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ /**
+ * Creates an empty Collection class based on the return type of the method called.
+ */
+ private Object createEmptyResults()
+ {
+ return null;
+ }
+
+ public Boolean getSearchBackupSubtrees()
+ {
+ return searchBackupSubtrees;
+ }
+
+ public DataCommand getDataCommand()
+ {
+ return dataCommand;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{dataCommand, searchBackupSubtrees}; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setParameters(int commandId, Object[] args)
+ {
+ dataCommand = (DataCommand) args[0];
+ searchBackupSubtrees = (Boolean) args[1];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ClusteredGetCommand that = (ClusteredGetCommand) o;
+
+ if (dataCommand != null ? !dataCommand.equals(that.dataCommand) : that.dataCommand != null)
+ return false;
+ return searchBackupSubtrees == that.searchBackupSubtrees;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result;
+ result = (dataCommand != null ? dataCommand.hashCode() : 0);
+ result = 31 * result + (searchBackupSubtrees ? 1 : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ClusteredGetCommand{" +
+ "dataCommand=" + dataCommand +
+ ", searchBackupSubtrees=" + searchBackupSubtrees +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/DataGravitationCleanupCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/DataGravitationCleanupCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/DataGravitationCleanupCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,245 @@
+/*
+ * 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.commands.remote;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.cache.commands.CommandsFactory;
+import org.jboss.starobrno.DataContainer;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.interceptors.InterceptorChain;
+import org.jboss.starobrno.transaction.GlobalTransaction;
+import org.jboss.starobrno.transaction.TransactionTable;
+
+/**
+ * Data gravitation cleanup handler. Primarily used by the {@link org.jboss.cache.interceptors.DataGravitatorInterceptor}.
+ * This is not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2
+ */
+public class DataGravitationCleanupCommand implements ReplicableCommand
+{
+ public static final int METHOD_ID = 34;
+ private static final Log log = LogFactory.getLog(DataGravitationCleanupCommand.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ /* dependencies */
+ private BuddyManager buddyManager;
+ private TransactionTable transactionTable;
+ private InterceptorChain invoker;
+ private CommandsFactory commandsFactory;
+ private DataContainer dataContainer;
+
+ /* parameters */
+ private GlobalTransaction globalTransaction;
+ private Fqn fqn;
+ private Fqn backup;
+ private BuddyFqnTransformer buddyFqnTransformer;
+
+
+ public DataGravitationCleanupCommand(Fqn primary, Fqn backup)
+ {
+ this.fqn = primary;
+ this.backup = backup;
+ }
+
+ public DataGravitationCleanupCommand()
+ {
+ }
+
+ public void initialize(BuddyManager buddyManager, InterceptorChain invoker, TransactionTable transactionTable,
+ CommandsFactory commandsFactory, DataContainer dataContainer, BuddyFqnTransformer buddyFqnTransformer)
+ {
+ this.buddyManager = buddyManager;
+ this.invoker = invoker;
+ this.transactionTable = transactionTable;
+ this.commandsFactory = commandsFactory;
+ this.dataContainer = dataContainer;
+ this.buddyFqnTransformer = buddyFqnTransformer;
+ }
+
+ /**
+ * Performs a cleanup on nodes that would have been previously gravitated away from the current cache instance.
+ */
+ public Object perform(InvocationContext ctx) throws Throwable
+ {/*
+ if (buddyManager.isDataGravitationRemoveOnFind())
+ {
+ if (trace)
+ log.trace("DataGravitationCleanup: Removing primary (" + fqn + ") and backup (" + backup + ")");
+
+ GlobalTransaction gtx = transactionTable.getCurrentTransaction();
+ if (!executeRemove(gtx, fqn))
+ {
+ // only attempt to clean up the backup if the primary did not exist - a waste of a call otherwise.
+ Object result = executeRemove(gtx, backup);
+ if (wasNodeRemoved(result))
+ {
+ // if this is a DIRECT child of a DEAD buddy backup region, then remove the empty dead region structural node.
+ if (buddyFqnTransformer.isDeadBackupFqn(backup) && buddyFqnTransformer.isDeadBackupRoot(backup.getAncestor(backup.size() - 2)))
+ {
+ Fqn deadBackupRootFqn = backup.getParent();
+ if (!dataContainer.hasChildren(deadBackupRootFqn))
+ {
+ if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
+ executeRemove(gtx, deadBackupRootFqn);
+
+ // now check the grand parent and see if we are free of versions
+ deadBackupRootFqn = deadBackupRootFqn.getParent();
+ if (!dataContainer.hasChildren(deadBackupRootFqn))
+ {
+ if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
+ executeRemove(gtx, deadBackupRootFqn);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (trace) log.trace("Managed to remove primary (" + fqn + "). Not bothering with backups.");
+ }
+ }
+ else
+ {
+ if (trace)
+ log.trace("DataGravitationCleanup: Evicting primary (" + fqn + ") and backup (" + backup + ")");
+ evictNode(fqn);
+ evictNode(backup);
+ }
+ return null; */
+ // TODO - needs implementation
+ throw new UnsupportedOperationException("Fix me!");
+ }
+
+ /**
+ * Returns true if such a node was removed.
+ */
+// private boolean executeRemove(GlobalTransaction gtx, Fqn toRemove) throws Throwable
+// {
+// Object result;
+// RemoveNodeCommand removeBackupCommand = commandsFactory.buildRemoveNodeCommand(gtx, toRemove);
+//
+// InvocationContext ctx = invoker.getInvocationContext();
+// ctx.getOptionOverrides().setCacheModeLocal(true);
+// result = invoker.invoke(ctx, removeBackupCommand);
+// return result != null && (Boolean) result;
+// }
+ private boolean wasNodeRemoved(Object result)
+ {
+ return result != null && (Boolean) result;
+ }
+
+// private void evictNode(Fqn fqn) throws Throwable
+// {
+// if (dataContainer.exists(fqn))
+// {
+// List<Fqn> toEvict = dataContainer.getNodesForEviction(fqn, true);
+// for (Fqn aFqn : toEvict)
+// {
+// EvictCommand evictFqnCommand = commandsFactory.buildEvictFqnCommand(aFqn);
+// invoker.invoke(evictFqnCommand);
+// }
+// }
+// else
+// {
+// if (trace) log.trace("Not evicting " + fqn + " as it doesn't exist");
+// }
+// }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ public Fqn getBackup()
+ {
+ return backup;
+ }
+
+ public GlobalTransaction getGlobalTransaction()
+ {
+ return globalTransaction;
+ }
+
+ public void setGlobalTransaction(GlobalTransaction gtx)
+ {
+ this.globalTransaction = gtx;
+ }
+
+ public Fqn getFqn()
+ {
+ return fqn;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{fqn, backup}; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setParameters(int commandId, Object[] args)
+ {
+ fqn = (Fqn) args[0];
+ backup = (Fqn) args[1];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ DataGravitationCleanupCommand that = (DataGravitationCleanupCommand) o;
+
+ if (backup != null ? !backup.equals(that.backup) : that.backup != null) return false;
+ if (globalTransaction != null ? !globalTransaction.equals(that.globalTransaction) : that.globalTransaction != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = super.hashCode();
+ result = 31 * result + (globalTransaction != null ? globalTransaction.hashCode() : 0);
+ result = 31 * result + (backup != null ? backup.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "DataGravitationCleanupCommand{" +
+ "fqn=" + fqn +
+ ", backup=" + backup +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/RemoveFromBuddyGroupCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/RemoveFromBuddyGroupCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/RemoveFromBuddyGroupCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,118 @@
+/*
+ * 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.commands.remote;
+
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+
+/**
+ * Removes a buddy from a group. This is not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2
+ */
+public class RemoveFromBuddyGroupCommand implements ReplicableCommand
+{
+ public static final int METHOD_ID = 30;
+
+ private BuddyManager buddyManager;
+
+ private String groupName;
+
+ public RemoveFromBuddyGroupCommand(String groupName)
+ {
+ this.groupName = groupName;
+ }
+
+ public RemoveFromBuddyGroupCommand()
+ {
+ }
+
+ public void initialize(BuddyManager buddyManager)
+ {
+ this.buddyManager = buddyManager;
+ }
+
+ /**
+ * This method calls the relevant handler on the buddy manager to deal with being removed from a buddy group
+ *
+ * @param ctx invocation context, ignored.
+ * @return null
+ */
+ public Object perform(InvocationContext ctx)
+ {
+ if (buddyManager != null)
+ buddyManager.handleRemoveFromBuddyGroup(groupName);
+ return null;
+ }
+
+ public int getCommandId()
+ {
+ return METHOD_ID;
+ }
+
+ public String getGroupName()
+ {
+ return groupName;
+ }
+
+ public Object[] getParameters()
+ {
+ return new Object[]{groupName};
+ }
+
+ public void setParameters(int commandId, Object[] args)
+ {
+ groupName = (String) args[0];
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ RemoveFromBuddyGroupCommand that = (RemoveFromBuddyGroupCommand) o;
+
+ if (groupName != null ? !groupName.equals(that.groupName) : that.groupName != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return (groupName != null ? groupName.hashCode() : 0);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "RemoveFromBuddyGroupCommand{" +
+ "buddyManager=" + buddyManager +
+ ", groupName='" + groupName + '\'' +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ReplicateCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ReplicateCommand.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/remote/ReplicateCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,278 @@
+/*
+ * 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.commands.remote;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.commands.read.GravitateDataCommand;
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jboss.starobrno.commands.VisitableCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.interceptors.InterceptorChain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Command that implements cluster replication logic. Essentially mimics the replicate() and replicateAll() methods
+ * in 2.1.x, we may need to revisit the usefulness of such a command.
+ * <p/>
+ * This is not a {@link org.jboss.cache.commands.VisitableCommand} and hence
+ * not passed up the {@link org.jboss.cache.interceptors.base.CommandInterceptor} chain.
+ * <p/>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2
+ */
+public class ReplicateCommand implements ReplicableCommand
+{
+ public static final int SINGLE_METHOD_ID = 13;
+ public static final int MULTIPLE_METHOD_ID = 14;
+
+ private InterceptorChain invoker;
+
+ private static final Log log = LogFactory.getLog(ReplicateCommand.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ /**
+ * optimisation - rather than constructing a new list each for scenarios where a single modification needs
+ * to be replicated rather use this instance.
+ */
+ private ReplicableCommand singleModification;
+ private List<ReplicableCommand> modifications;
+
+ public ReplicateCommand(List<ReplicableCommand> modifications)
+ {
+ if (modifications != null && modifications.size() == 1)
+ {
+ singleModification = modifications.get(0);
+ }
+ else
+ {
+ this.modifications = modifications;
+ }
+ }
+
+ public ReplicateCommand(ReplicableCommand command)
+ {
+ this.singleModification = command;
+ }
+
+ public ReplicateCommand()
+ {
+ }
+
+ public void initialize(InterceptorChain interceptorChain)
+ {
+ this.invoker = interceptorChain;
+ }
+
+ public void setSingleModification(ReplicableCommand singleModification)
+ {
+ this.singleModification = singleModification;
+ }
+
+ public void setModifications(List<ReplicableCommand> modifications)
+ {
+ if (modifications != null && modifications.size() == 1)
+ singleModification = modifications.get(0);
+ else
+ this.modifications = modifications;
+ }
+
+ /**
+ * Executes commands replicated to the current cache instance by other cache instances.
+ *
+ * @param ctx invocation context, ignored.
+ * @return if this is a single command being processed <b>and</b> it is a {@link org.jboss.cache.commands.read.GravitateDataCommand}, the result of processing this command is returned. Otherwise, null is returned.
+ * @throws Throwable
+ */
+ public Object perform(InvocationContext ctx) throws Throwable
+ {
+ if (isSingleCommand())
+ {
+ Object retVal = processSingleCommand(singleModification);
+
+ // only send back the result of the execution if it is a data gravitation command.
+ // all other commands don't need to send back return values, there will be an unnecessary overhead of
+ // marshalling results that won't ever be used.
+ if (singleModification instanceof GravitateDataCommand)
+ return retVal;
+ else
+ return null;
+ }
+ for (ReplicableCommand command : modifications) processSingleCommand(command);
+ return null;
+ }
+
+ private Object processSingleCommand(ReplicableCommand cacheCommand)
+ throws Throwable
+ {
+ Object result;
+ try
+ {
+ if (trace) log.trace("Invoking command " + cacheCommand + ", with originLocal flag set to false.");
+
+ if (cacheCommand instanceof VisitableCommand)
+ {
+ Object retVal = invoker.invokeRemote((VisitableCommand) cacheCommand);
+ // we only need to return values for a set of remote calls; not every call.
+ if (returnValueForRemoteCall(cacheCommand))
+ {
+ result = retVal;
+ }
+ else
+ {
+ result = null;
+ }
+ }
+ else
+ {
+ result = cacheCommand.perform(null);
+ }
+ }
+ catch (Throwable ex)
+ {
+ // TODO deal with PFER
+// if (!(cacheCommand instanceof PutForExternalReadCommand))
+// {
+ throw ex;
+// }
+// else
+// {
+// if (trace)
+// log.trace("Caught an exception, but since this is a putForExternalRead() call, suppressing the exception. Exception is:", ex);
+// result = null;
+// }
+ }
+ return result;
+ }
+
+ private boolean returnValueForRemoteCall(ReplicableCommand cacheCommand)
+ {
+ return cacheCommand instanceof GravitateDataCommand || cacheCommand instanceof ClusteredGetCommand;
+ }
+
+ public int getCommandId()
+ {
+ return isSingleCommand() ? SINGLE_METHOD_ID : MULTIPLE_METHOD_ID;
+ }
+
+ public List<ReplicableCommand> getModifications()
+ {
+ return modifications;
+ }
+
+ public ReplicableCommand getSingleModification()
+ {
+ return singleModification;
+ }
+
+ public Object[] getParameters()
+ {
+ if (isSingleCommand())
+ return new Object[]{singleModification};
+ else
+ return new Object[]{modifications};
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setParameters(int commandId, Object[] args)
+ {
+ if (commandId == SINGLE_METHOD_ID)
+ {
+ singleModification = (ReplicableCommand) args[0];
+ }
+ else
+ {
+ modifications = (List<ReplicableCommand>) args[0];
+ }
+ }
+
+ public boolean isSingleCommand()
+ {
+ return singleModification != null;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ReplicateCommand that = (ReplicateCommand) o;
+
+ if (modifications != null ? !modifications.equals(that.modifications) : that.modifications != null) return false;
+ if (singleModification != null ? !singleModification.equals(that.singleModification) : that.singleModification != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result;
+ result = (singleModification != null ? singleModification.hashCode() : 0);
+ result = 31 * result + (modifications != null ? modifications.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ReplicateCommand{" +
+ "cmds=" + (isSingleCommand() ? singleModification : modifications) +
+ '}';
+ }
+
+ /**
+ * Creates a copy of this command, amking a deep copy of any collections but everything else copied shallow.
+ *
+ * @return a copy
+ */
+ public ReplicateCommand copy()
+ {
+ ReplicateCommand clone;
+ clone = new ReplicateCommand();
+ clone.invoker = invoker;
+ clone.modifications = modifications == null ? null : new ArrayList<ReplicableCommand>(modifications);
+ clone.singleModification = singleModification;
+ return clone;
+ }
+
+ public boolean containsCommandType(Class<? extends ReplicableCommand> aClass)
+ {
+ if (isSingleCommand())
+ {
+ return getSingleModification().getClass().equals(aClass);
+ }
+ else
+ {
+ for (ReplicableCommand command : getModifications())
+ {
+ if (command.getClass().equals(aClass)) return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/AbstractTransactionBoundaryCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/AbstractTransactionBoundaryCommand.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/AbstractTransactionBoundaryCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,9 +21,9 @@
*/
package org.jboss.starobrno.commands.tx;
-import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.starobrno.commands.TransactionBoundaryCommand;
import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.transaction.GlobalTransaction;
/**
* // TODO: MANIK: Document this
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/CommitCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/CommitCommand.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/CommitCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,9 +21,9 @@
*/
package org.jboss.starobrno.commands.tx;
-import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.starobrno.commands.Visitor;
import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.transaction.GlobalTransaction;
/**
* // TODO: MANIK: Document this
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/PrepareCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/PrepareCommand.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/PrepareCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,11 +21,11 @@
*/
package org.jboss.starobrno.commands.tx;
-import org.jboss.cache.commands.WriteCommand;
-import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.starobrno.commands.ReplicableCommand;
import org.jboss.starobrno.commands.Visitor;
+import org.jboss.starobrno.commands.WriteCommand;
import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.transaction.GlobalTransaction;
import org.jgroups.Address;
import java.util.ArrayList;
@@ -42,11 +42,11 @@
{
public static final int METHOD_ID = 10;
- protected List<ReplicableCommand> modifications;
+ protected List<WriteCommand> modifications;
protected Address localAddress;
protected boolean onePhaseCommit;
- public PrepareCommand(GlobalTransaction gtx, List<ReplicableCommand> modifications, Address localAddress, boolean onePhaseCommit)
+ public PrepareCommand(GlobalTransaction gtx, List<WriteCommand> modifications, Address localAddress, boolean onePhaseCommit)
{
this.gtx = gtx;
this.modifications = modifications;
@@ -70,7 +70,7 @@
// return visitor.visitPrepareCommand(ctx, this);
}
- public List<ReplicableCommand> getModifications()
+ public List<WriteCommand> getModifications()
{
return modifications;
}
@@ -111,7 +111,7 @@
public void setParameters(int commandId, Object[] args)
{
gtx = (GlobalTransaction) args[0];
- modifications = (List<ReplicableCommand>) args[1];
+ modifications = (List<WriteCommand>) args[1];
localAddress = (Address) args[2];
onePhaseCommit = (Boolean) args[3];
}
@@ -147,7 +147,7 @@
PrepareCommand copy = new PrepareCommand();
copy.gtx = gtx;
copy.localAddress = localAddress;
- copy.modifications = modifications == null ? null : new ArrayList<ReplicableCommand>(modifications);
+ copy.modifications = modifications == null ? null : new ArrayList<WriteCommand>(modifications);
copy.onePhaseCommit = onePhaseCommit;
return copy;
}
@@ -165,7 +165,7 @@
public boolean containsModificationType(Class<? extends ReplicableCommand> replicableCommandClass)
{
- for (ReplicableCommand mod : getModifications())
+ for (WriteCommand mod : getModifications())
{
if (mod.getClass().equals(replicableCommandClass))
{
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/RollbackCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/RollbackCommand.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/tx/RollbackCommand.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,9 +21,9 @@
*/
package org.jboss.starobrno.commands.tx;
-import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.starobrno.commands.Visitor;
import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.transaction.GlobalTransaction;
/**
* // TODO: MANIK: Document this
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -23,12 +23,12 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.util.Immutables;
+import org.jboss.starobrno.commands.VisitableCommand;
import org.jboss.starobrno.mvcc.MVCCEntry;
import org.jboss.starobrno.transaction.GlobalTransaction;
-import org.jboss.starobrno.commands.VisitableCommand;
-import org.jboss.cache.config.Option;
-import org.jboss.cache.util.Immutables;
-import org.jboss.cache.transaction.TransactionTable;
+import org.jboss.starobrno.transaction.TransactionTable;
import javax.transaction.Transaction;
import java.util.Collections;
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 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContext.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,10 +21,9 @@
*/
package org.jboss.starobrno.context;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.commands.WriteCommand;
import org.jboss.cache.config.Option;
import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
+import org.jboss.starobrno.commands.WriteCommand;
import javax.transaction.Transaction;
import java.util.List;
@@ -75,14 +74,14 @@
* @param fqn fqn that has been removed.
* @throws NullPointerException if the Fqn is null.
*/
- void addRemovedNode(Fqn fqn);
+ void addRemovedEntry(Object key);
/**
* Gets the list of removed nodes.
*
* @return list of nodes removed in the current transaction scope. Note that this method will return an empty list if nothing has been removed. The list returned is defensively copied.
*/
- List<Fqn> getRemovedNodes();
+ List<Object> getRemovedEntries();
/**
* Sets the local transaction to be associated with this transaction context.
@@ -228,12 +227,12 @@
*
* @param fqn fqn to add. Must not be null.
*/
- void addDummyNodeCreatedByCacheLoader(Fqn fqn);
+ void addDummyEntryCreatedByCacheLoader(Object key);
/**
* @return a list of uninitialized nodes created by the cache loader, or an empty list.
*/
- List<Fqn> getDummyNodesCreatedByCacheLoader();
+ List<Object> getDummyEntriesCreatedByCacheLoader();
/**
* Sets a transaction-scope option override
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 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/context/TransactionContextImpl.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -21,11 +21,10 @@
*/
package org.jboss.starobrno.context;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.commands.WriteCommand;
import org.jboss.cache.config.Option;
import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
import org.jboss.cache.util.Immutables;
+import org.jboss.starobrno.commands.WriteCommand;
import org.jboss.starobrno.mvcc.MVCCEntry;
import javax.transaction.RollbackException;
@@ -80,12 +79,12 @@
* A list of dummy uninitialised nodes created by the cache loader interceptor to load data for a
* given node in this tx.
*/
- private List<Fqn> dummyNodesCreatedByCacheLoader;
+ private List<Object> dummyNodesCreatedByCacheLoader;
/**
* List<Fqn> of nodes that have been removed by the transaction
*/
- private List<Fqn> removedNodes = null;
+ private List<Object> removedNodes = null;
private final Map<Object, MVCCEntry> lookedUpEntries = new HashMap<Object, MVCCEntry>(8);
@@ -195,17 +194,17 @@
}
- public void addRemovedNode(Fqn fqn)
+ public void addRemovedEntry(Object key)
{
- if (fqn == null) throw new NullPointerException("Fqn is null!");
- if (removedNodes == null) removedNodes = new LinkedList<Fqn>();
- removedNodes.add(fqn);
+ if (key == null) throw new NullPointerException("Key is null!");
+ if (removedNodes == null) removedNodes = new LinkedList<Object>();
+ removedNodes.add(key);
}
- public List<Fqn> getRemovedNodes()
+ public List<Object> getRemovedEntries()
{
if (removedNodes == null) return Collections.emptyList();
- return new ArrayList<Fqn>(removedNodes);
+ return new ArrayList<Object>(removedNodes);
}
public void setTransaction(Transaction tx)
@@ -296,14 +295,14 @@
return sb.toString();
}
- public void addDummyNodeCreatedByCacheLoader(Fqn fqn)
+ public void addDummyEntryCreatedByCacheLoader(Object key)
{
if (dummyNodesCreatedByCacheLoader == null)
- dummyNodesCreatedByCacheLoader = new LinkedList<Fqn>();
- dummyNodesCreatedByCacheLoader.add(fqn);
+ dummyNodesCreatedByCacheLoader = new LinkedList<Object>();
+ dummyNodesCreatedByCacheLoader.add(key);
}
- public List<Fqn> getDummyNodesCreatedByCacheLoader()
+ public List<Object> getDummyEntriesCreatedByCacheLoader()
{
if (dummyNodesCreatedByCacheLoader == null) return Collections.emptyList();
return dummyNodesCreatedByCacheLoader;
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/factories/context/ContextFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/factories/context/ContextFactory.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/factories/context/ContextFactory.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -22,7 +22,7 @@
package org.jboss.starobrno.factories.context;
import org.jboss.starobrno.context.InvocationContext;
-import org.jboss.cache.transaction.TransactionContext;
+import org.jboss.starobrno.context.TransactionContext;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
Deleted: core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionContext.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionContext.java 2008-10-08 11:51:17 UTC (rev 6868)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionContext.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -1,283 +0,0 @@
-/*
- * 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.transaction;
-
-import org.jboss.cache.Fqn;
-import org.jboss.cache.commands.WriteCommand;
-import org.jboss.cache.config.Option;
-import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
-
-import javax.transaction.Transaction;
-import java.util.List;
-
-/**
- * Captures information pertaining to a specific JTA transaction.
- * <p/>
- * This was a concrete class called TransactionEntry prior to 3.0.
- * <p/>
- *
- * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @see org.jboss.cache.InvocationContext
- */
-public interface TransactionContext
-{
- /**
- * Adds a modification to the modification list.
- *
- * @param command modification
- */
- void addModification(WriteCommand command);
-
- /**
- * Returns all modifications. If there are no modifications in this transaction this method will return an empty list.
- *
- * @return list of modifications.
- */
- List<WriteCommand> getModifications();
-
- /**
- * Adds a modification to the local modification list.
- *
- * @param command command to add to list. Should not be null.
- * @throws NullPointerException if the command to be added is null.
- */
- void addLocalModification(WriteCommand command);
-
- /**
- * Returns all modifications that have been invoked with the LOCAL cache mode option. These will also be in the standard modification list.
- *
- * @return list of LOCAL modifications, or an empty list.
- */
- List<WriteCommand> getLocalModifications();
-
- /**
- * Adds the node that has been removed in the scope of the current transaction.
- *
- * @param fqn fqn that has been removed.
- * @throws NullPointerException if the Fqn is null.
- */
- void addRemovedNode(Fqn fqn);
-
- /**
- * Gets the list of removed nodes.
- *
- * @return list of nodes removed in the current transaction scope. Note that this method will return an empty list if nothing has been removed. The list returned is defensively copied.
- */
- List<Fqn> getRemovedNodes();
-
- /**
- * Sets the local transaction to be associated with this transaction context.
- *
- * @param tx JTA transaction to associate with.
- */
- void setTransaction(Transaction tx);
-
- /**
- * Returns a local transaction associated with this context.
- *
- * @return a JTA transaction
- */
- Transaction getTransaction();
-
- /**
- * Adds a lock to the currently maintained collection of locks acquired.
- * <p/>
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#addLock(Object)} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- * <p/>
- * Note that currently (as of 3.0.0) this lock is weakly typed. This is to allow support for both MVCC (which uses {@link org.jboss.cache.Fqn}s as locks)
- * as well as legacy Optimistic and Pessimistic Locking schemes (which use {@link org.jboss.cache.lock.NodeLock} as locks). Once support for
- * legacy node locking schemes are dropped, this method will be more strongly typed to accept {@link org.jboss.cache.Fqn}.
- *
- * @param lock lock to add
- * @see org.jboss.cache.InvocationContext#addLock(Object)
- */
- @SuppressWarnings("unchecked")
- void addLock(Object lock);
-
- /**
- * Removes a lock from the currently maintained collection of locks acquired.
- * <p/>
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#removeLock(Object)} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- * <p/>
- * Note that currently (as of 3.0.0) this lock is weakly typed. This is to allow support for both MVCC (which uses {@link org.jboss.cache.Fqn}s as locks)
- * as well as legacy Optimistic and Pessimistic Locking schemes (which use {@link org.jboss.cache.lock.NodeLock} as locks). Once support for
- * legacy node locking schemes are dropped, this method will be more strongly typed to accept {@link org.jboss.cache.Fqn}.
- *
- * @param lock lock to remove
- * @see org.jboss.cache.InvocationContext#removeLock(Object)
- */
- @SuppressWarnings("unchecked")
- void removeLock(Object lock);
-
- /**
- * Clears all locks from the currently maintained collection of locks acquired.
- * <p/>
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#clearLocks()} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- * <p/>
- * Note that currently (as of 3.0.0) this lock is weakly typed. This is to allow support for both MVCC (which uses {@link org.jboss.cache.Fqn}s as locks)
- * as well as legacy Optimistic and Pessimistic Locking schemes (which use {@link org.jboss.cache.lock.NodeLock} as locks). Once support for
- * legacy node locking schemes are dropped, this method will be more strongly typed to accept {@link org.jboss.cache.Fqn}.
- *
- * @see org.jboss.cache.InvocationContext#clearLocks()
- */
- void clearLocks();
-
- /**
- * Adds a List of locks to the currently maintained collection of locks acquired.
- * <p/>
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#addAllLocks(java.util.List)} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- * <p/>
- * Note that currently (as of 3.0.0) this list is unchecked. This is to allow support for both MVCC (which uses Fqns as locks)
- * as well as legacy Optimistic and Pessimistic Locking schemes (which use {@link org.jboss.cache.lock.NodeLock} as locks). Once support for
- * legacy node locking schemes are dropped, this method will be more strongly typed to accept <tt>List<Fqn></tt>.
- *
- * @param newLocks locks to add
- * @see org.jboss.cache.InvocationContext#addAllLocks(java.util.List)
- */
- @SuppressWarnings("unchecked")
- void addAllLocks(List newLocks);
-
- /**
- * Returns an immutable, defensive copy of the List of locks currently maintained for the transaction.
- * <p/>
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#getLocks()} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- * <p/>
- * Note that currently (as of 3.0.0) this list is unchecked. This is to allow support for both MVCC (which uses Fqns as locks)
- * as well as legacy Optimistic and Pessimistic Locking schemes (which use {@link org.jboss.cache.lock.NodeLock} as locks). Once support for
- * legacy node locking schemes are dropped, this method will be more strongly typed to return <tt>List<Fqn></tt>.
- *
- * @return locks held in current scope.
- * @see org.jboss.cache.InvocationContext#getLocks()
- */
- @SuppressWarnings("unchecked")
- List getLocks();
-
- /**
- * Most code could not use this method directly, but use {@link org.jboss.cache.InvocationContext#hasLock(Object)} ()} instead,
- * which would delegate to this method if a transaction is in scope or otherwise use invocation-specific locks.
- *
- * @param lock lock to test
- * @return true if the lock being tested is already held in the current scope, false otherwise.
- */
- boolean hasLock(Object lock);
-
- /**
- * Gets the value of the forceAsyncReplication flag. Used by ReplicationInterceptor and OptimisticReplicationInterceptor
- * when dealing with {@link org.jboss.cache.Cache#putForExternalRead(org.jboss.cache.Fqn,Object,Object)} within
- * a transactional context.
- *
- * @return true if the forceAsyncReplication flag is set to true.
- */
- boolean isForceAsyncReplication();
-
- /**
- * Sets the value of the forceAsyncReplication flag. Used by ReplicationInterceptor and OptimisticReplicationInterceptor
- * when dealing with {@link org.jboss.cache.Cache#putForExternalRead(org.jboss.cache.Fqn,Object,Object)} within
- * a transactional context. Also used by OptimisticReplicationInterceptor when dealing
- * with {@link org.jboss.cache.config.Option#setForceAsynchronous(boolean)} in a
- * non-transactional context (i.e. with an implicit transaction).
- *
- * @param forceAsyncReplication value of forceAsyncReplication
- */
- void setForceAsyncReplication(boolean forceAsyncReplication);
-
- /**
- * Gets the value of the forceSyncReplication flag. Used by ReplicationInterceptor and OptimisticReplicationInterceptor
- * when dealing with {@link org.jboss.cache.Cache#putForExternalRead(org.jboss.cache.Fqn,Object,Object)} within
- * a transactional context.
- *
- * @return true if the forceAsyncReplication flag is set to true.
- */
- boolean isForceSyncReplication();
-
- /**
- * Sets the value of the forceSyncReplication flag. Used by ReplicationInterceptor and OptimisticReplicationInterceptor
- * when dealing with {@link org.jboss.cache.Cache#putForExternalRead(org.jboss.cache.Fqn,Object,Object)} within
- * a transactional context.
- *
- * @param forceSyncReplication value of forceSyncReplication
- */
- void setForceSyncReplication(boolean forceSyncReplication);
-
- /**
- * Adds an Fqn to the list of uninitialized nodes created by the cache loader.
- *
- * @param fqn fqn to add. Must not be null.
- */
- void addDummyNodeCreatedByCacheLoader(Fqn fqn);
-
- /**
- * @return a list of uninitialized nodes created by the cache loader, or an empty list.
- */
- List<Fqn> getDummyNodesCreatedByCacheLoader();
-
- /**
- * Sets a transaction-scope option override
- *
- * @param o option to set
- */
- void setOption(Option o);
-
- /**
- * Retrieves a transaction scope option override
- *
- * @return option
- */
- Option getOption();
-
- /**
- * @return the ordered sync handler associated with this transaction
- */
- OrderedSynchronizationHandler getOrderedSynchronizationHandler();
-
- /**
- * Associates an ordered sync handler with this transaction.
- *
- * @param orderedSynchronizationHandler to set
- */
- void setOrderedSynchronizationHandler(OrderedSynchronizationHandler orderedSynchronizationHandler);
-
- /**
- * @return true if modifications were registered.
- */
- boolean hasModifications();
-
- /**
- * @return true if any modifications have been invoked with cache mode being LOCAL.
- */
- boolean hasLocalModifications();
-
- /**
- * @return true if either there are modifications or local modifications that are not for replicating.
- */
- boolean hasAnyModifications();
-
- /**
- * Cleans up internal state, freeing up references.
- */
- void reset();
-}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java 2008-10-08 11:53:03 UTC (rev 6869)
@@ -0,0 +1,427 @@
+/*
+ * 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.transaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.RPCManager;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.factories.annotations.NonVolatile;
+import org.jboss.starobrno.context.TransactionContext;
+import org.jboss.starobrno.factories.context.ContextFactory;
+import org.jgroups.Address;
+
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Maintains the mapping between a local {@link Transaction} and a {@link GlobalTransaction}.
+ * Also stores {@link TransactionContext} instances under a given transaction.
+ *
+ * @author <a href="mailto:bela at jboss.org">Bela Ban</a> Apr 14, 2003
+ * @version $Revision: 6776 $
+ */
+ at NonVolatile
+public class TransactionTable
+{
+ private static final Log log = LogFactory.getLog(TransactionTable.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ /**
+ * Mapping between local (javax.transaction.Transaction)
+ * and GlobalTransactions.
+ * New: a local TX can have a number of GTXs
+ */
+ protected final Map<Transaction, GlobalTransaction> tx2gtxMap = new ConcurrentHashMap<Transaction, GlobalTransaction>();
+
+ /**
+ * Mappings between GlobalTransactions and modifications.
+ */
+ protected final Map<GlobalTransaction, TransactionContext> gtx2ContextMap = new ConcurrentHashMap<GlobalTransaction, TransactionContext>();
+
+ protected final Map<GlobalTransaction, Transaction> gtx2TxMap = new ConcurrentHashMap<GlobalTransaction, Transaction>();
+
+ private TransactionManager transactionManager = null;
+
+ private RPCManager rpcManager;
+
+ private ContextFactory contextFactory;
+
+ @Inject
+ public void initialize(TransactionManager transactionManager, RPCManager rpcManager, ContextFactory contextFactory)
+ {
+ this.transactionManager = transactionManager;
+ this.rpcManager = rpcManager;
+ this.contextFactory = contextFactory;
+ }
+
+ /**
+ * Returns the number of local transactions.
+ */
+ public int getNumLocalTransactions()
+ {
+ return tx2gtxMap.size();
+ }
+
+ /**
+ * Returns the number of global transactions.
+ */
+ public int getNumGlobalTransactions()
+ {
+ return gtx2ContextMap.size();
+ }
+
+ /**
+ * Returns the global transaction associated with the local transaction.
+ * Returns null if tx is null or it was not found.
+ */
+ public GlobalTransaction get(Transaction tx)
+ {
+ if (tx == null)
+ return null;
+ return tx2gtxMap.get(tx);
+ }
+
+ /**
+ * Returns the local transaction associated with a GlobalTransaction.
+ *
+ * @param gtx The GlobalTransaction
+ * @return Transaction. The local transaction associated with a given
+ * GlobalTransaction). This will be null if no local transaction is
+ * associated with a given GTX
+ */
+ public Transaction getLocalTransaction(GlobalTransaction gtx)
+ {
+ if (gtx == null) return null;
+ return gtx2TxMap.get(gtx);
+ }
+
+ /**
+ * If assers exists is true and the coresponding local transaction is null an IllegalStateExcetpion is being thrown.
+ */
+ public Transaction getLocalTransaction(GlobalTransaction gtx, boolean assertExists)
+ {
+ Transaction ltx = getLocalTransaction(gtx);
+ if (!assertExists)
+ {
+ return ltx;
+ }
+ if (ltx != null)
+ {
+ if (log.isDebugEnabled()) log.debug("Found local TX=" + ltx + ", global TX=" + gtx);
+ return ltx;
+ }
+ else
+ {
+ throw new IllegalStateException(" found no local TX for global TX " + gtx);
+ }
+ }
+
+ /**
+ * Associates the global transaction with the local transaction.
+ */
+ public void put(Transaction tx, GlobalTransaction gtx)
+ {
+ if (tx == null)
+ {
+ log.error("key (Transaction) is null");
+ return;
+ }
+ tx2gtxMap.put(tx, gtx);
+ gtx2TxMap.put(gtx, tx);
+ }
+
+ /**
+ * Returns the local transaction entry for the global transaction.
+ * Returns null if tx is null or it was not found.
+ */
+ public TransactionContext get(GlobalTransaction gtx)
+ {
+ return gtx != null ? gtx2ContextMap.get(gtx) : null;
+ }
+
+ /**
+ * Associates the global transaction with a transaction context.
+ */
+ public void put(GlobalTransaction tx, TransactionContext transactionContext)
+ {
+ if (tx == null)
+ {
+ log.error("key (GlobalTransaction) is null");
+ return;
+ }
+ gtx2ContextMap.put(tx, transactionContext);
+ }
+
+ /**
+ * Removes a global transation, returns the old transaction entry.
+ */
+ public TransactionContext remove(GlobalTransaction tx)
+ {
+ if (tx == null) return null;
+ gtx2TxMap.remove(tx);
+ return gtx2ContextMap.remove(tx);
+ }
+
+ /**
+ * Removes a local transation, returns the global transaction entry.
+ */
+ public GlobalTransaction remove(Transaction tx)
+ {
+ if (tx == null)
+ return null;
+ return tx2gtxMap.remove(tx);
+ }
+
+ public void remove(GlobalTransaction gtx, Transaction tx)
+ {
+ gtx2TxMap.remove(gtx);
+ gtx2ContextMap.remove(gtx);
+ tx2gtxMap.remove(tx);
+ }
+
+ /**
+ * Returns summary debug information.
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(tx2gtxMap.size()).append(" mappings, ");
+ sb.append(gtx2ContextMap.size()).append(" transactions");
+ return sb.toString();
+ }
+
+ /**
+ * Returns detailed debug information.
+ */
+ public String toString(boolean printDetails)
+ {
+ if (!printDetails)
+ return toString();
+ StringBuilder sb = new StringBuilder();
+ sb.append("LocalTransactions: ").append(tx2gtxMap.size()).append("\n");
+ sb.append("GlobalTransactions: ").append(gtx2ContextMap.size()).append("\n");
+ sb.append("tx2gtxMap:\n");
+ for (Map.Entry<Transaction, GlobalTransaction> entry : tx2gtxMap.entrySet())
+ {
+ sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
+ }
+ sb.append("gtx2EntryMap:\n");
+ for (Map.Entry<GlobalTransaction, TransactionContext> transactionContextEntry : gtx2ContextMap.entrySet())
+ {
+ sb.append(transactionContextEntry.getKey()).append(": ").append(transactionContextEntry.getValue()).append("\n");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns the transaction associated with the current thread.
+ * If a local transaction exists, but doesn't yet have a mapping to a
+ * GlobalTransaction, a new GlobalTransaction will be created and mapped to
+ * the local transaction. Note that if a local transaction exists, but is
+ * not ACTIVE or PREPARING, null is returned.
+ *
+ * @return A GlobalTransaction, or null if no (local) transaction was associated with the current thread
+ */
+ public GlobalTransaction getCurrentTransaction()
+ {
+ return getCurrentTransaction(true);
+ }
+
+
+ /**
+ * Returns the transaction associated with the thread; optionally creating
+ * it if is does not exist.
+ */
+ public GlobalTransaction getCurrentTransaction(boolean createIfNotExists)
+ {
+ Transaction tx;
+
+ if ((tx = getLocalTransaction()) == null)
+ {// no transaction is associated with the current thread
+ return null;
+ }
+
+ if (!isValid(tx))
+ {// we got a non-null transaction, but it is not active anymore
+ int status = -1;
+ try
+ {
+ status = tx.getStatus();
+ }
+ catch (SystemException e)
+ {
+ }
+
+ // JBCACHE-982 -- don't complain if COMMITTED
+ if (status != Status.STATUS_COMMITTED)
+ {
+ log.warn("status is " + status + " (not ACTIVE or PREPARING); returning null)");
+ }
+ else
+ {
+ log.trace("status is COMMITTED; returning null");
+ }
+
+ return null;
+ }
+
+ return getCurrentTransaction(tx, createIfNotExists);
+ }
+
+ /**
+ * Returns the transaction associated with the current thread. We get the
+ * initial context and a reference to the TransactionManager to get the
+ * transaction. This method is used by {@link #getCurrentTransaction()}
+ */
+ protected Transaction getLocalTransaction()
+ {
+ if (transactionManager == null)
+ {
+ return null;
+ }
+ try
+ {
+ return transactionManager.getTransaction();
+ }
+ catch (Throwable t)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if transaction is ACTIVE, false otherwise
+ */
+ public static boolean isActive(Transaction tx)
+ {
+ if (tx == null) return false;
+ int status;
+ try
+ {
+ status = tx.getStatus();
+ return status == Status.STATUS_ACTIVE;
+ }
+ catch (SystemException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if transaction is PREPARING, false otherwise
+ */
+ public static boolean isPreparing(Transaction tx)
+ {
+ if (tx == null) return false;
+ int status;
+ try
+ {
+ status = tx.getStatus();
+ return status == Status.STATUS_PREPARING;
+ }
+ catch (SystemException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Return s true of tx's status is ACTIVE or PREPARING
+ *
+ * @param tx
+ * @return true if the tx is active or preparing
+ */
+ public static boolean isValid(Transaction tx)
+ {
+ return isActive(tx) || isPreparing(tx);
+ }
+
+ /**
+ * Tests whether the caller is in a valid transaction. If not, will throw a CacheException.
+ */
+ public static void assertTransactionValid(InvocationContext ctx)
+ {
+ Transaction tx = ctx.getTransaction();
+ if (!isValid(tx)) try
+ {
+ throw new CacheException("Invalid transaction " + tx + ", status = " + (tx == null ? null : tx.getStatus()));
+ }
+ catch (SystemException e)
+ {
+ throw new CacheException("Exception trying to analyse status of transaction " + tx, e);
+ }
+ }
+
+
+ /**
+ * Returns the global transaction for this local transaction.
+ */
+ public GlobalTransaction getCurrentTransaction(Transaction tx)
+ {
+ return getCurrentTransaction(tx, true);
+ }
+
+ /**
+ * Returns the global transaction for this local transaction.
+ *
+ * @param createIfNotExists if true, if a global transaction is not found; one is created
+ */
+ public GlobalTransaction getCurrentTransaction(Transaction tx, boolean createIfNotExists)
+ {
+ // removed synchronization on txTable because underlying implementation is thread safe
+ // and JTA spec (section 3.4.3 Thread of Control, par 2) says that only one thread may
+ // operate on the transaction at one time so no concern about 2 threads trying to call
+ // this method for the same Transaction instance at the same time
+ //
+ GlobalTransaction gtx = get(tx);
+ if (gtx == null && createIfNotExists)
+ {
+ Address addr = rpcManager.getLocalAddress();
+ gtx = GlobalTransaction.create(addr);
+ put(tx, gtx);
+ TransactionContext transactionContext;
+ try
+ {
+ transactionContext = contextFactory.createTransactionContext(tx);
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create a transaction entry!", e);
+ }
+
+ put(gtx, transactionContext);
+ if (trace)
+ {
+ log.trace("created new GTX: " + gtx + ", local TX=" + tx);
+ }
+ }
+ return gtx;
+ }
+}
More information about the jbosscache-commits
mailing list