diff --git a/server/integration/feature-pack/src/main/resources/modules/system/layers/base/org/infinispan/counter/main/module.xml b/server/integration/feature-pack/src/main/resources/modules/system/layers/base/org/infinispan/counter/main/module.xml index 32eb41341776..0a1205786518 100644 --- a/server/integration/feature-pack/src/main/resources/modules/system/layers/base/org/infinispan/counter/main/module.xml +++ b/server/integration/feature-pack/src/main/resources/modules/system/layers/base/org/infinispan/counter/main/module.xml @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/SecurityActions.java b/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/SecurityActions.java index a247c2675380..96b191341986 100644 --- a/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/SecurityActions.java +++ b/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/SecurityActions.java @@ -6,12 +6,15 @@ import java.security.PrivilegedExceptionAction; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.infinispan.AdvancedCache; import org.infinispan.Cache; import org.infinispan.cli.interpreter.Interpreter; import org.infinispan.configuration.cache.Configuration; +import org.infinispan.counter.EmbeddedCounterManagerFactory; +import org.infinispan.counter.api.CounterManager; import org.infinispan.factories.ComponentRegistry; import org.infinispan.factories.GlobalComponentRegistry; import org.infinispan.interceptors.AsyncInterceptor; @@ -306,5 +309,9 @@ public static Set getSitesView(DefaultCacheContainer cacheManager) { GetSitesViewAction action = new GetSitesViewAction(cacheManager); return doPrivileged(action); } + + public static Optional findCounterManager(EmbeddedCacheManager cacheManager) { + return Optional.ofNullable(doPrivileged((PrivilegedAction) () -> EmbeddedCounterManagerFactory.asCounterManager(cacheManager))); + } } diff --git a/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/spi/service/CounterServiceName.java b/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/spi/service/CounterServiceName.java new file mode 100644 index 000000000000..600afc283c76 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/infinispan/server/infinispan/spi/service/CounterServiceName.java @@ -0,0 +1,16 @@ +package org.infinispan.server.infinispan.spi.service; + +import org.jboss.msc.service.ServiceName; + +/** + * Enumeration of service name factories for services associated with a counter. + * + * @author Vladimir Blagojevic + */ +public class CounterServiceName { + + public static ServiceName getServiceName(String container, String counterName) { + return CacheContainerServiceName.CACHE_CONTAINER.getServiceName(container).append(counterName); + } + +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java index 96deedb231bd..82b59279f47f 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java @@ -90,6 +90,7 @@ public enum Attribute { INDEX(ModelKeys.INDEX), INITIAL_CLUSTER_SIZE(ModelKeys.INITIAL_CLUSTER_SIZE), INITIAL_CLUSTER_TIMEOUT(ModelKeys.INITIAL_CLUSTER_TIMEOUT), + INITIAL_VALUE(ModelKeys.INITIAL_VALUE), INTERVAL(ModelKeys.INTERVAL), ISOLATION(ModelKeys.ISOLATION), JNDI_NAME(ModelKeys.JNDI_NAME), @@ -100,6 +101,7 @@ public enum Attribute { LISTENER_EXECUTOR(ModelKeys.LISTENER_EXECUTOR), LOCK_TIMEOUT(ModelKeys.LOCK_TIMEOUT), LOCKING(ModelKeys.LOCKING), + LOWER_BOUND(ModelKeys.LOWER_BOUND), MACHINE(ModelKeys.MACHINE), MAPPER(ModelKeys.MAPPER), MARSHALLER(ModelKeys.MARSHALLER), @@ -120,6 +122,7 @@ public enum Attribute { MODULE(ModelKeys.MODULE), NAME(ModelKeys.NAME), NAMESPACE(XMLConstants.XMLNS_ATTRIBUTE), + NUM_OWNERS(ModelKeys.NUM_OWNERS), NOTIFICATIONS(ModelKeys.NOTIFICATIONS), OUTBOUND_SOCKET_BINDING(ModelKeys.OUTBOUND_SOCKET_BINDING), OWNERS(ModelKeys.OWNERS), @@ -140,6 +143,7 @@ public enum Attribute { READ_ONLY(ModelKeys.READ_ONLY), REALM(ModelKeys.REALM), RELATIVE_TO(ModelKeys.RELATIVE_TO), + RELIABILITY(ModelKeys.RELIABILITY), REMOTE_CACHE(ModelKeys.REMOTE_CACHE), @Deprecated REMOTE_COMMAND_EXECUTOR(ModelKeys.REMOTE_COMMAND_EXECUTOR), @@ -168,6 +172,7 @@ public enum Attribute { STATISTICS_AVAILABLE(ModelKeys.STATISTICS_AVAILABLE), STRICT_PEER_TO_PEER(ModelKeys.STRICT_PEER_TO_PEER), STOP_TIMEOUT(ModelKeys.STOP_TIMEOUT), + STORAGE(ModelKeys.STORAGE), STRATEGY(ModelKeys.STRATEGY), STRIPING(ModelKeys.STRIPING), TAKE_BACKUP_OFFLINE_AFTER_FAILURES(ModelKeys.TAKE_BACKUP_OFFLINE_AFTER_FAILURES), @@ -179,6 +184,8 @@ public enum Attribute { TOTAL_ORDER_EXECUTOR(ModelKeys.TOTAL_ORDER_EXECUTOR), TYPE(ModelKeys.TYPE), USERNAME(ModelKeys.USERNAME), + UPPER_BOUND(ModelKeys.UPPER_BOUND), + VALUE(ModelKeys.VALUE), WAIT_TIME(ModelKeys.WAIT_TIME), WHEN_SPLIT(ModelKeys.WHEN_SPLIT), ; diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerCountersResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerCountersResource.java new file mode 100644 index 000000000000..653f99bab598 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerCountersResource.java @@ -0,0 +1,64 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.infinispan.counter.configuration.CounterManagerConfigurationBuilder; +import org.infinispan.counter.configuration.Reliability; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; +import org.jboss.as.controller.SimpleAttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.SimpleResourceDefinition; +import org.jboss.as.controller.registry.AttributeAccess; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.as.controller.services.path.ResolvePathHandler; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; + +/** + * CacheContainerCountersResource + * + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class CacheContainerCountersResource extends SimpleResourceDefinition { + static final PathElement PATH = PathElement.pathElement(ModelKeys.COUNTERS, ModelKeys.COUNTERS_NAME); + + //attributes + static final SimpleAttributeDefinition RELIABILITY = new SimpleAttributeDefinitionBuilder(ModelKeys.RELIABILITY, + ModelType.STRING, false) + .setXmlName(Attribute.RELIABILITY.getLocalName()) + .setAllowExpression(false) + .setAllowedValues(Reliability.AVAILABLE.toString(), Reliability.CONSISTENT.toString()) + .setDefaultValue(new ModelNode().set(CounterManagerConfigurationBuilder.defaultConfiguration().reliability().toString())) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .build(); + + static final SimpleAttributeDefinition NUM_OWNERS = new SimpleAttributeDefinitionBuilder(ModelKeys.NUM_OWNERS, + ModelType.LONG, false) + .setXmlName(Attribute.NUM_OWNERS.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .setDefaultValue(new ModelNode().set(CounterManagerConfigurationBuilder.defaultConfiguration().numOwners())) + .build(); + + private final boolean runtimeRegistration; + + CacheContainerCountersResource(ResolvePathHandler resolvePathHandler, boolean runtimeRegistration) { + super(PATH, new InfinispanResourceDescriptionResolver(ModelKeys.CACHE_CONTAINER, ModelKeys.COUNTERS), + CacheConfigOperationHandlers.CONTAINER_CONFIGURATIONS_ADD, ReloadRequiredRemoveStepHandler.INSTANCE); + this.runtimeRegistration = runtimeRegistration; + } + + @Override + public void registerChildren(ManagementResourceRegistration rr) { + rr.registerSubModel(new StrongCounterResource(runtimeRegistration)); + rr.registerSubModel(new WeakCounterResource(runtimeRegistration)); + } + + @Override + public void registerAttributes(ManagementResourceRegistration resourceRegistration) { + super.registerAttributes(resourceRegistration); + if (runtimeRegistration) { + CountersMetricsHandler.INSTANCE.registerMetrics(resourceRegistration); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerResource.java index a09f8521fec2..5289ec8579c7 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerResource.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheContainerResource.java @@ -403,5 +403,6 @@ public void registerChildren(ManagementResourceRegistration resourceRegistration resourceRegistration.registerSubModel(new InvalidationCacheResource(resolvePathHandler, runtimeRegistration)); resourceRegistration.registerSubModel(new ReplicatedCacheResource(resolvePathHandler, runtimeRegistration)); resourceRegistration.registerSubModel(new DistributedCacheResource(resolvePathHandler, runtimeRegistration)); + resourceRegistration.registerSubModel(new CacheContainerCountersResource(resolvePathHandler, runtimeRegistration)); } } diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterAddHandler.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterAddHandler.java new file mode 100644 index 000000000000..6f66d7f2d3e3 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterAddHandler.java @@ -0,0 +1,164 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; + +import java.util.ArrayList; +import java.util.Collection; + +import org.infinispan.counter.api.CounterConfiguration; +import org.infinispan.counter.api.CounterConfiguration.Builder; +import org.infinispan.counter.api.CounterType; +import org.infinispan.counter.api.Storage; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.infinispan.spi.service.CacheContainerServiceName; +import org.infinispan.server.infinispan.spi.service.CounterServiceName; +import org.jboss.as.controller.AbstractAddStepHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PathAddress; +import org.jboss.dmr.ModelNode; +import org.jboss.msc.service.Service; +import org.jboss.msc.service.ServiceBuilder; +import org.jboss.msc.service.ServiceController; +import org.jboss.msc.service.ServiceTarget; +import org.jboss.msc.value.InjectedValue; + +/** + * Add operation handler for /subsystem=infinispan/cache-container=clustered/counter=* + * + * @author Vladimir Blagojevic + * + */ +public class CounterAddHandler extends AbstractAddStepHandler implements RestartableServiceHandler{ + + CounterAddHandler() { + } + + @Override + protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) + throws OperationFailedException { + + super.performRuntime(context, operation, model); + + this.installRuntimeServices(context, operation, model, null); + } + + @Override + public Collection> installRuntimeServices(OperationContext context, ModelNode operation, + ModelNode containerModel, ModelNode cacheModel) throws OperationFailedException { + + String counterName = getCounterName(operation); + String containerName = getContainerName(operation); + String counterType = getCounterType(operation); + + Builder b = getBuilder(containerModel, counterType); + processModelNode(context, containerModel, b); + String name = CounterResource.COUNTER_NAME.resolveModelAttribute(context, containerModel).asString(); + if (!counterName.equals(name)) { + throw new OperationFailedException("Counter node name and node's name attribute should be the same"); + } + + // wire counter service for this counter + Collection> controllers = new ArrayList<>(1); + ServiceController service = this.installCounterService(context.getServiceTarget(), + containerName, counterName, b.build()); + controllers.add(service); + + return controllers; + } + + @Override + public void removeRuntimeServices(OperationContext context, ModelNode operation, ModelNode containerModel, + ModelNode cacheModel) throws OperationFailedException { + + String counterName = getCounterName(operation); + String containerName = getContainerName(operation); + + context.removeService(CounterServiceName.getServiceName(containerName, counterName)); + } + + private ServiceController installCounterService(ServiceTarget target, String containerName, + String configurationName, CounterConfiguration configuration) { + final InjectedValue container = new InjectedValue<>(); + final CounterConfigurationDependencies dependencies = new CounterConfigurationDependencies(container); + final Service service = new CounterService(configuration, configurationName, dependencies); + final ServiceBuilder builder = target.addService(CounterServiceName.getServiceName(containerName, configurationName), service) + .addDependency(CacheContainerServiceName.CACHE_CONTAINER.getServiceName(containerName), EmbeddedCacheManager.class, container); + return builder.install(); + } + + @Override + protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { + this.populate(operation, model); + } + + void populate(ModelNode fromModel, ModelNode toModel) throws OperationFailedException { + for (AttributeDefinition attr : CounterResource.ATTRIBUTES) { + attr.validateAndSet(fromModel, toModel); + } + } + + private String getCounterName(ModelNode operation) { + PathAddress counterAddress = getCounterAddressFromOperation(operation); + return counterAddress.getLastElement().getValue(); + } + + private String getContainerName(ModelNode operation) { + PathAddress containerAddress = getCacheContainerAddressFromOperation(operation); + return containerAddress.getLastElement().getValue(); + } + + private PathAddress getCacheContainerAddressFromOperation(ModelNode operation) { + PathAddress counterAddress = getCounterAddressFromOperation(operation); + return counterAddress.subAddress(0, counterAddress.size() - 2); + } + + private String getCounterType(ModelNode operation) { + PathAddress counterAddress = getCounterAddressFromOperation(operation); + int size = counterAddress.size(); + PathAddress subAddress = counterAddress.subAddress(size - 1, size); + return subAddress.getLastElement().getKey(); + } + + private PathAddress getCounterAddressFromOperation(ModelNode operation) { + return PathAddress.pathAddress(operation.get(OP_ADDR)); + } + + private Builder getBuilder(ModelNode counter, String counterType) { + boolean isWeakCounter = ModelKeys.WEAK_COUNTER.equals(counterType); + if (isWeakCounter) { + return CounterConfiguration.builder(CounterType.WEAK); + } else { + ModelNode lowerBoundModel = counter.get(ModelKeys.LOWER_BOUND); + ModelNode upperBoundModel = counter.get(ModelKeys.UPPER_BOUND); + boolean isBounded = lowerBoundModel.isDefined() || upperBoundModel.isDefined(); + return isBounded ? CounterConfiguration.builder(CounterType.BOUNDED_STRONG) + : CounterConfiguration.builder(CounterType.UNBOUNDED_STRONG); + } + } + + void processModelNode(OperationContext context, ModelNode counter, + CounterConfiguration.Builder builder) throws OperationFailedException { + + long initialValue = CounterResource.INITIAL_VALUE.resolveModelAttribute(context, counter).asLong(); + String storageType = CounterResource.STORAGE.resolveModelAttribute(context, counter).asString(); + + builder.initialValue(initialValue); + builder.storage(Storage.valueOf(storageType)); + } + + private static class CounterConfigurationDependencies implements CounterService.Dependencies { + + private InjectedValue container; + public CounterConfigurationDependencies(InjectedValue container) { + this.container = container; + } + + @Override + public EmbeddedCacheManager getCacheContainer() { + return this.container.getValue(); + } + + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterMetricsHandler.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterMetricsHandler.java new file mode 100644 index 000000000000..d193156af83a --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterMetricsHandler.java @@ -0,0 +1,84 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; + +import org.infinispan.counter.EmbeddedCounterManagerFactory; +import org.infinispan.counter.api.CounterManager; +import org.infinispan.counter.api.StrongCounter; +import org.infinispan.counter.api.WeakCounter; +import org.infinispan.server.infinispan.spi.service.CacheContainerServiceName; +import org.jboss.as.clustering.infinispan.DefaultCacheContainer; +import org.jboss.as.controller.AbstractRuntimeOnlyHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; +import org.jboss.msc.service.ServiceController; + +/** + * Reflects runtime Counter attributes + * + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class CounterMetricsHandler extends AbstractRuntimeOnlyHandler { + + public static final CounterMetricsHandler INSTANCE = new CounterMetricsHandler(); + + private static final int CACHE_CONTAINER_INDEX = 1; + private static final int COUNTER_INDEX = 3; + + @Override + protected void executeRuntimeStep(OperationContext context, ModelNode operation) throws OperationFailedException { + + final ModelNode result = new ModelNode(); + final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); + final String cacheContainerName = address.getElement(CACHE_CONTAINER_INDEX).getValue(); + final String counterType = address.getElement(COUNTER_INDEX).getKey(); + final String counterName = address.getElement(COUNTER_INDEX).getValue(); + final ServiceController controller = context.getServiceRegistry(false) + .getService(CacheContainerServiceName.CACHE_CONTAINER.getServiceName(cacheContainerName)); + + Long value = null; + if (controller != null) { + DefaultCacheContainer cacheManager = (DefaultCacheContainer) controller.getValue(); + CounterManager counterManager = EmbeddedCounterManagerFactory.asCounterManager(cacheManager); + if (ModelKeys.STRONG_COUNTER.equals(counterType)) { + StrongCounter sc = counterManager.getStrongCounter(counterName); + value = sc.sync().getValue(); + } else { + WeakCounter wc = counterManager.getWeakCounter(counterName); + value = wc.sync().getValue(); + } + result.set(value); + } + context.getResult().set(result); + } + + public void registerMetrics(ManagementResourceRegistration container) { + for (CounterMetrics metric : CounterMetrics.values()) { + container.registerMetric(metric.definition, this); + } + } + + public enum CounterMetrics { + + VALUE(MetricKeys.VALUE, ModelType.LONG); + + final AttributeDefinition definition; + + CounterMetrics(String attributeName, ModelType type) { + this.definition = new SimpleAttributeDefinitionBuilder(attributeName, type).setAllowNull(false) + .setStorageRuntime().build(); + } + + @Override + public final String toString() { + return definition.getName(); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterResource.java new file mode 100644 index 000000000000..9502128811a2 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterResource.java @@ -0,0 +1,235 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import static org.jboss.as.controller.PathAddress.pathAddress; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; + +import java.util.Optional; + +import org.infinispan.counter.api.CounterManager; +import org.infinispan.counter.api.Storage; +import org.infinispan.counter.api.StrongCounter; +import org.infinispan.counter.api.WeakCounter; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.infinispan.SecurityActions; +import org.jboss.as.controller.AbstractAddStepHandler; +import org.jboss.as.controller.AbstractRemoveStepHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationDefinition; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.OperationStepHandler; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.SimpleAttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.SimpleOperationDefinitionBuilder; +import org.jboss.as.controller.SimpleResourceDefinition; +import org.jboss.as.controller.descriptions.ResourceDescriptionResolver; +import org.jboss.as.controller.registry.AttributeAccess; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; + +/** + * Resource description for the addressable resource + * /subsystem=infinispan/cache-container=X/counter=COUNTERS + * + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class CounterResource extends SimpleResourceDefinition { + + //attributes + static final SimpleAttributeDefinition COUNTER_NAME = new SimpleAttributeDefinitionBuilder(ModelKeys.NAME, + ModelType.STRING, false) + .setXmlName(Attribute.NAME.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .build(); + + static final SimpleAttributeDefinition STORAGE = new SimpleAttributeDefinitionBuilder(ModelKeys.STORAGE, + ModelType.STRING, false) + .setXmlName(Attribute.STORAGE.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .setAllowedValues(Storage.VOLATILE.toString(), Storage.PERSISTENT.toString()) + .setDefaultValue(new ModelNode().set(Storage.VOLATILE.toString())) + .build(); + + static final SimpleAttributeDefinition INITIAL_VALUE = new SimpleAttributeDefinitionBuilder(ModelKeys.INITIAL_VALUE, + ModelType.LONG, true) + .setXmlName(Attribute.INITIAL_VALUE.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .setDefaultValue(new ModelNode().set(0)) + .build(); + + static final AttributeDefinition[] ATTRIBUTES = { COUNTER_NAME, STORAGE, INITIAL_VALUE }; + + // operations + + private static final OperationDefinition COUNTER_RESET = buildOperation("counter-reset").build(); + private static final OperationDefinition COUNTER_INCREASE = buildOperation("counter-increase").build(); + private static final OperationDefinition COUNTER_DECREASE = buildOperation("counter-decrease").build(); + + private final boolean runtimeRegistration; + + public CounterResource(PathElement pathElement, ResourceDescriptionResolver descriptionResolver, + AbstractAddStepHandler addHandler, OperationStepHandler removeHandler, boolean runtimeRegistration) { + super(pathElement, descriptionResolver, addHandler, removeHandler); + this.runtimeRegistration = runtimeRegistration; + } + + @Override + public void registerAttributes(ManagementResourceRegistration resourceRegistration) { + super.registerAttributes(resourceRegistration); + for (AttributeDefinition attr : ATTRIBUTES) { + resourceRegistration.registerReadOnlyAttribute(attr, null); + } + + if (runtimeRegistration) { + CounterMetricsHandler.INSTANCE.registerMetrics(resourceRegistration); + } + } + + @Override + public void registerOperations(ManagementResourceRegistration resourceRegistration) { + super.registerOperations(resourceRegistration); + if (runtimeRegistration) { + resourceRegistration.registerOperationHandler(CounterResource.COUNTER_RESET, CounterResetCommand.INSTANCE); + resourceRegistration.registerOperationHandler(CounterResource.COUNTER_INCREASE, + CounterIncreaseCommand.INSTANCE); + resourceRegistration.registerOperationHandler(CounterResource.COUNTER_DECREASE, + CounterDecreaseCommand.INSTANCE); + } + } + + private static SimpleOperationDefinitionBuilder buildOperation(String name) { + return new SimpleOperationDefinitionBuilder(name, new InfinispanResourceDescriptionResolver(ModelKeys.COUNTERS)) + .setRuntimeOnly(); + } + + private static PathElement counterElement(ModelNode operation) { + final PathAddress address = pathAddress(operation.require(OP_ADDR)); + final PathElement counterElement = address.getElement(address.size() - 1); + return counterElement; + } + + private static String counterName(ModelNode operation) { + PathElement counterElement = counterElement(operation); + return counterElement.getValue(); + } + + private static String counterType(ModelNode operation) { + PathElement counterElement = counterElement(operation); + return counterElement.getKey(); + } + + private static OperationFailedException counterManagerNotFound() { + return new OperationFailedException("CounterManager not found in server."); + } + + public static class CounterRemoveHandler extends AbstractRemoveStepHandler { + + private final CounterAddHandler handler; + + public CounterRemoveHandler() { + handler = new CounterAddHandler(); + } + + @Override + protected void performRuntime(final OperationContext context, final ModelNode operation, final ModelNode model) throws OperationFailedException { + handler.removeRuntimeServices(context, operation, null, null); + } + + @Override + protected void recoverServices(final OperationContext context, final ModelNode operation, final ModelNode model) throws OperationFailedException { + handler.performRuntime(context, operation, model); + } + } + + private static class CounterResetCommand extends BaseCounterManagerCommand { + private static final CounterResetCommand INSTANCE = new CounterResetCommand(); + + @Override + protected ModelNode invoke(CounterManager counterManager, ModelNode operation) + throws Exception { + final String counterName = counterName(operation); + final String counterType = counterType(operation); + if (counterManager.isDefined(counterName)) { + boolean isStrongCounter = ModelKeys.STRONG_COUNTER.equals(counterType); + if (isStrongCounter) { + StrongCounter strongCounter = counterManager.getStrongCounter(counterName); + strongCounter.sync().reset(); + } else { + WeakCounter weakCounter = counterManager.getWeakCounter(counterName); + weakCounter.sync().reset(); + } + } + return new ModelNode(); + } + } + + private static class CounterIncreaseCommand extends BaseCounterManagerCommand { + private static final CounterIncreaseCommand INSTANCE = new CounterIncreaseCommand(); + + @Override + protected ModelNode invoke(CounterManager counterManager, ModelNode operation) + throws Exception { + final String counterName = counterName(operation); + final String counterType = counterType(operation); + if (counterManager.isDefined(counterName)) { + boolean isStrongCounter = ModelKeys.STRONG_COUNTER.equals(counterType); + if (isStrongCounter) { + StrongCounter strongCounter = counterManager.getStrongCounter(counterName); + strongCounter.sync().incrementAndGet(); + } else { + WeakCounter weakCounter = counterManager.getWeakCounter(counterName); + weakCounter.sync().increment(); + } + } + return new ModelNode(); + } + } + + private static class CounterDecreaseCommand extends BaseCounterManagerCommand { + private static final CounterDecreaseCommand INSTANCE = new CounterDecreaseCommand(); + + @Override + protected ModelNode invoke(CounterManager counterManager, ModelNode operation) + throws Exception { + final String counterName = counterName(operation); + final String counterType = counterType(operation); + if (counterManager.isDefined(counterName)) { + boolean isStrongCounter = ModelKeys.STRONG_COUNTER.equals(counterType); + if (isStrongCounter) { + StrongCounter strongCounter = counterManager.getStrongCounter(counterName); + strongCounter.sync().decrementAndGet(); + } else { + WeakCounter weakCounter = counterManager.getWeakCounter(counterName); + weakCounter.sync().decrement(); + } + } + return new ModelNode(); + } + } + + private static abstract class BaseCounterManagerCommand extends CacheContainerCommands { + + BaseCounterManagerCommand() { + //path to container from counter address has two elements + super(2); + } + + abstract ModelNode invoke(CounterManager counterManager, ModelNode operation) + throws Exception; + + @Override + protected final ModelNode invokeCommand(EmbeddedCacheManager cacheManager, OperationContext context, + ModelNode operation) throws Exception { + Optional optCounterManager = SecurityActions.findCounterManager(cacheManager); + CounterManager counterManager = optCounterManager.orElseThrow(CounterResource::counterManagerNotFound); + return invoke(counterManager, operation); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterService.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterService.java new file mode 100644 index 000000000000..a9519aea79f4 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CounterService.java @@ -0,0 +1,74 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.infinispan.counter.EmbeddedCounterManagerFactory; +import org.infinispan.counter.api.CounterConfiguration; +import org.infinispan.counter.api.CounterManager; +import org.infinispan.manager.EmbeddedCacheManager; +import org.jboss.logging.Logger; +import org.jboss.msc.service.Service; +import org.jboss.msc.service.StartContext; +import org.jboss.msc.service.StopContext; + +/** + * @author Vladimir Blagojevic + * + */ +public class CounterService implements Service { + + private static final Logger log = Logger.getLogger(CounterService.class.getPackage().getName()); + + private final Dependencies dependencies; + private final String counterConfigurationName; + private final CounterConfiguration counterConfiguration; + + public interface Dependencies { + EmbeddedCacheManager getCacheContainer(); + } + + public CounterService(CounterConfiguration configuration, String configurationName, Dependencies dependencies) { + this.counterConfiguration = configuration; + this.counterConfigurationName = configurationName; + this.dependencies = dependencies; + } + + /** + * {@inheritDoc} + * + * @see org.jboss.msc.value.Value#getValue() + */ + @Override + public CounterConfiguration getValue() { + return this.counterConfiguration; + } + + @Override + public void start(StartContext context) { + EmbeddedCacheManager container = this.dependencies.getCacheContainer(); + CounterManager counterManager = EmbeddedCounterManagerFactory.asCounterManager(container); + + //define counter + counterManager.defineCounter(counterConfigurationName, counterConfiguration); + + //but also instantiate the counter as well + switch (counterConfiguration.type()) { + case BOUNDED_STRONG: + case UNBOUNDED_STRONG: { + counterManager.getStrongCounter(counterConfigurationName); + break; + } + case WEAK: { + counterManager.getWeakCounter(counterConfigurationName); + break; + } + default: { + log.warn("Unknown counter type " + counterConfiguration.type() + " did not get instantiated"); + break; + } + } + } + + @Override + public void stop(StopContext context) { + // intentionally empty as we don't do anything on service stop + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CountersMetricsHandler.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CountersMetricsHandler.java new file mode 100644 index 000000000000..4c76fcc9d0a7 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CountersMetricsHandler.java @@ -0,0 +1,90 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; + +import org.infinispan.counter.configuration.CounterManagerConfiguration; +import org.infinispan.counter.configuration.CounterManagerConfigurationBuilder; +import org.infinispan.factories.GlobalComponentRegistry; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.infinispan.SecurityActions; +import org.infinispan.server.infinispan.spi.service.CacheContainerServiceName; +import org.jboss.as.clustering.infinispan.DefaultCacheContainer; +import org.jboss.as.controller.AbstractRuntimeOnlyHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; +import org.jboss.msc.service.ServiceController; + +/** + * Reflects runtime Counter attributes + * + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class CountersMetricsHandler extends AbstractRuntimeOnlyHandler { + + public static final CountersMetricsHandler INSTANCE = new CountersMetricsHandler(); + + private static final int CACHE_CONTAINER_INDEX = 1; + + @Override + protected void executeRuntimeStep(OperationContext context, ModelNode operation) throws OperationFailedException { + ModelNode attributeRead = operation.require(NAME); + final ModelNode result = new ModelNode(); + final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); + final String cacheContainerName = address.getElement(CACHE_CONTAINER_INDEX).getValue(); + final ServiceController controller = context.getServiceRegistry(false) + .getService(CacheContainerServiceName.CACHE_CONTAINER.getServiceName(cacheContainerName)); + + String attribute = attributeRead.asString(); + if (controller != null) { + DefaultCacheContainer cacheManager = (DefaultCacheContainer) controller.getValue(); + CounterManagerConfiguration counterManagerConfiguration = extractCounterManagerConfiguration(cacheManager); + + //we only have two attributes in CounterManagerConfiguration + if (CounterConfigurationMetrics.NUM_OF_OWNERS.toString().equals(attribute)) { + result.set(counterManagerConfiguration.numOwners()); + } else if (CounterConfigurationMetrics.RELIABILITY.toString().equals(attribute)) { + result.set(counterManagerConfiguration.reliability().name()); + } + } + context.getResult().set(result); + } + + public void registerMetrics(ManagementResourceRegistration container) { + for (CounterConfigurationMetrics metric : CounterConfigurationMetrics.values()) { + container.registerMetric(metric.definition, this); + } + } + + private CounterManagerConfiguration extractCounterManagerConfiguration(EmbeddedCacheManager cacheManager) { + GlobalComponentRegistry globalComponentRegistry = SecurityActions.getGlobalComponentRegistry(cacheManager); + CounterManagerConfiguration config = globalComponentRegistry.getGlobalConfiguration() + .module(CounterManagerConfiguration.class); + return config == null ? CounterManagerConfigurationBuilder.defaultConfiguration() : config; + } + + public enum CounterConfigurationMetrics { + + NUM_OF_OWNERS(MetricKeys.NUM_OF_OWNERS, ModelType.LONG), + RELIABILITY(MetricKeys.RELIABILITY, ModelType.STRING); + + final AttributeDefinition definition; + + CounterConfigurationMetrics(String attributeName, ModelType type) { + this.definition = new SimpleAttributeDefinitionBuilder(attributeName, type).setAllowNull(false) + .setStorageRuntime().build(); + } + + @Override + public final String toString() { + return definition.getName(); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Element.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Element.java index caa38fc3b63e..e1602db8efb7 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Element.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Element.java @@ -118,6 +118,11 @@ public enum Element { REPLICATION_QUEUE_THREAD_POOL(ModelKeys.REPLICATION_QUEUE_THREAD_POOL), STATE_TRANSFER_THREAD_POOL(ModelKeys.STATE_TRANSFER_THREAD_POOL), TRANSPORT_THREAD_POOL(ModelKeys.TRANSPORT_THREAD_POOL), + COUNTERS(ModelKeys.COUNTERS), + STRONG_COUNTER(ModelKeys.STRONG_COUNTER), + WEAK_COUNTER(ModelKeys.WEAK_COUNTER), + LOWER_BOUND(ModelKeys.LOWER_BOUND), + UPPER_BOUND(ModelKeys.UPPER_BOUND), ; private final String name; diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java index 07a8005bdf86..38c7ad3348f8 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java @@ -349,15 +349,183 @@ private void parseContainer(XMLExtendedStreamReader reader, PathAddress subsyste break; } } + case COUNTERS: { + if (namespace.since(Namespace.INFINISPAN_SERVER_9_2)) { + PathAddress countersAddress = containerAddress.append(CacheContainerCountersResource.PATH); + operations.put(countersAddress, Util.getEmptyOperation(ADD, countersAddress.toModelNode())); + this.parseCounters(reader, countersAddress, operations); + break; + } + } + default: { + throw ParseUtils.unexpectedElement(reader); + } + } + } + } + + private void parseCounters(XMLExtendedStreamReader reader, PathAddress countersAddress, + Map operations) throws XMLStreamException { + + ModelNode counters = operations.get(countersAddress); + for (int i = 0; i < reader.getAttributeCount(); i++) { + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); + switch (attribute) { + case NUM_OWNERS: { + CacheContainerCountersResource.NUM_OWNERS.parseAndSetParameter(value, counters, reader); + break; + } + case RELIABILITY: { + CacheContainerCountersResource.RELIABILITY.parseAndSetParameter(value, counters, reader); + break; + } + default: { + throw ParseUtils.unexpectedAttribute(reader, i); + } + } + } + + while (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) { + Element element = Element.forName(reader.getLocalName()); + switch (element) { + case STRONG_COUNTER: { + parseStrongCounterElement(reader, countersAddress, operations); + break; + } + case WEAK_COUNTER: { + parseWeakCounterElement(reader, countersAddress, operations); + break; + } + default: { + throw ParseUtils.unexpectedElement(reader); + } + } + } + } + + private void parseStrongCounterElement(XMLExtendedStreamReader reader, + PathAddress countersConfigurationAddress, Map operations) + throws XMLStreamException { + + PathAddress strongCounterAddress = countersConfigurationAddress; + ModelNode counter = Util.createAddOperation(strongCounterAddress); + for (int i = 0; i < reader.getAttributeCount(); i++) { + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); + switch (attribute) { + case INITIAL_VALUE: { + StrongCounterResource.INITIAL_VALUE.parseAndSetParameter(value, counter, reader); + break; + } + case NAME: { + StrongCounterResource.COUNTER_NAME.parseAndSetParameter(value, counter, reader); + strongCounterAddress = strongCounterAddress.append(StrongCounterResource.PATH.getKey(), + value); + counter.get(OP_ADDR).set(strongCounterAddress.toModelNode()); + break; + } + case STORAGE: { + StrongCounterResource.STORAGE.parseAndSetParameter(value, counter, reader); + break; + } + default: { + throw ParseUtils.unexpectedAttribute(reader, i); + } + } + } + while (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) { + Element e = Element.forName(reader.getLocalName()); + switch (e) { + case LOWER_BOUND: { + parseCounterBound(reader, e, counter); + break; + } + case UPPER_BOUND: { + parseCounterBound(reader, e, counter); + break; + } default: { throw ParseUtils.unexpectedElement(reader); } } } + operations.put(strongCounterAddress, counter); + + } + + private void parseWeakCounterElement(XMLExtendedStreamReader reader, + PathAddress countersConfigurationAddress, Map operations) + throws XMLStreamException { + + PathAddress weakCountersAddress = countersConfigurationAddress; + ModelNode counter = Util.createAddOperation(weakCountersAddress); + + for (int i = 0; i < reader.getAttributeCount(); i++) { + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); + switch (attribute) { + case INITIAL_VALUE: { + WeakCounterResource.INITIAL_VALUE.parseAndSetParameter(value, + counter, reader); + break; + } + case NAME: { + WeakCounterResource.COUNTER_NAME.parseAndSetParameter(value, + counter, reader); + weakCountersAddress = weakCountersAddress.append(WeakCounterResource.PATH.getKey(), + value); + counter.get(OP_ADDR).set(weakCountersAddress.toModelNode()); + break; + } + case STORAGE: { + WeakCounterResource.STORAGE.parseAndSetParameter(value, + counter, reader); + break; + } + case CONCURRENCY_LEVEL: { + WeakCounterResource.CONCURRENCY_LEVEL.parseAndSetParameter(value, + counter, reader); + break; + } + default: { + throw ParseUtils.unexpectedAttribute(reader, i); + } + } + } + if (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) { + throw ParseUtils.unexpectedElement(reader); + } + operations.put(weakCountersAddress, counter); + } + + private void parseCounterBound(XMLExtendedStreamReader reader, Element element, ModelNode counter) + throws XMLStreamException { + for (int i = 0; i < reader.getAttributeCount(); i++) { + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); + switch (attribute) { + case VALUE: { + if (element.equals(Element.LOWER_BOUND)) { + StrongCounterResource.LOWER_BOUND.parseAndSetParameter(value, counter, reader); + } + if (element.equals(Element.UPPER_BOUND)) { + StrongCounterResource.UPPER_BOUND.parseAndSetParameter(value, counter, reader); + } + break; + } + default: { + throw ParseUtils.unexpectedAttribute(reader, i); + } + } + } + if (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) { + throw ParseUtils.unexpectedElement(reader); + } } - private void parseGlobalState(XMLExtendedStreamReader reader, PathAddress containerAddress, + private void parseGlobalState(XMLExtendedStreamReader reader, PathAddress containerAddress, Map operations) throws XMLStreamException { PathAddress globalStateAddress = containerAddress.append(ModelKeys.GLOBAL_STATE, ModelKeys.GLOBAL_STATE_NAME); ModelNode globalState = Util.createAddOperation(globalStateAddress); diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLWriter.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLWriter.java index 309c06228d5f..7be1a9a5e130 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLWriter.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLWriter.java @@ -165,6 +165,9 @@ public void writeContent(XMLExtendedStreamWriter writer, SubsystemMarshallingCon processCacheConfiguration(writer, container, configurations, ModelKeys.REPLICATED_CACHE); processCacheConfiguration(writer, container, configurations, ModelKeys.DISTRIBUTED_CACHE); + // counters + processCounterConfigurations(writer, container); + writer.writeEndElement(); } } @@ -204,7 +207,69 @@ private static void writeScheduledThreadPoolElements(Element element, ScheduledT } } - private void processCacheConfiguration(XMLExtendedStreamWriter writer, ModelNode container, ModelNode configurations, String cacheType) + private void processCounterConfigurations(XMLExtendedStreamWriter writer, ModelNode container) + throws XMLStreamException { + + if (container.hasDefined(ModelKeys.COUNTERS)) { + writer.writeStartElement(Element.COUNTERS.getLocalName()); + + //counters element and its attributes + ModelNode counterRoot = container.get(ModelKeys.COUNTERS); + this.writeOptional(writer, Attribute.RELIABILITY, counterRoot, ModelKeys.RELIABILITY); + this.writeOptional(writer, Attribute.NUM_OWNERS, counterRoot, ModelKeys.NUM_OWNERS); + + //all counters configurations + ModelNode counterConfigurations = counterRoot.get(ModelKeys.COUNTERS_NAME); + processStrongCounterConfigurations(writer, counterConfigurations.get(ModelKeys.STRONG_COUNTER)); + processWeakCounterConfigurations(writer, counterConfigurations.get(ModelKeys.WEAK_COUNTER)); + writer.writeEndElement(); + } + } + + private void processWeakCounterConfigurations(XMLExtendedStreamWriter writer, ModelNode configurations) throws XMLStreamException { + if (configurations != null && configurations.isDefined()) { + for (Property e : configurations.asPropertyList()) { + processWeakCounterConfiguration(writer, e.getValue()); + } + } + } + + private void processStrongCounterConfigurations(XMLExtendedStreamWriter writer, ModelNode configurations) throws XMLStreamException { + if (configurations != null && configurations.isDefined()) { + for (Property e : configurations.asPropertyList()) { + processStrongCounterConfiguration(writer, e.getValue()); + } + } + } + + private void processWeakCounterConfiguration(XMLExtendedStreamWriter writer, ModelNode weakConfiguration) throws XMLStreamException { + writer.writeStartElement(Element.WEAK_COUNTER.getLocalName()); + this.writeRequired(writer, Attribute.NAME, weakConfiguration, ModelKeys.NAME); + this.writeOptional(writer, Attribute.INITIAL_VALUE, weakConfiguration, ModelKeys.INITIAL_VALUE); + this.writeOptional(writer, Attribute.STORAGE, weakConfiguration, ModelKeys.STORAGE); + this.writeOptional(writer, Attribute.CONCURRENCY_LEVEL, weakConfiguration, ModelKeys.CONCURRENCY_LEVEL); + writer.writeEndElement(); + } + + private void processStrongCounterConfiguration(XMLExtendedStreamWriter writer, ModelNode strongConfiguration) throws XMLStreamException { + writer.writeStartElement(Element.STRONG_COUNTER.getLocalName()); + this.writeRequired(writer, Attribute.NAME, strongConfiguration, ModelKeys.NAME); + this.writeOptional(writer, Attribute.INITIAL_VALUE, strongConfiguration, ModelKeys.INITIAL_VALUE); + this.writeOptional(writer, Attribute.STORAGE, strongConfiguration, ModelKeys.STORAGE); + if (strongConfiguration.hasDefined(ModelKeys.LOWER_BOUND)) { + writer.writeStartElement(Element.LOWER_BOUND.getLocalName()); + this.writeRequired(writer, Attribute.VALUE, strongConfiguration, ModelKeys.LOWER_BOUND); + writer.writeEndElement(); + } + if (strongConfiguration.hasDefined(ModelKeys.UPPER_BOUND)) { + writer.writeStartElement(Element.UPPER_BOUND.getLocalName()); + this.writeRequired(writer, Attribute.VALUE, strongConfiguration, ModelKeys.UPPER_BOUND); + writer.writeEndElement(); + } + writer.writeEndElement(); + } + + private void processCacheConfiguration(XMLExtendedStreamWriter writer, ModelNode container, ModelNode configurations, String cacheType) throws XMLStreamException { String cacheConfigurationType = cacheType + ModelKeys.CONFIGURATION_SUFFIX; Map> configurationMappings = new HashMap<>(); diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/MetricKeys.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/MetricKeys.java index aba67d91d2d0..fc487277ddeb 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/MetricKeys.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/MetricKeys.java @@ -101,4 +101,9 @@ public class MetricKeys { public static final String NUMBER_OF_NODES = "number-of-nodes"; public static final String CACHE_HEALTH = "cache-health"; public static final String LOG_TAIL = "log-tail"; + + // Counter + public static final String VALUE="value"; + public static final String NUM_OF_OWNERS = "num-owners"; + public static final String RELIABILITY = "reliability"; } diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java index a7f3827f0827..0c5368dc9af5 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java @@ -81,6 +81,8 @@ public class ModelKeys { static final String CONFIGURATIONS_NAME = "CONFIGURATIONS"; static final String CONNECTION_POOL = "connection-pool"; static final String CONNECTION_TIMEOUT = "connection-timeout"; + static final String COUNTERS = "counters"; + static final String COUNTERS_NAME = "COUNTERS"; static final String CREATE_ON_START = "create-on-start"; static final String CUSTOM_ROLE_MAPPER = "custom-role-mapper"; static final String DATA_COLUMN = "data-column"; @@ -126,6 +128,7 @@ public class ModelKeys { static final String INDEXING_PROPERTIES = "indexing-properties"; static final String INITIAL_CLUSTER_SIZE = "initial-cluster-size"; static final String INITIAL_CLUSTER_TIMEOUT = "initial-cluster-timeout"; + static final String INITIAL_VALUE = "initial-value"; static final String INTERVAL = "interval"; static final String INVALIDATION_CACHE = "invalidation-cache"; static final String INVALIDATION_CACHE_CONFIGURATION = INVALIDATION_CACHE + CONFIGURATION_SUFFIX; @@ -152,6 +155,7 @@ public class ModelKeys { static final String LOCK_TIMEOUT = "lock-timeout"; static final String LOCKING = "locking"; static final String LOCKING_NAME = "LOCKING"; + static final String LOWER_BOUND = "lower-bound"; static final String MACHINE = "machine"; static final String MAPPER = "mapper"; static final String MARSHALLER = "marshaller"; @@ -175,6 +179,7 @@ public class ModelKeys { static final String MODULES = "modules"; static final String MODULES_NAME = "MODULES"; static final String NAME = "name"; + static final String NUM_OWNERS = "num_owners"; static final String NOTIFICATIONS = "notifications"; static final String OBJECT_NAME = "OBJECT"; static final String OFF_HEAP_NAME = "OFF-HEAP"; @@ -188,6 +193,7 @@ public class ModelKeys { static final String PERMISSIONS = "permissions"; static final String PERSISTENCE = "persistence"; static final String PERSISTENT_LOCATION = "persistent-location"; + static final String RELIABILITY = "reliability"; static final String PLAIN = "plain"; static final String PREFIX = "prefix"; static final String PRELOAD = "preload"; @@ -244,6 +250,7 @@ public class ModelKeys { static final String STATISTICS = "statistics"; static final String STATISTICS_AVAILABLE = "statistics-available"; static final String STOP_TIMEOUT = "stop-timeout"; + static final String STORAGE = "storage"; static final String STORE = "store"; static final String STORE_NAME = "STORE"; static final String STRICT_PEER_TO_PEER = "strict-peer-to-peer"; @@ -268,6 +275,7 @@ public class ModelKeys { static final String TYPE = "type"; static final String TX_INTERNAL_ID = "internal-id"; static final String USERNAME = "username"; + static final String UPPER_BOUND = "upper-bound"; static final String VALUE = "value"; static final String WAIT = "wait"; static final String WAIT_TIME = "wait-time"; @@ -285,4 +293,6 @@ public class ModelKeys { static final String TRANSPORT_THREAD_POOL = "transport-thread-pool"; static final String READ_BATCH = "read-batch"; static final String WRITE_THREADS = "write-threads"; + static final String STRONG_COUNTER = "strong-counter"; + static final String WEAK_COUNTER = "weak-counter"; } diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterAddHandler.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterAddHandler.java new file mode 100644 index 000000000000..8317b217dae7 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterAddHandler.java @@ -0,0 +1,48 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.infinispan.counter.api.CounterConfiguration; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.dmr.ModelNode; + +/** + * Add operation handler for /subsystem=infinispan/cache-container=clustered/counter=* + * + * @author Vladimir Blagojevic + * + */ +public class StrongCounterAddHandler extends CounterAddHandler { + + /** + * + */ + @Override + void populate(ModelNode fromModel, ModelNode toModel) throws OperationFailedException { + super.populate(fromModel, toModel); + for (AttributeDefinition attr : StrongCounterResource.STRONG_ATTRIBUTES) { + attr.validateAndSet(fromModel, toModel); + } + } + + /** + * Implementation of abstract method processModelNode + * + */ + @Override + void processModelNode(OperationContext context, ModelNode counter, + CounterConfiguration.Builder builder) throws OperationFailedException { + super.processModelNode(context, counter, builder); + + ModelNode upperBoundModel = counter.get(ModelKeys.UPPER_BOUND); + ModelNode lowerBoundModel = counter.get(ModelKeys.LOWER_BOUND); + if (lowerBoundModel.isDefined()) { + Long lowerBound = StrongCounterResource.LOWER_BOUND.resolveModelAttribute(context, counter).asLong(); + builder.lowerBound(lowerBound); + } + if (upperBoundModel.isDefined()) { + Long upperBound = StrongCounterResource.UPPER_BOUND.resolveModelAttribute(context, counter).asLong(); + builder.upperBound(upperBound); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterResource.java new file mode 100644 index 000000000000..643365e55049 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/StrongCounterResource.java @@ -0,0 +1,53 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.SimpleAttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.registry.AttributeAccess; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.dmr.ModelType; + +/** + * Resource description for the addressable resource + * /subsystem=infinispan/cache-container=X/counter=* + * + * + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class StrongCounterResource extends CounterResource { + + public static final PathElement PATH = PathElement.pathElement(ModelKeys.STRONG_COUNTER); + + static final SimpleAttributeDefinition LOWER_BOUND = + new SimpleAttributeDefinitionBuilder(ModelKeys.LOWER_BOUND, ModelType.LONG, true) + .setXmlName(Attribute.LOWER_BOUND.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .build(); + + static final SimpleAttributeDefinition UPPER_BOUND = + new SimpleAttributeDefinitionBuilder(ModelKeys.UPPER_BOUND, ModelType.LONG, true) + .setXmlName(Attribute.UPPER_BOUND.getLocalName()) + .setAllowExpression(false) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .build(); + + static final SimpleAttributeDefinition[] STRONG_ATTRIBUTES = { LOWER_BOUND, UPPER_BOUND }; + + public StrongCounterResource(boolean runtimeRegistration) { + super(StrongCounterResource.PATH, + new InfinispanResourceDescriptionResolver(ModelKeys.COUNTERS), + new StrongCounterAddHandler(), new CounterRemoveHandler(), runtimeRegistration); + } + + @Override + public void registerAttributes(ManagementResourceRegistration resourceRegistration) { + super.registerAttributes(resourceRegistration); + + for (AttributeDefinition attr : STRONG_ATTRIBUTES) { + resourceRegistration.registerReadOnlyAttribute(attr, null); + } + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterAddHandler.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterAddHandler.java new file mode 100644 index 000000000000..6eb572e7be76 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterAddHandler.java @@ -0,0 +1,37 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.infinispan.counter.api.CounterConfiguration; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.dmr.ModelNode; + +/** + * Add operation handler for /subsystem=infinispan/cache-container=clustered/counter=* + * + * @author Vladimir Blagojevic + * + */ +public class WeakCounterAddHandler extends CounterAddHandler { + + @Override + void populate(ModelNode fromModel, ModelNode toModel) throws OperationFailedException { + super.populate(fromModel, toModel); + for (AttributeDefinition attr : WeakCounterResource.WEAK_ATTRIBUTES) { + attr.validateAndSet(fromModel, toModel); + } + } + + /** + * Implementation of abstract method processModelNode + * + */ + @Override + void processModelNode(OperationContext context, ModelNode counter, + CounterConfiguration.Builder builder) throws OperationFailedException { + super.processModelNode(context, counter, builder); + + Integer concurrency = WeakCounterResource.CONCURRENCY_LEVEL.resolveModelAttribute(context, counter).asInt(); + builder.concurrencyLevel(concurrency); + } +} diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterResource.java new file mode 100644 index 000000000000..c24d1717ca58 --- /dev/null +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/WeakCounterResource.java @@ -0,0 +1,46 @@ +package org.jboss.as.clustering.infinispan.subsystem; + +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.SimpleAttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.registry.AttributeAccess; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; + +/** + * Resource description for the addressable resource + * /subsystem=infinispan/cache-container=X/counter=* + * + * @author Pedro Ruivo + * @author Vladimir Blagojevic + * @since 9.2 + */ +public class WeakCounterResource extends CounterResource { + + public static final PathElement PATH = PathElement.pathElement(ModelKeys.WEAK_COUNTER); + + static final SimpleAttributeDefinition CONCURRENCY_LEVEL = new SimpleAttributeDefinitionBuilder(ModelKeys.CONCURRENCY_LEVEL, + ModelType.INT, true) + .setXmlName(Attribute.CONCURRENCY_LEVEL.getLocalName()) + .setAllowExpression(false) + .setDefaultValue(new ModelNode().set(64)) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES).build(); + + static final AttributeDefinition[] WEAK_ATTRIBUTES = { CONCURRENCY_LEVEL }; + + public WeakCounterResource(boolean runtimeRegistration) { + super(WeakCounterResource.PATH, new InfinispanResourceDescriptionResolver(ModelKeys.COUNTERS), + new WeakCounterAddHandler(), new CounterRemoveHandler(), runtimeRegistration); + } + + @Override + public void registerAttributes(ManagementResourceRegistration resourceRegistration) { + super.registerAttributes(resourceRegistration); + + for (AttributeDefinition attr : WEAK_ATTRIBUTES) { + resourceRegistration.registerReadOnlyAttribute(attr, null); + } + } +} diff --git a/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties b/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties index 60e3cdf3a489..d420e239489f 100644 --- a/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties +++ b/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties @@ -639,3 +639,52 @@ datagrid-infinispan.cache-container.health.number-of-nodes=Number of nodes in th datagrid-infinispan.cache-container.health.add=Add Health Check API datagrid-infinispan.cache-container.health.remove=Removed Health Check API datagrid-infinispan.cache-container.health.log-tail=Last 10 lines of the log file + +# counters +datagrid-infinispan.counter = A cluster counter +datagrid-infinispan.cache-container.counter = A cluster counter + +datagrid-infinispan.cache-container.configurations.counters = Cluster counters +datagrid-infinispan.cache-container.configurations.counters.add = Add new counter +datagrid-infinispan.cache-container.configurations.counters.remove = Remove counter + +datagrid-infinispan.cache-container.counters.num-owners = "Number of counter copies to keep cluster-wide" +datagrid-infinispan.cache-container.counters.reliability = "Counter update behavior in a network partition" + +datagrid-infinispan.cache-container.counters = Cluster counters +datagrid-infinispan.cache-container.counters.add = Add new counter +datagrid-infinispan.cache-container.counters.remove = Remove counter + +datagrid-infinispan.cache-container.counters.name=The counter's name +datagrid-infinispan.cache-container.counters.type=The counter's type (weak, strong bounded or strong unbounded) +datagrid-infinispan.cache-container.counters.storage=The counter's storage mode (volatile or persistent) +datagrid-infinispan.cache-container.counters.initial-value=The counter's initial value +datagrid-infinispan.cache-container.counters.upper-bound=The counter's upper-bound, if strong and bounded +datagrid-infinispan.cache-container.counters.lower-bound=The counter's lower-bound, if strong and bounded +datagrid-infinispan.cache-container.counters.concurrency-level=The counter's concurrency-level, if weak +datagrid-infinispan.cache-container.counters.value=The counter's value +datagrid-infinispan.cache-container.counters.counter-reset=Resets the counter value to initial value +datagrid-infinispan.cache-container.counters.counter-increase=Increase the counter value by 1 +datagrid-infinispan.cache-container.counters.counter-decrease=Decrease the counter value by 1 +datagrid-infinispan.cache-container.counters.counter-set=Set counter value +datagrid-infinispan.cache-container.counters.strong-counter="A strong counter" +datagrid-infinispan.cache-container.counters.weak-counter="A weak counter" + +datagrid-infinispan.counters = Cluster counters +datagrid-infinispan.counters.add = Add new counter +datagrid-infinispan.counters.remove = Remove counter + +datagrid-infinispan.counters.name=The counter's name +datagrid-infinispan.counters.type=The counter's type (weak, strong bounded or strong unbounded) +datagrid-infinispan.counters.storage=The counter's storage mode (volatile or persistent) +datagrid-infinispan.counters.initial-value=The counter's initial value +datagrid-infinispan.counters.upper-bound=The counter's upper-bound, if strong and bounded +datagrid-infinispan.counters.lower-bound=The counter's lower-bound, if strong and bounded +datagrid-infinispan.counters.concurrency-level=The counter's concurrency-level, if weak +datagrid-infinispan.counters.value=The counter's value +datagrid-infinispan.counters.counter-reset=Resets the counter value to initial value +datagrid-infinispan.counters.counter-increase=Increase the counter value by 1 +datagrid-infinispan.counters.counter-decrease=Decrease the counter value by 1 +datagrid-infinispan.counters.counter-set=Set counter value +datagrid-infinispan.counters.strong-counter="A strong counter" +datagrid-infinispan.counters.weak-counter="A weak counter" diff --git a/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd b/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd index fe366d9fad4d..63c2798f1298 100644 --- a/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd +++ b/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd @@ -143,6 +143,11 @@ + + + Defines counters. + + @@ -371,6 +376,121 @@ + + + + + + Defines strong counter + + + + + + + Defines strong counter + + + + + + + Sets the number of counter’s copies to keep + cluster-wide. It must be positive and its default value is 2. + + + + + + Sets the counter’s update behavior in a network + partition. Default value is AVAILABLE + + + + + + + + + + + + The lower bound for this + strong counter + + + + + + The upper bound for this + strong counter + + + + + + + + + + + + + + Sets the number of concurrent + updates. Its value + must be positive and the default value is 64. + + + + + + + + + + + Counter name + + + + + Counter initial value. Default is 0 + (zero) + + + + + + Sets the counter’s behavior when the + cluster is shutdown and restarted. Default value is + VOLATILE. + + + + + + + + + Counter lower bound + + + + + + + + Counter upper bound + + + + @@ -1712,6 +1832,43 @@ + + + + + All partitions are able to read and update the + counter’s value. + + + + + Only the primary partition (majority of nodes) + will be able to read and update the counter’s value. The remaining + partitions can only read its value. + + + + + + + + + + The counter’s value is only available in memory. + The value will be lost when a cluster is shutdown. + + + + + + The counter’s value is stored in a private and + local persistent store. The value is kept when the cluster is + shutdown and restored after a restart. + + + + + diff --git a/server/integration/infinispan/src/main/resources/subsystem-templates/infinispan-core.xml b/server/integration/infinispan/src/main/resources/subsystem-templates/infinispan-core.xml index ec0ce4182f21..2a1c6500eb75 100644 --- a/server/integration/infinispan/src/main/resources/subsystem-templates/infinispan-core.xml +++ b/server/integration/infinispan/src/main/resources/subsystem-templates/infinispan-core.xml @@ -122,6 +122,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/integration/infinispan/src/test/java/org/jboss/as/clustering/infinispan/subsystem/SubsystemParsingTestCase.java b/server/integration/infinispan/src/test/java/org/jboss/as/clustering/infinispan/subsystem/SubsystemParsingTestCase.java index f3ca4d1c270a..f5cd275a3e26 100644 --- a/server/integration/infinispan/src/test/java/org/jboss/as/clustering/infinispan/subsystem/SubsystemParsingTestCase.java +++ b/server/integration/infinispan/src/test/java/org/jboss/as/clustering/infinispan/subsystem/SubsystemParsingTestCase.java @@ -77,7 +77,7 @@ public static Collection data() { { Namespace.INFINISPAN_SERVER_8_2, 142, "schema/jboss-infinispan-core_8_2.xsd", null }, { Namespace.INFINISPAN_SERVER_9_0, 142, "schema/jboss-infinispan-core_9_0.xsd", null }, { Namespace.INFINISPAN_SERVER_9_1, 144, "schema/jboss-infinispan-core_9_1.xsd", new String[] { "/subsystem-templates/infinispan-core.xml" }}, - { Namespace.INFINISPAN_SERVER_9_2, 147, "schema/jboss-infinispan-core_9_2.xsd", new String[] { "/subsystem-templates/infinispan-core.xml" }}, + { Namespace.INFINISPAN_SERVER_9_2, 153, "schema/jboss-infinispan-core_9_2.xsd", new String[] { "/subsystem-templates/infinispan-core.xml" }}, }; return Arrays.asList(data); } diff --git a/server/integration/infinispan/src/test/resources/org/jboss/as/clustering/infinispan/subsystem/subsystem-infinispan_9_2.xml b/server/integration/infinispan/src/test/resources/org/jboss/as/clustering/infinispan/subsystem/subsystem-infinispan_9_2.xml index 39368ba8d1e5..e88f842703fd 100644 --- a/server/integration/infinispan/src/test/resources/org/jboss/as/clustering/infinispan/subsystem/subsystem-infinispan_9_2.xml +++ b/server/integration/infinispan/src/test/resources/org/jboss/as/clustering/infinispan/subsystem/subsystem-infinispan_9_2.xml @@ -186,6 +186,20 @@ + + + + + + + + + + + + + + diff --git a/wildfly-modules/build.xml b/wildfly-modules/build.xml index 85100d9a9e41..e690c4837e57 100644 --- a/wildfly-modules/build.xml +++ b/wildfly-modules/build.xml @@ -185,6 +185,10 @@ + + + + diff --git a/wildfly-modules/pom.xml b/wildfly-modules/pom.xml index 3d6e5ebfaabc..2b880dd2af43 100644 --- a/wildfly-modules/pom.xml +++ b/wildfly-modules/pom.xml @@ -32,6 +32,11 @@ infinispan-client-hotrod + + org.infinispan + infinispan-clustered-counter + + org.infinispan infinispan-cachestore-jdbc diff --git a/wildfly-modules/src/main/resources/org/infinispan/counter/main/module.xml b/wildfly-modules/src/main/resources/org/infinispan/counter/main/module.xml new file mode 100644 index 000000000000..bace84bc20db --- /dev/null +++ b/wildfly-modules/src/main/resources/org/infinispan/counter/main/module.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/wildfly-modules/src/main/resources/org/infinispan/extension/main/module.xml b/wildfly-modules/src/main/resources/org/infinispan/extension/main/module.xml index 20024afca8f7..9816a7945af7 100644 --- a/wildfly-modules/src/main/resources/org/infinispan/extension/main/module.xml +++ b/wildfly-modules/src/main/resources/org/infinispan/extension/main/module.xml @@ -15,6 +15,7 @@ +