/* * 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.loaders; import org.infinispan.config.ConfigurationBeanVisitor; import org.infinispan.config.ConfigurationDoc; import org.infinispan.config.ConfigurationDocRef; import org.infinispan.loaders.decorators.AsyncStoreConfig; import org.infinispan.loaders.decorators.SingletonStoreConfig; import org.infinispan.util.TypedProperties; import org.infinispan.util.Util; import javax.xml.bind.annotation.*; /** * Configures {@link AbstractCacheStore}. This allows you to tune a number of characteristics of the * {@link AbstractCacheStore}. * <p/> * <ul> * <li><tt>purgeSynchronously</tt> - whether * {@link org.infinispan.loaders.CacheStore#purgeExpired()} calls happen synchronously or not. By * default, this is set to <tt>false</tt>.</li> * <li><tt>purgerThreads</tt> - number of threads to use when purging. Defaults to <tt>1</tt> if * <tt>purgeSynchronously</tt> is <tt>true</tt>, ignored if <tt>false</tt>.</li> * </ul> * * * * @author Mircea.Markus@jboss.com * @author Vladimir Blagojevic * @since 4.0 * * @see <a href="../../../config.html#ce_loaders_loader">Configuration reference</a> */ @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) @XmlType(propOrder= {}) @ConfigurationDoc(name="loader",desc="Responsible for loading/storing cache data from/to an external source.") @SuppressWarnings("boxing") public class AbstractCacheStoreConfig extends AbstractCacheLoaderConfig implements CacheStoreConfig { /** The serialVersionUID */ private static final long serialVersionUID = 4607371052771122893L; @ConfigurationDocRef(bean=AbstractCacheStoreConfig.class,targetElement="setIgnoreModifications") protected Boolean ignoreModifications = false; @ConfigurationDocRef(bean=AbstractCacheStoreConfig.class,targetElement="setFetchPersistentState") protected Boolean fetchPersistentState = false; @ConfigurationDocRef(bean=AbstractCacheStoreConfig.class,targetElement="setPurgeOnStartup") protected Boolean purgeOnStartup = false; @ConfigurationDocRef(bean=AbstractCacheStoreConfig.class,targetElement="setPurgeSynchronously") protected Boolean purgeSynchronously = false; @ConfigurationDocRef(bean=AbstractCacheStoreConfig.class,targetElement="setPurgerThreads") protected Integer purgerThreads = 1; protected SingletonStoreConfig singletonStore = new SingletonStoreConfig(); protected AsyncStoreConfig async = new AsyncStoreConfig(); @Override public AsyncStoreConfig asyncStore() { async.setEnabled(true); async.setCacheStoreConfig(this); return async; } @Override public SingletonStoreConfig singletonStore() { singletonStore.setSingletonStoreEnabled(true); singletonStore.setCacheStoreConfig(this); return singletonStore; } @Override @XmlAttribute public Boolean isPurgeSynchronously() { return purgeSynchronously; } @Override @XmlAttribute public Integer getPurgerThreads() { return purgerThreads; } @XmlElement(name="properties") public TypedProperties getTypedProperties(){ return properties; } public void setTypedProperties (TypedProperties tp){ this.properties = tp; } /** * If true, CacheStore#purgeExpired() call will be done synchronously * * @param purgeSynchronously */ @Override public void setPurgeSynchronously(Boolean purgeSynchronously) { testImmutability("purgeSynchronously"); this.purgeSynchronously = purgeSynchronously; } /** * If true, CacheStore#purgeExpired() call will be done synchronously * * @param purgeSynchronously */ @Override public CacheStoreConfig purgeSynchronously(Boolean purgeSynchronously) { testImmutability("purgeSynchronously"); this.purgeSynchronously = purgeSynchronously; return this; } /** * The number of threads to use when purging asynchronously. * * @param purgerThreads * @deprecated use {@link #purgerThreads(Integer)} instead */ @Deprecated public void setPurgerThreads(Integer purgerThreads) { testImmutability("purgerThreads"); this.purgerThreads = purgerThreads; } @Override public CacheStoreConfig purgerThreads(Integer purgerThreads) { setPurgerThreads(purgerThreads); return this; } @Override @XmlAttribute public Boolean isFetchPersistentState() { return fetchPersistentState; } /** * If true, fetch persistent state when joining a cluster. If multiple cache stores are chained, * only one of them can have this property enabled. Persistent state transfer with a shared cache * store does not make sense, as the same persistent store that provides the data will just end * up receiving it. Therefore, if a shared cache store is used, the cache will not allow a * persistent state transfer even if a cache store has this property set to true. Finally, * setting it to true only makes sense if in a clustered environment, and only 'replication' and * 'invalidation' cluster modes are supported. * * * @param fetchPersistentState */ @Override public void setFetchPersistentState(Boolean fetchPersistentState) { testImmutability("fetchPersistentState"); this.fetchPersistentState = fetchPersistentState; } /** * If true, fetch persistent state when joining a cluster. If multiple cache stores are chained, * only one of them can have this property enabled. Persistent state transfer with a shared cache * store does not make sense, as the same persistent store that provides the data will just end * up receiving it. Therefore, if a shared cache store is used, the cache will not allow a * persistent state transfer even if a cache store has this property set to true. Finally, * setting it to true only makes sense if in a clustered environment, and only 'replication' and * 'invalidation' cluster modes are supported. * * * @param fetchPersistentState */ @Override public CacheStoreConfig fetchPersistentState(Boolean fetchPersistentState) { testImmutability("fetchPersistentState"); this.fetchPersistentState = fetchPersistentState; return this; } /** * If true, any operation that modifies the cache (put, remove, clear, store...etc) won't be * applied to the cache store. This means that the cache store could become out of sync with the * cache. * * @param ignoreModifications */ @Override public void setIgnoreModifications(Boolean ignoreModifications) { testImmutability("ignoreModifications"); this.ignoreModifications = ignoreModifications; } /** * If true, any operation that modifies the cache (put, remove, clear, store...etc) won't be * applied to the cache store. This means that the cache store could become out of sync with the * cache. * * @param ignoreModifications */ @Override public CacheStoreConfig ignoreModifications(Boolean ignoreModifications) { testImmutability("ignoreModifications"); this.ignoreModifications = ignoreModifications; return this; } @Override @XmlAttribute public Boolean isIgnoreModifications() { return ignoreModifications; } @Override @XmlAttribute public Boolean isPurgeOnStartup() { return purgeOnStartup; } /** * * If true, purges this cache store when it starts up. * * @param purgeOnStartup */ @Override public CacheStoreConfig purgeOnStartup(Boolean purgeOnStartup) { testImmutability("purgeOnStartup"); this.purgeOnStartup = purgeOnStartup; return this; } /** * * If true, purges this cache store when it starts up. * * @param purgeOnStartup */ @Override public void setPurgeOnStartup(Boolean purgeOnStartup) { testImmutability("purgeOnStartup"); this.purgeOnStartup = purgeOnStartup; } @Override @XmlElement(name="singletonStore") public SingletonStoreConfig getSingletonStoreConfig() { return singletonStore; } @Override public void setSingletonStoreConfig(SingletonStoreConfig singletonStoreConfig) { testImmutability("singletonStore"); this.singletonStore = singletonStoreConfig; } @Override @XmlElement(name="async") public AsyncStoreConfig getAsyncStoreConfig() { return async; } @Override public void setAsyncStoreConfig(AsyncStoreConfig asyncStoreConfig) { testImmutability("async"); this.async = asyncStoreConfig; } @Override public void accept(ConfigurationBeanVisitor v) { singletonStore.accept(v); async.accept(v); v.visitCacheLoaderConfig(this); } @Override public boolean equals(Object obj) { if (super.equals(obj)) { if (!(obj instanceof AbstractCacheStoreConfig)) return false; AbstractCacheStoreConfig i = (AbstractCacheStoreConfig) obj; return equalsExcludingProperties(i); } return false; } protected boolean equalsExcludingProperties(Object obj) { AbstractCacheStoreConfig other = (AbstractCacheStoreConfig) obj; return Util.safeEquals(this.cacheLoaderClassName, other.cacheLoaderClassName) && (this.ignoreModifications.equals(other.ignoreModifications)) && (this.fetchPersistentState.equals(other.fetchPersistentState)) && Util.safeEquals(this.singletonStore, other.singletonStore) && Util.safeEquals(this.async, other.async) && Util.safeEquals(this.purgeSynchronously, other.purgeSynchronously) && Util.safeEquals(this.purgerThreads, other.purgerThreads); } @Override public int hashCode() { return 31 * hashCodeExcludingProperties() + (properties == null ? 0 : properties.hashCode()); } protected int hashCodeExcludingProperties() { int result = 17; result = 31 * result + (cacheLoaderClassName == null ? 0 : cacheLoaderClassName.hashCode()); result = 31 * result + (ignoreModifications ? 0 : 1); result = 31 * result + (fetchPersistentState ? 0 : 1); result = 31 * result + (singletonStore == null ? 0 : singletonStore.hashCode()); result = 31 * result + (async == null ? 0 : async.hashCode()); result = 31 * result + (purgeOnStartup ? 0 : 1); result = 31 * result + (purgerThreads); return result; } @Override public String toString() { return new StringBuilder().append(getClass().getSimpleName()).append("{").append("className='").append(cacheLoaderClassName).append('\'') .append(", ignoreModifications=").append(ignoreModifications) .append(", fetchPersistentState=").append(fetchPersistentState) .append(", properties=").append(properties) .append(", purgeOnStartup=").append(purgeOnStartup).append("},") .append(", singletonStore{").append(singletonStore).append('}') .append(", async{").append(async).append('}') .append(", purgeSynchronously{").append(purgeSynchronously).append('}') .append(", purgerThreads{").append(purgerThreads).append('}') .toString(); } @Override public AbstractCacheStoreConfig clone() { AbstractCacheStoreConfig clone = (AbstractCacheStoreConfig) super.clone(); if (singletonStore != null) clone.setSingletonStoreConfig(singletonStore.clone()); if (async != null) clone.setAsyncStoreConfig(async.clone()); return clone; } }