Skip to content

Commit

Permalink
WFLY-9940 Reduce metaspace usage in wildfly-clustering-web modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
pferraro committed Mar 2, 2018
1 parent e215f2f commit 25fa27e
Show file tree
Hide file tree
Showing 23 changed files with 233 additions and 134 deletions.
Expand Up @@ -21,8 +21,6 @@
*/
package org.wildfly.clustering.web.infinispan.session;

import java.util.stream.Stream;

import org.infinispan.Cache;
import org.infinispan.remoting.transport.Address;
import org.jboss.as.clustering.controller.CapabilityServiceBuilder;
Expand All @@ -36,6 +34,7 @@
import org.wildfly.clustering.infinispan.spi.InfinispanCacheRequirement;
import org.wildfly.clustering.registry.Registry;
import org.wildfly.clustering.service.Builder;
import org.wildfly.clustering.service.CompositeDependency;
import org.wildfly.clustering.service.InjectedValueDependency;
import org.wildfly.clustering.service.ValueDependency;
import org.wildfly.clustering.spi.ClusteringCacheRequirement;
Expand All @@ -46,7 +45,7 @@
* Service providing an Infinispan-based {@link RouteLocator}.
* @author Paul Ferraro
*/
public class InfinispanRouteLocatorBuilder implements CapabilityServiceBuilder<RouteLocator>, InfinispanRouteLocatorConfiguration {
public class InfinispanRouteLocatorBuilder implements CapabilityServiceBuilder<RouteLocator>, InfinispanRouteLocatorConfiguration, Value<RouteLocator> {

private final String containerName = InfinispanSessionManagerFactoryBuilder.DEFAULT_CACHE_CONTAINER;
private final String serverName;
Expand All @@ -64,6 +63,11 @@ public InfinispanRouteLocatorBuilder(String serverName, String deploymentName) {
this.deploymentName = deploymentName;
}

@Override
public RouteLocator getValue() {
return new InfinispanRouteLocator(this);
}

@Override
public ServiceName getServiceName() {
return ServiceName.JBOSS.append("clustering", "web", "locator", this.deploymentName);
Expand All @@ -79,10 +83,8 @@ public Builder<RouteLocator> configure(CapabilityServiceSupport support) {

@Override
public ServiceBuilder<RouteLocator> build(ServiceTarget target) {
Value<RouteLocator> value = () -> new InfinispanRouteLocator(this);
ServiceBuilder<RouteLocator> builder = target.addService(this.getServiceName(), new ValueService<>(value));
Stream.of(this.factory, this.registry, this.cache).forEach(dependency -> dependency.register(builder));
return builder.setInitialMode(ServiceController.Mode.ON_DEMAND);
ServiceBuilder<RouteLocator> builder = target.addService(this.getServiceName(), new ValueService<>(this)).setInitialMode(ServiceController.Mode.ON_DEMAND);
return new CompositeDependency(this.factory, this.registry, this.cache).register(builder);
}

@Override
Expand Down
Expand Up @@ -25,8 +25,10 @@
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.function.Consumer;

import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.jboss.as.clustering.controller.CapabilityServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.kohsuke.MetaInfServices;
Expand All @@ -46,7 +48,7 @@
* @author Paul Ferraro
*/
@MetaInfServices(RouteLocatorBuilderProvider.class)
public class InfinispanRouteLocatorBuilderProvider implements RouteLocatorBuilderProvider {
public class InfinispanRouteLocatorBuilderProvider implements RouteLocatorBuilderProvider, Consumer<ConfigurationBuilder> {

@Override
public CapabilityServiceBuilder<RouteLocator> getRouteLocatorBuilder(String serverName, String deploymentName) {
Expand All @@ -60,14 +62,7 @@ public Collection<CapabilityServiceBuilder<?>> getRouteLocatorConfigurationBuild
List<CapabilityServiceBuilder<?>> builders = new LinkedList<>();

builders.add(new RouteRegistryEntryProviderBuilder(serverName, routeDependency));
builders.add(new TemplateConfigurationBuilder(ServiceName.parse(InfinispanCacheRequirement.CONFIGURATION.resolve(containerName, serverName)), containerName, serverName, null, builder -> {
CacheMode mode = builder.clustering().cacheMode();
builder.clustering().cacheMode(mode.isClustered() ? CacheMode.REPL_SYNC : CacheMode.LOCAL);
// don't use DefaultConsistentHashFactory for REPL caches (WFLY-9276)
builder.clustering().hash().consistentHashFactory(null);
builder.clustering().l1().disable();
builder.persistence().clearStores();
}));
builders.add(new TemplateConfigurationBuilder(ServiceName.parse(InfinispanCacheRequirement.CONFIGURATION.resolve(containerName, serverName)), containerName, serverName, null, this));
builders.add(new CacheBuilder<>(ServiceName.parse(InfinispanCacheRequirement.CACHE.resolve(containerName, serverName)), containerName, serverName));
ServiceNameRegistry<ClusteringCacheRequirement> registry = requirement -> ServiceName.parse(requirement.resolve(containerName, serverName));
for (CacheBuilderProvider provider : ServiceLoader.load(DistributedCacheBuilderProvider.class, DistributedCacheBuilderProvider.class.getClassLoader())) {
Expand All @@ -76,4 +71,14 @@ public Collection<CapabilityServiceBuilder<?>> getRouteLocatorConfigurationBuild

return builders;
}

@Override
public void accept(ConfigurationBuilder builder) {
CacheMode mode = builder.clustering().cacheMode();
builder.clustering().cacheMode(mode.isClustered() ? CacheMode.REPL_SYNC : CacheMode.LOCAL);
// don't use DefaultConsistentHashFactory for REPL caches (WFLY-9276)
builder.clustering().hash().consistentHashFactory(null);
builder.clustering().l1().disable();
builder.persistence().clearStores();
}
}
Expand Up @@ -22,6 +22,7 @@
package org.wildfly.clustering.web.infinispan.session;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -306,21 +307,32 @@ void triggerPrePassivationEvents(ImmutableSession session) {
List<HttpSessionActivationListener> listeners = findListeners(session);
if (!listeners.isEmpty()) {
HttpSessionEvent event = new HttpSessionEvent(new ImmutableHttpSessionAdapter(session, this.context));
listeners.forEach(listener -> listener.sessionWillPassivate(event));
for (HttpSessionActivationListener listener : listeners) {
listener.sessionWillPassivate(event);
}
}
}

void triggerPostActivationEvents(ImmutableSession session) {
List<HttpSessionActivationListener> listeners = findListeners(session);
if (!listeners.isEmpty()) {
HttpSessionEvent event = new HttpSessionEvent(new ImmutableHttpSessionAdapter(session, this.context));
listeners.forEach(listener -> listener.sessionDidActivate(event));
for (HttpSessionActivationListener listener : listeners) {
listener.sessionDidActivate(event);
}
}
}

private static List<HttpSessionActivationListener> findListeners(ImmutableSession session) {
ImmutableSessionAttributes attributes = session.getAttributes();
return attributes.getAttributeNames().stream().map(name -> attributes.getAttribute(name)).filter(attribute -> attribute instanceof HttpSessionActivationListener).map(attribute -> (HttpSessionActivationListener) attribute).collect(Collectors.toList());
List<HttpSessionActivationListener> listeners = new ArrayList<>(attributes.getAttributeNames().size());
for (String name : attributes.getAttributeNames()) {
Object attribute = attributes.getAttribute(name);
if (attribute instanceof HttpSessionActivationListener) {
listeners.add((HttpSessionActivationListener) attribute);
}
}
return listeners;
}

// Session decorator that performs scheduling on close().
Expand Down
Expand Up @@ -23,7 +23,6 @@

import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.infinispan.Cache;
import org.infinispan.configuration.cache.ConfigurationBuilder;
Expand All @@ -48,6 +47,7 @@
import org.wildfly.clustering.infinispan.spi.service.TemplateConfigurationBuilder;
import org.wildfly.clustering.marshalling.spi.Marshallability;
import org.wildfly.clustering.service.Builder;
import org.wildfly.clustering.service.CompositeDependency;
import org.wildfly.clustering.service.InjectedValueDependency;
import org.wildfly.clustering.service.SuppliedValueService;
import org.wildfly.clustering.service.ValueDependency;
Expand All @@ -58,7 +58,7 @@
import org.wildfly.clustering.web.infinispan.logging.InfinispanWebLogger;
import org.wildfly.clustering.web.session.SessionManagerFactory;

public class InfinispanSessionManagerFactoryBuilder<C extends Marshallability, L> implements CapabilityServiceBuilder<SessionManagerFactory<L, TransactionBatch>>, InfinispanSessionManagerFactoryConfiguration<C, L> {
public class InfinispanSessionManagerFactoryBuilder<C extends Marshallability, L> implements CapabilityServiceBuilder<SessionManagerFactory<L, TransactionBatch>>, InfinispanSessionManagerFactoryConfiguration<C, L>, Supplier<SessionManagerFactory<L, TransactionBatch>> {
public static final String DEFAULT_CACHE_CONTAINER = "web";

@SuppressWarnings("rawtypes")
Expand Down Expand Up @@ -107,6 +107,11 @@ public InfinispanSessionManagerFactoryBuilder(SessionManagerFactoryConfiguration
this.cacheBuilder = new CacheBuilder<>(ServiceName.parse(InfinispanCacheRequirement.CACHE.resolve(this.containerName, cacheName)), this.containerName, cacheName);
}

@Override
public SessionManagerFactory<L, TransactionBatch> get() {
return new InfinispanSessionManagerFactory<>(this);
}

@Override
public ServiceName getServiceName() {
return ServiceName.JBOSS.append("clustering", "web", this.configuration.getDeploymentName());
Expand All @@ -128,13 +133,11 @@ public ServiceBuilder<SessionManagerFactory<L, TransactionBatch>> build(ServiceT
this.configurationBuilder.build(target).install();
this.cacheBuilder.build(target).install();

Supplier<SessionManagerFactory<L, TransactionBatch>> value = () -> new InfinispanSessionManagerFactory<>(this);
ServiceBuilder<SessionManagerFactory<L, TransactionBatch>> builder = target.addService(this.getServiceName(), new SuppliedValueService<>(Functions.identity(), value, Consumers.close()))
ServiceBuilder<SessionManagerFactory<L, TransactionBatch>> builder = target.addService(this.getServiceName(), new SuppliedValueService<>(Functions.identity(), this, Consumers.close()))
.addDependency(this.cacheBuilder.getServiceName(), Cache.class, this.cache)
.setInitialMode(ServiceController.Mode.ON_DEMAND)
;
Stream.of(this.group, this.affinityFactory, this.dispatcherFactory).forEach(dependency -> dependency.register(builder));
return builder;
return new CompositeDependency(this.group, this.affinityFactory, this.dispatcherFactory).register(builder);
}

@Override
Expand Down
Expand Up @@ -39,7 +39,7 @@
* Service that provides the {@link Map.Entry} for the routing {@link org.wildfly.clustering.registry.Registry}.
* @author Paul Ferraro
*/
public class RouteRegistryEntryProviderBuilder implements CapabilityServiceBuilder<Map.Entry<String, Void>> {
public class RouteRegistryEntryProviderBuilder implements CapabilityServiceBuilder<Map.Entry<String, Void>>, Function<String, Map.Entry<String, Void>> {

private final String serverName;
private final ValueDependency<String> route;
Expand All @@ -49,14 +49,18 @@ public RouteRegistryEntryProviderBuilder(String serverName, ValueDependency<Stri
this.route = route;
}

@Override
public Map.Entry<String, Void> apply(String route) {
return new AbstractMap.SimpleImmutableEntry<>(route, null);
}

@Override
public ServiceName getServiceName() {
return ServiceName.parse(ClusteringCacheRequirement.REGISTRY_ENTRY.resolve(InfinispanSessionManagerFactoryBuilder.DEFAULT_CACHE_CONTAINER, this.serverName));
}

@Override
public ServiceBuilder<Map.Entry<String, Void>> build(ServiceTarget target) {
Function<String, Map.Entry<String, Void>> mapper = route -> new AbstractMap.SimpleImmutableEntry<>(route, null);
return this.route.register(target.addService(this.getServiceName(), new MappedValueService<>(mapper, this.route))).setInitialMode(ServiceController.Mode.ON_DEMAND);
return this.route.register(target.addService(this.getServiceName(), new MappedValueService<>(this, this.route))).setInitialMode(ServiceController.Mode.ON_DEMAND);
}
}
Expand Up @@ -117,16 +117,20 @@ public void cancel(Locality locality) {
@Override
public void close() {
this.executor.shutdown();
this.expirationFutures.values().forEach(future -> future.cancel(false));
this.expirationFutures.values().stream().filter(future -> !future.isDone()).forEach(future -> {
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
// Ignore
for (Future<?> future : this.expirationFutures.values()) {
future.cancel(true);
}
for (Future<?> future : this.expirationFutures.values()) {
if (!future.isDone()) {
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
// Ignore
}
}
});
}
this.expirationFutures.clear();
}

Expand Down
Expand Up @@ -113,7 +113,9 @@ public Object getAttribute(String name) {
@Override
public void close() {
if (!this.properties.isTransactional()) {
this.mutations.values().forEach(Mutator::mutate);
for (Mutator mutator : this.mutations.values()) {
mutator.mutate();
}
}
this.mutations.clear();
}
Expand Down
Expand Up @@ -92,7 +92,9 @@ public SessionAttributeNamesEntry findValue(String id) {
public boolean remove(String id) {
SessionAttributeNamesEntry entry = this.namesCache.getAdvancedCache().withFlags(Flag.FORCE_SYNCHRONOUS).remove(new SessionAttributeNamesKey(id));
if (entry == null) return false;
entry.getNames().values().forEach(attributeId -> this.attributeCache.getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES).remove(new SessionAttributeKey(id, attributeId)));
for (Integer attributeId : entry.getNames().values()) {
this.attributeCache.getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES).remove(new SessionAttributeKey(id, attributeId));
}
return true;
}

Expand All @@ -101,13 +103,13 @@ public boolean evict(String id) {
SessionAttributeNamesKey key = new SessionAttributeNamesKey(id);
SessionAttributeNamesEntry entry = this.namesCache.getAdvancedCache().withFlags(EVICTION_FLAGS).get(key);
if (entry != null) {
entry.getNames().entrySet().stream().forEach(attribute -> {
for (Map.Entry<String, Integer> attribute : entry.getNames().entrySet()) {
try {
this.attributeCache.evict(new SessionAttributeKey(id, attribute.getValue()));
} catch (Throwable e) {
InfinispanWebLogger.ROOT_LOGGER.failedToPassivateSessionAttribute(e, id, attribute.getKey());
}
});
}
this.namesCache.getAdvancedCache().withFlags(Flag.FAIL_SILENTLY).evict(key);
}
return (entry != null);
Expand Down
Expand Up @@ -37,7 +37,10 @@ public enum SessionAttributeImmutability implements Predicate<Object> {
@Override
public boolean test(Object object) {
// Skip Collection test, we override this below to extend the immutability test for collection elements.
return EnumSet.complementOf(EnumSet.of(Immutability.COLLECTION)).stream().anyMatch(predicate -> predicate.test(object));
for (Immutability immutability : EnumSet.complementOf(EnumSet.of(Immutability.COLLECTION))) {
if (immutability.test(object)) return true;
}
return false;
}
},
COLLECTION() {
Expand All @@ -54,6 +57,11 @@ public boolean test(Object object) {
},
;

public static final Predicate<Object> INSTANCE = object -> EnumSet.allOf(SessionAttributeImmutability.class).stream().anyMatch(predicate -> predicate.test(object));
public static final Predicate<Object> INSTANCE = object -> {
for (SessionAttributeImmutability immutability : EnumSet.allOf(SessionAttributeImmutability.class)) {
if (immutability.test(object)) return true;
}
return false;
};
static final Predicate<Object> COLLECTION_INSTANCE = new CollectionImmutability(INSTANCE);
}
Expand Up @@ -21,6 +21,8 @@
*/
package org.wildfly.clustering.web.undertow.session;

import java.util.function.Function;

import org.jboss.as.clustering.controller.CapabilityServiceBuilder;
import org.jboss.as.controller.capability.CapabilityServiceSupport;
import org.jboss.as.web.session.RoutingSupport;
Expand All @@ -41,18 +43,22 @@
* Builds a distributable {@link SessionIdentifierCodec} service.
* @author Paul Ferraro
*/
public class DistributableSessionIdentifierCodecBuilder implements CapabilityServiceBuilder<SessionIdentifierCodec> {
public class DistributableSessionIdentifierCodecBuilder implements CapabilityServiceBuilder<SessionIdentifierCodec>, Function<RouteLocator, SessionIdentifierCodec> {

private final ServiceName name;
private final CapabilityServiceBuilder<RouteLocator> locatorBuilder;
private final RoutingSupport routing = new SimpleRoutingSupport();

public DistributableSessionIdentifierCodecBuilder(ServiceName name, String serverName, String deploymentName, RouteLocatorBuilderProvider provider) {
this.name = name;

this.locatorBuilder = provider.getRouteLocatorBuilder(serverName, deploymentName);
}

@Override
public SessionIdentifierCodec apply(RouteLocator locator) {
return new DistributableSessionIdentifierCodec(locator, this.routing);
}

@Override
public ServiceName getServiceName() {
return this.name;
Expand All @@ -68,7 +74,7 @@ public Builder<SessionIdentifierCodec> configure(CapabilityServiceSupport suppor
public ServiceBuilder<SessionIdentifierCodec> build(ServiceTarget target) {
this.locatorBuilder.build(target).setInitialMode(ServiceController.Mode.ON_DEMAND).install();
InjectedValue<RouteLocator> locatorValue = new InjectedValue<>();
Service<SessionIdentifierCodec> service = new MappedValueService<>(locator -> new DistributableSessionIdentifierCodec(locator, this.routing), locatorValue);
Service<SessionIdentifierCodec> service = new MappedValueService<>(this, locatorValue);
return target.addService(this.name, service)
.addDependency(this.locatorBuilder.getServiceName(), RouteLocator.class, locatorValue)
.setInitialMode(ServiceController.Mode.ON_DEMAND)
Expand Down

0 comments on commit 25fa27e

Please sign in to comment.