Author: manik.surtani(a)jboss.com
Date: 2008-04-04 12:59:53 -0400 (Fri, 04 Apr 2008)
New Revision: 5502
Modified:
core/trunk/src/main/java/org/jboss/cache/AbstractNode.java
core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
core/trunk/src/main/java/org/jboss/cache/optimistic/WorkspaceNodeImpl.java
Log:
JBCACHE-890 : Use an EnumSet to encapsulate the multitude of boolean flags on Nodes
Modified: core/trunk/src/main/java/org/jboss/cache/AbstractNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/AbstractNode.java 2008-04-04 15:43:06 UTC
(rev 5501)
+++ core/trunk/src/main/java/org/jboss/cache/AbstractNode.java 2008-04-04 16:59:53 UTC
(rev 5502)
@@ -3,6 +3,10 @@
*/
package org.jboss.cache;
+import static org.jboss.cache.AbstractNode.NodeFlags.DELETED;
+import static org.jboss.cache.AbstractNode.NodeFlags.RESIDENT;
+
+import java.util.EnumSet;
import java.util.Map;
/**
@@ -12,14 +16,68 @@
*/
public abstract class AbstractNode<K, V>// implements Node<K, V>
{
- protected boolean deleted;
protected Map<Object, Node<K, V>> children;
protected Fqn<?> fqn;
- protected boolean resident;
+ /**
+ * Flags placed on the node. Replaces older 'boolean' flags.
+ */
+ protected EnumSet<NodeFlags> flags = EnumSet.noneOf(NodeFlags.class);
+ /**
+ * These flags were originally stored as booleans on the UnversionedNode class. They
have been replaced with an enum
+ * and an EnumSet, which is much more space-efficient for very little cost in
lookups.
+ */
+ public enum NodeFlags
+ {
+ /**
+ * All children are loaded from the cache loader if this flag is present.
+ */
+ CHILDREN_LOADED,
+ /**
+ * Data is loaded from the cache loader if this flag is present.
+ */
+ DATA_LOADED,
+ /**
+ * Node is write-locked when children are added or removed if this flag is
enabled.
+ */
+ LOCK_FOR_CHILD_INSERT_REMOVE,
+ /**
+ * Node is valid if this flag is present.
+ */
+ VALID,
+ /**
+ * Node has been deleted.
+ */
+ DELETED,
+ /**
+ * NOde is resident and excluded from evictions
+ */
+ RESIDENT,
+ /**
+ * Specific to Optimistic Locking Workspace nodes - set if a node has been modified
in a workspace.
+ */
+ MODIFIED_IN_WORKSPACE,
+ /**
+ * Specific to Optimistic Locking Workspace nodes - set if a node has been created
in a workspace.
+ */
+ CREATED_IN_WORKSPACE,
+ /**
+ * Specific to Optimistic Locking Workspace nodes - set if a node has added or
removed children in a workspace.
+ */
+ CHILDREN_MODIFIED_IN_WORKSPACE,
+ /**
+ * Specific to Optimistic Locking Workspace nodes - set if an implicit version is
associated with this node.
+ */
+ VERSIONING_IMPLICIT,
+ /**
+ * Specific to Optimistic Locking Workspace nodes - set if a node has been
resurrected in a workspace.
+ */
+ RESURRECTED_IN_WORKSPACE
+ }
+
public boolean isDeleted()
{
- return deleted;
+ return flags.contains(DELETED);
}
public void markAsDeleted(boolean marker)
@@ -29,7 +87,8 @@
public void markAsDeleted(boolean marker, boolean recursive)
{
- deleted = marker;
+ setFlag(DELETED, marker);
+
if (recursive && children != null)
{
synchronized (this)
@@ -44,16 +103,16 @@
public void setResident(boolean resident)
{
- this.resident = resident;
+ setFlag(RESIDENT, resident);
}
public boolean isResident()
{
- return resident;
+ return flags.contains(RESIDENT);
}
-
+ @Override
public boolean equals(Object another)
{
if (another instanceof AbstractNode)
@@ -64,9 +123,24 @@
return false;
}
-
+ @Override
public int hashCode()
{
return fqn.hashCode();
}
+
+ /**
+ * Utility method for setting or unsetting a flag. If status is true, the NodeFlag
specified is added to the {@link #flags}
+ * EnumSet. If status is false, the NodeFlag is removed from the EnumSet.
+ *
+ * @param flag flag to set or unset
+ * @param status true to set the flag, false to unset the flag.
+ */
+ protected void setFlag(NodeFlags flag, boolean status)
+ {
+ if (status)
+ flags.add(flag);
+ else
+ flags.remove(flag);
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-04-04 15:43:06 UTC
(rev 5501)
+++ core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-04-04 16:59:53 UTC
(rev 5502)
@@ -8,6 +8,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import static org.jboss.cache.AbstractNode.NodeFlags.*;
import org.jboss.cache.factories.annotations.CacheInjectionMethods;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.lock.IdentityLock;
@@ -43,16 +44,6 @@
protected static boolean trace = log.isTraceEnabled();
/**
- * True if all children have been loaded. This is set when
CacheImpl.getChildrenNames() is called.
- */
- private boolean childrenLoaded = false;
-
- /**
- * True if data has been loaded from the cache loader.
- */
- private boolean dataLoaded = true;
-
- /**
* Lock manager that manages locks to be acquired when accessing the node inside a
transaction. Lazy set just in case
* locking is not needed.
*/
@@ -69,13 +60,6 @@
*/
private final Map data = new HashMap();
- private boolean lockForChildInsertRemove;
-
- /**
- * Node moved or removed.
- */
- private boolean valid = true;
-
private NodeSPI delegate;
/**
@@ -84,6 +68,7 @@
public UnversionedNode()
{
this.fqn = Fqn.ROOT;
+ initFlags();
}
/**
@@ -95,10 +80,17 @@
*/
protected UnversionedNode(Object child_name, Fqn fqn, Map data, boolean mapSafe,
CacheSPI cache)
{
+ initFlags();
init(child_name, fqn, cache);
setInternalState(data);
}
+ protected void initFlags()
+ {
+ flags.add(DATA_LOADED);
+ flags.add(VALID);
+ }
+
public NodeSPI getDelegate()
{
return delegate;
@@ -131,7 +123,8 @@
{
throw new IllegalArgumentException("Child " + child_name + " must
be last part of " + fqn);
}
- lockForChildInsertRemove =
cache.getConfiguration().isLockParentForChildInsertRemove();
+
+
setLockForChildInsertRemove(cache.getConfiguration().isLockParentForChildInsertRemove());
}
/**
@@ -178,17 +171,17 @@
public boolean isChildrenLoaded()
{
- return childrenLoaded;
+ return flags.contains(CHILDREN_LOADED);
}
- public void setChildrenLoaded(boolean flag)
+ public void setChildrenLoaded(boolean childrenLoaded)
{
- childrenLoaded = flag;
+ setFlag(CHILDREN_LOADED, childrenLoaded);
}
private void assertValid()
{
- if (!valid)
+ if (!isValid())
throw new NodeNotValidException("Node " + getFqn() + " is not
valid. Perhaps it has been moved or removed.");
}
@@ -324,9 +317,9 @@
{
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
- if (!valid) sb.append(" (INVALID!) ");
+ if (!isValid()) sb.append(" (INVALID!) ");
- if (deleted)
+ if (isDeleted())
{
sb.append(" (deleted) [ ").append(fqn);
}
@@ -690,7 +683,7 @@
*/
public boolean isDataLoaded()
{
- return dataLoaded;
+ return flags.contains(DATA_LOADED);
}
/**
@@ -698,17 +691,18 @@
*/
public void setDataLoaded(boolean dataLoaded)
{
- this.dataLoaded = dataLoaded;
+ setFlag(DATA_LOADED, dataLoaded);
}
public boolean isValid()
{
- return valid;
+ return flags.contains(VALID);
}
public void setValid(boolean valid, boolean recursive)
{
- this.valid = valid;
+ setFlag(VALID, valid);
+
if (trace) log.trace("Marking node " + getFqn() + " as " +
(valid ? "" : "in") + "valid");
if (recursive)
{
@@ -721,12 +715,12 @@
public boolean isLockForChildInsertRemove()
{
- return lockForChildInsertRemove;
+ return flags.contains(LOCK_FOR_CHILD_INSERT_REMOVE);
}
public void setLockForChildInsertRemove(boolean lockForChildInsertRemove)
{
- this.lockForChildInsertRemove = lockForChildInsertRemove;
+ setFlag(LOCK_FOR_CHILD_INSERT_REMOVE, lockForChildInsertRemove);
}
public void setInternalState(Map state)
Modified: core/trunk/src/main/java/org/jboss/cache/optimistic/WorkspaceNodeImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/optimistic/WorkspaceNodeImpl.java 2008-04-04
15:43:06 UTC (rev 5501)
+++ core/trunk/src/main/java/org/jboss/cache/optimistic/WorkspaceNodeImpl.java 2008-04-04
16:59:53 UTC (rev 5502)
@@ -9,6 +9,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.AbstractNode;
+import static org.jboss.cache.AbstractNode.NodeFlags.*;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
@@ -40,26 +41,11 @@
private NodeSPI<K, V> node;
private TransactionWorkspace workspace;
private DataVersion version = DefaultDataVersion.ZERO;
- private boolean modified;
- private boolean created;
- private boolean childrenModified;
private Map<Object, NodeSPI<K, V>> optimisticChildNodeMap;
- private Set<Fqn> childrenAdded;// = new HashSet<Fqn>();
- private Set<Fqn> childrenRemoved;// = new HashSet<Fqn>();
+ private Set<Fqn> childrenAdded;
+ private Set<Fqn> childrenRemoved;
private Map<K, V> optimisticDataMap;
- private boolean versioningImplicit = true; // default
- private boolean resurrected = false;
- // the following boolean attributes are encoded as bits in a byte:
- // modified: attr & 1 (2 ^ 0)
- // created: attr & 2 (2 ^ 1)
- // childrenModified: attr & 4 (2 ^ 2)
- // versioningImplicit: attr & 8 (2 ^ 3)
- // resurrected: attr & 16 (2 ^ 4)
-
- // versioningImplicit is enabled by default.
- //private byte attr = 8;
-
/**
* Constructs with a node and workspace.
*/
@@ -81,6 +67,11 @@
}
}
+ protected void initFlags()
+ {
+ flags.add(VERSIONING_IMPLICIT);
+ }
+
protected Set<Fqn> getChildrenAddedSet()
{
if (childrenAdded == null) childrenAdded = new HashSet<Fqn>();
@@ -95,7 +86,7 @@
public boolean isChildrenModified()
{
- return childrenModified;
+ return flags.contains(CHILDREN_MODIFIED_IN_WORKSPACE);
}
public boolean isChildrenLoaded()
@@ -105,12 +96,12 @@
public boolean isResurrected()
{
- return resurrected;
+ return flags.contains(RESURRECTED_IN_WORKSPACE);
}
public void markAsResurrected(boolean resurrected)
{
- this.resurrected = resurrected;
+ setFlag(RESURRECTED_IN_WORKSPACE, resurrected);
}
@Override
@@ -129,7 +120,7 @@
*/
public boolean isModified()
{
- return modified;
+ return flags.contains(MODIFIED_IN_WORKSPACE);
}
/**
@@ -139,7 +130,7 @@
*/
public boolean isDirty()
{
- return modified || created || deleted;
+ return isModified() || isCreated() || isDeleted();
}
public Fqn getFqn()
@@ -150,7 +141,7 @@
public void putAll(Map<K, V> data)
{
realPut(data, false);
- modified = true;
+ setFlag(MODIFIED_IN_WORKSPACE, true);
}
public void replaceAll(Map<K, V> data)
@@ -161,7 +152,7 @@
public V put(K key, V value)
{
- modified = true;
+ setFlag(MODIFIED_IN_WORKSPACE, true);
if (optimisticDataMap == null) optimisticDataMap = new HashMap<K, V>();
return optimisticDataMap.put(key, value);
@@ -169,7 +160,7 @@
public V remove(K key)
{
- modified = true;
+ setFlag(MODIFIED_IN_WORKSPACE, true);
if (optimisticDataMap == null) return null;
return optimisticDataMap.remove(key);
@@ -217,7 +208,7 @@
private void realPut(Map<K, V> data, boolean eraseData, boolean forceDirtyFlag)
{
- if (forceDirtyFlag) modified = true;
+ if (forceDirtyFlag) setFlag(MODIFIED_IN_WORKSPACE, true);
if (eraseData && optimisticDataMap != null)
{
optimisticDataMap.clear();
@@ -246,18 +237,18 @@
NodeSPI<K, V> child = (NodeSPI<K, V>) factory.createNodeOfType(parent,
child_name, parent, null);
getChildrenAddedSet().add(child.getFqn());
if (childrenRemoved != null) childrenRemoved.remove(child.getFqn());
- childrenModified = true;
+ setFlag(CHILDREN_MODIFIED_IN_WORKSPACE, true);
return child;
}
public boolean isVersioningImplicit()
{
- return versioningImplicit;
+ return flags.contains(VERSIONING_IMPLICIT);
}
- public void setVersioningImplicit(boolean b)
+ public void setVersioningImplicit(boolean versioningImplicit)
{
- versioningImplicit = b;
+ setFlag(VERSIONING_IMPLICIT, versioningImplicit);
}
public NodeSPI<K, V> getChild(Object childName)
@@ -313,12 +304,12 @@
public boolean isCreated()
{
- return created;
+ return flags.contains(CREATED_IN_WORKSPACE);
}
public void markAsCreated()
{
- created = true;
+ setFlag(CREATED_IN_WORKSPACE, true);
// created != modified!!!
}
@@ -337,10 +328,10 @@
public String toString()
{
StringBuffer sb = new StringBuffer();
- if (deleted) sb.append("del ");
- if (modified) sb.append("modified ");
- if (created) sb.append("new ");
- return getClass().getSimpleName() + " [ fqn=" + getFqn() + " "
+ sb + "ver=" + version + " " + (versioningImplicit ?
"implicit" : "explicit") + "]";
+ if (isDeleted()) sb.append("del ");
+ if (isModified()) sb.append("modified ");
+ if (isCreated()) sb.append("new ");
+ return getClass().getSimpleName() + " [ fqn=" + getFqn() + " "
+ sb + "ver=" + version + " " + (isVersioningImplicit() ?
"implicit" : "explicit") + "]";
}
public Node<K, V> addChild(Fqn f)
@@ -392,7 +383,7 @@
if (optimisticDataMap != null)
{
optimisticDataMap.clear();
- modified = true;
+ setFlag(MODIFIED_IN_WORKSPACE, true);
}
}
@@ -480,7 +471,7 @@
{*/
getChildrenRemovedSet().add(childFqn);
if (childrenAdded != null) childrenAdded.remove(childFqn);
- childrenModified = true;
+ setFlag(CHILDREN_MODIFIED_IN_WORKSPACE, true);
return node.getChildDirect(childName) != null;
/*}
else