[jbosscache-commits] JBoss Cache SVN: r7150 - in core/branches/flat/src: main/java/org/jboss/starobrno and 9 other directories.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Mon Nov 17 18:26:22 EST 2008
Author: manik.surtani at jboss.com
Date: 2008-11-17 18:26:21 -0500 (Mon, 17 Nov 2008)
New Revision: 7150
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMap.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapDelta.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapProxy.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMap.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMapCache.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/ClearOperation.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaAware.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/NullDelta.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Operation.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/PutOperation.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/RemoveOperation.java
core/branches/flat/src/main/java/org/jboss/starobrno/batch/AutoBatchSupport.java
core/branches/flat/src/test/java/org/jboss/starobrno/atomic/
core/branches/flat/src/test/java/org/jboss/starobrno/atomic/APITest.java
Removed:
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java
core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaHashMap.java
core/branches/flat/src/main/java/org/jboss/starobrno/delta/
Modified:
core/branches/flat/src/main/java/org/jboss/cache/DefaultCacheFactory.java
core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java
core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
core/branches/flat/src/main/java/org/jboss/starobrno/batch/BatchContainer.java
core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutKeyValueCommand.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/marshall/CacheMarshallerStarobrno.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java
Log:
AtomicMap and Tree facade based on AtomicMap
Modified: core/branches/flat/src/main/java/org/jboss/cache/DefaultCacheFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/DefaultCacheFactory.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/cache/DefaultCacheFactory.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -23,9 +23,9 @@
import org.jboss.cache.annotations.Compat;
import org.jboss.cache.jmx.PlatformMBeanServerRegistration;
+import org.jboss.starobrno.Cache;
import org.jboss.starobrno.CacheDelegate;
import org.jboss.starobrno.CacheSPI;
-import org.jboss.starobrno.Cache;
import org.jboss.starobrno.config.Configuration;
import org.jboss.starobrno.config.ConfigurationException;
import org.jboss.starobrno.config.parsing.XmlConfigurationParser;
@@ -137,7 +137,7 @@
/**
* Bootstraps this factory with a Configuration and a ComponentRegistry.
*/
- private void bootstrap( CacheSPI spi, Configuration configuration)
+ private void bootstrap(CacheSPI spi, Configuration configuration)
{
// injection bootstrap stuff
componentRegistry = new ComponentRegistry(configuration, spi);
@@ -166,7 +166,7 @@
return createCache(c);
}
- public Cache<K, V> createCache(InputStream is, boolean start) throws ConfigurationException
+ public Cache<K, V> createCache(InputStream is, boolean start) throws ConfigurationException
{
XmlConfigurationParser parser = new XmlConfigurationParser();
Configuration c = parser.parseStream(is);
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/Cache.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -53,7 +53,10 @@
CacheStatus getCacheStatus();
- public void startBatch();
+ /**
+ * @return true if a batch was successfully started; false if one was available and already running.
+ */
+ public boolean startBatch();
public void endBatch(boolean successful);
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -27,6 +27,9 @@
import org.jboss.cache.buddyreplication.GravitateResult;
import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.marshall.Marshaller;
+import org.jboss.starobrno.atomic.AtomicHashMap;
+import org.jboss.starobrno.atomic.AtomicMap;
+import org.jboss.starobrno.atomic.AtomicMapCache;
import org.jboss.starobrno.batch.BatchContainer;
import org.jboss.starobrno.commands.CommandsFactory;
import org.jboss.starobrno.commands.read.GetKeyValueCommand;
@@ -64,7 +67,7 @@
* @author Mircea.Markus at jboss.com
*/
@NonVolatile
-public class CacheDelegate<K, V> implements CacheSPI<K, V>
+public class CacheDelegate<K, V> implements CacheSPI<K, V>, AtomicMapCache<K, V>
{
protected InvocationContextContainer invocationContextContainer;
protected CommandsFactory commandsFactory;
@@ -357,11 +360,11 @@
return componentRegistry.getState();
}
- public void startBatch()
+ public boolean startBatch()
{
if (!config.isInvocationBatchingEnabled())
throw new ConfigurationException("Invocation batching not enabled in current configuration! Please use the <invocationBatching /> element.");
- batchContainer.startBatch();
+ return batchContainer.startBatch();
}
public void endBatch(boolean successful)
@@ -406,4 +409,16 @@
{
return dataContainer == null ? super.toString() : dataContainer.toString();
}
+
+ public AtomicMap getAtomicMap(K key) throws ClassCastException
+ {
+ Object value = get(key);
+ if (value == null) value = AtomicHashMap.newInstance(this, key);
+ return ((AtomicHashMap) value).getProxy(this, key);
+ }
+
+ public <AMK, AMV> AtomicMap<AMK, AMV> getAtomicMap(K key, Class<AMK> atomicMapKeyType, Class<AMV> atomicMapValueType) throws ClassCastException
+ {
+ return getAtomicMap(key);
+ }
}
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/atomic (from rev 7145, core/branches/flat/src/main/java/org/jboss/starobrno/delta)
Copied: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMap.java (from rev 7145, core/branches/flat/src/main/java/org/jboss/starobrno/delta/DeltaHashMap.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMap.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMap.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,186 @@
+/*
+ * 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.atomic;
+
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.util.FastCopyHashMap;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Note that for replication to work properly, this class <b><i>requires</i></b> that all writes take place within the
+ * scope of an ongoing transaction or batch.
+ * <p/>
+ *
+ * @param <K>
+ * @param <V>
+ */
+ at NotThreadSafe
+public class AtomicHashMap<K, V> implements AtomicMap<K, V>, DeltaAware
+{
+ FastCopyHashMap<K, V> delegate;
+ AtomicHashMapDelta delta = null;
+ AtomicHashMapProxy proxy;
+
+ /**
+ * Construction only allowed through this factory method. This factory is intended for use internally by the
+ * CacheDelegate. User code should use {@link AtomicMapCache#getAtomicMap(Object)}.
+ */
+ public static AtomicHashMap newInstance(Cache cache, Object cacheKey)
+ {
+ AtomicHashMap value = new AtomicHashMap();
+ Object oldValue = cache.putIfAbsent(cacheKey, value);
+ if (oldValue != null) value = (AtomicHashMap) oldValue;
+ return value;
+ }
+
+ AtomicHashMap()
+ {
+ delegate = new FastCopyHashMap<K, V>();
+ }
+
+ public void rollback()
+ {
+ // replay reversal operations on the changelog, in reverse order
+
+// ListIterator<AtomicHashMapDelta.Operation> li = delta.changelog.listIterator(delta.changelog.size());
+// while (li.hasPrevious()) li.previous().rollback(delegate);
+
+ // surely a no-op?
+ }
+
+ public void commit()
+ {
+ if (delta != null) delta.changelog.clear();
+ }
+
+ public int size()
+ {
+ return delegate.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return delegate.isEmpty();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return delegate.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return delegate.containsValue(value);
+ }
+
+ public V get(Object key)
+ {
+ return delegate.get(key);
+ }
+
+ public V put(K key, V value)
+ {
+ PutOperation<K, V> op = new PutOperation<K, V>();
+ op.key = key;
+ op.newValue = value;
+ op.oldValue = delegate.put(key, value);
+ delta.changelog.add(op);
+ return op.oldValue;
+ }
+
+ public V remove(Object key)
+ {
+ RemoveOperation<K, V> op = new RemoveOperation<K, V>();
+ op.key = (K) key;
+ op.oldValue = delegate.remove(key);
+ delta.changelog.add(op);
+ return op.oldValue;
+ }
+
+ public void putAll(Map<? extends K, ? extends V> t)
+ {
+ // this is crappy - need to do this more efficiently!
+ for (Entry<? extends K, ? extends V> e : t.entrySet()) put(e.getKey(), e.getValue());
+ }
+
+ public void clear()
+ {
+ ClearOperation<K, V> op = new ClearOperation<K, V>();
+ op.originalEntries = (FastCopyHashMap<K, V>) delegate.clone();
+ delta.changelog.add(op);
+ delegate.clear();
+ }
+
+ public Set<K> keySet()
+ {
+ return delegate.keySet();
+ }
+
+ public Collection<V> values()
+ {
+ return delegate.values();
+ }
+
+ public Set<Entry<K, V>> entrySet()
+ {
+ return delegate.entrySet();
+ }
+
+ public AtomicMap getProxy(Cache cache, Object mapKey)
+ {
+ // construct the proxy lazily
+ if (proxy == null) // DCL is OK here since proxy is volatile (and we live in a post-JDK 5 world)
+ {
+ synchronized (this)
+ {
+ if (proxy == null) proxy = new AtomicHashMapProxy(cache, mapKey);
+ }
+ }
+ return proxy;
+ }
+
+ public Delta delta()
+ {
+ return delta == null ? NullDelta.INSTANCE : delta;
+ }
+
+ public AtomicHashMap copyForWrite()
+ {
+ AtomicHashMap clone = new AtomicHashMap();
+ clone.delegate = (FastCopyHashMap) delegate.clone();
+ clone.proxy = proxy;
+ clone.delta = new AtomicHashMapDelta();
+ return clone;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "AtomicHashMap{" +
+ "delegate=" + delegate +
+ '}';
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapDelta.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapDelta.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapDelta.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,76 @@
+/*
+ * 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.atomic;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Changes that have occured on an AtomicHashMap
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ */
+public class AtomicHashMapDelta implements Delta
+{
+ List<Operation> changelog = new LinkedList<Operation>();
+ private static final Log log = LogFactory.getLog(AtomicHashMapDelta.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ public DeltaAware merge(DeltaAware d)
+ {
+ AtomicHashMap other;
+ if (d != null && (d instanceof AtomicHashMap))
+ other = (AtomicHashMap) d;
+ else
+ other = new AtomicHashMap();
+
+ for (Operation o : changelog) o.replay(other.delegate);
+ other.commit();
+ return other;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ if (trace) log.trace("Serializing changelog " + changelog);
+ out.writeObject(changelog);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ changelog = (List<Operation>) in.readObject();
+ if (trace) log.trace("Deserialized changelog " + changelog);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "AtomicHashMapDelta{" +
+ "changelog=" + changelog +
+ '}';
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapProxy.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapProxy.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicHashMapProxy.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,170 @@
+/*
+ * 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.atomic;
+
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.batch.AutoBatchSupport;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A layer of indirection around an {@link org.jboss.starobrno.atomic.AtomicHashMap} to provide reader consistency
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ */
+public class AtomicHashMapProxy<K, V> extends AutoBatchSupport implements AtomicMap<K, V>
+{
+ Object deltaMapKey;
+
+ public AtomicHashMapProxy(Cache cache, Object deltaMapKey)
+ {
+ this.cache = cache;
+ this.deltaMapKey = deltaMapKey;
+ }
+
+ // internal helper, reduces lots of casts.
+ private AtomicHashMap<K, V> getDeltaMapForRead()
+ {
+ return (AtomicHashMap<K, V>) cache.get(deltaMapKey);
+ }
+
+ private AtomicHashMap<K, V> getDeltaMapForWrite()
+ {
+ if (ownsLock())
+ {
+ return (AtomicHashMap<K, V>) cache.get(deltaMapKey);
+ }
+ else
+ {
+ // acquire WL
+ cache.getInvocationContext().getOptionOverrides().setForceWriteLock(true);
+ AtomicHashMap map = getDeltaMapForRead();
+ // copy for write
+ AtomicHashMap copy = map == null ? new AtomicHashMap() : map.copyForWrite();
+ cache.put(deltaMapKey, copy);
+ return copy;
+ }
+ }
+
+ private boolean ownsLock()
+ {
+ return cache.getInvocationContext().hasLockedKey(deltaMapKey);
+ }
+
+ // readers
+
+ public Set<K> keySet()
+ {
+ return getDeltaMapForRead().keySet();
+ }
+
+ public Collection<V> values()
+ {
+ return getDeltaMapForRead().values();
+ }
+
+ public Set<Entry<K, V>> entrySet()
+ {
+ return getDeltaMapForRead().entrySet();
+ }
+
+ public int size()
+ {
+ return getDeltaMapForRead().size();
+ }
+
+ public boolean isEmpty()
+ {
+ return getDeltaMapForRead().isEmpty();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return getDeltaMapForRead().containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return getDeltaMapForRead().containsValue(value);
+ }
+
+ public V get(Object key)
+ {
+ return getDeltaMapForRead().get(key);
+ }
+
+ // writers
+
+ public V put(K key, V value)
+ {
+ try
+ {
+ startAtomic();
+ return getDeltaMapForWrite().put(key, value);
+ }
+ finally
+ {
+ endAtomic();
+ }
+ }
+
+ public V remove(Object key)
+ {
+ try
+ {
+ startAtomic();
+ return getDeltaMapForWrite().remove(key);
+ }
+ finally
+ {
+ endAtomic();
+ }
+ }
+
+ public void putAll(Map<? extends K, ? extends V> m)
+ {
+ try
+ {
+ startAtomic();
+ getDeltaMapForWrite().putAll(m);
+ }
+ finally
+ {
+ endAtomic();
+ }
+ }
+
+ public void clear()
+ {
+ try
+ {
+ startAtomic();
+ getDeltaMapForWrite().clear();
+ }
+ finally
+ {
+ endAtomic();
+ }
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMap.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMap.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMap.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,41 @@
+/*
+ * 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.atomic;
+
+import java.util.Map;
+
+/**
+ * This is a special type of Map geared for use in JBoss Cache. This map type supports JBoss Cache atomicizing writes
+ * on the cache such that a coarse grained locking is used if this map is stored in the cache, such that the entire map
+ * is locked for writes or is isolated for safe concurrent read.
+ * <p/>
+ * This is, for all practical purposes, a marker interface that indicates that Maps of this type will be locked
+ * atomically in the cache and replicated in a fine grained manner.
+ * <p/>
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @see DeltaAware
+ * @see AtomicHashMap
+ */
+public interface AtomicMap<K, V> extends Map<K, V>
+{
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMapCache.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMapCache.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/AtomicMapCache.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,56 @@
+/*
+ * 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.atomic;
+
+import org.jboss.starobrno.Cache;
+
+/**
+ * This interface adds the getAtomicMap() method which allows users to get a hold of a map type where operations on its
+ * elements are all atomic. Refer to the {@link AtomicMap} javadocs for more details.
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @see AtomicMap
+ */
+public interface AtomicMapCache<K, V> extends Cache<K, V>
+{
+ /**
+ * Returns an atomic map. The classes passed in are used to parameterize the Map returned.
+ *
+ * @param key key under which to obtain and store this map in the cache
+ * @param mapKeyType type of the key used for this map
+ * @param mapValueType type of the value used for this map.
+ * @param <X> map keys
+ * @param <Y> map values
+ * @return a new or existing atomic map. Never null.
+ * @throws ClassCastException if there already is a value stored under the given key and the type of value cannot be used as an AtomicMap.
+ */
+ <AMK, AMV> AtomicMap<AMK, AMV> getAtomicMap(K key, Class<AMK> atomicMapKeyType, Class<AMV> atomicMapValueType) throws ClassCastException;
+
+ /**
+ * Un-parameterized version of {@link #getAtomicMap(Object, Class, Class)} which returns an un-parameterized map.
+ *
+ * @param key key under which to obtain and store this map in the cache
+ * @return a new or existing atomic map. Never null.
+ * @throws ClassCastException if there already is a value stored under the given key and the type of value cannot be used as an AtomicMap.
+ */
+ AtomicMap getAtomicMap(K key) throws ClassCastException;
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/ClearOperation.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/ClearOperation.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/ClearOperation.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -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.atomic;
+
+import org.jboss.starobrno.util.FastCopyHashMap;
+
+import java.util.Map;
+
+
+public class ClearOperation<K, V> extends Operation<K, V>
+{
+ FastCopyHashMap<K, V> originalEntries;
+
+ public void rollback(Map<K, V> delegate)
+ {
+ if (!originalEntries.isEmpty()) delegate.putAll(originalEntries);
+ }
+
+ public void replay(Map<K, V> delegate)
+ {
+ delegate.clear();
+ }
+}
\ No newline at end of file
Deleted: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/delta/Delta.java 2008-11-17 10:43:05 UTC (rev 7145)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -1,97 +0,0 @@
-/*
- * 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.delta;
-
-import java.io.Externalizable;
-
-/**
- * This interface allows for implementations to be palced as values in the cache, and report what has changed. This
- * allows for finer grained replication messages.
- * <p/>
- * Basically, the first time a <tt>Delta</tt> object is placed in the cache, it is cached in its entirity. When a
- * <tt>Delta</tt> is removed, similarly, it is removed in its entirity.
- * <p/>
- * Special behavior is seen when a <tt>Delta</tt> object is changed and replicated though. For example, consider the
- * following code:
- * <code>
- * Person p = cache.get("personName");
- * p.setAge(p.getAge() + 1);
- * cache.put("personName", p);
- * </code>
- * <p/>
- * where <tt>Person</tt> implements Delta.
- * <p/>
- * Normally, the put() call would involve serializing and replicating the entire <tt>Person</tt> instance, but since
- * <tt>Person</tt> implements <tt>Delta</tt>, instead the marshaller will only expect the changes to be marshalled (when
- * calling the {@link Externalizable} interfaces. As such, implementations could safely only marshall modified fields when
- * {@link Externalizable#writeExternal(java.io.ObjectOutput)} is called, thereby reducing the time taken serializing
- * and replicating changes.
- * <p/>
- * On the receiving end, changes are applied as such. In a {@link org.jboss.starobrno.commands.write.PutKeyValueCommand},
- * if the value being put is a <tt>Delta</tt> and there is already a <tt>Delta</tt> under the same key, a merge operation
- * is called by invoking {@link Delta#merge(Delta)} on the <i>replicated</i> <tt>Delta</tt> value and passing in the
- * <i>original</i> <tt>Delta</tt> instance. It would then be up to the implementation to efficiently and correctly merge
- * in state, and return a coherent and complete <tt>Delta</tt> instance that could be placed in the cache.
- * <p/>
- * If the command does not find anything under the key - or emor importantly, finds an object that does not implement
- * <tt>Delta</tt> - it would pass a null into the {@link #merge(Delta)} method.
- * <p/>
- * It is important to note that {@link #merge(Delta)} is <b>only</b> called on remote nodes, after replication when
- * merging state. This is never used on the local cache instance.
- * <p/>
- * In addition to {@link #merge(Delta)}, other important methods on this interface are {@link #rollback()}. If running
- * within a JTA transaction scope, and a rollback occurs, no replication takes place so nothing needs to happen on
- * remote instances. However, on your local cache instance, you may have changed internal state of a reference
- * which already exists in the cache, such as in the above example. To correctly deal with JTA transaction rollbacks,
- * all {@link #rollback()} methods on <tt>Delta</tt> instances involved in a transaction will be called and it is
- * up to the implementation to reset internal state. There is a corresponding {@link #commit()} method where changes
- * should be considered as accepted, are flushed and rollback information can be cleared.
- * <p/>
- * For an example of a <tt>Delta</tt> implementation, and for typical use cases, please refer to {@link org.jboss.starobrno.delta.DeltaHashMap}.
- *
- * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
- * @see org.jboss.starobrno.delta.DeltaHashMap
- */
-public interface Delta extends Externalizable
-{
- /**
- * Invoked if a transaction involving modifying state on this instance has rolled back, and state needs to be reverted.
- */
- void rollback();
-
- /**
- * Invoked if a transaction involving modifying state on this instance completes successfully, and any recorded
- * rollback information can safely be discarded.
- */
- void commit();
-
- /**
- * Merges changes. Important to note that this method is always called on remote nodes, after replication, and is
- * called on the de-serialized instance read off the wire. What is passed in is an extisting <tt>Delta</tt> instance
- * to merge with, or a null. This method should return a fully coherent <tt>Delta</tt> instance than can be placed
- * in the cache
- *
- * @param toMergeInto
- * @return a fully coherent <tt>Delta</tt> instance
- */
- Delta merge(Delta toMergeInto);
-}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Delta.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,44 @@
+/*
+ * 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.atomic;
+
+import java.io.Externalizable;
+
+/**
+ * Represents changes made to a {@link DeltaAware} implementation. Should be efficiently externalizable.
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ */
+public interface Delta extends Externalizable
+{
+ /**
+ * Merge the current set of deltas with a given {@link DeltaAware} instance, and return a coherent and complete
+ * {@link DeltaAware} instance. Implementations should be able to deal with null values passed in, or values of a
+ * different type from the expected DeltaAware instance. Usually the approach would be to ignore what is passed in,
+ * create a new instance of the DeltaAware implementation that the current Delta implementation is written for,
+ * apply changes and pass it back.
+ *
+ * @param d instance to merge with, or null if no merging is needed
+ * @return a fully coherent and usable instance of DeltaAware which may or may not be the same instance passed in
+ */
+ DeltaAware merge(DeltaAware d);
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaAware.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaAware.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaAware.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,53 @@
+/*
+ * 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.atomic;
+
+/**
+ * This interface allows the extraction of deltas.
+ * <p/>
+ * Implementations would be closely coupled to a corresponding {@link Delta} implementation, since {@link org.jboss.starobrno.atomic.Delta#instantiate()}
+ * would need to know how to recreate this instance of DeltaAware if needed.
+ * <p/>
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @see Delta
+ */
+public interface DeltaAware
+{
+ /**
+ * Extracts changes made to implementations, in an efficient format that can easily and cheaply be serialized and
+ * deserialized.
+ *
+ * @return an instance of Delta
+ */
+ Delta delta();
+
+ /**
+ * Indicate that all deltas collected to date can be applied and discarded.
+ */
+ void commit();
+
+ /**
+ * Indicate that all deltas collected to date can be discarded.
+ */
+ void rollback();
+}
Deleted: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaHashMap.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/delta/DeltaHashMap.java 2008-11-17 10:43:05 UTC (rev 7145)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/DeltaHashMap.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -1,301 +0,0 @@
-/*
- * 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.delta;
-
-import org.jboss.starobrno.util.FastCopyHashMap;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-public class DeltaHashMap<K, V> implements Delta, Map<K, V>
-{
- FastCopyHashMap<K, V> delegate;
- List<Operation> changelog = new LinkedList<Operation>();
-
- /**
- * Constructs an empty <tt>HashMap</tt> with the specified initial
- * capacity and load factor.
- *
- * @param initialCapacity The initial capacity.
- * @param loadFactor The load factor.
- * @throws IllegalArgumentException if the initial capacity is negative
- * or the load factor is nonpositive.
- */
- public DeltaHashMap(int initialCapacity, float loadFactor)
- {
- delegate = new FastCopyHashMap(initialCapacity, loadFactor);
- }
-
- /**
- * Constructs an empty <tt>HashMap</tt> with the specified initial
- * capacity and the default load factor (0.75).
- *
- * @param initialCapacity the initial capacity.
- * @throws IllegalArgumentException if the initial capacity is negative.
- */
- public DeltaHashMap(int initialCapacity)
- {
- delegate = new FastCopyHashMap<K, V>(initialCapacity);
- }
-
- /**
- * Constructs an empty <tt>HashMap</tt> with the default initial capacity
- * (16) and the default load factor (0.75).
- */
- public DeltaHashMap()
- {
- delegate = new FastCopyHashMap<K, V>();
- }
-
- /**
- * Constructs a new <tt>HashMap</tt> with the same mappings as the
- * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
- * default load factor (0.75) and an initial capacity sufficient to
- * hold the mappings in the specified <tt>Map</tt>.
- *
- * @param m the map whose mappings are to be placed in this map.
- * @throws NullPointerException if the specified map is null.
- */
- public DeltaHashMap(Map<? extends K, ? extends V> m)
- {
- delegate = new FastCopyHashMap<K, V>(m);
- }
-
-
- public void rollback()
- {
- // replay reversal operations on the changelog, in reverse order
- ListIterator<Operation> li = changelog.listIterator(changelog.size());
- while (li.hasPrevious()) li.previous().rollback(delegate);
- }
-
- public void commit()
- {
- changelog.clear();
- }
-
- public Delta merge(Delta toMergeInto)
- {
- if (toMergeInto != null)
- {
- if (toMergeInto instanceof DeltaHashMap)
- {
- DeltaHashMap other = (DeltaHashMap) toMergeInto;
- for (Operation o : changelog) o.replay(other.delegate);
- commit();
- other.commit();
- return toMergeInto;
- }
- else
- {
- throw new IllegalArgumentException("This instance of " + getClass().getSimpleName() + " can only merge with other instances of the same type. Don't know how to deal with " + toMergeInto.getClass());
- }
- }
- else
- {
- // use the current instance, since there is nothing to merge into.
- for (Operation o : changelog) o.replay(delegate);
- commit();
- return this;
- }
- }
-
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeObject(changelog);
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- changelog = (List<Operation>) in.readObject();
- }
-
- public int size()
- {
- return delegate.size();
- }
-
- public boolean isEmpty()
- {
- return delegate.isEmpty();
- }
-
- public boolean containsKey(Object key)
- {
- return delegate.containsKey(key);
- }
-
- public boolean containsValue(Object value)
- {
- return delegate.containsValue(value);
- }
-
- public V get(Object key)
- {
- return delegate.get(key);
- }
-
- public V put(K key, V value)
- {
- PutOperation<K, V> op = new PutOperation<K, V>();
- op.key = key;
- op.newValue = value;
- op.oldValue = delegate.put(key, value);
- changelog.add(op);
- return op.oldValue;
- }
-
- public V remove(Object key)
- {
- RemoveOperation<K, V> op = new RemoveOperation<K, V>();
- op.key = (K) key;
- op.oldValue = delegate.remove(key);
- changelog.add(op);
- return op.oldValue;
- }
-
- public void putAll(Map<? extends K, ? extends V> t)
- {
- // this is crappy - need to do this more efficiently!
- for (Entry<? extends K, ? extends V> e : t.entrySet()) put(e.getKey(), e.getValue());
- }
-
- public void clear()
- {
- ClearOperation<K, V> op = new ClearOperation<K, V>();
- op.originalEntries = (FastCopyHashMap<K, V>) delegate.clone();
- changelog.add(op);
- delegate.clear();
- }
-
- public Set<K> keySet()
- {
- return delegate.keySet();
- }
-
- public Collection<V> values()
- {
- return delegate.values();
- }
-
- public Set<Entry<K, V>> entrySet()
- {
- return delegate.entrySet();
- }
-
- private static abstract class Operation<K, V> implements Externalizable
- {
- abstract void rollback(Map<K, V> delegate);
-
- abstract void replay(Map<K, V> delegate);
-
- public void writeExternal(ObjectOutput out) throws IOException
- {
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- }
- }
-
- private static class PutOperation<K, V> extends Operation<K, V>
- {
- K key;
- V oldValue;
- V newValue;
-
- void rollback(Map<K, V> delegate)
- {
- if (oldValue == null)
- delegate.remove(key);
- else
- delegate.put(key, oldValue);
- }
-
- void replay(Map<K, V> delegate)
- {
- delegate.put(key, newValue);
- }
-
- public void writeExternal(ObjectOutput out) throws IOException
- {
- // don't bother writing out the old value since it will never be rolled back
- out.writeObject(key);
- out.writeObject(newValue);
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- key = (K) in.readObject();
- newValue = (V) in.readObject();
- }
- }
-
- private static class RemoveOperation<K, V> extends Operation<K, V>
- {
- K key;
- V oldValue;
-
- void rollback(Map<K, V> delegate)
- {
- if (oldValue != null) delegate.put(key, oldValue);
- }
-
- void replay(Map<K, V> delegate)
- {
- delegate.remove(key);
- }
-
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeObject(key);
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- key = (K) in.readObject();
- }
- }
-
- private static class ClearOperation<K, V> extends Operation<K, V>
- {
- FastCopyHashMap<K, V> originalEntries;
-
- void rollback(Map<K, V> delegate)
- {
- if (!originalEntries.isEmpty()) delegate.putAll(originalEntries);
- }
-
- void replay(Map<K, V> delegate)
- {
- delegate.clear();
- }
- }
-}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/NullDelta.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/NullDelta.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/NullDelta.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,52 @@
+/*
+ * 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.atomic;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Represents no changes.
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ */
+public class NullDelta implements Externalizable, Delta
+{
+ static final NullDelta INSTANCE = new NullDelta();
+
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ // don't bother writing anything
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ // nothing to read
+ }
+
+ public DeltaAware merge(DeltaAware d)
+ {
+ return (d != null && d instanceof AtomicHashMap) ? d : new AtomicHashMap();
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Operation.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Operation.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/Operation.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,45 @@
+/*
+ * 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.atomic;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+
+public abstract class Operation<K, V> implements Externalizable
+{
+ public abstract void replay(Map<K, V> delegate);
+
+ public abstract void rollback(Map<K, V> delegate);
+
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ //no op
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ //no op
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/PutOperation.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/PutOperation.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/PutOperation.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,63 @@
+/*
+ * 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.atomic;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+
+
+public class PutOperation<K, V> extends Operation<K, V>
+{
+ K key;
+ V oldValue;
+ V newValue;
+
+ public void rollback(Map<K, V> delegate)
+ {
+ if (oldValue == null)
+ delegate.remove(key);
+ else
+ delegate.put(key, oldValue);
+ }
+
+ public void replay(Map<K, V> delegate)
+ {
+ delegate.put(key, newValue);
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ // don't bother writing out the old value since it will never be rolled back
+ out.writeObject(key);
+ out.writeObject(newValue);
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ key = (K) in.readObject();
+ newValue = (V) in.readObject();
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/atomic/RemoveOperation.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/atomic/RemoveOperation.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/atomic/RemoveOperation.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,56 @@
+/*
+ * 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.atomic;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+
+
+public class RemoveOperation<K, V> extends Operation<K, V>
+{
+ K key;
+ V oldValue;
+
+ public void rollback(Map<K, V> delegate)
+ {
+ if (oldValue != null) delegate.put(key, oldValue);
+ }
+
+ public void replay(Map<K, V> delegate)
+ {
+ delegate.remove(key);
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ out.writeObject(key);
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ key = (K) in.readObject();
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/batch/AutoBatchSupport.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/batch/AutoBatchSupport.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/batch/AutoBatchSupport.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,45 @@
+/*
+ * 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.batch;
+
+import org.jboss.starobrno.Cache;
+
+/**
+ * Enables for automatic batching.
+ *
+ * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ */
+public abstract class AutoBatchSupport
+{
+ boolean startedBatch;
+ protected Cache cache;
+
+ protected void startAtomic()
+ {
+ if (!startedBatch) startedBatch = cache.startBatch();
+ }
+
+ protected void endAtomic()
+ {
+ if (startedBatch) cache.endBatch(true);
+ }
+}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/batch/BatchContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/batch/BatchContainer.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/batch/BatchContainer.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -45,16 +45,23 @@
this.transactionManager = transactionManager;
}
- public void startBatch() throws CacheException
+ /**
+ * Starts a batch
+ *
+ * @return true if a batch was started; false if one was already available.
+ * @throws CacheException
+ */
+ public boolean startBatch() throws CacheException
{
try
{
- if (transactionManager.getTransaction() != null) return;
- if (batchTransactionContainer.get() == null)
+ if (transactionManager.getTransaction() == null && batchTransactionContainer.get() == null)
{
transactionManager.begin();
batchTransactionContainer.set(transactionManager.suspend());
+ return true;
}
+ return false;
}
catch (Exception e)
{
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutKeyValueCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutKeyValueCommand.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutKeyValueCommand.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -21,6 +21,8 @@
*/
package org.jboss.starobrno.commands.write;
+import org.jboss.starobrno.atomic.Delta;
+import org.jboss.starobrno.atomic.DeltaAware;
import org.jboss.starobrno.commands.Visitor;
import org.jboss.starobrno.commands.read.AbstractDataCommand;
import org.jboss.starobrno.container.MVCCEntry;
@@ -77,7 +79,21 @@
{
notifier.notifyCacheEntryModified(key, true, ctx);
MVCCEntry e = ctx.lookupEntry(key);
- Object o = e.setValue(value);
+ Object o = null;
+ if (value instanceof Delta)
+ {
+ // magic
+ Delta dv = (Delta) value;
+ Object existing = e.getValue();
+ DeltaAware toMergeWith = null;
+ if (existing instanceof DeltaAware) toMergeWith = (DeltaAware) existing;
+ e.setValue(dv.merge(toMergeWith));
+ o = existing;
+ }
+ else
+ {
+ o = e.setValue(value);
+ }
notifier.notifyCacheEntryModified(key, false, ctx);
return o;
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -47,8 +47,8 @@
private static final JBossEntityResolver resolver = new JBossEntityResolver();
- public static final String JBOSSCACHE_CORE_NS = "urn:jboss:jbosscache-core:config:3.0";
- public static final String JBOSSCACHE_REPO_NS = "urn:jboss:jbosscache-core:cache-repo:3.0";
+ public static final String JBOSSCACHE_CORE_NS = "urn:jboss:starobrno-core:config:1.0";
+ public static final String JBOSSCACHE_REPO_NS = "urn:jboss:starobrno-core:cache-repo:1.0";
static
{
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -19,7 +19,7 @@
* 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.cache.config.parsing;
+package org.jboss.starobrno.config.parsing;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.util.FileLookup;
@@ -29,9 +29,6 @@
import org.jboss.starobrno.config.Configuration.CacheMode;
import org.jboss.starobrno.config.ConfigurationException;
import org.jboss.starobrno.config.CustomInterceptorConfig;
-import org.jboss.starobrno.config.parsing.JGroupsStackParser;
-import org.jboss.starobrno.config.parsing.RootElementBuilder;
-import org.jboss.starobrno.config.parsing.XmlParserBase;
import org.jboss.starobrno.config.parsing.element.BuddyElementParser;
import org.jboss.starobrno.config.parsing.element.CustomInterceptorsElementParser;
import org.jboss.starobrno.config.parsing.element.EvictionElementParser;
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/marshall/CacheMarshallerStarobrno.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/marshall/CacheMarshallerStarobrno.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/marshall/CacheMarshallerStarobrno.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -24,25 +24,40 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.starobrno.CacheException;
-import org.jboss.starobrno.io.ByteBuffer;
-import org.jboss.starobrno.io.ExposedByteArrayOutputStream;
+import org.jboss.starobrno.atomic.DeltaAware;
import org.jboss.starobrno.commands.CommandsFactory;
import org.jboss.starobrno.commands.ReplicableCommand;
import org.jboss.starobrno.config.Configuration;
-import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.io.ByteBuffer;
+import org.jboss.starobrno.io.ExposedByteArrayOutputStream;
import org.jboss.starobrno.transaction.GlobalTransaction;
import org.jboss.starobrno.util.FastCopyHashMap;
import org.jboss.starobrno.util.Immutables;
import org.jboss.util.NotImplementedException;
import org.jboss.util.stream.MarshalledValueInputStream;
-import org.jboss.cache.marshall.Marshaller;
import org.jgroups.Address;
import org.jgroups.stack.IpAddress;
import org.jgroups.util.Buffer;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.lang.reflect.Array;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
/**
* Abstract AbstractMarshaller for JBoss Cache.
@@ -129,7 +144,8 @@
if (o != null && o.getClass().isArray() && isKnownType(o.getClass().getComponentType()))
{
marshallArray(o, out, refMap);
- } else
+ }
+ else
{
if (o == null)
{
@@ -163,6 +179,13 @@
out.writeByte(MAGICNUMBER_MARSHALLEDVALUE);
((MarshalledValue) o).writeExternal(out);
}
+ else if (o instanceof DeltaAware)
+ {
+ // reading in should be nothing special.
+ out.writeByte(MAGICNUMBER_SERIALIZABLE);
+ // only write the delta for these maps.
+ out.writeObject(((DeltaAware) o).delta());
+ }
else if (o instanceof GlobalTransaction)
{
out.writeByte(MAGICNUMBER_GTX);
@@ -341,7 +364,8 @@
if (loader == null)
{
return unmarshallObject(in, refMap);
- } else
+ }
+ else
{
Thread currentThread = Thread.currentThread();
ClassLoader old = currentThread.getContextClassLoader();
@@ -372,7 +396,8 @@
{
reference = readReference(in);
return refMap.getReferencedObject(reference);
- } else break;
+ }
+ else break;
case MAGICNUMBER_SERIALIZABLE:
if (useRefs) reference = readReference(in);
retVal = in.readObject();
@@ -671,7 +696,8 @@
boolean[] a = new boolean[sz];
for (int i = 0; i < sz; i++) a[i] = in.readBoolean();
return a;
- } else
+ }
+ else
{
Boolean[] a = new Boolean[sz];
for (int i = 0; i < sz; i++) a[i] = in.readBoolean();
@@ -686,7 +712,8 @@
int[] a = new int[sz];
for (int i = 0; i < sz; i++) a[i] = in.readInt();
return a;
- } else
+ }
+ else
{
Integer[] a = new Integer[sz];
for (int i = 0; i < sz; i++) a[i] = in.readInt();
@@ -701,7 +728,8 @@
long[] a = new long[sz];
for (int i = 0; i < sz; i++) a[i] = in.readLong();
return a;
- } else
+ }
+ else
{
Long[] a = new Long[sz];
for (int i = 0; i < sz; i++) a[i] = in.readLong();
@@ -716,7 +744,8 @@
char[] a = new char[sz];
for (int i = 0; i < sz; i++) a[i] = in.readChar();
return a;
- } else
+ }
+ else
{
Character[] a = new Character[sz];
for (int i = 0; i < sz; i++) a[i] = in.readChar();
@@ -739,7 +768,8 @@
bytesLeft -= read;
}
return a;
- } else
+ }
+ else
{
Byte[] a = new Byte[sz];
for (int i = 0; i < sz; i++) a[i] = in.readByte();
@@ -754,7 +784,8 @@
short[] a = new short[sz];
for (int i = 0; i < sz; i++) a[i] = in.readShort();
return a;
- } else
+ }
+ else
{
Short[] a = new Short[sz];
for (int i = 0; i < sz; i++) a[i] = in.readShort();
@@ -769,7 +800,8 @@
float[] a = new float[sz];
for (int i = 0; i < sz; i++) a[i] = in.readFloat();
return a;
- } else
+ }
+ else
{
Float[] a = new Float[sz];
for (int i = 0; i < sz; i++) a[i] = in.readFloat();
@@ -784,7 +816,8 @@
double[] a = new double[sz];
for (int i = 0; i < sz; i++) a[i] = in.readDouble();
return a;
- } else
+ }
+ else
{
Double[] a = new Double[sz];
for (int i = 0; i < sz; i++) a[i] = in.readDouble();
@@ -814,7 +847,8 @@
{
out.writeByte(MAGICNUMBER_OBJECT);
for (int i = 0; i < sz; i++) marshallObject(Array.get(o, i), out, refMap);
- } else if (arrayTypeClass.equals(byte.class) || arrayTypeClass.equals(Byte.class))
+ }
+ else if (arrayTypeClass.equals(byte.class) || arrayTypeClass.equals(Byte.class))
{
out.writeByte(MAGICNUMBER_BYTE);
out.writeBoolean(isPrim);
@@ -822,7 +856,8 @@
out.write((byte[]) o);
else
for (int i = 0; i < sz; i++) out.writeByte((Byte) Array.get(o, i));
- } else if (arrayTypeClass.equals(int.class) || arrayTypeClass.equals(Integer.class))
+ }
+ else if (arrayTypeClass.equals(int.class) || arrayTypeClass.equals(Integer.class))
{
out.writeByte(MAGICNUMBER_INTEGER);
out.writeBoolean(isPrim);
@@ -830,7 +865,8 @@
for (int i = 0; i < sz; i++) out.writeInt(Array.getInt(o, i));
else
for (int i = 0; i < sz; i++) out.writeInt((Integer) Array.get(o, i));
- } else if (arrayTypeClass.equals(long.class) || arrayTypeClass.equals(Long.class))
+ }
+ else if (arrayTypeClass.equals(long.class) || arrayTypeClass.equals(Long.class))
{
out.writeByte(MAGICNUMBER_LONG);
out.writeBoolean(isPrim);
@@ -838,7 +874,8 @@
for (int i = 0; i < sz; i++) out.writeLong(Array.getLong(o, i));
else
for (int i = 0; i < sz; i++) out.writeLong((Long) Array.get(o, i));
- } else if (arrayTypeClass.equals(boolean.class) || arrayTypeClass.equals(Boolean.class))
+ }
+ else if (arrayTypeClass.equals(boolean.class) || arrayTypeClass.equals(Boolean.class))
{
out.writeByte(MAGICNUMBER_BOOLEAN);
out.writeBoolean(isPrim);
@@ -846,7 +883,8 @@
for (int i = 0; i < sz; i++) out.writeBoolean(Array.getBoolean(o, i));
else
for (int i = 0; i < sz; i++) out.writeBoolean((Boolean) Array.get(o, i));
- } else if (arrayTypeClass.equals(char.class) || arrayTypeClass.equals(Character.class))
+ }
+ else if (arrayTypeClass.equals(char.class) || arrayTypeClass.equals(Character.class))
{
out.writeByte(MAGICNUMBER_CHAR);
out.writeBoolean(isPrim);
@@ -854,7 +892,8 @@
for (int i = 0; i < sz; i++) out.writeChar(Array.getChar(o, i));
else
for (int i = 0; i < sz; i++) out.writeChar((Character) Array.get(o, i));
- } else if (arrayTypeClass.equals(short.class) || arrayTypeClass.equals(Short.class))
+ }
+ else if (arrayTypeClass.equals(short.class) || arrayTypeClass.equals(Short.class))
{
out.writeByte(MAGICNUMBER_SHORT);
out.writeBoolean(isPrim);
@@ -862,7 +901,8 @@
for (int i = 0; i < sz; i++) out.writeShort(Array.getShort(o, i));
else
for (int i = 0; i < sz; i++) out.writeShort((Short) Array.get(o, i));
- } else if (arrayTypeClass.equals(float.class) || arrayTypeClass.equals(Float.class))
+ }
+ else if (arrayTypeClass.equals(float.class) || arrayTypeClass.equals(Float.class))
{
out.writeByte(MAGICNUMBER_FLOAT);
out.writeBoolean(isPrim);
@@ -870,7 +910,8 @@
for (int i = 0; i < sz; i++) out.writeFloat(Array.getFloat(o, i));
else
for (int i = 0; i < sz; i++) out.writeFloat((Float) Array.get(o, i));
- } else if (arrayTypeClass.equals(double.class) || arrayTypeClass.equals(Double.class))
+ }
+ else if (arrayTypeClass.equals(double.class) || arrayTypeClass.equals(Double.class))
{
out.writeByte(MAGICNUMBER_DOUBLE);
out.writeBoolean(isPrim);
@@ -878,7 +919,8 @@
for (int i = 0; i < sz; i++) out.writeDouble(Array.getDouble(o, i));
else
for (int i = 0; i < sz; i++) out.writeDouble((Double) Array.get(o, i));
- } else throw new CacheException("Unknown array type!");
+ }
+ else throw new CacheException("Unknown array type!");
}
protected boolean isKnownType(Class c)
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -25,7 +25,6 @@
import org.jboss.starobrno.util.Immutables;
import org.jboss.starobrno.util.Util;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -41,9 +40,9 @@
Fqn fqn;
Key dataKey, structureKey;
- public NodeImpl(Fqn fqn, Cache cache, ThreadLocal<Boolean> atomicityContainer)
+ public NodeImpl(Fqn fqn, Cache cache)
{
- super(atomicityContainer, cache);
+ super(cache);
this.fqn = fqn;
dataKey = new Key(fqn, Type.DATA);
structureKey = new Key(fqn, Type.STRUCTURE);
@@ -52,7 +51,7 @@
public Node<K, V> getParent()
{
if (fqn.isRoot()) return this;
- return new NodeImpl(fqn.getParent(), cache, batchStarted);
+ return new NodeImpl(fqn.getParent(), cache);
}
public Set<Node<K, V>> getChildren()
@@ -63,7 +62,7 @@
Set set = new HashSet();
for (Fqn f : getStructure().children.values())
{
- NodeImpl n = new NodeImpl(f, cache, batchStarted);
+ NodeImpl n = new NodeImpl(f, cache);
set.add(n);
}
return Immutables.immutableSetWrap(set);
@@ -108,7 +107,7 @@
try
{
Fqn absoluteChildFqn = Fqn.fromRelativeFqn(fqn, f);
- NodeImpl child = new NodeImpl(absoluteChildFqn, cache, batchStarted);
+ NodeImpl child = new NodeImpl(absoluteChildFqn, cache);
Structure s = getStructure();
s.children.put(f.getLastElement(), absoluteChildFqn);
updateStructure(s);
@@ -135,7 +134,7 @@
Fqn childFqn = s.children.remove(childName);
if (childFqn != null)
{
- Node child = new NodeImpl(childFqn, cache, batchStarted);
+ Node child = new NodeImpl(childFqn, cache);
child.removeChildren();
cache.remove(new Key(childFqn, Type.DATA));
cache.remove(new Key(childFqn, Type.STRUCTURE));
@@ -157,7 +156,7 @@
try
{
if (hasChild(f))
- return new NodeImpl(Fqn.fromRelativeFqn(fqn, f), cache, batchStarted);
+ return new NodeImpl(Fqn.fromRelativeFqn(fqn, f), cache);
else
return null;
}
@@ -173,7 +172,7 @@
try
{
if (hasChild(name))
- return new NodeImpl(Fqn.fromRelativeElements(fqn, name), cache, batchStarted);
+ return new NodeImpl(Fqn.fromRelativeElements(fqn, name), cache);
else
return null;
}
@@ -225,10 +224,8 @@
startAtomic();
try
{
- Map data = getData();
- V old = (V) data.put(key, value);
- putData(data);
- return old;
+ Map<K, V> data = getDataInternal();
+ return data.put(key, value);
}
finally
{
@@ -263,7 +260,6 @@
{
Map data = getDataInternal();
data.putAll(map);
- putData(data);
}
finally
{
@@ -273,7 +269,17 @@
public void replaceAll(Map<? extends K, ? extends V> map)
{
- putData(map);
+ startAtomic();
+ try
+ {
+ Map data = getDataInternal();
+ data.clear();
+ data.putAll(map);
+ }
+ finally
+ {
+ endAtomic();
+ }
}
public V get(K key)
@@ -286,10 +292,8 @@
startAtomic();
try
{
- Map data = getDataInternal();
- V old = (V) data.remove(key);
- putData(data);
- return old;
+ Map<K, V> data = getDataInternal();
+ return data.remove(key);
}
finally
{
@@ -299,7 +303,7 @@
public void clearData()
{
- putData(Collections.emptyMap());
+ getDataInternal().clear();
}
public int dataSize()
@@ -359,14 +363,9 @@
}
}
- void putData(Map m)
- {
- cache.put(dataKey, m);
- }
-
Map<K, V> getDataInternal()
{
- return (Map<K, V>) cache.get(dataKey);
+ return (Map<K, V>) atomicMapCache.getAtomicMap(dataKey);
}
void updateStructure(Structure s)
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -42,20 +42,13 @@
{
public TreeCacheImpl(Cache<K, V> cache)
{
- super(new ThreadLocal<Boolean>()
- {
- @Override
- protected Boolean initialValue()
- {
- return false;
- }
- }, cache);
+ super(cache);
createRoot();
}
public Node<K, V> getRoot()
{
- return new NodeImpl(Fqn.ROOT, cache, batchStarted);
+ return new NodeImpl(Fqn.ROOT, cache);
}
public V put(String fqn, K key, V value)
@@ -130,7 +123,7 @@
try
{
if (exists(fqn))
- return new NodeImpl(fqn, cache, batchStarted);
+ return new NodeImpl(fqn, cache);
else return null;
}
finally
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -22,42 +22,23 @@
package org.jboss.starobrno.tree;
import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.atomic.AtomicMapCache;
+import org.jboss.starobrno.batch.AutoBatchSupport;
import org.jboss.starobrno.util.Util;
import java.util.HashMap;
import java.util.Map;
-public class TreeStructureSupport
+public class TreeStructureSupport extends AutoBatchSupport
{
- ThreadLocal<Boolean> batchStarted;
- Cache cache;
- boolean batchOwner;
+ AtomicMapCache atomicMapCache;
- public TreeStructureSupport(ThreadLocal<Boolean> batchStarted, Cache cache)
+ public TreeStructureSupport(Cache cache)
{
- this.batchStarted = batchStarted;
this.cache = cache;
+ atomicMapCache = (AtomicMapCache) cache;
}
- void startAtomic()
- {
- if (!batchStarted.get())
- {
- cache.startBatch();
- batchStarted.set(true);
- batchOwner = true;
- }
- }
-
- void endAtomic()
- {
- if (batchOwner)
- {
- cache.endBatch(true);
- batchStarted.set(false);
- }
- }
-
public boolean exists(Fqn f)
{
startAtomic();
@@ -89,7 +70,7 @@
if (cache.containsKey(dataKey) && cache.containsKey(structureKey)) return;
Structure s = new Structure();
s.parent = fqn.getParent();
- cache.put(dataKey, new HashMap());
+ atomicMapCache.getAtomicMap(dataKey);
cache.put(structureKey, s);
}
finally
Added: core/branches/flat/src/test/java/org/jboss/starobrno/atomic/APITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/atomic/APITest.java (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/atomic/APITest.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -0,0 +1,254 @@
+/*
+ * 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.atomic;
+
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.Configuration.CacheMode;
+import org.jboss.starobrno.util.TestingUtil;
+import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+import java.util.Map;
+
+ at Test(groups = "functional")
+public class APITest
+{
+
+ private void assertIsEmpty(Map map)
+ {
+ assert map.size() == 0;
+ assert map.get("blah") == null;
+ assert !map.containsKey("blah");
+ }
+
+ private void assertIsEmptyMap(AtomicMapCache cache, Object key)
+ {
+ assertIsEmpty(cache.getAtomicMap(key));
+ }
+
+ public void testAtomicMap()
+ {
+ Configuration c = new Configuration();
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache = (AtomicMapCache) new DefaultCacheFactory().createCache(c);
+ try
+ {
+ AtomicMap map = cache.getAtomicMap("map");
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+
+ map.put("blah", "blah");
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+
+ map.clear();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+ }
+ finally
+ {
+ cache.stop();
+ }
+ }
+
+
+ public void testReadSafetyEmptyCache() throws Exception
+ {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache = (AtomicMapCache) new DefaultCacheFactory().createCache(c);
+ try
+ {
+ AtomicMap map = cache.getAtomicMap("map");
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+
+ DummyTransactionManager.getInstance().begin();
+ map.put("blah", "blah");
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+ Transaction t = DummyTransactionManager.getInstance().suspend();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+
+ DummyTransactionManager.getInstance().resume(t);
+ DummyTransactionManager.getInstance().commit();
+
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+
+ map.clear();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+ }
+ finally
+ {
+ cache.stop();
+ }
+ }
+
+ public void testReadSafetyNotEmptyCache() throws Exception
+ {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache = (AtomicMapCache) new DefaultCacheFactory().createCache(c);
+ try
+ {
+ AtomicMap map = cache.getAtomicMap("map");
+
+ DummyTransactionManager.getInstance().begin();
+ map.put("blah", "blah");
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+ Transaction t = DummyTransactionManager.getInstance().suspend();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+
+ DummyTransactionManager.getInstance().resume(t);
+ DummyTransactionManager.getInstance().commit();
+
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+
+ map.clear();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+ }
+ finally
+ {
+ cache.stop();
+ }
+ }
+
+ public void testReadSafetyRollback() throws Exception
+ {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache = (AtomicMapCache) new DefaultCacheFactory().createCache(c);
+ try
+ {
+ AtomicMap map = cache.getAtomicMap("map");
+
+ DummyTransactionManager.getInstance().begin();
+ map.put("blah", "blah");
+ assert map.size() == 1;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+ Transaction t = DummyTransactionManager.getInstance().suspend();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+
+ DummyTransactionManager.getInstance().resume(t);
+ DummyTransactionManager.getInstance().rollback();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache, "map");
+ }
+ finally
+ {
+ cache.stop();
+ }
+ }
+
+ public void testReplicationCommit() throws Exception
+ {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ c.setCacheMode(CacheMode.REPL_SYNC);
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache1 = (AtomicMapCache) new DefaultCacheFactory().createCache(c.clone());
+ AtomicMapCache cache2 = (AtomicMapCache) new DefaultCacheFactory().createCache(c.clone());
+
+ try
+ {
+ TestingUtil.blockUntilViewsReceived(20000, cache1, cache2);
+ AtomicMap map = cache1.getAtomicMap("map");
+
+ DummyTransactionManager.getInstance().begin();
+ map.put("existing", "existing");
+ map.put("blah", "blah");
+ DummyTransactionManager.getInstance().commit();
+
+ assert map.size() == 2;
+ assert map.get("blah").equals("blah");
+ assert map.containsKey("blah");
+
+ System.out.println("Map on cache 2 is " + cache2.getAtomicMap("map"));
+
+ assert cache2.getAtomicMap("map").size() == 2;
+ assert cache2.getAtomicMap("map").get("blah").equals("blah");
+ assert cache2.getAtomicMap("map").containsKey("blah");
+ }
+ finally
+ {
+ TestingUtil.killCaches(cache1, cache2);
+ }
+ }
+
+ public void testReplicationRollback() throws Exception
+ {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ c.setCacheMode(CacheMode.REPL_SYNC);
+ c.setInvocationBatchingEnabled(true);
+ AtomicMapCache cache1 = (AtomicMapCache) new DefaultCacheFactory().createCache(c.clone());
+ AtomicMapCache cache2 = (AtomicMapCache) new DefaultCacheFactory().createCache(c.clone());
+
+ try
+ {
+ TestingUtil.blockUntilViewsReceived(20000, cache1, cache2);
+ AtomicMap map = cache1.getAtomicMap("map");
+
+ DummyTransactionManager.getInstance().begin();
+ map.put("existing", "existing");
+ map.put("blah", "blah");
+ DummyTransactionManager.getInstance().rollback();
+
+ assertIsEmpty(map);
+ assertIsEmptyMap(cache1, "map");
+ assertIsEmptyMap(cache2, "map");
+ }
+ finally
+ {
+ TestingUtil.killCaches(cache1, cache2);
+ }
+ }
+}
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -1,7 +1,10 @@
package org.jboss.cache.api;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
import org.jboss.starobrno.CacheSPI;
import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.config.Configuration;
import org.jboss.starobrno.tree.Fqn;
import org.jboss.starobrno.tree.Node;
import org.jboss.starobrno.tree.TreeCache;
@@ -37,7 +40,9 @@
public void setUp() throws Exception
{
// start a single cache instance
- CacheSPI<Object, Object> cache = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache("configs/local-tx.xml", false);
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ CacheSPI<Object, Object> cache = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache(c, false);
cache.getConfiguration().setInvocationBatchingEnabled(true);
cache.start();
cacheTL.set(new TreeCacheImpl(cache));
@@ -355,7 +360,9 @@
{
TreeCache<Object, Object> cache = cacheTL.get();
+ assert DummyTransactionManager.getInstance().getTransaction() == null;
cache.put("/foo/1/2/3", "item", 1);
+ assert DummyTransactionManager.getInstance().getTransaction() == null;
assert 1 == (Integer) cache.get("/foo/1/2/3", "item");
tm.begin();
assert 1 == (Integer) cache.get("/foo/1/2/3", "item");
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java 2008-11-17 23:15:11 UTC (rev 7149)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java 2008-11-17 23:26:21 UTC (rev 7150)
@@ -1,8 +1,8 @@
package org.jboss.starobrno.tree.api;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
import org.jboss.starobrno.CacheSPI;
import org.jboss.starobrno.config.Configuration;
-import org.jboss.starobrno.config.parsing.XmlConfigurationParser;
import org.jboss.starobrno.manager.CacheManager;
import org.jboss.starobrno.tree.Fqn;
import org.jboss.starobrno.tree.Node;
@@ -33,10 +33,8 @@
public void setUp() throws Exception
{
// start a single cache instance
- XmlConfigurationParser parser = new XmlConfigurationParser();
- Configuration c;
- c = parser.parseFile("configs/local-tx.xml");
- c.setEvictionConfig(null);
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
CacheManager cm = new CacheManager(c);
cache = cm.createTreeCache(getClass().getSimpleName());
More information about the jbosscache-commits
mailing list