Package org.jboss.as.clustering.infinispan.subsystem

Source Code of org.jboss.as.clustering.infinispan.subsystem.CacheContainerAdd

/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

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

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.AccessController;
import java.util.AbstractMap;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import org.infinispan.config.CacheLoaderManagerConfig;
import org.infinispan.config.Configuration;
import org.infinispan.config.Configuration.CacheMode;
import org.infinispan.config.GlobalConfiguration;
import org.infinispan.config.InfinispanConfiguration;
import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.loaders.AbstractCacheStoreConfig;
import org.infinispan.loaders.CacheStore;
import org.infinispan.loaders.CacheStoreConfig;
import org.infinispan.manager.CacheContainer;
import org.infinispan.util.concurrent.IsolationLevel;
import org.jboss.as.controller.BasicOperationResult;
import org.jboss.as.controller.ModelAddOperationHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationResult;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.ResultHandler;
import org.jboss.as.controller.RuntimeOperationContext;
import org.jboss.as.controller.RuntimeTask;
import org.jboss.as.controller.RuntimeTaskContext;
import org.jboss.as.controller.descriptions.DescriptionProvider;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.server.ServerEnvironment;
import org.jboss.as.server.services.path.AbstractPathService;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.Property;
import org.jboss.logging.Logger;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.jboss.util.loading.ContextClassLoaderSwitcher;
import org.jboss.util.loading.ContextClassLoaderSwitcher.SwitchContext;

/**
* @author Paul Ferraro
*/
public class CacheContainerAdd implements ModelAddOperationHandler, DescriptionProvider {

    private static final String DEFAULTS = "infinispan-defaults.xml";
    private static final Logger log = Logger.getLogger(CacheContainerAdd.class.getPackage().getName());

    static ModelNode createOperation(ModelNode address, ModelNode existing) {
        ModelNode operation = Util.getEmptyOperation(ModelDescriptionConstants.ADD, address);
        populate(existing, operation);
        return operation;
    }

    private static void populate(ModelNode source, ModelNode target) {
        target.get(ModelKeys.DEFAULT_CACHE).set(source.require(ModelKeys.DEFAULT_CACHE));
        if (source.hasDefined(ModelKeys.LISTENER_EXECUTOR)) {
            target.get(ModelKeys.LISTENER_EXECUTOR).set(source.get(ModelKeys.LISTENER_EXECUTOR));
        }
        if (source.hasDefined(ModelKeys.EVICTION_EXECUTOR)) {
            target.get(ModelKeys.EVICTION_EXECUTOR).set(source.get(ModelKeys.EVICTION_EXECUTOR));
        }
        if (source.hasDefined(ModelKeys.REPLICATION_QUEUE_EXECUTOR)) {
            target.get(ModelKeys.REPLICATION_QUEUE_EXECUTOR).set(source.get(ModelKeys.REPLICATION_QUEUE_EXECUTOR));
        }
        if (source.hasDefined(ModelKeys.ALIAS)) {
            ModelNode aliases = target.get(ModelKeys.ALIAS);
            for (ModelNode alias: source.get(ModelKeys.ALIAS).asList()) {
                aliases.add(alias);
            }
        }
        if (source.hasDefined(ModelKeys.TRANSPORT)) {
            target.get(ModelKeys.TRANSPORT).set(source.get(ModelKeys.TRANSPORT));
        }
        ModelNode caches = target.get(ModelKeys.CACHE);
        for (ModelNode cache: source.require(ModelKeys.CACHE).asList()) {
            caches.add(cache);
        }
    }

    @SuppressWarnings("unchecked")
    final ContextClassLoaderSwitcher switcher = (ContextClassLoaderSwitcher) AccessController.doPrivileged(ContextClassLoaderSwitcher.INSTANTIATOR);

    final GlobalConfiguration global;
    final Configuration defaultConfig;
    final Map<CacheMode, Configuration> configs;

