[jboss-cvs] JBossCache/src/org/jboss/cache ...
Manik Surtani
msurtani at jboss.com
Thu Dec 14 12:18:48 EST 2006
User: msurtani
Date: 06/12/14 12:18:47
Modified: src/org/jboss/cache TreeCacheProxyImpl.java
TransactionEntry.java TreeCache.java TreeNode.java
AbstractNode.java RegionManager.java NodeImpl.java
Removed: src/org/jboss/cache ExtendedTreeCacheListener.java
Log:
The beginnings of porting JBCACHE-871 and JBCACHE-875 as well as rearranging the Node/Cache object model to something sensible
Revision Changes Path
1.54 +5 -0 JBossCache/src/org/jboss/cache/TreeCacheProxyImpl.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: TreeCacheProxyImpl.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/TreeCacheProxyImpl.java,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -b -r1.53 -r1.54
--- TreeCacheProxyImpl.java 27 Nov 2006 17:07:05 -0000 1.53
+++ TreeCacheProxyImpl.java 14 Dec 2006 17:18:47 -0000 1.54
@@ -440,4 +440,9 @@
return getRoot().getNodeSPI();
}
+ public void realRemove(Fqn f, boolean skipMarkerCheck)
+ {
+ treeCache.realRemove(f, skipMarkerCheck);
+ }
+
}
1.17 +163 -95 JBossCache/src/org/jboss/cache/TransactionEntry.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: TransactionEntry.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/TransactionEntry.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- TransactionEntry.java 8 Dec 2006 03:49:28 -0000 1.16
+++ TransactionEntry.java 14 Dec 2006 17:18:47 -0000 1.17
@@ -7,16 +7,21 @@
package org.jboss.cache;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.config.Option;
import org.jboss.cache.lock.IdentityLock;
import org.jboss.cache.lock.NodeLock;
-import org.jboss.cache.config.Option;
import org.jboss.cache.marshall.MethodCall;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import javax.transaction.Transaction;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
/**
* This is the value (key being the {@link GlobalTransaction}) in the transaction table
@@ -32,22 +37,23 @@
* </ul>
*
* @author <a href="mailto:bela at jboss.org">Bela Ban</a> Apr 14, 2003
- * @version $Revision: 1.16 $
+ * @version $Revision: 1.17 $
*/
-public class TransactionEntry {
+public class TransactionEntry
+{
static Log log = LogFactory.getLog(TransactionEntry.class);
/**
* Local transaction
*/
- private Transaction ltx=null;
+ private Transaction ltx = null;
private Option option;
/**
* List<MethodCall> of modifications ({@link MethodCall}). They will be replicated on TX commit
*/
- private List<MethodCall> modification_list=new LinkedList<MethodCall>();
+ private List<MethodCall> modification_list = new LinkedList<MethodCall>();
private List<MethodCall> cl_mod_list = new LinkedList<MethodCall>();
/**
@@ -56,7 +62,7 @@
* we have a corresponding entry in this list. A rollback will simply iterate over this list in
* reverse to undo the modifications. Note that these undo-ops will never be replicated.
*/
- private List undo_list=new LinkedList();
+ private List undo_list = new LinkedList();
/**
* LinkedHashSet<IdentityLock> of locks acquired by the transaction. We use
@@ -73,29 +79,37 @@
private List dummyNodesCreatedByCacheLoader;
/**
+ * List<Fqn> of nodes that have been removed by the transaction
+ */
+ private List<Fqn> removedNodes = new LinkedList<Fqn>();
+
+ /**
* Constructs a new TransactionEntry.
*/
- public TransactionEntry() {
+ public TransactionEntry()
+ {
}
/**
* Adds a modification to the modification list.
*/
- public void addModification(MethodCall m) {
+ public void addModification(MethodCall m)
+ {
if (m == null) return;
modification_list.add(m);
}
public void addCacheLoaderModification(MethodCall m)
{
- if (m!=null) cl_mod_list.add(m);
+ if (m != null) cl_mod_list.add(m);
}
/**
* Returns all modifications.
*/
- public List<MethodCall> getModifications() {
+ public List<MethodCall> getModifications()
+ {
return modification_list;
}
@@ -106,40 +120,67 @@
/**
* Adds an undo operation to the undo list.
+ *
* @see #undoOperations
*/
- public void addUndoOperation(MethodCall m) {
+ public void addUndoOperation(MethodCall m)
+ {
undo_list.add(m);
}
/**
+ * Adds the node that has been removed.
+ *
+ * @param fqn
+ */
+ public void addRemovedNode(Fqn fqn)
+ {
+ removedNodes.add(fqn);
+ }
+
+ /**
+ * Gets the list of removed nodes.
+ */
+ public List<Fqn> getRemovedNodes()
+ {
+ return new ArrayList(removedNodes);
+ }
+
+
+ /**
* Returns the undo operations in use.
* Note: This list may be concurrently modified.
*/
- public List getUndoOperations() {
+ public List getUndoOperations()
+ {
return undo_list;
}
/**
* Sets the local transaction for this entry.
*/
- public void setTransaction(Transaction tx) {
- ltx=tx;
+ public void setTransaction(Transaction tx)
+ {
+ ltx = tx;
}
/**
* Returns a local transaction associated with this TransactionEntry
*/
- public Transaction getTransaction() {
+ public Transaction getTransaction()
+ {
return ltx;
}
/**
* Adds a lock to the end of the lock list, if it isn't already present.
*/
- public void addLock(NodeLock l) {
- if(l != null) {
- synchronized(locks) {
+ public void addLock(NodeLock l)
+ {
+ if (l != null)
+ {
+ synchronized (locks)
+ {
locks.add(l);
}
}
@@ -147,11 +188,15 @@
/**
* Add multiple locks to the lock list.
+ *
* @param newLocks Collection<IdentityLock>
*/
- public void addLocks(Collection newLocks) {
- if(newLocks != null) {
- synchronized(locks) {
+ public void addLocks(Collection newLocks)
+ {
+ if (newLocks != null)
+ {
+ synchronized (locks)
+ {
locks.addAll(newLocks);
}
}
@@ -162,8 +207,9 @@
*
* @return a defensive copy of the internal data structure.
*/
- public List getLocks() {
- synchronized(locks)
+ public List getLocks()
+ {
+ synchronized (locks)
{
return new ArrayList(locks);
}
@@ -171,11 +217,14 @@
/**
* Calls {@link #releaseAllLocksFIFO}.
+ *
* @deprecated don't think this is used anymore
*/
- public void releaseAllLocks(Object owner) {
+ public void releaseAllLocks(Object owner)
+ {
releaseAllLocksFIFO(owner);
- synchronized (locks) {
+ synchronized (locks)
+ {
locks.clear();
}
}
@@ -184,13 +233,16 @@
* Releases all locks held by the owner, in reverse order of creation.
* Clears the list of locks held.
*/
- public void releaseAllLocksLIFO(Object owner) {
+ public void releaseAllLocksLIFO(Object owner)
+ {
- synchronized (locks) {
+ synchronized (locks)
+ {
// Copying out to an array is faster than creating an ArrayList and iterating,
// since list creation will just copy out to an array internally
IdentityLock[] lockArray = (IdentityLock[]) locks.toArray(new IdentityLock[locks.size()]);
- for (int i = lockArray.length -1; i >= 0; i--) {
+ for (int i = lockArray.length - 1; i >= 0; i--)
+ {
if (log.isTraceEnabled())
{
log.trace("releasing lock for " + lockArray[i].getFqn() + " (" + lockArray[i] + ")");
@@ -205,12 +257,15 @@
* Releases all locks held by the owner, in order of creation.
* Does not clear the list of locks held.
*/
- public void releaseAllLocksFIFO(Object owner) {
+ public void releaseAllLocksFIFO(Object owner)
+ {
// I guess a copy would work as well
// This seems fairly safe though
- synchronized (locks) {
- for (Iterator i = locks.iterator(); i.hasNext();) {
- IdentityLock lock = (IdentityLock)i.next();
+ synchronized (locks)
+ {
+ for (Iterator i = locks.iterator(); i.hasNext();)
+ {
+ IdentityLock lock = (IdentityLock) i.next();
lock.release(owner);
if (log.isTraceEnabled())
{
@@ -223,27 +278,36 @@
/**
* Posts all undo operations to the TreeCache.
*/
- public void undoOperations(CacheSPI cache) {
+ public void undoOperations(CacheSPI cache)
+ {
if (log.isTraceEnabled())
+ {
log.trace("undoOperations " + undo_list);
+ }
ArrayList l;
- synchronized (undo_list) {
+ synchronized (undo_list)
+ {
l = new ArrayList(undo_list);
}
- for (ListIterator i = l.listIterator(l.size()); i.hasPrevious();) {
- MethodCall undo_op = (MethodCall)i.previous();
+ for (ListIterator i = l.listIterator(l.size()); i.hasPrevious();)
+ {
+ MethodCall undo_op = (MethodCall) i.previous();
undo(undo_op, cache);
}
}
- private void undo(MethodCall undo_op, CacheSPI cache) {
- try {
- Object retval = undo_op.invoke(((TreeCacheProxyImpl)cache).getTreeCache());
+ private void undo(MethodCall undo_op, CacheSPI cache)
+ {
+ try
+ {
+ Object retval = undo_op.invoke(((TreeCacheProxyImpl) cache).getTreeCache());
if (retval instanceof Throwable)
{
- throw (Throwable) retval;
+ throw(Throwable) retval;
+ }
}
- } catch (Throwable t) {
+ catch (Throwable t)
+ {
log.error("undo operation failed, error=" + t);
log.trace(t, t);
}
@@ -252,13 +316,16 @@
/**
* Returns debug information about this transaction.
*/
- public String toString() {
- StringBuffer sb=new StringBuffer();
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
sb.append("\nmodification_list: ").append(modification_list);
- synchronized (undo_list) {
+ synchronized (undo_list)
+ {
sb.append("\nundo_list: ").append(undo_list);
}
- synchronized (locks) {
+ synchronized (locks)
+ {
sb.append("\nlocks: ").append(locks);
}
return sb.toString();
@@ -277,6 +344,7 @@
/**
* Sets a transaction-scope option override
+ *
* @param o
*/
public void setOption(Option o)
1.292 +195 -141 JBossCache/src/org/jboss/cache/TreeCache.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: TreeCache.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/TreeCache.java,v
retrieving revision 1.291
retrieving revision 1.292
diff -u -b -r1.291 -r1.292
--- TreeCache.java 8 Dec 2006 18:49:17 -0000 1.291
+++ TreeCache.java 14 Dec 2006 17:18:47 -0000 1.292
@@ -94,7 +94,7 @@
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
* @author Brian Stansberry
* @author Daniel Huang (dhuang at jboss.org)
- * @version $Id: TreeCache.java,v 1.291 2006/12/08 18:49:17 genman Exp $
+ * @version $Id: TreeCache.java,v 1.292 2006/12/14 17:18:47 msurtani Exp $
* <p/>
* @see <a href="http://labs.jboss.com/portal/jbosscache/docs">JBossCache doc</a>
*/
@@ -110,6 +110,7 @@
* Root DataNode.
*/
protected DataNode root;
+
{
this.rootSpi = new TreeCacheProxyImpl(this);
this.root = NodeFactory.getInstance().createRootDataNode(NodeFactory.NODE_TYPE_TREENODE, this.rootSpi);
@@ -548,8 +549,10 @@
// Yes -- cache is configured LOCAL but app doesn't know it -- Brian
//throw new IllegalArgumentException("Cannot fetch partial state, targets are " + sources + " and stateId is " + stateId);
if (log.isWarnEnabled())
+ {
log.warn("Cannot fetch partial state, targets are " + Arrays.asList(sources) +
" and stateId is " + stateId);
+ }
return;
}
@@ -634,7 +637,7 @@
initialiseCacheLoaderManager();
}
- getRegionManager(); // make sure we create one
+ getRegionManager();// make sure we create one
createEvictionPolicy();
switch (configuration.getCacheMode())
@@ -648,7 +651,7 @@
case INVALIDATION_SYNC:
if (log.isDebugEnabled()) log.debug("cache mode is " + configuration.getCacheMode());
if (channel != null)
- { // already started
+ {// already started
log.info("channel is already running");
return;
}
@@ -657,7 +660,7 @@
channel = getMultiplexerChannel();
if (channel != null)
- { // mux channel
+ {// mux channel
if (log.isDebugEnabled())
{
log.debug("Created Multiplexer Channel for cache cluster " + configuration.getClusterName() +
@@ -681,14 +684,14 @@
channel.setOpt(Channel.AUTO_GETSTATE, true);
channel.setOpt(Channel.BLOCK, true);
-/* Used for JMX jconsole for JDK5.0
+ /* Used for JMX jconsole for JDK5.0
ArrayList servers=MBeanServerFactory.findMBeanServer(null);
if(servers == null || servers.size() == 0) {
throw new Exception("No MBeanServers found;" +
"\nJmxTest needs to be run with an MBeanServer present, or inside JDK 5"); }
MBeanServer server=(MBeanServer)servers.get(0);
JmxConfigurator.registerChannel(channel, server, "JGroups:channel=" + channel.getChannelName() , true);
-*/
+ */
// disp = new InactiveRegionAwareRpcDispatcher(channel, ml, this, this);
disp = new RpcDispatcher(channel, ml, this, this);
disp.setMarshaller(getMarshaller());
@@ -790,7 +793,9 @@
// start any eviction threads.
if (regionManager.isUsingEvictions())
+ {
regionManager.startEvictionThread();
+ }
notifier.notifyCacheStarted(getCacheSPI());
started = true;
@@ -950,7 +955,9 @@
public Address getCoordinator()
{
if (channel == null)
+ {
return null;
+ }
synchronized (members)
{
@@ -1074,7 +1081,7 @@
if (!exists(subtree))
{
- return; // node does not exist. Maybe it has been recursively removed.
+ return;// node does not exist. Maybe it has been recursively removed.
}
if (log.isTraceEnabled())
@@ -1096,7 +1103,7 @@
tmp,
false, // no undo ops
false, // no nodeEvent
- true); // is an eviction
+ true);// is an eviction
}
}
@@ -1260,7 +1267,7 @@
*/
public Map _getData(Fqn fqn)
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null) return null;
return n.getNodeSPI().getRawData();
}
@@ -1293,7 +1300,7 @@
public Set _getKeys(Fqn fqn) throws CacheException
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null)
{
return null;
@@ -1340,7 +1347,7 @@
append(sendNodeEvent).append("\")"));
}
if (sendNodeEvent) notifier.notifyNodeVisited(fqn, true);
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null)
{
log.trace("node not found");
@@ -1378,7 +1385,7 @@
*/
public Node peek(Fqn fqn)
{
- return findInternal(fqn);
+ return findInternal(fqn, true);
}
/**
@@ -1407,7 +1414,7 @@
*/
public boolean exists(Fqn fqn)
{
- Node n = findInternal(fqn);
+ Node n = findInternal(fqn, false);
return n != null;
}
@@ -1416,7 +1423,7 @@
*
* @param fqn
*/
- private Node findInternal(Fqn fqn)
+ private Node findInternal(Fqn fqn, boolean includeNodesMarkedAsRemoved)
{
if (fqn == null || fqn.size() == 0) return root;
Node n = root;
@@ -1429,8 +1436,12 @@
{
return null;
}
+ else if (!includeNodesMarkedAsRemoved && ((DataNode) n).isDeleted())
+ {
+ return null;
}
- return (DataNode) n;
+ }
+ return n;
}
@@ -1454,7 +1465,7 @@
*/
public boolean exists(Fqn fqn, Object key)
{
- Node n = findInternal(fqn);
+ Node n = findInternal(fqn, false);
if (n == null)
{
return false;
@@ -1620,9 +1631,9 @@
* @throws CacheException If node doesn't exist, a NodeNotExistsException is throw. Other exceptions are
* LockingException, TimeoutException and UpgradeException
*/
-// public void lock(Fqn fqn, Object owner, int lock_type, boolean lock_recursive) throws CacheException {
-//
-// }
+ // public void lock(Fqn fqn, Object owner, int lock_type, boolean lock_recursive) throws CacheException {
+ //
+ // }
/**
* Unlock a given node (or the entire subtree starting at this node)
@@ -1632,9 +1643,9 @@
* @param unlock_recursive If true, the entire subtree is unlocked, else only the given node
* @param force Release the lock even if we're not the owner
*/
-// public void unlock(Fqn fqn, Object owner, boolean unlock_recursive, boolean force) {
-//
-// }
+ // public void unlock(Fqn fqn, Object owner, boolean unlock_recursive, boolean force) {
+ //
+ // }
/**
* Releases all locks for this node and the entire node subtree.
@@ -1728,7 +1739,7 @@
public Set _getChildrenNames(Fqn fqn) throws CacheException
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null) return null;
Set s = n.getChildrenNames();
return s;
@@ -1859,7 +1870,7 @@
{
return 0;
}
- int count = 1; // for n
+ int count = 1;// for n
for (Node child : n.getNodeSPI().getChildrenMap().values())
{
count += numNodes(child);
@@ -1886,7 +1897,7 @@
*/
public int getNumberOfAttributes(Fqn fqn)
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
return numAttributes(n);
}
@@ -1990,7 +2001,7 @@
if (mode == GroupRequest.GET_NONE)
{
- return new ArrayList(); // async case
+ return new ArrayList();// async case
}
if (log.isTraceEnabled())
@@ -2101,6 +2112,7 @@
Method method = getClass().getDeclaredMethod(method_name, types);
return callRemoteMethods(members, method, args, synchronous, exclude_self, timeout);
}
+
/* -------------------- End Remote method calls ------------------ */
/* --------------------- Callbacks -------------------------- */
@@ -2224,7 +2236,7 @@
tx_table.addUndoOperation(tx, undo_op);
}
- ((DataNode)n).put(data, (boolean)erase_contents);
+ ((DataNode) n).put(data, (boolean) erase_contents);
notifier.notifyNodeModified(fqn, false, rawData);
@@ -2261,7 +2273,7 @@
log.warn("using a map as a key in a map, did you mean to do that?");
}
- DataNode n = findNodeCheck(tx, fqn);
+ Node n = findNodeCheck(tx, fqn);
Map rawData = n.getNodeSPI().getRawData();
notifier.notifyNodeModified(fqn, true, rawData);
@@ -2342,7 +2354,7 @@
throws CacheException
{
- DataNode n;
+ Node n;
Node parent_node;
MethodCall undo_op = null;
@@ -2351,6 +2363,26 @@
log.trace("_remove(" + tx + ", \"" + fqn + "\", undo=" + create_undo_ops + ")");
}
+ // check if this is triggered by a rollback operation ...
+ if (tx != null)
+ {
+ try
+ {
+ int status = getTransactionManager().getTransaction().getStatus();
+ if (status == Status.STATUS_MARKED_ROLLBACK || status == Status.STATUS_ROLLEDBACK || status == Status.STATUS_ROLLING_BACK)
+ {
+ log.debug("This remove call is triggered by a transaction rollback, as a compensation operation. Do a realRemove() instead.");
+ realRemove(fqn, true);
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ // what do we do here?
+ log.trace("Caught exception dealing with transaction manager", e);
+ }
+ }
+
if (fqn.size() == 0)
{
Set children = getChildrenNames(fqn);
@@ -2398,20 +2430,28 @@
parent_node = n.getParent();
// remove subtree from parent
- parent_node.getNodeSPI().getChildrenMap().remove(n.getName());
+ if (eviction || configuration.isNodeLockingOptimistic())
+ {
+ parent_node.getNodeSPI().getChildrenMap().remove(n.getFqn().getLast());
+ }
+ else
+ {
+ ((DataNode) n).markAsDeleted(true);
+ }
+
if (eviction)
{
parent_node.getNodeSPI().setChildrenLoaded(false);
}
// release all locks for the entire subtree
- n.getNodeSPI().getLock().releaseAll(tx != null ? tx : (Object) Thread.currentThread());
+ // n.getNodeSPI().getLock().releaseAll(tx != null ? tx : (Object) Thread.currentThread());
// create a compensating method call (reverting the effect of
// this modification) and put it into the TX's undo list.
if (tx != null && create_undo_ops && !eviction)
{
- undo_op = MethodCallFactory.create(MethodDeclarations.addChildMethodLocal, tx, parent_node.getFqn(), n.getName(), n, false);
+ undo_op = MethodCallFactory.create(MethodDeclarations.addChildMethodLocal, tx, parent_node.getFqn(), n.getFqn().getLast(), n, false);
// 1. put undo-op in TX' undo-operations list (needed to rollback TX)
tx_table.addUndoOperation(tx, undo_op);
@@ -2450,7 +2490,7 @@
public Object _remove(GlobalTransaction tx, Fqn fqn, Object key, boolean create_undo_ops)
throws CacheException
{
- DataNode n = null;
+ Node n = null;
MethodCall undo_op = null;
Object old_value = null;
@@ -2529,7 +2569,7 @@
public void _removeData(GlobalTransaction tx, Fqn fqn, boolean create_undo_ops, boolean sendNodeEvent, boolean eviction, DataVersion version)
throws CacheException
{
- DataNode n = null;
+ Node n = null;
MethodCall undo_op = null;
if (log.isTraceEnabled())
@@ -2579,7 +2619,7 @@
notifier.notifyNodeVisited(fqn, false);
}
else
- { // FIXME Bela did this so GUI view can refresh the view after node is evicted. But this breaks eviction policy, especially AOP!!!!
+ {// FIXME Bela did this so GUI view can refresh the view after node is evicted. But this breaks eviction policy, especially AOP!!!!
if (eviction)
{
notifier.notifyNodeEvicted(fqn, false);
@@ -2606,7 +2646,7 @@
*/
public void _evict(Fqn fqn) throws CacheException
{
- if (!exists(fqn)) return; // node does not exist. Maybe it has been recursively removed.
+ if (!exists(fqn)) return;// node does not exist. Maybe it has been recursively removed.
// use remove method now if there is a child node. Otherwise, it is removed
boolean create_undo_ops = false;
boolean sendNodeEvent = false;
@@ -2634,7 +2674,7 @@
*/
public void _evict(Fqn fqn, DataVersion version) throws CacheException
{
- if (!exists(fqn)) return; // node does not exist
+ if (!exists(fqn)) return;// node does not exist
boolean create_undo_ops = false;
boolean sendNodeEvent = false;
@@ -2659,13 +2699,13 @@
* @param key
* @throws CacheException
*/
-// public void _evict(Fqn fqn, Object key) throws CacheException {
-// if(!exists(fqn)) return;
-// boolean create_undo_ops = false;
-// boolean sendNodeEvent = false;
-// boolean eviction=true;
-// _removeData(null, fqn, create_undo_ops, sendNodeEvent, eviction);
-// }
+ // public void _evict(Fqn fqn, Object key) throws CacheException {
+ // if(!exists(fqn)) return;
+ // boolean create_undo_ops = false;
+ // boolean sendNodeEvent = false;
+ // boolean eviction=true;
+ // _removeData(null, fqn, create_undo_ops, sendNodeEvent, eviction);
+ // }
/**
@@ -2676,7 +2716,7 @@
{
if (log.isTraceEnabled())
{
- log.trace("_addChild(\"" + parent_fqn +"\", \"" + child_name + "\", node=" + childNode + ")");
+ log.trace("_addChild(\"" + parent_fqn + "\", \"" + child_name + "\", node=" + childNode + ")");
}
if (parent_fqn == null || child_name == null || childNode == null)
@@ -2684,8 +2724,8 @@
log.error("parent_fqn or child_name or childNode was null");
return;
}
- DataNode tmp = findNode(parent_fqn);
- if (tmp == null)
+ DataNode parentNode = (DataNode) findNode(parent_fqn);
+ if (parentNode == null)
{
log.warn("node " + parent_fqn + " not found");
return;
@@ -2693,7 +2733,9 @@
Fqn fqn = new Fqn(parent_fqn, child_name);
notifier.notifyNodeCreated(fqn, true);
- tmp.addChild(child_name, childNode);
+ parentNode.addChild(child_name, childNode);
+
+ childNode.markAsDeleted(false, true);
if (gtx != null && undoOps)
{
@@ -2820,11 +2862,11 @@
// for now, perform a very simple series of getData calls.
- DataNode actualNode = findNode(fqn);
+ Node actualNode = findNode(fqn);
Fqn backupNodeFqn = null;
if (actualNode == null && searchSubtrees)
{
- DataNode backupSubtree = findNode(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
+ Node backupSubtree = findNode(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
if (backupSubtree != null)
{
Map children = backupSubtree.getNodeSPI().getChildrenMap();
@@ -2878,7 +2920,7 @@
NodeData data = new NodeData(BuddyManager.getActualFqn(node.getFqn()), node.getData());
list.add(data);
Map<Object, Node> children = node.getNodeSPI().getChildrenMap();
- for (Node childNode: children.values())
+ for (Node childNode : children.values())
{
getNodeData(list, childNode);
}
@@ -2960,7 +3002,7 @@
*/
public void _releaseAllLocks(Fqn fqn)
{
- DataNode n;
+ Node n;
try
{
@@ -2996,7 +3038,7 @@
{
try
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null) return null;
return n.toString();
}
@@ -3182,13 +3224,13 @@
private void moveFqns(Node node, Fqn newBase)
{
- Fqn newFqn = new Fqn(newBase, ((TreeNode)node).getName());
+ Fqn newFqn = new Fqn(newBase, ((TreeNode) node).getName());
node.getNodeSPI().setFqn(newFqn);
}
class MessageListenerAdaptor implements ExtendedMessageListener
{
- final Log my_log; // Need this to run under jdk1.3
+ final Log my_log;// Need this to run under jdk1.3
final boolean trace;
/**
@@ -3245,13 +3287,13 @@
{
try
{
-// // We use the lock acquisition timeout rather than the
-// // state transfer timeout, otherwise we'd never try
-// // to break locks before the requesting node gives up
-// return cache._getState(Fqn.fromString(SEPARATOR),
-// cache.getLockAcquisitionTimeout(),
-// true,
-// true);
+ // // We use the lock acquisition timeout rather than the
+ // // state transfer timeout, otherwise we'd never try
+ // // to break locks before the requesting node gives up
+ // return cache._getState(Fqn.fromString(SEPARATOR),
+ // cache.getLockAcquisitionTimeout(),
+ // true,
+ // true);
// Until flush is in place, use the old mechanism
// where we wait the full state retrieval timeout
return _getState(Fqn.ROOT, configuration.getInitialStateRetrievalTimeout(), true, true);
@@ -3565,8 +3607,6 @@
/**
* Indicates that a channel has received a BLOCK event from FLUSH protocol.
- *
- *
*/
public void block()
{
@@ -3643,12 +3683,12 @@
Transaction tx;
if ((tx = getLocalTransaction()) == null)
- { // no transaction is associated with the current thread
+ {// 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
+ {// we got a non-null transaction, but it is not active anymore
int status = -1;
try
{
@@ -3717,7 +3757,7 @@
{
if (t instanceof CacheException)
{
- throw (CacheException) t;
+ throw(CacheException) t;
}
throw new RuntimeException(t);
}
@@ -3744,7 +3784,7 @@
* nodes have to be added to the transaction's {@link TransactionEntry}
* field.<br>
* When a lock is acquired on a node, a reference to the lock has to be
- * {@link TransactionEntry#addLock(IdentityLock) added to the list of locked nodes}
+ * {@link TransactionEntry#addLock(org.jboss.cache.lock.NodeLock) added to the list of locked nodes}
* in the {@link TransactionEntry}.
* <p>This operation will also apply different locking to the tree nodes, depending on
* <tt>operation_type</tt>. If it is <tt>read</tt> type, all nodes will be acquired with
@@ -3754,7 +3794,7 @@
* @param fqn Fully qualified name for the corresponding node.
* @return DataNode
*/
- public DataNode findNode(Fqn fqn)
+ public Node findNode(Fqn fqn)
{
try
{
@@ -3767,9 +3807,9 @@
}
}
- private DataNode findNodeCheck(GlobalTransaction tx, Fqn fqn)
+ private Node findNodeCheck(GlobalTransaction tx, Fqn fqn)
{
- DataNode n = findNode(fqn);
+ Node n = findNode(fqn);
if (n == null)
{
String errStr = "node " + fqn + " not found (gtx=" + tx + ", caller=" + Thread.currentThread() + ")";
@@ -3783,36 +3823,49 @@
}
/**
- * Finds a node given a fully qualified name and DataVersion.
+ * Internal method; not to be used externally.
+ *
+ * @param f
*/
- private DataNode findNode(Fqn fqn, DataVersion version) throws CacheException
+ public void realRemove(Fqn f, boolean skipMarkerCheck)
{
- Node n, child_node = null;
- Object child_name;
-
- if (fqn == null) return null;
- DataNode toReturn = null;
- if (fqn.isRoot())
+ DataNode n = (DataNode) findInternal(f, true);
+ if (n == null)
{
- toReturn = root;
+ return;
}
- else
+
+ if (log.isDebugEnabled()) log.debug("Performing a real remove for node " + f + ", marked for removal.");
+ if (skipMarkerCheck || n.isDeleted())
{
- n = root;
- int size = fqn.size();
- for (int i = 0; i < size; i++)
+ if (n.getFqn().isRoot())
{
- child_name = fqn.get(i);
- child_node = n.getNodeSPI().getChildrenMap().get(child_name);
- if (child_node == null)
+ // do not actually delete; just remove deletion marker
+ n.markAsDeleted(false);
+ // but now remove all children, since the call has been to remove("/")
+ n.removeChildren();
+ }
+ else
{
- return null;
+ getInvocationContext().getOptionOverrides().setBypassInterceptorChain(true);
+ n.getParent().removeChild(n.getFqn());
}
- n = child_node;
}
- toReturn = (DataNode) child_node;
+ else
+ {
+ if (log.isDebugEnabled()) log.debug("Node " + f + " NOT marked for removal as expected, not removing!");
+ }
}
+ /**
+ * Finds a node given a fully qualified name and DataVersion.
+ */
+ private Node findNode(Fqn fqn, DataVersion version) throws CacheException
+ {
+ if (fqn == null) return null;
+
+ Node toReturn = findInternal(fqn, false);
+
if (version != null)
{
// we need to check the version of the data node...
@@ -3826,7 +3879,6 @@
// we have a versioning problem; throw an exception!
throw new CacheException("Unable to validate versions.");
}
-
}
return toReturn;
}
@@ -3834,7 +3886,9 @@
public synchronized RegionManager getRegionManager()
{
if (regionManager == null)
+ {
regionManager = new RegionManager(this);
+ }
return regionManager;
}
1.30 +63 -45 JBossCache/src/org/jboss/cache/TreeNode.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: TreeNode.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/TreeNode.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- TreeNode.java 8 Dec 2006 19:03:56 -0000 1.29
+++ TreeNode.java 14 Dec 2006 17:18:47 -0000 1.30
@@ -13,20 +13,20 @@
* hashmap of general data. If the node is created in a replicated cache, the
* relative and fully qualified name, and the keys and values of the hashmap
* must be serializable.
- * <p>
+ * <p/>
* The current version supports different levels of transaction locking such as
* simple locking ({@link org.jboss.cache.lock.IsolationLevel#SERIALIZABLE}, or Read/Write lock with
* upgrade ( {@link org.jboss.cache.lock.IsolationLevel#REPEATABLE_READ}) --that is the read lock will be
* automatically upgraded to write lock when the same owner intends to modify
* the data after read.
- * <p>
+ * <p/>
* Implementations may not necessarily be <em>not</em> synchronized, so access
* to instances of need to be run under an isolation level above NONE.
*
* @author Bela Ban March 25 2003
* @author Ben Wang
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
- * @version $Revision: 1.29 $
+ * @version $Revision: 1.30 $
*/
public interface TreeNode extends Node
@@ -45,6 +45,7 @@
/**
* Puts the contents of a map into this node.
* Optionally erases the existing contents.
+ *
* @param eraseData true to erase the existing contents
*/
void put(Map data, boolean eraseData);
@@ -75,4 +76,21 @@
*/
void addChild(Object child_name, Node n);
+ /**
+ * Tests whether a node has been marked as deleted.
+ */
+ public boolean isDeleted();
+
+ /**
+ * Sets the deletion marker on the node (but not on children)
+ *
+ * @param isDeleted
+ */
+ public void markAsDeleted(boolean isDeleted);
+
+ /**
+ * Sets the deletion marker on the node, with the option to set this on children as well.
+ */
+ public void markAsDeleted(boolean isDeleted, boolean recursive);
+
}
1.23 +27 -1 JBossCache/src/org/jboss/cache/AbstractNode.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: AbstractNode.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/AbstractNode.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- AbstractNode.java 20 Nov 2006 03:53:53 -0000 1.22
+++ AbstractNode.java 14 Dec 2006 17:18:47 -0000 1.23
@@ -3,6 +3,8 @@
*/
package org.jboss.cache;
+import java.util.Map;
+
/**
* Base class for {@link NodeImpl}.
*
@@ -10,4 +12,28 @@
*/
public abstract class AbstractNode implements DataNode, NodeSPI
{
+ protected boolean deleted;
+ protected Map<Object, AbstractNode> children;
+
+ public boolean isDeleted()
+ {
+ return deleted;
+ }
+
+ public void markAsDeleted(boolean marker)
+ {
+ markAsDeleted(marker, false);
+ }
+
+ public void markAsDeleted(boolean marker, boolean recursive)
+ {
+ deleted = marker;
+ if (recursive && children != null)
+ {
+ for (AbstractNode child : children.values())
+ {
+ child.markAsDeleted(marker, true);
+ }
+ }
+ }
}
1.16 +24 -7 JBossCache/src/org/jboss/cache/RegionManager.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: RegionManager.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/RegionManager.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- RegionManager.java 27 Nov 2006 04:49:46 -0000 1.15
+++ RegionManager.java 14 Dec 2006 17:18:47 -0000 1.16
@@ -136,8 +136,10 @@
// first test if the default region has been defined. If not, and if eviction regions
// are in use, throw an exception since it is required.
if (isUsingEvictions() && !regionsRegistry.containsKey(Fqn.ROOT))
+ {
throw new RuntimeException("No default eviction region defined!");
}
+ }
// else try and find a parent which has a defined region, may return null if nothing is defined.
Region r = null;
@@ -262,9 +264,11 @@
r.setActive(true);
// FIXME - persistent state transfer counts too!
if (treeCache.getConfiguration().isFetchInMemoryState())
+ {
activateRegion(r.getFqn().toString());
}
}
+ }
else if (defaultInactive)
{
// "Active" region is not the default, so create a region
@@ -272,9 +276,11 @@
r.setActive(true);
// FIXME - persistent state transfer counts too!
if (treeCache.getConfiguration().isFetchInMemoryState())
+ {
activateRegion(r.getFqn().toString());
}
}
+ }
catch (Exception e)
{
throw new RuntimeException(e);
@@ -302,7 +308,7 @@
Fqn fqn = Fqn.fromString(subtreeFqn);
// Check whether the node already exists and has data
- DataNode subtreeRoot = treeCache.findNode(fqn);
+ Node subtreeRoot = treeCache.findNode(fqn);
/*
* Commented out on Nov 16,2006 Manik&Vladimir
@@ -355,8 +361,10 @@
if (groupMembers.length < 2)
{
if (log.isDebugEnabled())
+ {
log.debug("No nodes able to give state");
}
+ }
else
{
treeCache.fetchPartialState(groupMembers, subtreeRoot.getFqn());
@@ -431,7 +439,7 @@
* managed (either by activate/inactiveRegion()
* or by registerClassLoader())
* @throws CacheException if there is a problem evicting nodes
- * @throws IllegalStateException if {@link Configuration#isUseRegionBasedMarshalling()} is <code>false</code>
+ * @throws IllegalStateException if {@link org.jboss.cache.config.Configuration#isUseRegionBasedMarshalling()} is <code>false</code>
*/
public void inactivateRegion(String subtreeFqn) throws CacheException
{
@@ -623,9 +631,11 @@
// FIXME - we should always clean up; otherwise stale data
// is in memory!
if (treeCache.getConfiguration().isFetchInMemoryState())
+ {
inactivateRegion(fqn.toString());
}
}
+ }
else if (!defaultInactive)
{
region = getRegion(fqn, true);
@@ -633,9 +643,11 @@
// FIXME - we should always clean up; otherwise stale data
// is in memory!
if (treeCache.getConfiguration().isFetchInMemoryState())
+ {
inactivateRegion(fqn.toString());
}
}
+ }
catch (Exception e)
{
throw new RuntimeException(e);
@@ -687,7 +699,9 @@
List<Region> regions = new ArrayList<Region>();
for (Region r : regionsRegistry.values())
+ {
if (r.getEvictionPolicy() != null && evictionTimerTask.isRegionRegisteredForProcessing(r)) regions.add(r);
+ }
Collections.sort(regions);
@@ -726,7 +740,9 @@
if (fqn.equals(DEFAULT_REGION))
{
if (setDefault)
+ {
throw new ConfigurationException("A default region for evictions has already been set for this cache");
+ }
if (log.isTraceEnabled()) log.trace("Applying settings for " + DEFAULT_REGION + " to Fqn.ROOT");
fqn = Fqn.ROOT;
setDefault = true;
@@ -755,7 +771,8 @@
return sb.toString();
}
- public String toString() {
+ public String toString()
+ {
return "RegionManager " + dumpRegions();
}
}
@@ -774,7 +791,7 @@
* @author Ben Wang 02-2004
* @author Daniel Huang (dhuang at jboss.org)
* @author Brian Stansberry
- * @version $Id: RegionManager.java,v 1.15 2006/11/27 04:49:46 genman Exp $
+ * @version $Id: RegionManager.java,v 1.16 2006/12/14 17:18:47 msurtani Exp $
*/
/*public class ERegionManager
{
1.25 +42 -15 JBossCache/src/org/jboss/cache/NodeImpl.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: NodeImpl.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/NodeImpl.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- NodeImpl.java 12 Dec 2006 15:08:05 -0000 1.24
+++ NodeImpl.java 14 Dec 2006 17:18:47 -0000 1.25
@@ -31,7 +31,7 @@
/**
* Basic data node class.
*/
-public class NodeImpl implements DataNode, Node, NodeSPI, Serializable
+public class NodeImpl extends AbstractNode implements Node, Serializable
{
private static final long serialVersionUID = -8200950905894940931L;
@@ -73,11 +73,6 @@
private Fqn fqn;
/**
- * Map of children names to children.
- */
- private Map<Object, Node> children;
-
- /**
* Map of general data keys to values.
*/
private Map data;
@@ -180,12 +175,12 @@
{
if (getFqn().isRoot())
{
- children = new ConcurrentHashMap<Object, Node>(64, .5f, 16);
+ children = new ConcurrentHashMap<Object, AbstractNode>(64, .5f, 16);
}
else
{
// Less segments to save memory
- children = new ConcurrentHashMap<Object, Node>(4, .75f, 4);
+ children = new ConcurrentHashMap<Object, AbstractNode>(4, .75f, 4);
}
}
return children;
@@ -343,19 +338,20 @@
private Node getOrCreateChild(Object child_name, GlobalTransaction gtx, boolean createIfNotExists)
{
- DataNode child;
+
+ NodeImpl child;
if (child_name == null)
{
throw new IllegalArgumentException("null child name");
}
- child = (DataNode) children().get(child_name);
+ child = (NodeImpl) children().get(child_name);
if (createIfNotExists && child == null)
{
// construct the new child outside the synchronized block to avoid
// spending any more time than necessary in the synchronized section
Fqn child_fqn = new Fqn(this.fqn, child_name);
- DataNode newChild = (DataNode) NodeFactory.getInstance().createNode(child_name, child_fqn, this, null, cache);
+ NodeImpl newChild = (NodeImpl) NodeFactory.getInstance().createNode(child_name, child_fqn, this, null, cache);
if (newChild == null)
{
throw new IllegalStateException();
@@ -632,8 +628,25 @@
public void removeChild(Fqn fqn)
{
+ if (cache.getInvocationContext().getOptionOverrides().isBypassInterceptorChain())
+ {
+ if (fqn.size() == 1)
+ {
+ children.remove(fqn.getName());
+ }
+ else
+ {
+ Node c = getChild(fqn);
+ cache.getInvocationContext().getOptionOverrides().setBypassInterceptorChain(true);
+ c.getParent().removeChild(new Fqn(fqn.getName()));
+ }
+ cache.getInvocationContext().getOptionOverrides().setBypassInterceptorChain(false);
+ }
+ else
+ {
cache.removeChild(new Fqn(getFqn(), fqn));
}
+ }
public Map<Object, Node> getChildrenMap()
{
@@ -752,7 +765,7 @@
}
// process children
- for (Map.Entry<Object, Node> me : children.entrySet())
+ for (Map.Entry<Object, AbstractNode> me : children.entrySet())
{
NodeSPI n = me.getValue().getNodeSPI();
Fqn cfqn = new Fqn(fqn, me.getKey());
@@ -780,7 +793,7 @@
public Set<Node> getChildren()
{
- return new ChildrenNodes();
+ return new ChildrenNodes<Node>(false);
}
public synchronized Map<Object, Object> getRawData()
@@ -839,7 +852,9 @@
{
// TODO remove this
if (!dataLoaded && !data().isEmpty())
+ {
log.warn("data exists, but setDataLoaded(false)", new Throwable());
+ }
this.dataLoaded = dataLoaded;
}
@@ -907,8 +922,20 @@
}
- private class ChildrenNodes extends AbstractSet
+ private class ChildrenNodes<T> extends AbstractSet
+ {
+ private boolean includeDeleted;
+
+ public ChildrenNodes(boolean includeDeleted)
{
+ this.includeDeleted = includeDeleted;
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return children != null && children.containsValue(o);
+ }
@Override
public Iterator iterator()
More information about the jboss-cvs-commits
mailing list