diff --git a/build/src/main/resources/docs/schema/wildfly-undertow_1_0.xsd b/build/src/main/resources/docs/schema/wildfly-undertow_1_0.xsd
index a5b038f6c559..6a185b364bfa 100644
--- a/build/src/main/resources/docs/schema/wildfly-undertow_1_0.xsd
+++ b/build/src/main/resources/docs/schema/wildfly-undertow_1_0.xsd
@@ -168,6 +168,7 @@
+
@@ -302,6 +303,18 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/AffinityIdentifierFactory.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/AffinityIdentifierFactory.java
new file mode 100644
index 000000000000..7e62a922c9d0
--- /dev/null
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/AffinityIdentifierFactory.java
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2013, Red Hat, Inc., 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.wildfly.clustering.web.infinispan;
+
+import org.infinispan.Cache;
+import org.infinispan.affinity.KeyAffinityService;
+import org.infinispan.affinity.KeyGenerator;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.jboss.as.clustering.infinispan.affinity.KeyAffinityServiceFactory;
+import org.wildfly.clustering.web.IdentifierFactory;
+
+/**
+ * {@link IdentifierFactory} that uses a {@link KeyAffinityService} to generate identifiers.
+ * @author Paul Ferraro
+ * @param the key type
+ */
+public class AffinityIdentifierFactory implements IdentifierFactory, KeyGenerator {
+
+ private final IdentifierFactory factory;
+ private final KeyAffinityService affinity;
+ private final EmbeddedCacheManager manager;
+
+ public AffinityIdentifierFactory(IdentifierFactory factory, Cache cache, KeyAffinityServiceFactory affinityFactory) {
+ this.factory = factory;
+ this.affinity = affinityFactory.createService(cache, this);
+ this.manager = cache.getCacheManager();
+ }
+
+ @Override
+ public K createIdentifier() {
+ return this.affinity.getKeyForAddress(this.manager.getAddress());
+ }
+
+ @Override
+ public K getKey() {
+ return this.factory.createIdentifier();
+ }
+
+ @Override
+ public void start() {
+ this.factory.start();
+ this.affinity.start();
+ }
+
+ @Override
+ public void stop() {
+ this.affinity.stop();
+ this.factory.stop();
+ }
+}
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/sso/SSOMutator.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/CacheEntryMutator.java
similarity index 59%
rename from clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/sso/SSOMutator.java
rename to clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/CacheEntryMutator.java
index b369939abc3b..d807144c8156 100644
--- a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/sso/SSOMutator.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/CacheEntryMutator.java
@@ -1,6 +1,6 @@
/*
* JBoss, Home of Professional Open Source.
- * Copyright 2013, Red Hat, Inc., and individual contributors
+ * Copyright 2014, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
@@ -19,7 +19,12 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
-package org.wildfly.clustering.web.infinispan.sso;
+
+package org.wildfly.clustering.web.infinispan;
+
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.infinispan.Cache;
import org.infinispan.context.Flag;
@@ -27,25 +32,31 @@
import org.jboss.as.clustering.infinispan.invoker.Mutator;
/**
- * Mutates an SSO in the distributed cache
+ * Mutates a given cache entry.
* @author Paul Ferraro
*/
-public class SSOMutator implements Mutator {
+public class CacheEntryMutator implements Mutator {
- private final Cache cache;
+ private final Cache cache;
private final CacheInvoker invoker;
- private final String id;
- final V value;
+ private final K id;
+ private final V value;
+ private final Set flags;
+ private final AtomicBoolean mutated = new AtomicBoolean(false);
- public SSOMutator(Cache cache, CacheInvoker invoker, String id, V value) {
+ public CacheEntryMutator(Cache cache, CacheInvoker invoker, K id, V value, Flag... flags) {
this.cache = cache;
this.invoker = invoker;
this.id = id;
this.value = value;
+ this.flags = EnumSet.of(Flag.IGNORE_RETURN_VALUES, flags);
}
@Override
public void mutate() {
- this.invoker.invoke(this.cache, new MutateOperation<>(this.id, this.value), Flag.IGNORE_RETURN_VALUES);
+ // We only ever have to perform a replace once within a batch
+ if (this.mutated.compareAndSet(false, true)) {
+ this.invoker.invoke(this.cache, new MutateOperation<>(this.id, this.value), this.flags.toArray(new Flag[this.flags.size()]));
+ }
}
}
diff --git a/clustering/web/spi/src/main/java/org/wildfly/clustering/web/sso/WebApplication.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/InfinispanBatcher.java
similarity index 53%
rename from clustering/web/spi/src/main/java/org/wildfly/clustering/web/sso/WebApplication.java
rename to clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/InfinispanBatcher.java
index 901911f0e6cc..7e65838e4e3b 100644
--- a/clustering/web/spi/src/main/java/org/wildfly/clustering/web/sso/WebApplication.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/InfinispanBatcher.java
@@ -19,43 +19,43 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
-package org.wildfly.clustering.web.sso;
+package org.wildfly.clustering.web.infinispan;
+
+import org.infinispan.Cache;
+import org.wildfly.clustering.web.Batch;
+import org.wildfly.clustering.web.Batcher;
/**
- * Uniquely identifies a web application.
+ * A Batcher based on Infinispan's batch capability.
* @author Paul Ferraro
*/
-public class WebApplication {
- private final String context;
- private final String host;
-
- public WebApplication(String context, String host) {
- this.context = context;
- this.host = host;
- }
+public class InfinispanBatcher implements Batcher {
- public String getContext() {
- return this.context;
- }
+ final Cache, ?> cache;
- public String getHost() {
- return this.host;
+ public InfinispanBatcher(Cache, ?> cache) {
+ this.cache = cache;
}
@Override
- public int hashCode() {
- return this.context.hashCode() ^ this.host.hashCode();
- }
+ public Batch startBatch() {
+ final boolean started = this.cache.startBatch();
+ return new Batch() {
+ @Override
+ public void close() {
+ this.end(true);
+ }
- @Override
- public boolean equals(Object object) {
- if ((object == null) || !(object instanceof WebApplication)) return false;
- WebApplication application = (WebApplication) object;
- return this.context.equals(application.context) && this.host.equals(application.host);
- }
+ @Override
+ public void discard() {
+ this.end(false);
+ }
- @Override
- public String toString() {
- return String.format("%s:%s", this.host, this.context);
+ private void end(boolean success) {
+ if (started) {
+ InfinispanBatcher.this.cache.endBatch(success);
+ }
+ }
+ };
}
}
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManager.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManager.java
index 40521cffb99f..79cc516a755d 100644
--- a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManager.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManager.java
@@ -36,8 +36,6 @@
import javax.servlet.http.HttpSessionListener;
import org.infinispan.Cache;
-import org.infinispan.affinity.KeyAffinityService;
-import org.infinispan.affinity.KeyGenerator;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.context.Flag;
import org.infinispan.distribution.ch.ConsistentHash;
@@ -53,10 +51,9 @@
import org.infinispan.notifications.cachelistener.event.TopologyChangedEvent;
import org.infinispan.remoting.transport.Address;
import org.jboss.as.clustering.concurrent.Scheduler;
-import org.jboss.as.clustering.infinispan.affinity.KeyAffinityServiceFactory;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
-import org.wildfly.clustering.web.Batch;
import org.wildfly.clustering.web.Batcher;
+import org.wildfly.clustering.web.IdentifierFactory;
import org.wildfly.clustering.web.infinispan.InfinispanWebLogger;
import org.wildfly.clustering.web.session.ImmutableHttpSessionAdapter;
import org.wildfly.clustering.web.session.ImmutableSession;
@@ -64,7 +61,6 @@
import org.wildfly.clustering.web.session.Session;
import org.wildfly.clustering.web.session.SessionAttributes;
import org.wildfly.clustering.web.session.SessionContext;
-import org.wildfly.clustering.web.session.SessionIdentifierFactory;
import org.wildfly.clustering.web.session.SessionManager;
import org.wildfly.clustering.web.session.SessionMetaData;
@@ -73,23 +69,23 @@
* @author Paul Ferraro
*/
@Listener
-public class InfinispanSessionManager implements SessionManager, KeyGenerator, Batcher, KeyFilter {
+public class InfinispanSessionManager implements SessionManager, KeyFilter {
private final SessionContext context;
- final Cache cache;
+ private final Batcher batcher;
+ private final Cache cache;
private final SessionFactory factory;
- private final SessionIdentifierFactory idFactory;
- private final KeyAffinityService affinity;
+ private final IdentifierFactory identifierFactory;
private final List> schedulers = new CopyOnWriteArrayList<>();
private final int maxActiveSessions;
private volatile Time defaultMaxInactiveInterval = new Time(30, TimeUnit.MINUTES);
private final boolean persistent;
- public InfinispanSessionManager(SessionContext context, SessionIdentifierFactory idFactory, Cache cache, SessionFactory factory, KeyAffinityServiceFactory affinityFactory, JBossWebMetaData metaData) {
+ public InfinispanSessionManager(SessionContext context, IdentifierFactory identifierFactory, Cache cache, SessionFactory factory, Batcher batcher, JBossWebMetaData metaData) {
this.context = context;
this.factory = factory;
- this.idFactory = idFactory;
+ this.identifierFactory = identifierFactory;
this.cache = cache;
- this.affinity = affinityFactory.createService(this.cache, this);
+ this.batcher = batcher;
this.maxActiveSessions = metaData.getMaxActiveSessions().intValue();
Configuration config = cache.getCacheConfiguration();
// If cache is clustered or configured with a write-through cache store
@@ -101,10 +97,10 @@ public InfinispanSessionManager(SessionContext context, SessionIdentifierFactory
@Override
public void start() {
this.cache.addListener(this, this);
- this.affinity.start();
- this.schedulers.add(new SessionExpirationScheduler(this, new ExpiredSessionRemover<>(this.factory)));
+ this.identifierFactory.start();
+ this.schedulers.add(new SessionExpirationScheduler(this.batcher, new ExpiredSessionRemover<>(this.factory)));
if (this.maxActiveSessions >= 0) {
- this.schedulers.add(new SessionEvictionScheduler(this, this.factory, this.maxActiveSessions));
+ this.schedulers.add(new SessionEvictionScheduler(this.batcher, this.factory, this.maxActiveSessions));
}
}
@@ -114,7 +110,7 @@ public void stop() {
scheduler.close();
}
this.schedulers.clear();
- this.affinity.stop();
+ this.identifierFactory.stop();
this.cache.removeListener(this);
}
@@ -123,31 +119,9 @@ public boolean accept(Object key) {
return key instanceof String;
}
- @Override
- public Batch startBatch() {
- final boolean started = this.cache.startBatch();
- return new Batch() {
- @Override
- public void close() {
- this.end(true);
- }
-
- @Override
- public void discard() {
- this.end(false);
- }
-
- private void end(boolean success) {
- if (started) {
- InfinispanSessionManager.this.cache.endBatch(success);
- }
- }
- };
- }
-
@Override
public Batcher getBatcher() {
- return this;
+ return this.batcher;
}
@Override
@@ -161,13 +135,8 @@ public void setDefaultMaxInactiveInterval(long value, TimeUnit unit) {
}
@Override
- public String getKey() {
- return this.idFactory.createSessionId();
- }
-
- @Override
- public String createSessionId() {
- return this.affinity.getKeyForAddress(this.cache.getCacheManager().getAddress());
+ public String createIdentifier() {
+ return this.identifierFactory.createIdentifier();
}
@Override
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactory.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactory.java
index 8e77127b91cc..69581a3712f3 100644
--- a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactory.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactory.java
@@ -36,7 +36,11 @@
import org.jboss.modules.Module;
import org.jboss.msc.service.AbstractService;
import org.jboss.msc.value.Value;
+import org.wildfly.clustering.web.Batcher;
+import org.wildfly.clustering.web.IdentifierFactory;
import org.wildfly.clustering.web.LocalContextFactory;
+import org.wildfly.clustering.web.infinispan.InfinispanBatcher;
+import org.wildfly.clustering.web.infinispan.AffinityIdentifierFactory;
import org.wildfly.clustering.web.infinispan.InfinispanWebMessages;
import org.wildfly.clustering.web.infinispan.session.coarse.CoarseSessionCacheEntry;
import org.wildfly.clustering.web.infinispan.session.coarse.CoarseSessionFactory;
@@ -45,7 +49,6 @@
import org.wildfly.clustering.web.infinispan.session.fine.FineSessionFactory;
import org.wildfly.clustering.web.infinispan.session.fine.SessionAttributeCacheKey;
import org.wildfly.clustering.web.session.SessionContext;
-import org.wildfly.clustering.web.session.SessionIdentifierFactory;
import org.wildfly.clustering.web.session.SessionManager;
import org.wildfly.clustering.web.session.SessionManagerFactory;
@@ -74,8 +77,10 @@ public SessionManagerFactory getValue() {
}
@Override
- public SessionManager createSessionManager(SessionContext context, SessionIdentifierFactory identifierFactory, LocalContextFactory localContextFactory) {
- return new InfinispanSessionManager<>(context, identifierFactory, this.cache.getValue(), this.getSessionFactory(context, localContextFactory), this.affinityFactory.getValue(), this.metaData);
+ public SessionManager createSessionManager(SessionContext context, IdentifierFactory identifierFactory, LocalContextFactory localContextFactory) {
+ Batcher batcher = new InfinispanBatcher(this.cache.getValue());
+ IdentifierFactory factory = new AffinityIdentifierFactory<>(identifierFactory, this.cache.getValue(), this.affinityFactory.getValue());
+ return new InfinispanSessionManager<>(context, factory, this.cache.getValue(), this.getSessionFactory(context, localContextFactory), batcher, this.metaData);
}
private SessionFactory, L> getSessionFactory(SessionContext context, LocalContextFactory localContextFactory) {
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactoryBuilder.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactoryBuilder.java
index fedc514805f5..c7a684142f74 100644
--- a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactoryBuilder.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/InfinispanSessionManagerFactoryBuilder.java
@@ -22,7 +22,6 @@
package org.wildfly.clustering.web.infinispan.session;
import org.infinispan.Cache;
-import org.infinispan.configuration.cache.Configuration;
import org.infinispan.manager.EmbeddedCacheManager;
import org.jboss.as.clustering.infinispan.CacheContainer;
import org.jboss.as.clustering.infinispan.affinity.KeyAffinityServiceFactory;
@@ -56,7 +55,6 @@ public ServiceBuilder buildDeploymentDependency(ServiceTa
String templateCacheName = templateCacheServiceName.getSimpleName();
ServiceName containerServiceName = templateCacheServiceName.getParent();
String containerName = containerServiceName.getSimpleName();
- ServiceName templateCacheConfigurationServiceName = CacheConfigurationService.getServiceName(containerName, templateCacheName);
String host = deploymentServiceName.getParent().getSimpleName();
String contextPath = deploymentServiceName.getSimpleName();
StringBuilder cacheNameBuilder = new StringBuilder(host).append(contextPath);
@@ -67,11 +65,7 @@ public ServiceBuilder buildDeploymentDependency(ServiceTa
ServiceName cacheConfigurationServiceName = CacheConfigurationService.getServiceName(containerName, cacheName);
ServiceName cacheServiceName = CacheService.getServiceName(containerName, cacheName);
- InjectedValue container = new InjectedValue<>();
- InjectedValue config = new InjectedValue<>();
- target.addService(cacheConfigurationServiceName, new SessionCacheConfigurationService(cacheName, container, config, metaData))
- .addDependency(containerServiceName, EmbeddedCacheManager.class, container)
- .addDependency(templateCacheConfigurationServiceName, Configuration.class, config)
+ SessionCacheConfigurationService.build(target, containerName, cacheName, templateCacheName, metaData)
.setInitialMode(ServiceController.Mode.ON_DEMAND)
.install()
;
diff --git a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/CacheMutator.java b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/MutableDetector.java
similarity index 71%
rename from clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/CacheMutator.java
rename to clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/MutableDetector.java
index 8c1ebd677089..79ef5ca2346f 100644
--- a/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/CacheMutator.java
+++ b/clustering/web/infinispan/src/main/java/org/wildfly/clustering/web/infinispan/session/MutableDetector.java
@@ -34,25 +34,18 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Currency;
-import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.infinispan.Cache;
-import org.infinispan.context.Flag;
-import org.jboss.as.clustering.infinispan.invoker.CacheInvoker;
-import org.jboss.as.clustering.infinispan.invoker.Mutator;
import org.wildfly.clustering.web.annotation.Immutable;
/**
- * Ensures that an object that exists in the distributed cache replicates.
+ * Determines whether a given object is mutable.
* @author Paul Ferraro
*/
-public class CacheMutator implements Mutator {
+public class MutableDetector {
private static List