    public CacheContainerAdd() {
        InfinispanConfiguration config = load(DEFAULTS);
        this.global = config.parseGlobalConfiguration();
        this.configs = new EnumMap<CacheMode, Configuration>(CacheMode.class);
        this.defaultConfig = config.parseDefaultConfiguration();
        Map<String, Configuration> namedConfigs = config.parseNamedConfigurations();
        for (CacheMode mode: CacheMode.values()) {
            Configuration configuration = this.defaultConfig.clone();
            Configuration override = namedConfigs.get(mode.name());
            if (override != null) {
                configuration.applyOverrides(override);
            }
            configuration.setCacheMode(mode);
            this.configs.put(mode, configuration);
        }
    }

    /**
     * {@inheritDoc}
     * @see org.jboss.as.controller.descriptions.DescriptionProvider#getModelDescription(java.util.Locale)
     */
    @Override
    public ModelNode getModelDescription(Locale locale) {
        return LocalDescriptions.getCacheContainerAddDescription(locale);
    }

    /**
     * {@inheritDoc}
     * @see org.jboss.as.controller.ModelAddOperationHandler#execute(org.jboss.as.controller.OperationContext, org.jboss.dmr.ModelNode, org.jboss.as.controller.ResultHandler)
     */
    @Override
    public OperationResult execute(OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {
        ModelNode opAddr = operation.require(ModelDescriptionConstants.OP_ADDR);

        final ModelNode removeOperation = Util.getResourceRemoveOperation(opAddr);
        final PathAddress address = PathAddress.pathAddress(opAddr);
        final String name = address.getLastElement().getValue();

        populate(operation, context.getSubModel());

        RuntimeOperationContext runtime = context.getRuntimeContext();
        if (runtime != null) {
            RuntimeTask task = new RuntimeTask() {
                @Override
                public void execute(RuntimeTaskContext context) throws OperationFailedException {
                    String defaultCache = operation.require(ModelKeys.DEFAULT_CACHE).asString();
                    ServiceName[] aliases = null;
                    if (operation.hasDefined(ModelKeys.ALIAS)) {
                        List<ModelNode> list = operation.get(ModelKeys.ALIAS).asList();
                        aliases = new ServiceName[list.size()];
                        for (int i = 0; i < list.size(); i++) {
                            aliases[i] = EmbeddedCacheManagerService.getServiceName(list.get(i).asString());
                        }
                    }
                    GlobalConfiguration global = CacheContainerAdd.this.global.clone();
                    String transportExecutor = null;
                    String stack = null;
                    if (operation.hasDefined(ModelKeys.TRANSPORT)) {
                        ModelNode transport = operation.get(ModelKeys.TRANSPORT);
                        if (transport.hasDefined(ModelKeys.STACK)) {
                            stack = transport.get(ModelKeys.STACK).asString();
                        }
                        if (transport.hasDefined(ModelKeys.EXECUTOR)) {
                            transportExecutor = transport.get(ModelKeys.EXECUTOR).asString();
                        }
                        if (transport.hasDefined(ModelKeys.LOCK_TIMEOUT)) {
                            global.setDistributedSyncTimeout(transport.get(ModelKeys.LOCK_TIMEOUT).asLong());
                        }
                        if (transport.hasDefined(ModelKeys.SITE)) {
                            global.setSiteId(transport.get(ModelKeys.SITE).asString());
                        }
                        if (transport.hasDefined(ModelKeys.RACK)) {
                            global.setRackId(transport.get(ModelKeys.RACK).asString());
                        }
                        if (transport.hasDefined(ModelKeys.MACHINE)) {
                            global.setMachineId(transport.get(ModelKeys.MACHINE).asString());
                        }
                    }
                    List<Map.Entry<String, Injector<String>>> locationInjectors = new LinkedList<Map.Entry<String, Injector<String>>>();
                    Map<String, Configuration> configs = new LinkedHashMap<String, Configuration>();
                    for (ModelNode cache: operation.require(ModelKeys.CACHE).asList()) {
                        String cacheName = cache.require(ModelKeys.NAME).asString();
                        CacheMode mode = CacheMode.valueOf(cache.require(ModelKeys.MODE).asString());
                        Configuration config = CacheContainerAdd.this.configs.get(mode).clone();
                        if (cache.hasDefined(ModelKeys.QUEUE_SIZE)) {
                            int queueSize = cache.get(ModelKeys.QUEUE_SIZE).asInt();
                            config.setUseReplQueue(queueSize > 0);
                            config.setReplQueueMaxElements(queueSize);
                        }
                        if (cache.hasDefined(ModelKeys.QUEUE_FLUSH_INTERVAL)) {
                            config.setReplQueueInterval(cache.get(ModelKeys.QUEUE_FLUSH_INTERVAL).asLong());
                        }
                        if (cache.hasDefined(ModelKeys.REMOTE_TIMEOUT)) {
                            config.setSyncReplTimeout(cache.get(ModelKeys.REMOTE_TIMEOUT).asLong());
                        }
                        if (cache.hasDefined(ModelKeys.OWNERS)) {
                            config.setNumOwners(cache.get(ModelKeys.OWNERS).asInt());
                        }
                        if (cache.hasDefined(ModelKeys.L1_LIFESPAN)) {
                            long lifespan = cache.get(ModelKeys.L1_LIFESPAN).asLong();
                            config.setL1CacheEnabled(lifespan > 0);
                            config.setL1Lifespan(lifespan);
                        }
                        if (cache.hasDefined(ModelKeys.LOCKING)) {
                            ModelNode locking = cache.get(ModelKeys.LOCKING);
                            if (locking.hasDefined(ModelKeys.ISOLATION)) {
                                IsolationLevel level = IsolationLevel.valueOf(locking.get(ModelKeys.ISOLATION).asString());
                                config.setIsolationLevel(level);
                            }
                            if (locking.hasDefined(ModelKeys.STRIPING)) {
                                config.setUseLockStriping(locking.get(ModelKeys.STRIPING).asBoolean());
                            }
                            if (locking.hasDefined(ModelKeys.ACQUIRE_TIMEOUT)) {
                                config.setLockAcquisitionTimeout(locking.get(ModelKeys.ACQUIRE_TIMEOUT).asLong());
                            }
                            if (locking.hasDefined(ModelKeys.CONCURRENCY_LEVEL)) {
                                config.setConcurrencyLevel(locking.get(ModelKeys.CONCURRENCY_LEVEL).asInt());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.TRANSACTION)) {
                            ModelNode transaction = cache.get(ModelKeys.TRANSACTION);
                            if (transaction.hasDefined(ModelKeys.STOP_TIMEOUT)) {
                                config.setCacheStopTimeout(transaction.get(ModelKeys.TIMEOUT).asInt());
                            }
                            if (transaction.hasDefined(ModelKeys.SYNC_PHASE)) {
                                SyncPhase phase = SyncPhase.valueOf(transaction.get(ModelKeys.SYNC_PHASE).asString());
                                config.setSyncCommitPhase(phase.isCommit());
                                config.setSyncRollbackPhase(phase.isRollback());
                            }
                            if (transaction.hasDefined(ModelKeys.EAGER_LOCKING)) {
                                EagerLocking eager = EagerLocking.valueOf(transaction.get(ModelKeys.EAGER_LOCKING).asString());
                                config.setUseEagerLocking(eager.isEnabled());
                                config.setEagerLockSingleNode(eager.isSingleOwner());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.EVICTION)) {
                            ModelNode eviction = cache.get(ModelKeys.EVICTION);
                            if (eviction.hasDefined(ModelKeys.STRATEGY)) {
                                EvictionStrategy strategy = EvictionStrategy.valueOf(eviction.get(ModelKeys.STRATEGY).asString());
                                config.setEvictionStrategy(strategy);
                            }
                            if (eviction.hasDefined(ModelKeys.MAX_ENTRIES)) {
                                config.setEvictionMaxEntries(eviction.get(ModelKeys.MAX_ENTRIES).asInt());
                            }
                            if (eviction.hasDefined(ModelKeys.INTERVAL)) {
                                config.setEvictionWakeUpInterval(eviction.get(ModelKeys.INTERVAL).asLong());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.EXPIRATION)) {
                            ModelNode expiration = cache.get(ModelKeys.EXPIRATION);
                            if (expiration.hasDefined(ModelKeys.MAX_IDLE)) {
                                config.setExpirationMaxIdle(expiration.get(ModelKeys.MAX_IDLE).asLong());
                            }
                            if (expiration.hasDefined(ModelKeys.LIFESPAN)) {
                                config.setExpirationLifespan(expiration.get(ModelKeys.LIFESPAN).asLong());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.STATE_TRANSFER)) {
                            ModelNode stateTransfer = cache.get(ModelKeys.STATE_TRANSFER);
                            if (stateTransfer.hasDefined(ModelKeys.ENABLED)) {
                                config.setFetchInMemoryState(stateTransfer.get(ModelKeys.ENABLED).asBoolean());
                            }
                            if (stateTransfer.hasDefined(ModelKeys.TIMEOUT)) {
                                config.setStateRetrievalTimeout(stateTransfer.get(ModelKeys.TIMEOUT).asLong());
                            }
                            if (stateTransfer.hasDefined(ModelKeys.FLUSH_TIMEOUT)) {
                                config.setStateRetrievalLogFlushTimeout(stateTransfer.get(ModelKeys.FLUSH_TIMEOUT).asLong());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.REHASHING)) {
                            ModelNode rehashing = cache.get(ModelKeys.REHASHING);
                            if (rehashing.hasDefined(ModelKeys.ENABLED)) {
                                config.setRehashEnabled(rehashing.get(ModelKeys.ENABLED).asBoolean());
                            }
                            if (rehashing.hasDefined(ModelKeys.TIMEOUT)) {
                                config.setRehashRpcTimeout(rehashing.get(ModelKeys.TIMEOUT).asLong());
                            }
                        }
                        if (cache.hasDefined(ModelKeys.STORE)) {
                            ModelNode store = cache.get(ModelKeys.STORE);
                            CacheLoaderManagerConfig storeManagerConfig = config.getCacheLoaderManagerConfig();
                            storeManagerConfig.setShared(store.hasDefined(ModelKeys.SHARED) ? store.get(ModelKeys.SHARED).asBoolean() : false);
                            storeManagerConfig.setPreload(store.hasDefined(ModelKeys.PRELOAD) ? store.get(ModelKeys.PRELOAD).asBoolean() : false);
                            storeManagerConfig.setPassivation(store.hasDefined(ModelKeys.PASSIVATION) ? store.get(ModelKeys.PASSIVATION).asBoolean() : true);
                            CacheStoreConfig storeConfig = this.createCacheLoaderConfig(store, locationInjectors);
                            storeConfig.getSingletonStoreConfig().setSingletonStoreEnabled(store.hasDefined(ModelKeys.SINGLETON) ? store.get(ModelKeys.SINGLETON).asBoolean() : false);
                            storeConfig.setFetchPersistentState(store.hasDefined(ModelKeys.FETCH_STATE) ? store.get(ModelKeys.FETCH_STATE).asBoolean() : true);
                            storeConfig.setPurgeOnStartup(store.hasDefined(ModelKeys.PURGE) ? store.get(ModelKeys.PURGE).asBoolean() : true);
                            if (store.hasDefined(ModelKeys.PROPERTY) && (storeConfig instanceof AbstractCacheStoreConfig)) {
                                Properties properties = new Properties();
                                for (Property property: store.get(ModelKeys.PROPERTY).asPropertyList()) {
                                    properties.setProperty(property.getName(), property.getValue().asString());
                                }
                                ((AbstractCacheStoreConfig) storeConfig).setProperties(properties);
                            }
                            storeManagerConfig.addCacheLoaderConfig(storeConfig);
                        }
                        configs.put(cacheName, config);
                    }
                    if (!configs.containsKey(defaultCache)) {
                        throw new IllegalArgumentException(String.format("%s is not a valid default cache. The %s cache container does not contain a cache with that name", defaultCache, name));
                    }
                    EmbeddedCacheManagerService service = new EmbeddedCacheManagerService(name, defaultCache, global, CacheContainerAdd.this.defaultConfig.clone(), configs);
                    ServiceBuilder<CacheContainer> builder = service.build(context.getServiceTarget());
                    if (aliases != null) {
                        builder.addAliases(aliases);
                    }
                    service.addTransportDependency(builder, stack);
                    if (operation.hasDefined(ModelKeys.LISTENER_EXECUTOR)) {
                        service.addListenerExecutorDependency(builder, operation.get(ModelKeys.LISTENER_EXECUTOR).asString());
                    }
                    if (operation.hasDefined(ModelKeys.EVICTION_EXECUTOR)) {
                        service.addEvictionExecutorDependency(builder, operation.get(ModelKeys.EVICTION_EXECUTOR).asString());
                    }
                    if (operation.hasDefined(ModelKeys.REPLICATION_QUEUE_EXECUTOR)) {
                        service.addReplicationQueueExecutorDependency(builder, operation.get(ModelKeys.REPLICATION_QUEUE_EXECUTOR).asString());
                    }
                    if (transportExecutor != null) {
                        service.addTransportExecutorDependency(builder, transportExecutor);
                    }
                    for (Map.Entry<String, Injector<String>> injector: locationInjectors) {
                        builder.addDependency(AbstractPathService.pathNameOf(injector.getKey()), String.class, injector.getValue());
                    }
                    builder.install();
                    resultHandler.handleResultComplete();
                }

                private CacheStoreConfig createCacheLoaderConfig(ModelNode store, List<Map.Entry<String, Injector<String>>> injectors) {
                    if (store.hasDefined(ModelKeys.CLASS)) {
                        String className = store.get(ModelKeys.CLASS).asString();
                        try {
                            CacheStore cacheStore = Class.forName(className).asSubclass(CacheStore.class).newInstance();
                            return cacheStore.getConfigurationClass().asSubclass(CacheStoreConfig.class).newInstance();
                        } catch (Exception e) {
                            throw new IllegalArgumentException(String.format("%s is not a valid cache store", className), e);
                        }
                    }
                    // If no class, we assume it's a file cache store
                    String relativeTo = ServerEnvironment.SERVER_DATA_DIR;
                    if (store.hasDefined(ModelKeys.RELATIVE_TO)) {
                        relativeTo = store.get(ModelKeys.RELATIVE_TO).asString();
                    }
                    FileCacheStoreConfig storeConfig = new FileCacheStoreConfig();
                    injectors.add(new AbstractMap.SimpleImmutableEntry<String, Injector<String>>(relativeTo, storeConfig.getRelativeToInjector()));
                    storeConfig.setPath(store.hasDefined(ModelKeys.PATH) ? store.get(ModelKeys.PATH).asString() : name);
                    return storeConfig;
                }
            };
            runtime.setRuntimeTask(task);
        } else {
            resultHandler.handleResultComplete();
        }

        return new BasicOperationResult(removeOperation);
    }

    private InfinispanConfiguration load(String resource) {
        URL url = InfinispanExtension.class.getClassLoader().getResource(resource);
        if (url == null) {
            throw new IllegalStateException(String.format("Failed to locate %s", resource));
        }
        try {
            InputStream input = url.openStream();
            SwitchContext context = this.switcher.getSwitchContext(InfinispanConfiguration.class.getClassLoader());
            try {
                return InfinispanConfiguration.newInfinispanConfiguration(input);
            } finally {
                context.reset();
                try {
                    input.close();
                } catch (IOException e) {
                    log.warn(e.getMessage(), e);
                }
            }
        } catch (IOException e) {
            throw new IllegalStateException(String.format("Failed to parse %s", url), e);
        }
    }
}
TOP

Related Classes of org.jboss.as.clustering.infinispan.subsystem.CacheContainerAdd

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.