/* * JBoss, Home of Professional Open Source * Copyright 2009 Red Hat Inc. and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt 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.infinispan.config; import org.infinispan.config.Configuration.EvictionType; import org.infinispan.config.GlobalConfiguration.TransportType; import org.infinispan.configuration.cache.VersioningScheme; import org.infinispan.loaders.CacheLoaderConfig; import org.infinispan.loaders.CacheStoreConfig; import org.infinispan.loaders.decorators.SingletonStoreConfig; import org.infinispan.transaction.TransactionMode; import org.infinispan.transaction.TransactionProtocol; import org.infinispan.util.concurrent.IsolationLevel; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import java.util.Set; /** * ConfigurationValidatingVisitor checks semantic validity of InfinispanConfiguration instance. * * * @author Vladimir Blagojevic * @author Pedro Ruivo * @since 4.0 * @deprecated Belongs to old configuration and so will dissapear in future releases */ @SuppressWarnings("boxing") @Deprecated public class ConfigurationValidatingVisitor extends AbstractConfigurationBeanVisitor { private static final Log log = LogFactory.getLog(ConfigurationValidatingVisitor.class); private TransportType tt = null; private boolean evictionEnabled = false; private Configuration cfg; @Override public void visitSingletonStoreConfig(SingletonStoreConfig ssc) { if (tt == null && ssc.isSingletonStoreEnabled()) throw new ConfigurationException("Singleton store configured without transport being configured"); } @Override public void visitTransportType(TransportType tt) { this.tt = tt; } @Override public void visitConfiguration(Configuration cfg) { this.cfg= cfg; } @Override public void visitClusteringType(Configuration.ClusteringType clusteringType) { Configuration.CacheMode mode = clusteringType.mode; Configuration.AsyncType async = clusteringType.async; Configuration.StateRetrievalType state = clusteringType.stateRetrieval; // certain combinations are illegal, such as state transfer + invalidation if (mode.isInvalidation() && state.fetchInMemoryState) throw new ConfigurationException("Cache cannot use INVALIDATION mode and have fetchInMemoryState set to true."); if (mode.isDistributed() && async.useReplQueue) throw new ConfigurationException("Use of the replication queue is invalid when using DISTRIBUTED mode."); if (mode.isSynchronous() && async.useReplQueue) throw new ConfigurationException("Use of the replication queue is only allowed with an ASYNCHRONOUS cluster mode."); // If replicated and fetch state transfer was not explicitly // disabled, then force enabling of state transfer Set<String> overriden = clusteringType.stateRetrieval.overriddenConfigurationElements; if (mode.isReplicated() && !state.isFetchInMemoryState() && !overriden.contains("fetchInMemoryState")) { log.debug("Cache is replicated but state transfer was not defined, so force enabling it"); state.fetchInMemoryState(true); } } @Override public void visitL1Type(Configuration.L1Type l1Type) { boolean l1Enabled = l1Type.enabled; boolean l1OnRehash = l1Type.onRehash; // If L1 is disabled, L1ForRehash should also be disabled if (!l1Enabled && l1OnRehash) { Set<String> overridden = l1Type.overriddenConfigurationElements; if (overridden.contains("onRehash")) { throw new ConfigurationException("Can only move entries to L1 on rehash when L1 is enabled"); } else { log.debug("L1 is disabled and L1OnRehash was not defined, disabling it"); l1Type.onRehash(false); } } } @Override public void visitCacheLoaderManagerConfig(CacheLoaderManagerConfig cacheLoaderManagerConfig) { if (!evictionEnabled && cacheLoaderManagerConfig.isPassivation()) log.passivationWithoutEviction(); boolean shared = cacheLoaderManagerConfig.isShared(); if (!shared) { for (CacheLoaderConfig loaderConfig : cacheLoaderManagerConfig.getCacheLoaderConfigs()) { if (loaderConfig instanceof CacheStoreConfig) { CacheStoreConfig storeConfig = (CacheStoreConfig)loaderConfig; Boolean fetchPersistentState = storeConfig.isFetchPersistentState(); Boolean purgeOnStartup = storeConfig.isPurgeOnStartup(); if (!fetchPersistentState && !purgeOnStartup && cfg.getCacheMode().isClustered()) { log.staleEntriesWithoutFetchPersistentStateOrPurgeOnStartup(); } } } } } @Override public void visitVersioningConfigurationBean(Configuration.VersioningConfigurationBean config) { if (cfg.getIsolationLevel() == IsolationLevel.SERIALIZABLE && (!cfg.isEnableVersioning() || cfg.getVersioningScheme() != VersioningScheme.GMU)) { throw new ConfigurationException("Expected GMU versioning scheme when SERIALIZABLE is enabled"); } } @Override public void visitEvictionType(EvictionType et) { evictionEnabled = et.strategy.isEnabled(); if (et.strategy.isEnabled() && et.maxEntries <= 0) throw new ConfigurationException("Eviction maxEntries value cannot be less than or equal to zero if eviction is enabled"); } @Override public void visitQueryConfigurationBean(Configuration.QueryConfigurationBean qcb) { if ( ! qcb.enabled ) { return; } // Check that the query module is on the classpath. try { String clazz = "org.infinispan.query.Search"; ClassLoader classLoader; if ((classLoader = cfg.getClassLoader()) == null) Class.forName(clazz); else classLoader.loadClass(clazz); } catch (ClassNotFoundException e) { log.warnf("Indexing can only be enabled if infinispan-query.jar is available on your classpath, and this jar has not been detected. Intended behavior may not be exhibited."); } } @Override public void visitTransactionType(Configuration.TransactionType bean) { if (bean.transactionManagerLookup == null && bean.transactionManagerLookupClass == null) { if (bean.build().isInvocationBatchingEnabled()) { bean.transactionManagerLookupClass = null; if (!bean.useSynchronization) log.debug("Switching to Synchronization-based enlistment."); bean.useSynchronization = true; } } if (bean.transactionProtocol.isTotalOrder()) { //in the future we can allow this in total order?? if (bean.transactionMode == TransactionMode.NON_TRANSACTIONAL) { log.tracef("Non transactional cache is not supported in Total Order protocol. Total Order protocol will" + " be ignored."); return; } //total order only supports replicated and distributed mode if (!cfg.getCacheMode().isReplicated() && !cfg.getCacheMode().isDistributed()) { log.cacheModeNotSupportedByTOProtocol(cfg.getCacheModeString()); bean.transactionProtocol(TransactionProtocol.TWO_PHASE_COMMIT); return; } if (cfg.isRequireVersioning() && cfg.getVersioningScheme() == null) { log.trace("No versioning scheme specified but versioning is required, defaulting to simple versioning."); cfg.setVersioningScheme(VersioningScheme.SIMPLE); } //eager locking is no longer needed if(bean.isUseEagerLocking()) { log.tracef("Eager locking will be ignore with Total Order protocol"); } } if (bean.transactionProtocol.isPassiveReplication()) { if (bean.transactionMode == TransactionMode.NON_TRANSACTIONAL) { log.tracef("Non transactional cache is not supported in Passive Replication protocol. Passive Replication " + "protocol will be ignored."); return; } //for now, only supports full replication if (!cfg.getCacheMode().isReplicated()) { log.cacheModeNotSupportedByPRProtocol(cfg.getCacheModeString()); bean.transactionProtocol(TransactionProtocol.TWO_PHASE_COMMIT); return; } if (cfg.isRequireVersioning() && cfg.getVersioningScheme() == null) { log.trace("No versioning scheme specified but versioning is required, defaulting to simple versioning."); cfg.setVersioningScheme(VersioningScheme.SIMPLE); } } } @Override public void visitDataPlacementType(Configuration.DataPlacementType dataPlacementType) { if (dataPlacementType.enabled) { if (!cfg.getCacheMode().isDistributed()) { throw new ConfigurationException("Data Placement Optimizer only works in distributed mode"); } if (dataPlacementType.objectLookupFactory == null) { throw new ConfigurationException("Expected an Object Lookup Factory instance"); } if (dataPlacementType.coolDowntime < 1000) { throw new ConfigurationException("Expected a cool down time higher or equal than 1000"); } if (dataPlacementType.maxNumberOfKeysToRequest < 1) { throw new ConfigurationException("The max number of keys to request should be higher than 0"); } } } }