Skip to content

Commit

Permalink
ISPN-8670 Implement a managed configuration storage for standalone se…
Browse files Browse the repository at this point in the history
…rvers
  • Loading branch information
tristantarrant authored and ryanemerson committed Jan 17, 2018
1 parent b71895c commit 5132364
Show file tree
Hide file tree
Showing 19 changed files with 373 additions and 8 deletions.
Expand Up @@ -34,9 +34,6 @@
public class OverlayLocalConfigurationStorage extends VolatileLocalConfigurationStorage {
private ConcurrentHashSet<String> persistentCaches = new ConcurrentHashSet<>();

public OverlayLocalConfigurationStorage() {
}

@Override
public void validateFlags(EnumSet<CacheContainerAdmin.AdminFlag> flags) {
if (flags.contains(CacheContainerAdmin.AdminFlag.PERMANENT) && !globalConfiguration.globalState().enabled())
Expand Down
Expand Up @@ -38,9 +38,6 @@ public class VolatileLocalConfigurationStorage implements LocalConfigurationStor
protected ParserRegistry parserRegistry;
protected GlobalConfiguration globalConfiguration;

public VolatileLocalConfigurationStorage() {
}

public void initialize(EmbeddedCacheManager cacheManager) {
this.globalConfiguration = cacheManager.getCacheManagerConfiguration();
this.cacheManager = cacheManager;
Expand Down
Expand Up @@ -90,7 +90,7 @@ In order for the above to work, global state must be enabled and a suitable conf
The available configuration stores are:

- `VOLATILE`: as the name implies, this configuration storage does not support +PERMANENT+ caches.
- `OVERLAY`: this stores configurations in the global state persistent path in a file named _caches.xml_.
- `OVERLAY`: this stores configurations in the global shared state persistent path in a file named _caches.xml_.
- `MANAGED`: this is only supported in server deployments, and will store +PERMANENT+ caches in the server model.
- `CUSTOM`: a custom configuration store.

Expand Down
Expand Up @@ -194,4 +194,8 @@ public interface InfinispanLogger extends BasicLogger {
@LogMessage(level = ERROR)
@Message(id = 20, value = "Waiting for deployment of custom EntryMergePolicy (%s) timed out. Please check if this EntryMergePolicy is really present.")
void loadingCustomMergePolicyTimeout(String className);

@LogMessage(level = WARN)
@Message(id = 21, value = "Managed configuration storage is currently unsupported in domain mode. Please use Overlay storage.")
void managedConfigurationUnavailableInDomainMode();
}
Expand Up @@ -278,4 +278,19 @@ public interface InfinispanMessages {

@Message(id = 125, value = "%s is not a valid EntryMergePolicy")
IllegalArgumentException invalidEntryMergePolicy(@Cause Throwable cause, String mergePolicy);

@Message(id = 126, value = "Cannot create cache '%s'")
CacheConfigurationException cannotCreateCache(@Cause Throwable cause, String name);

@Message(id = 127, value = "Cannot remove cache '%s'")
CacheConfigurationException cannotRemoveCache(@Cause Throwable e, String name);

@Message(id = 128, value = "Cache '%s' does not exist")
CacheConfigurationException nonExistingCache(String name);

@Message(id = 129, value = "Cannot create non-permanent cache '%s'")
CacheConfigurationException cannotCreateNonPermamentCache(String name);

@Message(id = 130, value = "Cannot create cache '%s' since template '%s' does not exist")
CacheConfigurationException nonExistingTemplate(String name, String template);
}
Expand Up @@ -64,6 +64,8 @@ public enum Attribute {
CLUSTER(ModelKeys.CLUSTER),
CONCURRENCY_LEVEL(ModelKeys.CONCURRENCY_LEVEL),
CONFIGURATION(ModelKeys.CONFIGURATION),
CONFIGURATION_STORAGE(ModelKeys.CONFIGURATION_STORAGE),
CONFIGURATION_STORAGE_CLASS(ModelKeys.CONFIGURATION_STORAGE_CLASS),
CONNECTION_TIMEOUT(ModelKeys.CONNECTION_TIMEOUT),
CREATE_ON_START(ModelKeys.CREATE_ON_START),
DATASOURCE(ModelKeys.DATASOURCE),
Expand Down
Expand Up @@ -28,6 +28,7 @@
import java.util.concurrent.TimeUnit;

import org.infinispan.Cache;
import org.infinispan.globalstate.ConfigurationStorage;
import org.infinispan.server.commons.controller.ReloadRequiredAddStepHandler;
import org.infinispan.server.commons.dmr.ModelNodes;
import org.infinispan.server.commons.naming.BinderServiceBuilder;
Expand All @@ -45,6 +46,7 @@
import org.infinispan.server.jgroups.spi.service.ChannelServiceNameFactory;
import org.infinispan.server.jgroups.spi.service.ProtocolStackServiceName;
import org.infinispan.server.jgroups.subsystem.JGroupsBindingFactory;
import org.jboss.as.clustering.infinispan.InfinispanLogger;
import org.jboss.as.controller.AbstractAddStepHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
Expand Down Expand Up @@ -147,6 +149,23 @@ static void installRuntimeServices(OperationContext context, ModelNode operation
} else {
globalStateBuilder.setTemporaryPath(defaultPersistentLocation).setTemporaryRelativeTo(ServerEnvironment.SERVER_TEMP_DIR);
}
ConfigurationStorage configurationStorage = ConfigurationStorage.valueOf(GlobalStateResource.CONFIGURATION_STORAGE.resolveModelAttribute(context, globalState).asString());
globalStateBuilder.setConfigurationStorage(configurationStorage);
if (configurationStorage.equals(ConfigurationStorage.MANAGED)) {
switch (context.getProcessType()) {
case STANDALONE_SERVER:
globalStateBuilder.setConfigurationStorageClass(StandaloneServerLocalConfigurationStorage.class.getName());
break;
case DOMAIN_SERVER:
InfinispanLogger.ROOT_LOGGER.managedConfigurationUnavailableInDomainMode();
break;
default:
// No need
break;
}
} else if (configurationStorage.equals(ConfigurationStorage.CUSTOM)) {
globalStateBuilder.setConfigurationStorageClass(GlobalStateResource.CONFIGURATION_STORAGE_CLASS.resolveModelAttribute(context, globalState).asString());
}
}

if (model.hasDefined(ModelKeys.SECURITY) && model.get(ModelKeys.SECURITY).hasDefined(ModelKeys.SECURITY_NAME)) {
Expand Down
Expand Up @@ -26,6 +26,7 @@
import java.util.Map.Entry;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.Executors;

import javax.management.MBeanServer;

Expand All @@ -38,6 +39,7 @@
import org.infinispan.configuration.global.ShutdownHookBehavior;
import org.infinispan.configuration.global.ThreadPoolConfiguration;
import org.infinispan.configuration.internal.PrivateGlobalConfigurationBuilder;
import org.infinispan.globalstate.LocalConfigurationStorage;
import org.infinispan.marshall.core.Ids;
import org.infinispan.security.AuditLogger;
import org.infinispan.security.PrincipalRoleMapper;
Expand All @@ -57,6 +59,8 @@
import org.jboss.as.clustering.infinispan.subsystem.EmbeddedCacheManagerConfigurationService.AuthorizationConfiguration;
import org.jboss.as.clustering.infinispan.subsystem.EmbeddedCacheManagerConfigurationService.GlobalStateLocationConfiguration;
import org.jboss.as.clustering.infinispan.subsystem.EmbeddedCacheManagerConfigurationService.TransportConfiguration;
import org.jboss.as.controller.ModelController;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.services.path.PathManager;
import org.jboss.as.controller.services.path.PathManagerService;
import org.jboss.as.jmx.MBeanServerService;
Expand Down Expand Up @@ -97,6 +101,7 @@ public class CacheContainerConfigurationBuilder implements Builder<GlobalConfigu
private final InjectedValue<ThreadPoolConfiguration> transportThreadPool = new InjectedValue<>();
private final InjectedValue<ThreadPoolConfiguration> replicationQueueThreadPool = new InjectedValue<>();
private final InjectedValue<PathManager> pathManager = new InjectedValue<>();
private final InjectedValue<ModelController> modelController = new InjectedValue<>();

public CacheContainerConfigurationBuilder(String name) {
this.name = name;
Expand All @@ -110,6 +115,7 @@ public ServiceName getServiceName() {
@Override
public ServiceBuilder<GlobalConfiguration> build(ServiceTarget target) {
ServiceBuilder<GlobalConfiguration> builder = target.addService(this.getServiceName(), new ValueService<>(this))
.addDependency(Services.JBOSS_SERVER_CONTROLLER, ModelController.class, this.modelController)
.addDependency(Services.JBOSS_SERVICE_MODULE_LOADER, ModuleLoader.class, this.loader)
.addDependency(MBeanServerService.SERVICE_NAME, MBeanServer.class, this.server)
.addDependency(ThreadPoolResource.ASYNC_OPERATIONS.getServiceName(this.name), ThreadPoolConfiguration.class, this.asyncOperationsThreadPool)
Expand Down Expand Up @@ -226,6 +232,22 @@ public GlobalConfiguration getValue() {
statePersistenceBuilder.persistentLocation(persistentLocation);
String temporaryLocation = pathManager.getValue().resolveRelativePathEntry(statePersistence.getPersistencePath(), statePersistence.getPersistenceRelativeTo());
statePersistenceBuilder.temporaryLocation(temporaryLocation);
statePersistenceBuilder.configurationStorage(statePersistence.getConfigurationStorage());
// If the LocalConfigurationStorage is server-aware, apply some context
String configurationStorageClass = statePersistence.getConfigurationStorageClass();
if (configurationStorageClass != null) {
try {
LocalConfigurationStorage localConfigurationStorage = Class.forName(configurationStorageClass, true, loader).asSubclass(LocalConfigurationStorage.class).newInstance();
if (localConfigurationStorage != null && localConfigurationStorage instanceof ServerLocalConfigurationStorage) {
ServerLocalConfigurationStorage serverLocalConfigurationManager = (ServerLocalConfigurationStorage)localConfigurationStorage;
serverLocalConfigurationManager.setRootPath(PathAddress.pathAddress(InfinispanExtension.SUBSYSTEM_PATH).append("cache-container", name));
serverLocalConfigurationManager.setModelControllerClient(modelController.getValue().createClient(Executors.newCachedThreadPool()));
}
statePersistenceBuilder.configurationStorageSupplier(() -> localConfigurationStorage);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}

builder.asyncThreadPool().read(this.asyncOperationsThreadPool.getValue());
Expand Down
Expand Up @@ -52,6 +52,7 @@ public enum Element {
COMPRESSION(ModelKeys.COMPRESSION),
COMMON_NAME_ROLE_MAPPER(ModelKeys.COMMON_NAME_ROLE_MAPPER),
CLUSTER_ROLE_MAPPER(ModelKeys.CLUSTER_ROLE_MAPPER),
CUSTOM_CONFIGURATION_STORAGE(ModelKeys.CUSTOM_CONFIGURATION_STORAGE),
CUSTOM_ROLE_MAPPER(ModelKeys.CUSTOM_ROLE_MAPPER),
DATA_COLUMN(ModelKeys.DATA_COLUMN),
DIGEST(ModelKeys.DIGEST),
Expand All @@ -64,6 +65,7 @@ public enum Element {
EXTERNAL(ModelKeys.EXTERNAL),
FILE_STORE(ModelKeys.FILE_STORE),
GLOBAL_STATE(ModelKeys.GLOBAL_STATE),
MANAGED_CONFIGURATION_STORAGE(ModelKeys.MANAGED_CONFIGURATION_STORAGE),
MODULES(ModelKeys.MODULES),
MODULE(ModelKeys.MODULE),
ID_COLUMN(ModelKeys.ID_COLUMN),
Expand All @@ -85,6 +87,7 @@ public enum Element {
MEMORY(ModelKeys.MEMORY),
OBJECT("object"),
OFF_HEAP("off-heap"),
OVERLAY_CONFIGURATION_STORAGE(ModelKeys.OVERLAY_CONFIGURATION_STORAGE),
PARTITION_HANDLING(ModelKeys.PARTITION_HANDLING),
PERSISTENCE(ModelKeys.PERSISTENCE),
PERSISTENT_LOCATION(ModelKeys.PERSISTENT_LOCATION),
Expand All @@ -108,6 +111,7 @@ public enum Element {
TRANSACTION(ModelKeys.TRANSACTION),
TRANSPORT(ModelKeys.TRANSPORT),
VALUE(ModelKeys.VALUE),
VOLATILE_CONFIGURATION_STORAGE(ModelKeys.VOLATILE_CONFIGURATION_STORAGE),
WRITE_BEHIND(ModelKeys.WRITE_BEHIND),

ASYNC_OPERATIONS_THREAD_POOL(ModelKeys.ASYNC_OPERATIONS_THREAD_POOL),
Expand Down
Expand Up @@ -26,6 +26,7 @@

import javax.management.MBeanServer;

import org.infinispan.globalstate.ConfigurationStorage;
import org.infinispan.server.jgroups.spi.ChannelFactory;
import org.jboss.modules.ModuleLoader;
import org.jgroups.JChannel;
Expand Down Expand Up @@ -55,6 +56,8 @@ interface GlobalStateLocationConfiguration {
String getPersistenceRelativeTo();
String getTemporaryPath();
String getTemporaryRelativeTo();
ConfigurationStorage getConfigurationStorage();
String getConfigurationStorageClass();
}

interface Dependencies {
Expand Down
@@ -1,5 +1,6 @@
package org.jboss.as.clustering.infinispan.subsystem;

import org.infinispan.globalstate.ConfigurationStorage;
import org.jboss.as.clustering.infinispan.subsystem.EmbeddedCacheManagerConfigurationService.GlobalStateLocationConfiguration;
import org.jboss.msc.value.Value;

Expand All @@ -14,6 +15,8 @@ public class GlobalStateLocationConfigurationBuilder implements Value<GlobalStat
private String persistenceRelativeTo;
private String temporaryPath;
private String temporaryRelativeTo;
private ConfigurationStorage configurationStorage;
private String configurationStorageClass;

@Override
public String getPersistencePath() {
Expand Down Expand Up @@ -55,6 +58,26 @@ public String getTemporaryRelativeTo() {
return temporaryRelativeTo;
}

public GlobalStateLocationConfigurationBuilder setConfigurationStorage(ConfigurationStorage configurationStorage) {
this.configurationStorage = configurationStorage;
return this;
}

@Override
public ConfigurationStorage getConfigurationStorage() {
return configurationStorage;
}

public GlobalStateLocationConfigurationBuilder setConfigurationStorageClass(String configurationStorageClass) {
this.configurationStorageClass = configurationStorageClass;
return this;
}

@Override
public String getConfigurationStorageClass() {
return configurationStorageClass;
}

@Override
public GlobalStateLocationConfiguration getValue() throws IllegalStateException, IllegalArgumentException {
return this;
Expand Down
Expand Up @@ -22,6 +22,7 @@

package org.jboss.as.clustering.infinispan.subsystem;

import org.infinispan.globalstate.ConfigurationStorage;
import org.jboss.as.clustering.infinispan.subsystem.CacheConfigOperationHandlers.CacheConfigAdd;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.ObjectTypeAttributeDefinition;
Expand All @@ -32,6 +33,7 @@
import org.jboss.as.controller.SimpleAttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.SimpleResourceDefinition;
import org.jboss.as.controller.operations.validation.EnumValidator;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.server.ServerEnvironment;
Expand Down Expand Up @@ -79,7 +81,23 @@ public class GlobalStateResource extends SimpleResourceDefinition {
.setXmlName(ModelKeys.TEMPORARY_LOCATION)
.build();

static final AttributeDefinition[] ATTRIBUTES = { PERSISTENT_LOCATION_PATH, TEMPORARY_STATE_PATH };
static final SimpleAttributeDefinition CONFIGURATION_STORAGE =
new SimpleAttributeDefinitionBuilder(ModelKeys.CONFIGURATION_STORAGE, ModelType.STRING, true)
.setXmlName(Attribute.CONFIGURATION_STORAGE.getLocalName())
.setAllowExpression(true)
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
.setValidator(new EnumValidator<>(ConfigurationStorage.class, false, true))
.setDefaultValue(new ModelNode().set(ConfigurationStorage.OVERLAY.toString()))
.build();

static final SimpleAttributeDefinition CONFIGURATION_STORAGE_CLASS =
new SimpleAttributeDefinitionBuilder(ModelKeys.CONFIGURATION_STORAGE_CLASS, ModelType.STRING, true)
.setXmlName(Attribute.CONFIGURATION_STORAGE_CLASS.getLocalName())
.setAllowExpression(true)
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
.build();

static final AttributeDefinition[] ATTRIBUTES = { PERSISTENT_LOCATION_PATH, TEMPORARY_STATE_PATH, CONFIGURATION_STORAGE, CONFIGURATION_STORAGE_CLASS};

GlobalStateResource() {
super(GLOBAL_STATE_PATH,
Expand Down
Expand Up @@ -40,6 +40,7 @@

import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.eviction.EvictionType;
import org.infinispan.globalstate.ConfigurationStorage;
import org.infinispan.partitionhandling.PartitionHandling;
import org.infinispan.security.impl.ClusterRoleMapper;
import org.infinispan.security.impl.CommonNameRoleMapper;
Expand Down Expand Up @@ -527,6 +528,7 @@ private void parseCounterBound(XMLExtendedStreamReader reader, Element element,

private void parseGlobalState(XMLExtendedStreamReader reader, PathAddress containerAddress,
Map<PathAddress, ModelNode> operations) throws XMLStreamException {
ConfigurationStorage storage = null;
PathAddress globalStateAddress = containerAddress.append(ModelKeys.GLOBAL_STATE, ModelKeys.GLOBAL_STATE_NAME);
ModelNode globalState = Util.createAddOperation(globalStateAddress);
while (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) {
Expand All @@ -540,11 +542,44 @@ private void parseGlobalState(XMLExtendedStreamReader reader, PathAddress contai
parseGlobalStatePath(reader, globalState, GlobalStateResource.TEMPORARY_STATE_PATH);
break;
}
case VOLATILE_CONFIGURATION_STORAGE: {
if (storage != null) {
throw ParseUtils.unexpectedElement(reader);
}
storage = ConfigurationStorage.VOLATILE;
break;
}
case OVERLAY_CONFIGURATION_STORAGE: {
if (storage != null) {
throw ParseUtils.unexpectedElement(reader);
}
storage = ConfigurationStorage.OVERLAY;
break;
}
case MANAGED_CONFIGURATION_STORAGE: {
if (storage != null) {
throw ParseUtils.unexpectedElement(reader);
}
storage = ConfigurationStorage.MANAGED;
break;
}
case CUSTOM_CONFIGURATION_STORAGE: {
if (storage != null) {
throw ParseUtils.unexpectedElement(reader);
}
storage = ConfigurationStorage.CUSTOM;
String klass = ParseUtils.readStringAttributeElement(reader, Attribute.CLASS.getLocalName());
GlobalStateResource.CONFIGURATION_STORAGE_CLASS.parseAndSetParameter(klass, globalState, reader);
break;
}
default: {
throw ParseUtils.unexpectedElement(reader);
}
}
}
if (storage != null) {
GlobalStateResource.CONFIGURATION_STORAGE.parseAndSetParameter(storage.name(), globalState, reader);
}

operations.put(globalStateAddress, globalState);
}
Expand Down

0 comments on commit 5132364

Please sign in to comment.