Author: manik.surtani(a)jboss.com
Date: 2008-10-07 12:22:07 -0400 (Tue, 07 Oct 2008)
New Revision: 6854
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/DataContainer.java
core/branches/flat/src/main/java/org/jboss/starobrno/UnsortedDataContainer.java
core/branches/flat/src/main/java/org/jboss/starobrno/context/
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContext.java
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryReference.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/MVCCEntry.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/NullMarkerEntry.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/ReadCommittedEntry.java
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/RepeatableReadEntry.java
Log:
Another pint of Starobrno
Added: core/branches/flat/src/main/java/org/jboss/starobrno/DataContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/DataContainer.java
(rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/DataContainer.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.starobrno;
+
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public interface DataContainer<K, V>
+{
+ Set<Entry<K, V>> getEntries();
+
+ Entry<K, V> getEntry(K k);
+
+ void putEntry(Entry<K, V> entry);
+
+ boolean exists(Entry<K, V> entry);
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/UnsortedDataContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/UnsortedDataContainer.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/UnsortedDataContainer.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.starobrno;
+
+import java.util.LinkedHashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * // TODO: crappy and inefficient - but just a placeholder for now.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class UnsortedDataContainer<K, V> implements DataContainer<K, V>
+{
+ Set<Entry<K, V>> entries = new LinkedHashSet<Entry<K, V>>();
+
+ public Set<Entry<K, V>> getEntries()
+ {
+ return entries;
+ }
+
+ public Entry<K, V> getEntry(K k)
+ {
+ if (k == null) throw new NullPointerException("I don't like
nulls!");
+ for (Entry<K, V> e : entries)
+ {
+ if (k.equals(e.getKey())) return e;
+ }
+ return null;
+ }
+
+ public void putEntry(Entry<K, V> kvEntry)
+ {
+ entries.add(kvEntry);
+ }
+
+ public boolean exists(Entry<K, V> kvEntry)
+ {
+ return getEntry(kvEntry.getKey()) != null;
+ }
+}
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContext.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContext.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContext.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt 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.context;
+
+import org.jboss.cache.commands.VisitableCommand;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.transaction.TransactionContext;
+import org.jboss.starobrno.mvcc.MVCCEntry;
+
+import javax.transaction.Transaction;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public interface InvocationContext
+{
+ MVCCEntry lookupEntry(Object key);
+
+ Map<Object, MVCCEntry> getLookedUpEntries();
+
+ void putLookedUpEntry(MVCCEntry e);
+
+ void putLookedUpEntries(Set<MVCCEntry> lookedUpEntries);
+
+ void clearLookedUpEntries();
+
+ void setLocalRollbackOnly(boolean localRollbackOnly);
+
+ Transaction getTransaction();
+
+ void setTransaction(Transaction transaction);
+
+ TransactionContext getTransactionContext();
+
+ void setTransactionContext(TransactionContext transactionContext);
+
+ GlobalTransaction getGlobalTransaction();
+
+ void setGlobalTransaction(GlobalTransaction globalTransaction);
+
+ Option getOptionOverrides();
+
+ boolean isOptionsUninitialised();
+
+ void setOptionOverrides(Option optionOverrides);
+
+ boolean isOriginLocal();
+
+ List<Object> getKeysLocked();
+
+ void addAllKeysLocked(List<Object> keysLocked);
+
+ void addKeyLocked(Object keyLocked);
+
+ void removeKeyLocked(Object keyLocked);
+
+ void clearKeysLocked();
+
+ boolean hasLockedKey(Object key);
+
+ boolean isLockingSuppressed();
+
+ void setOriginLocal(boolean originLocal);
+
+ boolean isLocalRollbackOnly();
+
+ void reset();
+
+ InvocationContext copy();
+
+ void setState(InvocationContext template);
+
+ long getLockAcquisitionTimeout(long timeout);
+
+ void setCommand(VisitableCommand cacheCommand);
+
+ VisitableCommand getCommand();
+
+ boolean isValidTransaction();
+
+ void throwIfNeeded(Throwable e) throws Throwable;
+}
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java
===================================================================
---
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/context/InvocationContextImpl.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,619 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt 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.context;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.commands.VisitableCommand;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.marshall.MethodCall;
+import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.transaction.TransactionContext;
+import org.jboss.cache.transaction.TransactionTable;
+import org.jboss.cache.util.Immutables;
+import org.jboss.starobrno.mvcc.MVCCEntry;
+
+import javax.transaction.Transaction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class InvocationContextImpl implements InvocationContext
+{
+ private static final Log log = LogFactory.getLog(InvocationContext.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ private Transaction transaction;
+ private GlobalTransaction globalTransaction;
+ protected TransactionContext transactionContext;
+ private Option optionOverrides;
+ // defaults to true.
+ private boolean originLocal = true;
+ private boolean localRollbackOnly;
+ @Deprecated
+ private MethodCall methodCall;
+ @Deprecated
+ private VisitableCommand command;
+
+ /**
+ * LinkedHashSet of locks acquired by the invocation. We use a LinkedHashSet because
we need efficient Set semantics
+ * but also need guaranteed ordering for use by lock release code (see JBCCACHE-874).
+ * <p/>
+ * This needs to be unchecked since we support both MVCC (Fqns held here) or legacy
Opt/Pess locking (NodeLocks held here).
+ * once we drop support for opt/pess locks we can genericise this to contain Fqns. -
Manik Surtani, June 2008
+ */
+ protected LinkedHashSet<Object> invocationLocks;
+ private HashMap<Object, MVCCEntry> lookedUpEntries = null;
+
+ /**
+ * Retrieves a node from the registry of looked up nodes in the current scope.
+ * <p/>
+ * If a transaction is in progress, implementations should delegate to {@link
org.jboss.cache.transaction.MVCCTransactionContext#lookUpNode(Fqn)}
+ * <p/>
+ *
+ * @param fqn fqn to look up
+ * @return a node, or null if it cannot be found.
+ */
+ public MVCCEntry lookupEntry(Object k)
+ {
+ // TODO: Fix this after we have a Transaction context that works.
+// if (transactionContext != null) return transactionContext.lookupEntry(k);
+// return lookedUpEntries == null ? null : lookedUpEntries.get(k);
+ return null;
+ }
+
+ /**
+ * Puts an entry in the registry of looked up nodes in the current scope.
+ * <p/>
+ * If a transaction is in progress, implementations should delegate to {@link
org.jboss.cache.transaction.MVCCTransactionContext#putLookedUpNode(Fqn, NodeSPI)}
+ * <p/>
+ *
+ * @param f fqn to add
+ * @param n node to add
+ */
+ public void putLookedUpEntry(MVCCEntry e)
+ {
+ // TODO: Fix this after we have a Transaction context that works.
+
+// if (transactionContext != null)
+// transactionContext.putLookedUpEntry(e);
+// else
+// {
+// if (lookedUpEntries == null) lookedUpEntries = new HashMap<Object,
MVCCEntry>(4);
+// lookedUpEntries.put(e.getKey(), e);
+// }
+ }
+
+ public void putLookedUpEntries(Set<MVCCEntry> lookedUpEntries)
+ {
+ // TODO: Fix this after we have a Transaction context that works.
+// if (transactionContext != null)
+// transactionContext.putLookedUpEntries(lookedUpEntries);
+// else
+// {
+// if (this.lookedUpEntries == null)
+// this.lookedUpEntries = new HashMap<Object, MVCCEntry>();
+//
+// for (MVCCEntry e: lookedUpEntries) this.lookedUpEntries.put(e.getKey(), e);
+// }
+ }
+
+ /**
+ * Clears the registry of looked up nodes.
+ * <p/>
+ * If a transaction is in progress, implementations should delegate to {@link
org.jboss.cache.transaction.MVCCTransactionContext#clearLookedUpNodes()}.
+ */
+ public void clearLookedUpEntries()
+ {
+ // TODO: see if we can reinstate common behaviour once we have the ICI calling
ctx.reset() instead of ctx.clearLookedUpNodes()
+// if (transactionContext != null)
+// transactionContext.clearLookedUpNodes();
+// else
+
+ if (lookedUpEntries != null) lookedUpEntries.clear();
+ }
+
+ /**
+ * Retrieves a map of nodes looked up within the current invocation's scope.
+ * <p/>
+ * If a transaction is in progress, implementations should delegate to {@link
org.jboss.cache.transaction.MVCCTransactionContext#getLookedUpNodes()}.
+ * <p/>
+ *
+ * @return a map of looked up nodes.
+ */
+ @SuppressWarnings("unchecked")
+ public Map<Object, MVCCEntry> getLookedUpEntries()
+ {
+ // TODO: Fix this after we have a Transaction context that works.
+// if (transactionContext != null) return transactionContext.getLookedUpNodes();
+// return (Map<Fqn, NodeSPI>) (lookedUpEntries == null ?
Collections.emptyMap() : lookedUpEntries);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public InvocationContext copy()
+ {
+ InvocationContextImpl copy = new InvocationContextImpl();
+ doCopy(copy);
+ if (lookedUpEntries != null) copy.lookedUpEntries = (HashMap<Object,
MVCCEntry>) lookedUpEntries.clone();
+ return copy;
+ }
+
+
+ /**
+ * Marks teh context as only rolling back.
+ *
+ * @param localRollbackOnly if true, the context is only rolling back.
+ */
+ public void setLocalRollbackOnly(boolean localRollbackOnly)
+ {
+ this.localRollbackOnly = localRollbackOnly;
+ }
+
+ /**
+ * Retrieves the transaction associated with this invocation
+ *
+ * @return The transaction associated with this invocation
+ */
+ public Transaction getTransaction()
+ {
+ return transaction;
+ }
+
+ /**
+ * Sets a transaction object on the invocation context.
+ *
+ * @param transaction transaction to set
+ */
+ public void setTransaction(Transaction transaction)
+ {
+ this.transaction = transaction;
+ }
+
+ /**
+ * @return the transaction entry associated with the current transaction, or null if
the current thread is not associated with a transaction.
+ * @since 2.2.0
+ */
+ public TransactionContext getTransactionContext()
+ {
+ return transactionContext;
+ }
+
+ /**
+ * Sets the transaction context to be associated with the current thread.
+ *
+ * @param transactionContext transaction context to set
+ * @since 2.2.0
+ */
+ public void setTransactionContext(TransactionContext transactionContext)
+ {
+ this.transactionContext = transactionContext;
+ }
+
+ /**
+ * Retrieves the global transaction associated with this invocation
+ *
+ * @return the global transaction associated with this invocation
+ */
+ public GlobalTransaction getGlobalTransaction()
+ {
+ return globalTransaction;
+ }
+
+ /**
+ * Sets the global transaction associated with this invocation
+ *
+ * @param globalTransaction global transaction to set
+ */
+ public void setGlobalTransaction(GlobalTransaction globalTransaction)
+ {
+ this.globalTransaction = globalTransaction;
+ }
+
+
+ /**
+ * Retrieves the option overrides associated with this invocation
+ *
+ * @return the option overrides associated with this invocation
+ */
+ public Option getOptionOverrides()
+ {
+ if (optionOverrides == null)
+ {
+ optionOverrides = new Option();
+ }
+ return optionOverrides;
+ }
+
+ /**
+ * @return true of no options have been set on this context, false otherwise.
+ */
+ public boolean isOptionsUninitialised()
+ {
+ return optionOverrides == null;
+ }
+
+ /**
+ * Sets the option overrides to be associated with this invocation
+ *
+ * @param optionOverrides options to set
+ */
+ public void setOptionOverrides(Option optionOverrides)
+ {
+ this.optionOverrides = optionOverrides;
+ }
+
+ /**
+ * Tests if this invocation originated locally or from a remote cache.
+ *
+ * @return true if the invocation originated locally.
+ */
+ public boolean isOriginLocal()
+ {
+ return originLocal;
+ }
+
+ /**
+ * Returns an immutable, defensive copy of the List of locks currently maintained for
the current scope.
+ * <p/>
+ * Note that if a transaction is in scope, implementations should retrieve these locks
from the {@link org.jboss.cache.transaction.TransactionContext}.
+ * Retrieving locks from this method should always ensure they are retrieved from the
appropriate scope.
+ * <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.
+ */
+ @SuppressWarnings("unchecked")
+ public List getKeysLocked()
+ {
+ // first check transactional scope
+ if (transactionContext != null) return transactionContext.getLocks();
+ return invocationLocks == null || invocationLocks.isEmpty() ?
Collections.emptyList() : Immutables.immutableListConvert(invocationLocks);
+ }
+
+ /**
+ * Adds a List of locks to the currently maintained collection of locks acquired.
+ * <p/>
+ * Note that if a transaction is in scope, implementations should record locks on the
{@link org.jboss.cache.transaction.TransactionContext}.
+ * Adding locks using this method should always ensure they are applied to the
appropriate scope.
+ * <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 locks locks to add
+ */
+ @SuppressWarnings("unchecked")
+ public void addAllKeysLocked(List locks)
+ {
+ // first check transactional scope
+ if (transactionContext != null)
+ {
+ transactionContext.addAllLocks(locks);
+ }
+ else
+ {
+ // no need to worry about concurrency here - a context is only valid for a
single thread.
+ if (invocationLocks == null) invocationLocks = new LinkedHashSet(4);
+ invocationLocks.addAll(locks);
+ }
+ }
+
+ /**
+ * Adds a lock to the currently maintained collection of locks acquired.
+ * <p/>
+ * Note that if a transaction is in scope, implementations should record this lock on
the {@link org.jboss.cache.transaction.TransactionContext}.
+ * Using this method should always ensure that the appropriate scope is used.
+ * <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 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 Fqn}.
+ *
+ * @param lock lock to add
+ */
+ @SuppressWarnings("unchecked")
+ public void addKeyLocked(Object lock)
+ {
+ // first check transactional scope
+ if (transactionContext != null)
+ {
+ transactionContext.addLock(lock);
+ }
+ else
+ {
+ // no need to worry about concurrency here - a context is only valid for a
single thread.
+ if (invocationLocks == null) invocationLocks = new LinkedHashSet(4);
+ invocationLocks.add(lock);
+ }
+ }
+
+ /**
+ * Removes a lock from the currently maintained collection of locks acquired.
+ * <p/>
+ * Note that if a transaction is in scope, implementations should remove this lock
from the {@link org.jboss.cache.transaction.TransactionContext}.
+ * Using this method should always ensure that the lock is removed from the
appropriate scope.
+ * <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 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 Fqn}.
+ *
+ * @param lock lock to remove
+ */
+ @SuppressWarnings("unchecked")
+ public void removeKeyLocked(Object lock)
+ {
+ // first check transactional scope
+ if (transactionContext != null)
+ {
+ transactionContext.removeLock(lock);
+ }
+ else
+ {
+ // no need to worry about concurrency here - a context is only valid for a
single thread.
+ if (invocationLocks != null) invocationLocks.remove(lock);
+ }
+ }
+
+ /**
+ * Clears all locks from the currently maintained collection of locks acquired.
+ * <p/>
+ * Note that if a transaction is in scope, implementations should clear locks from the
{@link org.jboss.cache.transaction.TransactionContext}.
+ * Using this method should always ensure locks are cleared in the appropriate scope.
+ * <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 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 Fqn}.
+ */
+ public void clearKeysLocked()
+ {
+ // first check transactional scope
+ if (transactionContext != null)
+ {
+ transactionContext.clearLocks();
+ }
+ else
+ {
+ // no need to worry about concurrency here - a context is only valid for a
single thread.
+ if (invocationLocks != null) invocationLocks.clear();
+ }
+ }
+
+ /**
+ * Note that if a transaction is in scope, implementations should test this lock from
on {@link org.jboss.cache.transaction.TransactionContext}.
+ * Using this method should always ensure locks checked in the appropriate scope.
+ *
+ * @param lock lock to test
+ * @return true if the lock being tested is already held in the current scope, false
otherwise.
+ */
+ public boolean hasLockedKey(Object lock)
+ {
+ // first check transactional scope
+ if (transactionContext != null)
+ {
+ return transactionContext.hasLock(lock);
+ }
+ else
+ {
+ return invocationLocks != null && invocationLocks.contains(lock);
+ }
+ }
+
+ /**
+ * @return true if options exist to suppress locking - false otherwise. Note that
this is only used by the {@link org.jboss.cache.interceptors.PessimisticLockInterceptor}.
+ */
+ public boolean isLockingSuppressed()
+ {
+ return getOptionOverrides() != null &&
getOptionOverrides().isSuppressLocking();
+ }
+
+ /**
+ * If set to true, the invocation is assumed to have originated locally. If set to
false,
+ * assumed to have originated from a remote cache.
+ *
+ * @param originLocal flag to set
+ */
+ public void setOriginLocal(boolean originLocal)
+ {
+ this.originLocal = originLocal;
+ }
+
+ /**
+ * @return true if the current transaction is set to rollback only.
+ */
+ public boolean isLocalRollbackOnly()
+ {
+ return localRollbackOnly;
+ }
+
+ /**
+ * Resets the context, freeing up any references.
+ */
+ public void reset()
+ {
+ transaction = null;
+ globalTransaction = null;
+ optionOverrides = null;
+ originLocal = true;
+ invocationLocks = null;
+ methodCall = null;
+ command = null;
+ if (lookedUpEntries != null)
+ {
+ lookedUpEntries.clear();
+ lookedUpEntries = null;
+ }
+ }
+
+ /**
+ * Sets the state of the InvocationContext based on the template context passed in
+ *
+ * @param template template to copy from
+ */
+ public void setState(InvocationContext template)
+ {
+ if (template == null)
+ {
+ throw new NullPointerException("Template InvocationContext passed in to
InvocationContext.setState() passed in is null");
+ }
+
+ this.setGlobalTransaction(template.getGlobalTransaction());
+ this.setLocalRollbackOnly(template.isLocalRollbackOnly());
+ this.setOptionOverrides(template.getOptionOverrides());
+ this.setOriginLocal(template.isOriginLocal());
+ this.setTransaction(template.getTransaction());
+ }
+
+ /**
+ * @return the method call associated with this invocation
+ */
+ @Deprecated
+ @SuppressWarnings("deprecation")
+ public MethodCall getMethodCall()
+ {
+ if (methodCall == null)
+ {
+ methodCall = createMethodCall();
+ }
+ return methodCall;
+ }
+
+ @SuppressWarnings("deprecation")
+ private MethodCall createMethodCall()
+ {
+ if (command == null) return null;
+ MethodCall call = new MethodCall();
+ call.setMethodId(command.getCommandId());
+ call.setArgs(command.getParameters());
+ return call;
+ }
+
+ /**
+ * Sets the method call associated with this invocation.
+ *
+ * @param methodCall methodcall to set
+ * @deprecated not used anymore. Interceptors will get a {@link
org.jboss.cache.commands.ReplicableCommand} instance passed in along with an
InvocationContext.
+ */
+ @Deprecated
+ public void setMethodCall(MethodCall methodCall)
+ {
+ this.methodCall = methodCall;
+ }
+
+ /**
+ * If the lock acquisition timeout is overridden for current call using an option,
then return that one.
+ * If not overridden, return default value.
+ *
+ * @param timeout timeout to fall back to
+ * @return timeout to use
+ */
+ public long getLockAcquisitionTimeout(long timeout)
+ {
+ // TODO: this stuff really doesn't belong here. Put it somewhere else.
+ if (getOptionOverrides() != null
+ && getOptionOverrides().getLockAcquisitionTimeout() >= 0)
+ {
+ timeout = getOptionOverrides().getLockAcquisitionTimeout();
+ }
+ return timeout;
+ }
+
+ /**
+ * This is only used for backward compatibility with old interceptors implementation
and should <b>NOT</b> be
+ * use by any new custom interceptors. The commands is now passed in as the second
param in each implementing
+ * handlers (handler = method in ChainedInterceptor class)
+ *
+ * @param cacheCommand command to set
+ */
+ @Deprecated
+ @SuppressWarnings("deprecation")
+ public void setCommand(VisitableCommand cacheCommand)
+ {
+ this.command = cacheCommand;
+ }
+
+ /**
+ * @return command that is in scope
+ * @see #setCommand(org.jboss.cache.commands.VisitableCommand)
+ */
+ @Deprecated
+ @SuppressWarnings("deprecation")
+ public VisitableCommand getCommand()
+ {
+ return command;
+ }
+
+ /**
+ * @return true if there is current transaction associated with the invocation, and
this transaction is in a valid state.
+ */
+ public boolean isValidTransaction()
+ {
+ // ought to move to the transaction context
+ return transaction != null && TransactionTable.isValid(transaction);
+ }
+
+ /**
+ * Throws the given throwable provided no options suppress or prevent this from
happening.
+ *
+ * @param e throwable to throw
+ * @throws Throwable if allowed to throw one.
+ */
+ public void throwIfNeeded(Throwable e) throws Throwable
+ {
+ // TODO: this stuff really doesn't belong here. Put it somewhere else.
+ Option optionOverride = getOptionOverrides();
+ boolean shouldRethtrow = optionOverride == null ||
!optionOverride.isFailSilently();
+ if (!shouldRethtrow)
+ {
+ if (trace)
+ log.trace("There was a problem handling this request, but failSilently
was set, so suppressing exception", e);
+ return;
+ }
+ throw e;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void doCopy(InvocationContext c)
+ {
+ InvocationContextImpl copy = (InvocationContextImpl) c;
+ copy.command = command;
+ copy.globalTransaction = globalTransaction;
+ copy.invocationLocks = invocationLocks == null ? null : new
LinkedHashSet(invocationLocks);
+ copy.localRollbackOnly = localRollbackOnly;
+ copy.optionOverrides = optionOverrides == null ? null : optionOverrides.copy();
+ copy.originLocal = originLocal;
+ copy.transaction = transaction;
+ copy.transactionContext = transactionContext;
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryImpl.java
(rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryImpl.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt 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.mvcc;
+
+import java.util.Map.Entry;
+
+/**
+ * A basic map entry
+ */
+public class EntryImpl<K, V> implements Entry<K, V>
+{
+ private K key;
+ private V value;
+
+ public EntryImpl()
+ {
+ }
+
+ public EntryImpl(Entry<K, V> e)
+ {
+ this.key = e.getKey();
+ this.value = e.getValue();
+ }
+
+ public EntryImpl(K key, V value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public V getValue()
+ {
+ return value;
+ }
+
+ public V setValue(V value)
+ {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EntryImpl entry = (EntryImpl) o;
+
+ if (key != null ? !key.equals(entry.key) : entry.key != null) return false;
+ if (value != null ? !value.equals(entry.value) : entry.value != null) return
false;
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = (key != null ? key.hashCode() : 0);
+ result = 31 * result + (value != null ? value.hashCode() : 0);
+ return result;
+ }
+
+ public String toString()
+ {
+ return "EntryImpl{" +
+ "key=" + key +
+ ", value=" + value +
+ '}';
+ }
+}
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryReference.java
(from rev 6851, core/branches/flat/src/main/java/org/jboss/cache/mvcc/NodeReference.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryReference.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/EntryReference.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,106 @@
+/*
+ * 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.mvcc;
+
+import net.jcip.annotations.ThreadSafe;
+
+import java.util.Map.Entry;
+
+/**
+ * A node reference that delegates all calls to a different {@link
org.jboss.cache.InternalNode}. Simple indirection
+ * is all this class does, allowing other processes to change the delegate.
+ * <p/>
+ * The delegate is a volatile field so the class is thread safe.
+ * <p/>
+ * This is used to wrap all {@link org.jboss.cache.invocation.NodeInvocationDelegate}s in
the {@link org.jboss.cache.DataContainer}
+ * when using {@link org.jboss.cache.config.Configuration.NodeLockingScheme#MVCC} and
{@link org.jboss.cache.lock.IsolationLevel#READ_COMMITTED}.
+ * <p/>
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @see org.jboss.cache.mvcc.ReadCommittedNode
+ * @since 3.0
+ */
+@ThreadSafe
+public class EntryReference<K, V> implements Entry<K, V>
+{
+ transient volatile Entry<K, V> delegate;
+
+ public EntryReference(Entry<K, V> delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ /**
+ * @return the InternalNode being delegated to.
+ */
+ public final Entry<K, V> getDelegate()
+ {
+ return delegate;
+ }
+
+ public K getKey()
+ {
+ return delegate.getKey();
+ }
+
+ public V getValue()
+ {
+ return delegate.getValue();
+ }
+
+ public V setValue(V value)
+ {
+ return delegate.setValue(value);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EntryReference that = (EntryReference) o;
+
+ if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null)
return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return (delegate != null ? delegate.hashCode() : 0);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "EntryReference{" +
+ "delegate=" + delegate +
+ '}';
+ }
+
+ public void setDelegate(Entry entry)
+ {
+ delegate = entry;
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/MVCCEntry.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/MVCCEntry.java
(rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/MVCCEntry.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt 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.mvcc;
+
+import org.jboss.cache.InvocationContext;
+import org.jboss.starobrno.DataContainer;
+
+import java.util.Map.Entry;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public interface MVCCEntry extends Entry
+{
+ boolean isNullEntry();
+
+ void copyForUpdate(DataContainer container, boolean writeSkewCheck);
+
+ void commitUpdate(InvocationContext ctx, DataContainer container);
+
+ void rollbackUpdate();
+
+ boolean isChanged();
+
+ boolean isCreated();
+
+ void setCreated(boolean created);
+
+ boolean isDeleted();
+
+ void setDeleted(boolean deleted);
+
+ boolean isValid();
+
+ void setValid(boolean valid);
+}
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/NullMarkerEntry.java
(from rev 6851,
core/branches/flat/src/main/java/org/jboss/cache/mvcc/NullMarkerNode.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/NullMarkerEntry.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/NullMarkerEntry.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,75 @@
+/*
+ * 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.mvcc;
+
+import org.jboss.starobrno.DataContainer;
+
+/**
+ * A marker node to represent a null node for repeatable read, so that a read that
returns a null can continue to return
+ * null.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class NullMarkerEntry extends RepeatableReadEntry
+{
+ public NullMarkerEntry()
+ {
+ super(null);
+ }
+
+ /**
+ * @return always returns true
+ */
+ @Override
+ public boolean isNullEntry()
+ {
+ return true;
+ }
+
+ /**
+ * @return always returns true so that any get commands, upon getting this node, will
ignore the node as though it were removed.
+ */
+ @Override
+ public boolean isDeleted()
+ {
+ return true;
+ }
+
+ /**
+ * @return always returns true so that any get commands, upon getting this node, will
ignore the node as though it were invalid.
+ */
+ @Override
+ public boolean isValid()
+ {
+ return false;
+ }
+
+ /**
+ * A no-op.
+ */
+ @Override
+ public void copyForUpdate(DataContainer d, boolean b)
+ {
+ // no op
+ }
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/ReadCommittedEntry.java
(from rev 6851,
core/branches/flat/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/ReadCommittedEntry.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/ReadCommittedEntry.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,226 @@
+/*
+ * 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.mvcc;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.mvcc.ReadCommittedNode;
+import org.jboss.starobrno.DataContainer;
+import static org.jboss.starobrno.mvcc.ReadCommittedEntry.Flags.*;
+
+import java.util.Map.Entry;
+
+/**
+ * A node delegate that encapsulates read committed semantics when writes are initiated,
committed or rolled back.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class ReadCommittedEntry implements MVCCEntry
+{
+ private static final Log log = LogFactory.getLog(ReadCommittedNode.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ protected volatile Entry entry, backup;
+ protected byte flags = 0;
+
+ public Object getKey()
+ {
+ return entry.getKey();
+ }
+
+ public Object getValue()
+ {
+ return entry.getValue();
+ }
+
+ public Object setValue(Object value)
+ {
+ return entry.setValue(value);
+ }
+
+ protected static enum Flags
+ {
+ CHANGED(0x1), CREATED(0x2), DELETED(0x4), VALID(0x8);
+ final byte mask;
+
+ Flags(int mask)
+ {
+ this.mask = (byte) mask;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public ReadCommittedEntry(Entry entry)
+ {
+ setValid(true);
+ this.entry = entry;
+ }
+
+ /**
+ * Tests whether a flag is set.
+ *
+ * @param flag flag to test
+ * @return true if set, false otherwise.
+ */
+ protected final boolean isFlagSet(Flags flag)
+ {
+ return (flags & flag.mask) != 0;
+ }
+
+ /**
+ * Unility method that sets the value of the given flag to true.
+ *
+ * @param flag flag to set
+ */
+ protected final void setFlag(Flags flag)
+ {
+ flags |= flag.mask;
+ }
+
+ /**
+ * Utility method that sets the value of the flag to false.
+ *
+ * @param flag flag to unset
+ */
+ protected final void unsetFlag(Flags flag)
+ {
+ flags &= ~flag.mask;
+ }
+
+ public boolean isNullEntry()
+ {
+ return false;
+ }
+
+ public void copyForUpdate(DataContainer container, boolean writeSkewCheck)
+ {
+ if (isFlagSet(CHANGED)) return; // already copied
+
+ setFlag(CHANGED); // mark as changed
+ if (!isFlagSet(CREATED)) // if newly created, then nothing to copy.
+ {
+ backup = entry;
+ // don't copy the NodeReference but the InternalNode that the NodeReference
delegates to.
+ Entry backupDelegationTarget = ((EntryReference) backup).getDelegate();
+ entry = copyEntry(backupDelegationTarget);
+ }
+ }
+
+ protected Entry copyEntry(Entry e)
+ {
+ if (e instanceof EntryReference)
+ {
+ return new EntryReference(copyEntry(e));
+ }
+ else
+ {
+ return new EntryImpl(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void commitUpdate(InvocationContext ctx, DataContainer container)
+ {
+ // only do stuff if there are changes.
+ if (isFlagSet(CHANGED))
+ {
+ if (trace)
+ log.trace("Updating entry [" + getKey() + "]. deleted="
+ isDeleted() + " valid=" + isValid() + " changed=" + isChanged() +
" created=" + isFlagSet(CREATED));
+ updateEntry(container);
+ container.putEntry(entry);
+ reset();
+ }
+ }
+
+ private void reset()
+ {
+ backup = null;
+ flags = 0;
+ setValid(true);
+ }
+
+ /**
+ * Updates state changes on the current node in the underlying data structure.
+ *
+ * @param ctx invocation context
+ * @param dataContainer data container
+ */
+ @SuppressWarnings("unchecked")
+ protected void updateEntry(DataContainer dataContainer)
+ {
+ // swap refs
+ if (!isFlagSet(CREATED)) ((EntryReference) backup).setDelegate(entry);
+ entry = backup;
+ }
+
+ public void rollbackUpdate()
+ {
+ entry = backup;
+ reset();
+ }
+
+ public boolean isChanged()
+ {
+ return isFlagSet(CHANGED);
+ }
+
+ public boolean isValid()
+ {
+ return isFlagSet(VALID);
+ }
+
+ public void setValid(boolean valid)
+ {
+ if (valid)
+ setFlag(VALID);
+ else
+ unsetFlag(VALID);
+ }
+
+ public boolean isCreated()
+ {
+ return isFlagSet(CREATED);
+ }
+
+ public void setCreated(boolean created)
+ {
+ if (created)
+ setFlag(CREATED);
+ else
+ unsetFlag(CREATED);
+ }
+
+ public boolean isDeleted()
+ {
+ return isFlagSet(DELETED);
+ }
+
+ public void setDeleted(boolean deleted)
+ {
+ if (deleted)
+ setFlag(DELETED);
+ else
+ unsetFlag(DELETED);
+ }
+}
\ No newline at end of file
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/RepeatableReadEntry.java
(from rev 6851,
core/branches/flat/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/RepeatableReadEntry.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/mvcc/RepeatableReadEntry.java 2008-10-07
16:22:07 UTC (rev 6854)
@@ -0,0 +1,80 @@
+/*
+ * 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.mvcc;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.mvcc.RepeatableReadNode;
+import org.jboss.cache.optimistic.DataVersioningException;
+import org.jboss.starobrno.DataContainer;
+import static org.jboss.starobrno.mvcc.ReadCommittedEntry.Flags.CHANGED;
+
+import java.util.Map.Entry;
+
+/**
+ * A node delegate that encapsulates repeatable read semantics when writes are initiated,
committed or rolled back.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class RepeatableReadEntry extends ReadCommittedEntry
+{
+ private static final Log log = LogFactory.getLog(RepeatableReadNode.class);
+
+ public RepeatableReadEntry(Entry entry)
+ {
+ super(entry);
+ }
+
+ @Override
+ public void copyForUpdate(DataContainer container, boolean writeSkewCheck)
+ {
+ if (isFlagSet(CHANGED)) return; // already copied
+
+ // mark node as changed.
+ setFlag(CHANGED);
+
+ if (writeSkewCheck)
+ {
+ // check for write skew.
+ Entry actualEntry = null; // get this from somewhere -
container.peekInternalNode(fqn, true);
+
+ if (actualEntry != null && actualEntry != entry)
+ {
+ String errormsg = new StringBuilder().append("Detected write skew on key
[").append(getKey()).append("]. Another process has changed the node since we
last read it!").toString();
+ if (log.isWarnEnabled()) log.warn(errormsg + ". Unable to copy node for
update.");
+ throw new DataVersioningException(errormsg);
+ }
+ }
+
+ // make a backup copy
+ backup = entry;
+ entry = copyEntry(backup);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void updateEntry(DataContainer dataContainer)
+ {
+ entry = backup;
+ }
+}
\ No newline at end of file