View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.config;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  import java.util.concurrent.CopyOnWriteArraySet;
25  
26  import net.sf.ehcache.CacheException;
27  import net.sf.ehcache.Element;
28  import net.sf.ehcache.config.TerracottaConfiguration.Consistency;
29  import net.sf.ehcache.config.TerracottaConfiguration.StorageStrategy;
30  import net.sf.ehcache.event.NotificationScope;
31  import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
32  import net.sf.ehcache.store.compound.ReadWriteCopyStrategy;
33  
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /***
38   * A value object used to represent cache configuration.
39   * <h4>Construction Patterns</h4>
40   * The recommended way of creating a <code>Cache</code> in Ehcache 2.0 and above is to create a <code>CacheConfiguration</code> object
41   * and pass it to the <code>Cache</code> constructor. See {@link net.sf.ehcache.Cache#Cache(CacheConfiguration)}.
42   * <p/>
43   * This class supports setter injection and also the fluent builder pattern.
44   * e.g.
45   * <code>Cache cache = new Cache(new CacheConfiguration("test2", 1000).eternal(true).memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.FIFO));</code>
46   * <p/>
47   * Rather than proliferation of new constructors as new versions of Ehcache come out, it intended to add the new configuration to this
48   * class.
49   * <p/>
50   * Another way to set configuration is declaratively in the <code>ehcache.xml</code> configuration file.
51   * e.g.
52   * <pre>{@code
53   * <cache name="testCache1"
54   *   maxElementsInMemory="10000"
55   *   eternal="false"
56   *   timeToIdleSeconds="3600"
57   *   timeToLiveSeconds="10"
58   *   overflowToDisk="true"
59   *   diskPersistent="true"
60   *   diskExpiryThreadIntervalSeconds="120"
61   *   maxElementsOnDisk="10000"
62   * />
63   * }</pre>
64   * <p/>
65   * <h4>Dynamic Configuration</h4>
66   * CacheConfiguration instances retrieved from Cache instances allow the dynamic
67   * modification of certain configuration properties.  Currently the dynamic
68   * properties are:
69   * <ul>
70   * <li>Time To Idle</li>
71   * <li>Time To Live</li>
72   * <li>Max Elements in Memory</li>
73   * <li>Max Elements on Disk</li>
74   * </ul>
75   * Dynamic changes are however not persistent across cache restarts.  On restart
76   * the cache configuration will be reloaded from its original source, erasing any
77   * changes made previously at runtime.
78   *
79   * @author Greg Luck
80   * @author Chris Dennis
81   * @version $Id: CacheConfiguration.html 13146 2011-08-01 17:12:39Z oletizi $
82   */
83  public class CacheConfiguration implements Cloneable {
84  
85      /***
86       * Default value for clearOnFlush
87       */
88      public static final boolean DEFAULT_CLEAR_ON_FLUSH = true;
89  
90      /***
91       * The default interval between runs of the expiry thread.
92       */
93      public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = 120;
94  
95      /***
96       * Set a buffer size for the spool of approx 30MB.
97       */
98      public static final int DEFAULT_SPOOL_BUFFER_SIZE = 30;
99  
100     /***
101      * Default number of diskAccessStripes.
102      */
103     public static final int DEFAULT_DISK_ACCESS_STRIPES = 1;
104 
105     /***
106      * Logging is off by default.
107      */
108     public static final boolean DEFAULT_LOGGING = false;
109 
110     /***
111      * The default memory store eviction policy is LRU.
112      */
113     public static final MemoryStoreEvictionPolicy DEFAULT_MEMORY_STORE_EVICTION_POLICY = MemoryStoreEvictionPolicy.LRU;
114 
115     /***
116      * The default cacheWriterConfiguration
117      */
118     public static final CacheWriterConfiguration DEFAULT_CACHE_WRITER_CONFIGURATION = new CacheWriterConfiguration();
119 
120     /***
121      * Default value for copyOnRead
122      */
123     public static final boolean DEFAULT_COPY_ON_READ = false;
124 
125     /***
126      * Default value for copyOnRead
127      */
128     public static final boolean DEFAULT_COPY_ON_WRITE = false;
129 
130     /***
131      * Default value for ttl
132      */
133     public static final long DEFAULT_TTL = 0;
134 
135     /***
136      * Default value for tti
137      */
138     public static final long DEFAULT_TTI = 0;
139 
140     /***
141      * Default value for maxElementsOnDisk
142      */
143     public static final int DEFAULT_MAX_ELEMENTS_ON_DISK = 0;
144 
145     /***
146      * Default value for transactionalMode
147      */
148     public static final TransactionalMode DEFAULT_TRANSACTIONAL_MODE = TransactionalMode.OFF;
149 
150     /***
151      * Default value for statistics
152      */
153     public static final boolean DEFAULT_STATISTICS = false;
154 
155     /***
156      * Default value for diskPersistent
157      */
158     public static final boolean DEFAULT_DISK_PERSISTENT = false;
159 
160     /***
161      * Default copyStrategyConfiguration
162      */
163     public static final CopyStrategyConfiguration DEFAULT_COPY_STRATEGY_CONFIGURATION = new CopyStrategyConfiguration();
164 
165     /***
166      * Default elementComparatorConfiguration
167      */
168     public static final ElementValueComparatorConfiguration DEFAULT_ELEMENT_VALUE_COMPARATOR_CONFIGURATION =
169            new ElementValueComparatorConfiguration();
170 
171     /***
172      * Default maxBytesOnHeap value
173      */
174     public static final long DEFAULT_MAX_BYTES_ON_HEAP  = 0;
175 
176     /***
177      * Default maxBytesOffHeap value
178      */
179     public static final long DEFAULT_MAX_BYTES_OFF_HEAP = 0;
180 
181     /***
182      * Default maxBytesOnDisk value
183      */
184     public static final long DEFAULT_MAX_BYTES_ON_DISK  = 0;
185 
186 
187     private static final Logger LOG = LoggerFactory.getLogger(CacheConfiguration.class.getName());
188     private static final int HUNDRED_PERCENT = 100;
189 
190     /***
191      * the name of the cache.
192      */
193     protected volatile String name;
194 
195     /***
196      * Timeout in milliseconds for CacheLoader related calls
197      */
198     protected volatile long cacheLoaderTimeoutMillis;
199 
200     /***
201      * the maximum objects to be held in the {@link net.sf.ehcache.store.MemoryStore}.
202      * <p/>
203      * <code>0</code> translates to no-limit.
204      */
205     protected volatile int maxEntriesLocalHeap;
206 
207     /***
208      * the maximum objects to be held in the {@link net.sf.ehcache.store.disk.DiskStore}.
209      * <p/>
210      * <code>0</code> translates to no-limit.
211      */
212     protected volatile int maxElementsOnDisk = DEFAULT_MAX_ELEMENTS_ON_DISK;
213 
214     /***
215      * The policy used to evict elements from the {@link net.sf.ehcache.store.MemoryStore}.
216      * This can be one of:
217      * <ol>
218      * <li>LRU - least recently used
219      * <li>LFU - Less frequently used
220      * <li>FIFO - first in first out, the oldest element by creation time
221      * </ol>
222      * The default value is LRU
223      *
224      * @since 1.2
225      */
226     protected volatile MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
227 
228     /***
229      * Sets whether the MemoryStore should be cleared when
230      * {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
231      */
232     protected volatile boolean clearOnFlush = DEFAULT_CLEAR_ON_FLUSH;
233 
234     /***
235      * Sets whether elements are eternal. If eternal, timeouts are ignored and the element
236      * is never expired.
237      */
238     protected volatile boolean eternal;
239 
240     /***
241      * the time to idle for an element before it expires. Is only used
242      * if the element is not eternal.A value of 0 means do not check for idling.
243      */
244     protected volatile long timeToIdleSeconds = DEFAULT_TTI;
245 
246     /***
247      * Sets the time to idle for an element before it expires. Is only used
248      * if the element is not eternal. This attribute is optional in the configuration.
249      * A value of 0 means do not check time to live.
250      */
251     protected volatile long timeToLiveSeconds = DEFAULT_TTL;
252 
253     /***
254      * whether elements can overflow to disk when the in-memory cache
255      * has reached the set limit.
256      */
257     protected volatile boolean overflowToDisk;
258 
259     /***
260      * For caches that overflow to disk, whether the disk cache persists between CacheManager instances.
261      */
262     protected volatile boolean diskPersistent = DEFAULT_DISK_PERSISTENT;
263 
264     /***
265      * The path where the disk store is located
266      */
267     protected volatile String diskStorePath;
268 
269     /***
270      * The size of the disk spool used to buffer writes
271      */
272     protected volatile int diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
273 
274     /***
275      * The number of concurrent disk access stripes.
276      */
277     protected volatile int diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
278 
279     /***
280      * The interval in seconds between runs of the disk expiry thread.
281      * <p/>
282      * 2 minutes is the default.
283      * This is not the same thing as time to live or time to idle. When the thread runs it checks
284      * these things. So this value is how often we check for expiry.
285      */
286     protected volatile long diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
287 
288     /***
289      * Indicates whether logging is enabled or not. False by default.
290      * Only used when cache is clustered with Terracotta.
291      */
292     protected volatile boolean logging = DEFAULT_LOGGING;
293 
294     /***
295      * whether elements can overflow to off heap memory when the in-memory cache
296      * has reached the set limit.
297      */
298     protected volatile boolean overflowToOffHeap;
299 
300     /***
301      * The event listener factories added by BeanUtils.
302      */
303     protected volatile List<CacheEventListenerFactoryConfiguration> cacheEventListenerConfigurations =
304             new ArrayList<CacheEventListenerFactoryConfiguration>();
305 
306     /***
307      * The cache extension factories added by BeanUtils.
308      */
309     protected volatile List<CacheExtensionFactoryConfiguration> cacheExtensionConfigurations =
310             new ArrayList<CacheExtensionFactoryConfiguration>();
311 
312     /***
313      * The BootstrapCacheLoaderFactoryConfiguration.
314      */
315     protected BootstrapCacheLoaderFactoryConfiguration bootstrapCacheLoaderFactoryConfiguration;
316 
317     /***
318      * The CacheExceptionHandlerFactoryConfiguration.
319      */
320     protected CacheExceptionHandlerFactoryConfiguration cacheExceptionHandlerFactoryConfiguration;
321 
322     /***
323      * The TerracottaConfiguration.
324      */
325     protected TerracottaConfiguration terracottaConfiguration;
326 
327     /***
328      * The PinningConfiguration.
329      */
330     protected volatile PinningConfiguration pinningConfiguration;
331 
332     /***
333      * The CacheWriterConfiguration.
334      */
335     protected CacheWriterConfiguration cacheWriterConfiguration = DEFAULT_CACHE_WRITER_CONFIGURATION;
336 
337     /***
338      * The cache loader factories added by BeanUtils.
339      */
340     protected volatile List<CacheLoaderFactoryConfiguration> cacheLoaderConfigurations = new ArrayList<CacheLoaderFactoryConfiguration>();
341 
342     /***
343      * The cache decorator factories added by BeanUtils.
344      */
345     protected volatile List<CacheDecoratorFactoryConfiguration> cacheDecoratorConfigurations =
346             new ArrayList<CacheDecoratorFactoryConfiguration>();
347 
348     /***
349      * The listeners for this configuration.
350      */
351     protected volatile Set<CacheConfigurationListener> listeners = new CopyOnWriteArraySet<CacheConfigurationListener>();
352 
353     private volatile boolean frozen;
354     private TransactionalMode transactionalMode = DEFAULT_TRANSACTIONAL_MODE;
355     private volatile boolean statistics = DEFAULT_STATISTICS;
356     private volatile CopyStrategyConfiguration copyStrategyConfiguration = DEFAULT_COPY_STRATEGY_CONFIGURATION.copy();
357     private volatile ElementValueComparatorConfiguration elementValueComparatorConfiguration =
358             DEFAULT_ELEMENT_VALUE_COMPARATOR_CONFIGURATION;
359     private volatile Boolean copyOnRead;
360     private volatile Boolean copyOnWrite;
361     private volatile boolean conflictingEternalValuesWarningLogged;
362     private volatile Searchable searchable;
363     private Long maxBytesLocalHeap;
364     private Long maxBytesLocalOffHeap;
365     private Long maxBytesLocalDisk;
366     private Integer maxBytesLocalHeapPercentage;
367     private Integer maxBytesLocalOffHeapPercentage;
368     private Integer maxBytesLocalDiskPercentage;
369 
370     /***
371      * Default constructor.
372      * <p/>
373      * Note that an empty Cache is not valid and must have extra configuration added which can be done
374      * through the fluent methods in this class. Call <code>validateConfiguration()</code> to check your configuration.
375      *
376      * @see #validateCompleteConfiguration
377      */
378     public CacheConfiguration() {
379         // empty constructor
380     }
381 
382     /***
383      * Create a new cache configuration.
384      * <p/>
385      * Extra configuration can added after construction via the fluent methods in this class.
386      * Call <code>validateConfiguration()</code> to check your configuration.
387      *
388      * @param name                the name of the cache. Note that "default" is a reserved name for the defaultCache.
389      * @param maxEntriesLocalHeap the maximum number of elements in memory, before they are evicted (0 == no limit)
390      * @see #validateCompleteConfiguration()
391      */
392     public CacheConfiguration(String name, int maxEntriesLocalHeap) {
393         this.name = name;
394         this.maxEntriesLocalHeap = maxEntriesLocalHeap;
395     }
396 
397     /***
398      * Clones this object, following the usual contract.
399      *
400      * @return a copy, which independent other than configurations than cannot change.
401      */
402     @Override
403     public CacheConfiguration clone() {
404         CacheConfiguration config;
405         try {
406             config = (CacheConfiguration) super.clone();
407         } catch (CloneNotSupportedException e) {
408             throw new RuntimeException(e);
409         }
410 
411         cloneCacheEventListenerConfigurations(config);
412 
413         cloneCacheExtensionConfigurations(config);
414 
415         if (bootstrapCacheLoaderFactoryConfiguration != null) {
416             config.bootstrapCacheLoaderFactoryConfiguration = bootstrapCacheLoaderFactoryConfiguration.clone();
417         }
418 
419         if (cacheExceptionHandlerFactoryConfiguration != null) {
420             config.cacheExceptionHandlerFactoryConfiguration = cacheExceptionHandlerFactoryConfiguration.clone();
421         }
422 
423         if (terracottaConfiguration != null) {
424             config.terracottaConfiguration = terracottaConfiguration.clone();
425         }
426 
427         if (cacheWriterConfiguration != null) {
428             config.cacheWriterConfiguration = cacheWriterConfiguration.clone();
429         }
430 
431         cloneCacheLoaderConfigurations(config);
432 
433         cloneCacheDecoratorConfigurations(config);
434 
435         config.listeners = new CopyOnWriteArraySet<CacheConfigurationListener>();
436 
437         return config;
438     }
439 
440     private void cloneCacheEventListenerConfigurations(CacheConfiguration config) {
441         if (cacheEventListenerConfigurations.size() > 0) {
442             List<CacheEventListenerFactoryConfiguration> copy = new ArrayList<CacheEventListenerFactoryConfiguration>();
443             for (CacheEventListenerFactoryConfiguration item : cacheEventListenerConfigurations) {
444                 copy.add(item.clone());
445             }
446             config.cacheEventListenerConfigurations = copy;
447         }
448     }
449 
450     private void cloneCacheExtensionConfigurations(CacheConfiguration config) {
451         if (cacheExtensionConfigurations.size() > 0) {
452             List<CacheExtensionFactoryConfiguration> copy = new ArrayList<CacheExtensionFactoryConfiguration>();
453             for (CacheConfiguration.CacheExtensionFactoryConfiguration item : cacheExtensionConfigurations) {
454                 copy.add(item.clone());
455             }
456             config.cacheExtensionConfigurations = copy;
457         }
458     }
459 
460     private void cloneCacheLoaderConfigurations(CacheConfiguration config) {
461         if (cacheLoaderConfigurations.size() > 0) {
462             List<CacheLoaderFactoryConfiguration> copy = new ArrayList<CacheLoaderFactoryConfiguration>();
463             for (CacheConfiguration.CacheLoaderFactoryConfiguration item : cacheLoaderConfigurations) {
464                 copy.add(item.clone());
465             }
466             config.cacheLoaderConfigurations = copy;
467         }
468     }
469 
470     private void cloneCacheDecoratorConfigurations(CacheConfiguration config) {
471         if (cacheDecoratorConfigurations.size() > 0) {
472             List<CacheDecoratorFactoryConfiguration> copy = new ArrayList<CacheDecoratorFactoryConfiguration>();
473             for (CacheDecoratorFactoryConfiguration item : cacheDecoratorConfigurations) {
474                 copy.add(item.clone());
475             }
476             config.cacheDecoratorConfigurations = copy;
477         }
478     }
479 
480     /***
481      * Sets the name of the cache.
482      *
483      * @param name the cache name. This must be unique. The / character is illegal. The # character does not work with RMI replication.
484      */
485     public final void setName(String name) {
486         checkDynamicChange();
487         if (name == null) {
488             throw new IllegalArgumentException("Cache name cannot be null.");
489         }
490         this.name = name;
491     }
492 
493     /***
494      * Builder to set the name of the cache.
495      *
496      * @param name the cache name. This must be unique. The / character is illegal. The # character does not work with RMI replication.
497      * @return this configuration instance
498      * @see #setName(String)
499      */
500     public final CacheConfiguration name(String name) {
501         setName(name);
502         return this;
503     }
504 
505     /***
506      * Enables or disables logging for the cache
507      * <p/>
508      * This property can be modified dynamically while the cache is operating.
509      * Only used when cache is clustered with Terracotta
510      *
511      * @param enable If true, enables logging otherwise disables logging
512      */
513     public final void setLogging(boolean enable) {
514         checkDynamicChange();
515         boolean oldLoggingEnabled = this.logging;
516         this.logging = enable;
517         fireLoggingChanged(oldLoggingEnabled, enable);
518     }
519 
520     /***
521      * Enables or disables offheap store for the cache.
522      *
523      * @param overflowToOffHeap If true, enables offheap store otherwise disables it.
524      */
525     public final void setOverflowToOffHeap(boolean overflowToOffHeap) {
526         checkDynamicChange();
527         this.overflowToOffHeap = overflowToOffHeap;
528     }
529 
530     /***
531      * Builder to enable or disable offheap store for the cache.
532      *
533      * @param overflowToOffHeap If true, enables offheap store otherwise disables it.
534      * @return this configuration instance
535      * @see #setOverflowToOffHeap(boolean)
536      */
537     public CacheConfiguration overflowToOffHeap(boolean overflowToOffHeap) {
538         setOverflowToOffHeap(overflowToOffHeap);
539         return this;
540     }
541 
542     /***
543      * Sets the max off heap memory size allocated for this cache.
544      *
545      * @param maxMemoryOffHeap the max off heap memory size allocated for this cache.
546      */
547     public final void setMaxMemoryOffHeap(String maxMemoryOffHeap) {
548         checkDynamicChange();
549         setMaxBytesLocalOffHeap(maxMemoryOffHeap);
550     }
551 
552     /***
553      * Builder to set the max off heap memory size allocated for this cache.
554      *
555      * @param maxMemoryOffHeap the max off heap memory size allocated for this cache.
556      * @return this configuration instance
557      * @see #setMaxMemoryOffHeap(String)
558      */
559     public CacheConfiguration maxMemoryOffHeap(String maxMemoryOffHeap) {
560         setMaxMemoryOffHeap(maxMemoryOffHeap);
561         return this;
562     }
563 
564     /***
565      * Builder to enable or disable logging for the cache
566      * <p/>
567      * This property can be modified dynamically while the cache is operating.
568      * Only used when cache is clustered with Terracotta
569      *
570      * @param enable If true, enables logging otherwise disables logging
571      * @return this configuration instance
572      * @see #setLogging(boolean)
573      */
574     public final CacheConfiguration logging(boolean enable) {
575         setLogging(enable);
576         return this;
577     }
578 
579     /***
580      * Sets the maximum objects to be held in memory (0 = no limit).
581      * <p/>
582      * This property can be modified dynamically while the cache is operating.
583      *
584      * @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
585      * @deprecated use {@link #setMaxEntriesLocalHeap(long)}
586      */
587     @Deprecated
588     public final void setMaxElementsInMemory(int maxElementsInMemory) {
589         setMaxEntriesLocalHeap(maxElementsInMemory);
590     }
591 
592     /***
593      * Sets the maximum objects to be held in local heap memory (0 = no limit).
594      * <p/>
595      * This property can be modified dynamically while the cache is operating.
596      *
597      * @param maxEntriesInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
598      */
599     public final void setMaxEntriesLocalHeap(long maxEntriesInMemory) {
600         if (maxEntriesInMemory > Integer.MAX_VALUE) {
601             throw new IllegalArgumentException("Values larger than Integer.MAX_VALUE are not currently supported.");
602         }
603 
604         checkDynamicChange();
605         int oldCapacity = this.maxEntriesLocalHeap;
606         int newCapacity = (int) maxEntriesInMemory;
607         this.maxEntriesLocalHeap = (int) maxEntriesInMemory;
608         fireMemoryCapacityChanged(oldCapacity, newCapacity);
609     }
610 
611     /***
612      * Builder that sets the maximum objects to be held in memory (0 = no limit).
613      * <p/>
614      * This property can be modified dynamically while the cache is operating.
615      *
616      * @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
617      * @return this configuration instance
618      * @deprecated use {@link #maxEntriesLocalHeap(int)}
619      */
620     @Deprecated
621     public final CacheConfiguration maxElementsInMemory(int maxElementsInMemory) {
622         setMaxElementsInMemory(maxElementsInMemory);
623         return this;
624     }
625 
626     /***
627      * Builder that sets the maximum objects to be held in memory (0 = no limit).
628      * <p/>
629      * This property can be modified dynamically while the cache is operating.
630      *
631      * @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
632      * @return this configuration instance
633      */
634     public final CacheConfiguration maxEntriesLocalHeap(int maxElementsInMemory) {
635         setMaxEntriesLocalHeap(maxElementsInMemory);
636         return this;
637     }
638 
639     /***
640      * Sets the timeout for CacheLoader execution (0 = no timeout).
641      *
642      * @param cacheLoaderTimeoutMillis the timeout in milliseconds.
643      */
644     public final void setCacheLoaderTimeoutMillis(long cacheLoaderTimeoutMillis) {
645         checkDynamicChange();
646         this.cacheLoaderTimeoutMillis = cacheLoaderTimeoutMillis;
647     }
648 
649     /***
650      * Builder that sets the timeout for CacheLoader execution (0 = no timeout).
651 
652      * @param timeoutMillis the timeout in milliseconds.
653      * @return this configuration instance
654      */
655     public CacheConfiguration timeoutMillis(long timeoutMillis) {
656         setCacheLoaderTimeoutMillis(timeoutMillis);
657         return this;
658     }
659 
660     /***
661      * Sets the eviction policy. An invalid argument will set it to null.
662      *
663      * @param memoryStoreEvictionPolicy a String representation of the policy. One of "LRU", "LFU" or "FIFO".
664      */
665     public final void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
666         setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy.fromString(memoryStoreEvictionPolicy));
667     }
668 
669     /***
670      * Builder that sets the eviction policy. An invalid argument will set it to null.
671      *
672      * @param memoryStoreEvictionPolicy a String representation of the policy. One of "LRU", "LFU" or "FIFO".
673      * @return this configuration instance
674      * @see #setMemoryStoreEvictionPolicy(String)
675      */
676     public final CacheConfiguration memoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
677         setMemoryStoreEvictionPolicy(memoryStoreEvictionPolicy);
678         return this;
679     }
680 
681     /***
682      * Sets the eviction policy. This method has a strange name to workaround a problem with XML parsing.
683      */
684     public final void setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
685         checkDynamicChange();
686         if (null == memoryStoreEvictionPolicy) {
687             this.memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
688         } else {
689             this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
690         }
691     }
692 
693     /***
694      * Builder which Sets the eviction policy. An invalid argument will set it to null.
695      *
696      * @return this configuration instance
697      * @see #setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy)
698      */
699     public final CacheConfiguration memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
700         setMemoryStoreEvictionPolicyFromObject(memoryStoreEvictionPolicy);
701         return this;
702     }
703 
704     /***
705      * Sets whether the MemoryStore should be cleared when
706      * {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
707      *
708      * @param clearOnFlush true to clear on flush
709      */
710     public final void setClearOnFlush(boolean clearOnFlush) {
711         checkDynamicChange();
712         this.clearOnFlush = clearOnFlush;
713     }
714 
715     /***
716      * Builder which sets whether the MemoryStore should be cleared when
717      * {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
718      *
719      * @param clearOnFlush true to clear on flush
720      * @return this configuration instance
721      * @see #setClearOnFlush(boolean)
722      */
723     public final CacheConfiguration clearOnFlush(boolean clearOnFlush) {
724         setClearOnFlush(clearOnFlush);
725         return this;
726     }
727 
728     /***
729      * Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. False by default.
730      *
731      * @param eternal true for eternal
732      */
733     public final void setEternal(boolean eternal) {
734         checkDynamicChange();
735         isEternalValueConflictingWithTTIOrTTL(eternal, getTimeToLiveSeconds(), getTimeToIdleSeconds());
736         this.eternal = eternal;
737         if (eternal) {
738             setTimeToIdleSeconds(0);
739             setTimeToLiveSeconds(0);
740         }
741     }
742 
743     private boolean isEternalValueConflictingWithTTIOrTTL(boolean newEternalValue, long newTTLValue, long newTTIValue) {
744         boolean conflicting = false;
745 
746         if (newEternalValue && (newTTLValue != 0 || newTTIValue != 0)) {
747             conflicting = true;
748         }
749 
750         if (conflicting && !conflictingEternalValuesWarningLogged) {
751             conflictingEternalValuesWarningLogged = true;
752             LOG.warn("Cache '" + getName() + "' is set to eternal but also has TTI/TTL set. "
753                     + " To avoid this warning, clean up the config " + "removing conflicting values of eternal,"
754                     + " TTI and TTL. Effective configuration for Cache '" + getName() + "' will be eternal='" + newEternalValue
755                     + "', timeToIdleSeconds='0', timeToLiveSeconds='0'.");
756         }
757         return conflicting;
758     }
759 
760     /***
761      * Builder which sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. False by default.
762      *
763      * @param eternal true for eternal
764      * @return this configuration instance
765      * @see #setEternal(boolean)
766      */
767     public final CacheConfiguration eternal(boolean eternal) {
768         setEternal(eternal);
769         return this;
770     }
771 
772     /***
773      * Sets the time to idle for an element before it expires. Is only used if the element is not eternal. This can be overidden in
774      * {@link net.sf.ehcache.Element}
775      * <p/>
776      * This property can be modified dynamically while the cache is operating.
777      *
778      * @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
779      */
780     public final void setTimeToIdleSeconds(long timeToIdleSeconds) {
781         checkDynamicChange();
782         if (!isEternalValueConflictingWithTTIOrTTL(eternal, 0, timeToIdleSeconds)) {
783             long oldTti = this.timeToIdleSeconds;
784             long newTti = timeToIdleSeconds;
785             this.timeToIdleSeconds = timeToIdleSeconds;
786             fireTtiChanged(oldTti, newTti);
787         }
788     }
789 
790     /***
791      * Builder which sets the time to idle for an element before it expires. Is only used if the element is not eternal.
792      * This default can be overridden in {@link net.sf.ehcache.Element}
793      * <p/>
794      * This property can be modified dynamically while the cache is operating.
795      *
796      * @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
797      * @return this configuration instance
798      * @see #setTimeToIdleSeconds(long)
799      */
800     public final CacheConfiguration timeToIdleSeconds(long timeToIdleSeconds) {
801         setTimeToIdleSeconds(timeToIdleSeconds);
802         return this;
803     }
804 
805     /***
806      * Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
807      * This default can be overridden in {@link net.sf.ehcache.Element}
808      * <p/>
809      * This property can be modified dynamically while the cache is operating.
810      *
811      * @param timeToLiveSeconds the default amount of time to live for an element from its creation date
812      */
813     public final void setTimeToLiveSeconds(long timeToLiveSeconds) {
814         checkDynamicChange();
815         if (!isEternalValueConflictingWithTTIOrTTL(eternal, timeToLiveSeconds, 0)) {
816             long oldTtl = this.timeToLiveSeconds;
817             long newTtl = timeToLiveSeconds;
818             this.timeToLiveSeconds = timeToLiveSeconds;
819             fireTtlChanged(oldTtl, newTtl);
820         }
821     }
822 
823     /***
824      * Builder which sets the time to idle for an element before it expires. Is only used if the element is not eternal.
825      * This default can be overridden in {@link net.sf.ehcache.Element}
826      * <p/>
827      * This property can be modified dynamically while the cache is operating.
828      *
829      * @param timeToLiveSeconds the default amount of time to live for an element from its creation date
830      * @return this configuration instance
831      * @see #setTimeToLiveSeconds(long)
832      */
833     public final CacheConfiguration timeToLiveSeconds(long timeToLiveSeconds) {
834         setTimeToLiveSeconds(timeToLiveSeconds);
835         return this;
836     }
837 
838     /***
839      * Sets whether elements can overflow to disk when the in-memory cache has reached the set limit.
840      *
841      * @param overflowToDisk whether to use the disk store
842      */
843     public final void setOverflowToDisk(boolean overflowToDisk) {
844         checkDynamicChange();
845         this.overflowToDisk = overflowToDisk;
846         validateConfiguration();
847     }
848 
849     /***
850      * Builder which sets whether elements can overflow to disk when the in-memory cache has reached the set limit.
851      *
852      * @param overflowToDisk whether to use the disk store
853      * @return this configuration instance
854      * @see #setOverflowToDisk(boolean)
855      */
856     public final CacheConfiguration overflowToDisk(boolean overflowToDisk) {
857         setOverflowToDisk(overflowToDisk);
858         return this;
859     }
860 
861     /***
862      * Sets whether the disk store persists between CacheManager instances. Note that this operates independently of {@link #overflowToDisk}.
863      *
864      * @param diskPersistent whether to persist the cache to disk between JVM restarts
865      */
866     public final void setDiskPersistent(boolean diskPersistent) {
867         checkDynamicChange();
868         this.diskPersistent = diskPersistent;
869         validateConfiguration();
870     }
871 
872     /***
873      * Builder which sets whether the disk store persists between CacheManager instances. Note that this operates independently of {@link #overflowToDisk}.
874      *
875      * @param diskPersistent whether to persist the cache to disk between JVM restarts.
876      * @return this configuration instance
877      * @see #setDiskPersistent(boolean)
878      */
879     public final CacheConfiguration diskPersistent(boolean diskPersistent) {
880         setDiskPersistent(diskPersistent);
881         return this;
882     }
883 
884     /***
885      * Sets the path that will be used for the disk store.
886      * If you use this feature, beware of collisions with CacheManagers
887      * potentially have a Cache with the same name!
888      *
889      * @param diskStorePath if <code>null</code>, CacheManager sets it using setter injection.
890      */
891     public final void setDiskStorePath(String diskStorePath) {
892         checkDynamicChange();
893         if (null == diskStorePath) {
894             this.diskStorePath = DiskStoreConfiguration.getDefaultPath();
895         }
896         this.diskStorePath = diskStorePath;
897         validateConfiguration();
898     }
899 
900     /***
901      * Builder which sets the path that will be used for the disk store.
902      * If you use this feature, beware of collisions with CacheManagers
903      * potentially have a Cache with the same name!
904      *
905      * @param diskStorePath if <code>null</code>, CacheManager sets it using setter injection.
906      * @return this configuration instance
907      * @see #setDiskStorePath(String)
908      */
909     public final CacheConfiguration diskStorePath(String diskStorePath) {
910         setDiskStorePath(diskStorePath);
911         return this;
912     }
913 
914     /***
915      * Sets the disk spool size, which is used to buffer writes to the DiskStore.
916      * If not set it defaults to {@link #DEFAULT_SPOOL_BUFFER_SIZE}
917      *
918      * @param diskSpoolBufferSizeMB a positive number
919      */
920     public void setDiskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
921         checkDynamicChange();
922         if (diskSpoolBufferSizeMB <= 0) {
923             this.diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
924         } else {
925             this.diskSpoolBufferSizeMB = diskSpoolBufferSizeMB;
926         }
927     }
928 
929     /***
930      * Builder which sets the disk spool size, which is used to buffer writes to the DiskStore.
931      * If not set it defaults to {@link #DEFAULT_SPOOL_BUFFER_SIZE}
932      *
933      * @param diskSpoolBufferSizeMB a positive number
934      * @return this configuration instance
935      * @see #setDiskSpoolBufferSizeMB(int)
936      */
937     public final CacheConfiguration diskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
938         setDiskSpoolBufferSizeMB(diskSpoolBufferSizeMB);
939         return this;
940     }
941 
942     /***
943      * Sets the number of disk stripes. RandomAccessFiles used to access the data file. By default there
944      * is one stripe.
945      *
946      * @param stripes number of stripes (rounded up to a power-of-2)
947      */
948     public void setDiskAccessStripes(int stripes) {
949         checkDynamicChange();
950         if (stripes <= 0) {
951             this.diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
952         } else {
953             this.diskAccessStripes = stripes;
954         }
955     }
956 
957     /***
958      * Builder which sets the number of disk stripes. RandomAccessFiles used to access the data file. By default there
959      * is one stripe.
960      *
961      * @return this configuration instance
962      * @see #setDiskAccessStripes(int)
963      */
964     public final CacheConfiguration diskAccessStripes(int stripes) {
965         setDiskAccessStripes(stripes);
966         return this;
967     }
968 
969     /***
970      * Sets the maximum number elements on Disk. 0 means unlimited.
971      * <p/>
972      * This property can be modified dynamically while the cache is operating.
973      *
974      * @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
975      * @deprecated use {@link #setMaxEntriesLocalDisk(long)}
976      */
977     @Deprecated
978     public void setMaxElementsOnDisk(int maxElementsOnDisk) {
979         setMaxEntriesLocalDisk(maxElementsOnDisk);
980     }
981 
982     /***
983      * Sets the maximum number elements on Disk. 0 means unlimited.
984      * <p/>
985      * This property can be modified dynamically while the cache is operating.
986      *
987      * @param maxEntriesOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
988      */
989     public void setMaxEntriesLocalDisk(long maxEntriesOnDisk) {
990         if (maxEntriesOnDisk > Integer.MAX_VALUE) {
991             throw new IllegalArgumentException("Values greater than Integer.MAX_VALUE are not currently supported.");
992         }
993 
994         checkDynamicChange();
995         int oldCapacity = this.maxElementsOnDisk;
996         int newCapacity = (int) maxEntriesOnDisk;
997         this.maxElementsOnDisk = (int) maxEntriesOnDisk;
998         fireDiskCapacityChanged(oldCapacity, newCapacity);
999     }
1000 
1001     /***
1002      * Builder which sets the maximum number elements on Disk. 0 means unlimited.
1003      * <p/>
1004      * This property can be modified dynamically while the cache is operating.
1005      *
1006      * @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
1007      * @return this configuration instance
1008      * @see #setMaxElementsOnDisk(int)
1009      * @deprecated use {@link #maxEntriesLocalDisk(int)}
1010      */
1011     @Deprecated
1012     public final CacheConfiguration maxElementsOnDisk(int maxElementsOnDisk) {
1013         setMaxElementsOnDisk(maxElementsOnDisk);
1014         return this;
1015     }
1016 
1017     /***
1018      * Builder which sets the maximum number elements on Disk. 0 means unlimited.
1019      * <p/>
1020      * This property can be modified dynamically while the cache is operating.
1021      *
1022      * @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
1023      * @return this configuration instance
1024      * @see #setMaxElementsOnDisk(int)
1025      */
1026     public final CacheConfiguration maxEntriesLocalDisk(int maxElementsOnDisk) {
1027         setMaxEntriesLocalDisk(maxElementsOnDisk);
1028         return this;
1029     }
1030 
1031     /***
1032      * Sets the interval in seconds between runs of the disk expiry thread.
1033      * <p/>
1034      * 2 minutes is the default.
1035      * This is not the same thing as time to live or time to idle. When the thread runs it checks
1036      * these things. So this value is how often we check for expiry.
1037      */
1038     public final void setDiskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
1039         checkDynamicChange();
1040         if (diskExpiryThreadIntervalSeconds <= 0) {
1041             this.diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
1042         } else {
1043             this.diskExpiryThreadIntervalSeconds = diskExpiryThreadIntervalSeconds;
1044         }
1045     }
1046 
1047     /***
1048      * Builder which sets the interval in seconds between runs of the disk expiry thread.
1049      * <p/>
1050      * 2 minutes is the default.
1051      * This is not the same thing as time to live or time to idle. When the thread runs it checks
1052      * these things. So this value is how often we check for expiry.
1053      *
1054      * @return this configuration instance
1055      * @see #setDiskExpiryThreadIntervalSeconds(long)
1056      */
1057     public final CacheConfiguration diskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
1058         setDiskExpiryThreadIntervalSeconds(diskExpiryThreadIntervalSeconds);
1059         return this;
1060     }
1061 
1062     /***
1063      * Freeze this configuration. Any subsequent changes will throw a CacheException
1064      */
1065     public void freezeConfiguration() {
1066         frozen = true;
1067         if (searchable != null) {
1068             searchable.freezeConfiguration();
1069         }
1070     }
1071 
1072     /***
1073      * @return true is this configuration is frozen - it cannot be changed dynamically.
1074      */
1075     public boolean isFrozen() {
1076         return frozen;
1077     }
1078 
1079     /***
1080      * Getter to the CopyStrategy set in the config (really? how?).
1081      * This will always return the same unique instance per cache
1082      *
1083      * @return the {@link ReadWriteCopyStrategy} for instance for this cache
1084      */
1085     public ReadWriteCopyStrategy<Element> getCopyStrategy() {
1086         // todo really make this pluggable through config!
1087         return copyStrategyConfiguration.getCopyStrategyInstance();
1088     }
1089 
1090     /***
1091      * Whether the Cache should copy elements it returns
1092      *
1093      * @param copyOnRead true, if copyOnRead
1094      */
1095     public CacheConfiguration copyOnRead(boolean copyOnRead) {
1096         this.setCopyOnRead(copyOnRead);
1097         return this;
1098     }
1099 
1100     /***
1101      * Whether the Cache should copy elements it returns
1102      *
1103      * @return true, is copyOnRead
1104      */
1105     public boolean isCopyOnRead() {
1106         validateTransactionalSettings();
1107         return copyOnRead;
1108     }
1109 
1110     /***
1111      * Whether the Cache should copy elements it returns
1112      *
1113      * @param copyOnRead true, if copyOnRead
1114      */
1115     public void setCopyOnRead(final boolean copyOnRead) {
1116         this.copyOnRead = copyOnRead;
1117     }
1118 
1119     /***
1120      * Whether the Cache should copy elements it gets
1121      *
1122      * @param copyOnWrite true, if copyOnWrite
1123      */
1124     public CacheConfiguration copyOnWrite(boolean copyOnWrite) {
1125         this.copyOnWrite = copyOnWrite;
1126         return this;
1127     }
1128 
1129     /***
1130      * Whether the Cache should copy elements it gets
1131      *
1132      * @return true, if copyOnWrite
1133      */
1134     public boolean isCopyOnWrite() {
1135         validateTransactionalSettings();
1136         return copyOnWrite;
1137     }
1138 
1139     /***
1140      * Whether the Cache should copy elements it gets
1141      *
1142      * @param copyOnWrite true, if copyOnWrite
1143      */
1144     public void setCopyOnWrite(final boolean copyOnWrite) {
1145         this.copyOnWrite = copyOnWrite;
1146     }
1147 
1148     /***
1149      * Sets the CopyStrategyConfiguration for this cache
1150      *
1151      * @param copyStrategyConfiguration the CopyStrategy Configuration
1152      */
1153     public void addCopyStrategy(CopyStrategyConfiguration copyStrategyConfiguration) {
1154         this.copyStrategyConfiguration = copyStrategyConfiguration;
1155     }
1156 
1157     /***
1158      * Sets the ElementValueComparatorConfiguration for this cache
1159      *
1160      * @param elementValueComparatorConfiguration the ElementComparator Configuration
1161      */
1162     public void addElementValueComparator(ElementValueComparatorConfiguration elementValueComparatorConfiguration) {
1163         this.elementValueComparatorConfiguration = elementValueComparatorConfiguration;
1164     }
1165 
1166     /***
1167      * Add configuration to make this cache searchable
1168      *
1169      * @param searchable search config to add
1170      */
1171     public final void addSearchable(Searchable searchable) {
1172         checkDynamicChange();
1173         this.searchable = searchable;
1174     }
1175 
1176     /***
1177      * The maximum amount of bytes the cache should occupy on heap
1178      * @return value in bytes, 0 if none set
1179      */
1180     public long getMaxBytesLocalHeap() {
1181         return maxBytesLocalHeap == null ? DEFAULT_MAX_BYTES_ON_HEAP : maxBytesLocalHeap;
1182     }
1183 
1184     /***
1185      * Setter for maxBytesLocalHeap as a String. Value can have a one char unit suffix or be a percentage (ending in %)
1186      * @param maxBytesHeap String representation of the size, can be relative (in %)
1187      */
1188     public void setMaxBytesLocalHeap(final String maxBytesHeap) {
1189         if (isPercentage(maxBytesHeap)) {
1190             maxBytesLocalHeapPercentage = parsePercentage(maxBytesHeap);
1191         } else {
1192             setMaxBytesLocalHeap(MemoryUnit.parseSizeInBytes(maxBytesHeap));
1193         }
1194     }
1195 
1196     /***
1197      * Setter for maxBytesLocalDisk in bytes
1198      * @param maxBytesHeap max bytes on disk in bytes
1199      */
1200     public void setMaxBytesLocalHeap(final Long maxBytesHeap) {
1201         verifyGreaterThanZero(maxBytesHeap, "maxBytesLocalHeap");
1202         this.maxBytesLocalHeap = maxBytesHeap;
1203     }
1204 
1205     /***
1206      * Sets the maxOnHeap size
1207      * @param amount the amount of unit
1208      * @param memoryUnit the actual unit
1209      * @return this
1210      */
1211 
1212     public CacheConfiguration maxBytesLocalHeap(final long amount, final MemoryUnit memoryUnit) {
1213         setMaxBytesLocalHeap(memoryUnit.toBytes(amount));
1214         return this;
1215     }
1216 
1217     /***
1218      * The maximum amount of bytes the cache should occupy off heap
1219      * @return value in bytes, 0 if none set
1220      */
1221     public long getMaxBytesLocalOffHeap() {
1222         return maxBytesLocalOffHeap == null ? DEFAULT_MAX_BYTES_OFF_HEAP : maxBytesLocalOffHeap;
1223     }
1224 
1225     /***
1226      * Setter for maximum bytes off heap as a String. Value can have a one char unit suffix or be a percentage (ending in %)
1227      * @param maxBytesOffHeap String representation of the size, can be relative (in %)
1228      */
1229     public void setMaxBytesLocalOffHeap(final String maxBytesOffHeap) {
1230         if (isPercentage(maxBytesOffHeap)) {
1231             maxBytesLocalOffHeapPercentage = parsePercentage(maxBytesOffHeap);
1232         } else {
1233             setMaxBytesLocalOffHeap(MemoryUnit.parseSizeInBytes(maxBytesOffHeap));
1234         }
1235     }
1236 
1237     /***
1238      * Getter for maximum bytes off heap expressed as a percentage
1239      * @return percentage (between 0 and 100)
1240      */
1241     public Integer getMaxBytesLocalOffHeapPercentage() {
1242         return maxBytesLocalOffHeapPercentage;
1243     }
1244 
1245     /***
1246      * Getter for maximum bytes on heap expressed as a percentage
1247      * @return percentage (between 0 and 100)
1248      */
1249     public Integer getMaxBytesLocalHeapPercentage() {
1250         return maxBytesLocalHeapPercentage;
1251     }
1252 
1253     /***
1254      * Getter for maximum bytes on disk expressed as a percentage
1255      * @return percentage (between 0 and 100)
1256      */
1257     public Integer getMaxBytesLocalDiskPercentage() {
1258         return maxBytesLocalDiskPercentage;
1259     }
1260 
1261     private int parsePercentage(final String stringValue) {
1262         String trimmed = stringValue.trim();
1263         int percentage = Integer.parseInt(trimmed.substring(0, trimmed.length() - 1));
1264         if (percentage > HUNDRED_PERCENT || percentage < 0) {
1265             throw new IllegalArgumentException("Percentage need values need to be between 0 and 100 inclusive, but got : " + percentage);
1266         }
1267         return percentage;
1268     }
1269 
1270     private boolean isPercentage(final String stringValue) {
1271         String trimmed = stringValue.trim();
1272         return trimmed.charAt(trimmed.length() - 1) == '%';
1273     }
1274 
1275     /***
1276      * Sets the maximum amount of bytes the cache being configured will use on the OffHeap tier
1277      * @param maxBytesOffHeap max bytes on disk in bytes
1278      */
1279     public void setMaxBytesLocalOffHeap(final Long maxBytesOffHeap) {
1280         verifyGreaterThanZero(maxBytesOffHeap, "maxBytesLocalOffHeap");
1281         this.maxBytesLocalOffHeap = maxBytesOffHeap;
1282     }
1283 
1284     /***
1285      * Sets the maxOffHeap tier size
1286      * @param amount the amount of unit
1287      * @param memoryUnit the actual unit
1288      * @return this
1289      */
1290     public CacheConfiguration maxBytesLocalOffHeap(final long amount, final MemoryUnit memoryUnit) {
1291         setMaxBytesLocalOffHeap(memoryUnit.toBytes(amount));
1292         return this;
1293     }
1294 
1295     /***
1296      * The maximum amount of bytes the cache should occupy on disk
1297      * @return value in bytes, 0 if none set
1298      */
1299     public long getMaxBytesLocalDisk() {
1300         return maxBytesLocalDisk == null ? DEFAULT_MAX_BYTES_ON_DISK : maxBytesLocalDisk;
1301     }
1302 
1303     /***
1304      * Setter for maxBytesOnDisk as a String. Value can have a one char unit suffix or be a percentage (ending in %)
1305      * @param maxBytesDisk String representation of the size, can be relative (in %)
1306      */
1307     public void setMaxBytesLocalDisk(final String maxBytesDisk) {
1308         if (isPercentage(maxBytesDisk)) {
1309             maxBytesLocalDiskPercentage = parsePercentage(maxBytesDisk);
1310         } else {
1311             setMaxBytesLocalDisk(MemoryUnit.parseSizeInBytes(maxBytesDisk));
1312         }
1313     }
1314 
1315     /***
1316      * Sets the maximum amount of bytes the cache being configured will use on the OnDisk tier
1317      * @param maxBytesDisk max bytes on disk in bytes
1318      */
1319     public void setMaxBytesLocalDisk(final Long maxBytesDisk) {
1320         verifyGreaterThanZero(maxBytesDisk, "maxBytesLocalDisk");
1321         this.maxBytesLocalDisk = maxBytesDisk;
1322     }
1323 
1324     /***
1325      * Sets the maxOnDisk size
1326      * @param amount the amount of unit
1327      * @param memoryUnit the actual unit
1328      * @return this
1329      */
1330     public CacheConfiguration maxBytesLocalDisk(final long amount, final MemoryUnit memoryUnit) {
1331         setMaxBytesLocalDisk(memoryUnit.toBytes(amount));
1332         return this;
1333     }
1334 
1335     private void verifyGreaterThanZero(final Long maxBytesOnHeap, final String field) {
1336         if (maxBytesOnHeap != null && maxBytesOnHeap < 1) {
1337             throw new IllegalArgumentException(field + " has to be larger than 0");
1338         }
1339     }
1340 
1341     /***
1342      * Returns the copyStrategyConfiguration
1343      *
1344      * @return the copyStrategyConfiguration
1345      */
1346     public CopyStrategyConfiguration getCopyStrategyConfiguration() {
1347         return this.copyStrategyConfiguration;
1348     }
1349 
1350     /***
1351      * Returns the elementComparatorConfiguration
1352      *
1353      * @return the elementComparatorConfiguration
1354      */
1355     public ElementValueComparatorConfiguration getElementValueComparatorConfiguration() {
1356         return elementValueComparatorConfiguration;
1357     }
1358 
1359     /***
1360      * Checks whether the user explicitly set the maxBytesOnHeapPercentage
1361      * @return true if set by user, false otherwise
1362      * @see #setMaxBytesLocalHeap(String)
1363      */
1364     public boolean isMaxBytesLocalHeapPercentageSet() {
1365         return maxBytesLocalHeapPercentage != null;
1366     }
1367 
1368     /***
1369      * Checks whether the user explicitly set the maxBytesOffHeapPercentage
1370      * @return true if set by user, false otherwise
1371      * @see #setMaxBytesLocalOffHeap(String)
1372      */
1373     public boolean isMaxBytesLocalOffHeapPercentageSet() {
1374         return maxBytesLocalOffHeapPercentage != null;
1375     }
1376 
1377     /***
1378      * Checks whether the user explicitly set the maxBytesOnDiskPercentage
1379      * @return true if set by user, false otherwise
1380      * @see #setMaxBytesLocalDisk(String)
1381      */
1382     public boolean isMaxBytesLocalDiskPercentageSet() {
1383         return maxBytesLocalDiskPercentage != null;
1384     }
1385 
1386     /***
1387      * Configuration for the CacheEventListenerFactory.
1388      */
1389     public static final class CacheEventListenerFactoryConfiguration extends FactoryConfiguration<CacheEventListenerFactoryConfiguration> {
1390         private NotificationScope notificationScope = NotificationScope.ALL;
1391 
1392         /***
1393          * Used by BeanHandler to set the mode during parsing. Convert listenFor string to uppercase and
1394          * look up enum constant in NotificationScope.
1395          */
1396         public void setListenFor(String listenFor) {
1397             if (listenFor == null) {
1398                 throw new IllegalArgumentException("listenFor must be non-null");
1399             }
1400             this.notificationScope = NotificationScope.valueOf(NotificationScope.class, listenFor.toUpperCase());
1401         }
1402 
1403         /***
1404          * @return this factory configuration instance
1405          * @see #setListenFor(String)
1406          */
1407         public final CacheEventListenerFactoryConfiguration listenFor(String listenFor) {
1408             setListenFor(listenFor);
1409             return this;
1410         }
1411 
1412         /***
1413          * Get the value mode in terms of the mode enum
1414          */
1415         public NotificationScope getListenFor() {
1416             return this.notificationScope;
1417         }
1418     }
1419 
1420     /***
1421      * Used by BeanUtils to add cacheEventListenerFactory elements to the cache configuration.
1422      */
1423     public final void addCacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
1424         checkDynamicChange();
1425         cacheEventListenerConfigurations.add(factory);
1426         validateConfiguration();
1427     }
1428 
1429     /***
1430      * @return this configuration instance
1431      * @see #addCacheEventListenerFactory(CacheEventListenerFactoryConfiguration)
1432      */
1433     public final CacheConfiguration cacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
1434         addCacheEventListenerFactory(factory);
1435         return this;
1436     }
1437 
1438     /***
1439      * Configuration for the CacheExtensionFactoryConfiguration.
1440      */
1441     public static final class CacheExtensionFactoryConfiguration extends FactoryConfiguration<CacheExtensionFactoryConfiguration> {
1442     }
1443 
1444     /***
1445      * Used by BeanUtils to add cacheExtensionFactory elements to the cache configuration.
1446      */
1447     public final void addCacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
1448         checkDynamicChange();
1449         cacheExtensionConfigurations.add(factory);
1450     }
1451 
1452     /***
1453      * @return this configuration instance
1454      * @see #addCacheExtensionFactory(CacheExtensionFactoryConfiguration)
1455      */
1456     public final CacheConfiguration cacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
1457         /***
1458          * {@inheritDoc}
1459          */
1460         addCacheExtensionFactory(factory);
1461         return this;
1462     }
1463 
1464     /***
1465      * Configuration for the BootstrapCacheLoaderFactoryConfiguration.
1466      */
1467     public static final class BootstrapCacheLoaderFactoryConfiguration extends
1468             FactoryConfiguration<BootstrapCacheLoaderFactoryConfiguration> {
1469     }
1470 
1471     /***
1472      * Allows BeanHandler to add the CacheManagerEventListener to the configuration.
1473      */
1474     public final void addBootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
1475         checkDynamicChange();
1476         this.bootstrapCacheLoaderFactoryConfiguration = factory;
1477     }
1478 
1479     /***
1480      * @return this configuration instance
1481      * @see #addBootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration)
1482      */
1483     public final CacheConfiguration bootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
1484         addBootstrapCacheLoaderFactory(factory);
1485         return this;
1486     }
1487 
1488     /***
1489      * Configuration for the BootstrapCacheLoaderFactoryConfiguration.
1490      */
1491     public static final class CacheExceptionHandlerFactoryConfiguration extends
1492             FactoryConfiguration<CacheExceptionHandlerFactoryConfiguration> {
1493     }
1494 
1495     /***
1496      * Add the CacheExceptionHandlerFactory to the configuration.
1497      * <p/>
1498      * Note that this will not have any effect when creating a cache solely through its constructed. The exception
1499      * handler will only be taken into account when {@link ConfigurationHelper} is used, for example through
1500      * {@link net.sf.ehcache.CacheManager}.
1501      */
1502     public final void addCacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
1503         checkDynamicChange();
1504         this.cacheExceptionHandlerFactoryConfiguration = factory;
1505     }
1506 
1507     /***
1508      * @return this configuration instance
1509      * @see #addCacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration)
1510      */
1511     public final CacheConfiguration cacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
1512         addCacheExceptionHandlerFactory(factory);
1513         return this;
1514     }
1515 
1516     /***
1517      * Configuration for the CacheLoaderFactoryConfiguration.
1518      */
1519     public static final class CacheLoaderFactoryConfiguration extends FactoryConfiguration<CacheLoaderFactoryConfiguration> {
1520     }
1521 
1522     /***
1523      * Used by BeanUtils to add each cacheLoaderFactory to the cache configuration.
1524      *
1525      * @param factory
1526      */
1527     public final void addCacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
1528         checkDynamicChange();
1529         cacheLoaderConfigurations.add(factory);
1530     }
1531 
1532     /***
1533      * Configuration for the CacheDecoratorFactoryConfiguration.
1534      */
1535     public static final class CacheDecoratorFactoryConfiguration extends FactoryConfiguration<CacheDecoratorFactoryConfiguration> {
1536     }
1537 
1538     /***
1539      * Used by BeanUtils to add each cacheDecoratorFactory to the cache configuration.
1540      *
1541      * @param factory
1542      */
1543     public final void addCacheDecoratorFactory(CacheDecoratorFactoryConfiguration factory) {
1544         checkDynamicChange();
1545         cacheDecoratorConfigurations.add(factory);
1546     }
1547 
1548     /***
1549      * @return this configuration instance
1550      * @see #addCacheLoaderFactory(CacheLoaderFactoryConfiguration)
1551      */
1552     public final CacheConfiguration cacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
1553         addCacheLoaderFactory(factory);
1554         return this;
1555     }
1556 
1557     /***
1558      * Allows BeanHandler to add the TerracottaConfiguration to the configuration.
1559      */
1560     public final void addTerracotta(TerracottaConfiguration terracottaConfiguration) {
1561         this.terracottaConfiguration = terracottaConfiguration;
1562         validateConfiguration();
1563     }
1564 
1565     /***
1566      * Allows BeanHandler to add the PinningConfiguration to the configuration.
1567      */
1568     public final void addPinning(PinningConfiguration pinningConfiguration) {
1569         this.pinningConfiguration = pinningConfiguration;
1570         validateConfiguration();
1571     }
1572 
1573     /***
1574      * @return this configuration instance
1575      * @see #addPinning(PinningConfiguration)
1576      */
1577     public final CacheConfiguration pinning(PinningConfiguration pinningConfiguration) {
1578         addPinning(pinningConfiguration);
1579         return this;
1580     }
1581 
1582     /***
1583      * @return this configuration instance
1584      * @see #addTerracotta(TerracottaConfiguration)
1585      */
1586     public final CacheConfiguration terracotta(TerracottaConfiguration terracottaConfiguration) {
1587         addTerracotta(terracottaConfiguration);
1588         return this;
1589     }
1590 
1591     /***
1592      * @see #addSearchable(Searchable)
1593      * @param searchable
1594      * @return this
1595      */
1596     public final CacheConfiguration searchable(Searchable searchable) {
1597         addSearchable(searchable);
1598         return this;
1599     }
1600 
1601     /***
1602      * Allows BeanHandler to add the CacheWriterConfiguration to the configuration.
1603      */
1604     public final void addCacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
1605         if (null == cacheWriterConfiguration) {
1606             this.cacheWriterConfiguration = new CacheWriterConfiguration();
1607         } else {
1608             this.cacheWriterConfiguration = cacheWriterConfiguration;
1609         }
1610     }
1611 
1612     /***
1613      * @return this configuration instance
1614      * @see #addCacheWriter(CacheWriterConfiguration)
1615      */
1616     public final CacheConfiguration cacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
1617         addCacheWriter(cacheWriterConfiguration);
1618         return this;
1619     }
1620 
1621     /***
1622      * Sets the transactionalMode
1623      *
1624      * @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
1625      */
1626     public final void setTransactionalMode(final String transactionalMode) {
1627         if (null == transactionalMode) {
1628             throw new IllegalArgumentException("TransactionalMode value must be non-null");
1629         }
1630         this.transactionalMode = TransactionalMode.valueOf(transactionalMode.toUpperCase());
1631     }
1632 
1633     /***
1634      * Builder which sets the transactionalMode
1635      *
1636      * @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
1637      * @return this configuration instance
1638      * @see #setTransactionalMode(String)
1639      */
1640     public final CacheConfiguration transactionalMode(String transactionalMode) {
1641         setTransactionalMode(transactionalMode);
1642         return this;
1643     }
1644 
1645     /***
1646      * Builder which sets the transactionalMode
1647      *
1648      * @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
1649      * @return this configuration instance
1650      * @see #setTransactionalMode(String)
1651      */
1652     public final CacheConfiguration transactionalMode(TransactionalMode transactionalMode) {
1653         if (null == transactionalMode) {
1654             throw new IllegalArgumentException("TransactionalMode value must be non-null");
1655         }
1656         this.transactionalMode = transactionalMode;
1657         return this;
1658     }
1659 
1660     /***
1661      * Sets whether the cache's statistics are enabled. at startup
1662      */
1663     public final void setStatistics(boolean enabled) {
1664         this.statistics = enabled;
1665     }
1666 
1667     /***
1668      * Builder which sets whether the cache's statistics are enabled.
1669      *
1670      * @return this configuration instance
1671      * @see #setStatistics(boolean)
1672      */
1673     public final CacheConfiguration statistics(boolean statistics) {
1674         setStatistics(statistics);
1675         return this;
1676     }
1677 
1678     /***
1679      * Gets whether the cache's statistics will be enabled at startup
1680      */
1681     public final boolean getStatistics() {
1682         return statistics;
1683     }
1684 
1685     /***
1686      * Used to validate what should be a complete Cache Configuration.
1687      */
1688     public void validateCompleteConfiguration() {
1689 
1690         validateConfiguration();
1691 
1692         // Extra checks that a completed cache config should have
1693 
1694         if (name == null) {
1695             throw new InvalidConfigurationException("Caches must be named.");
1696         }
1697     }
1698 
1699     /***
1700      * Used to validate a Cache Configuration.
1701      */
1702     public void validateConfiguration() {
1703         if (terracottaConfiguration != null && terracottaConfiguration.isClustered()) {
1704             if (overflowToDisk) {
1705                 throw new InvalidConfigurationException("overflowToDisk isn't supported for a clustered Terracotta cache");
1706             }
1707             if (diskPersistent) {
1708                 throw new InvalidConfigurationException("diskPersistent isn't supported for a clustered Terracotta cache");
1709             }
1710             if (cacheEventListenerConfigurations != null) {
1711                 for (CacheEventListenerFactoryConfiguration listenerConfig : cacheEventListenerConfigurations) {
1712                     if (null == listenerConfig.getFullyQualifiedClassPath()) {
1713                         continue;
1714                     }
1715                     if (!listenerConfig.getFullyQualifiedClassPath().startsWith("net.sf.ehcache.") &&
1716                             LOG.isWarnEnabled()) {
1717                         LOG.warn("The non-standard CacheEventListenerFactory '" + listenerConfig.getFullyQualifiedClassPath() +
1718                                 "' is used with a clustered Terracotta cache, " +
1719                                 "if the purpose of this listener is replication it is not supported in a clustered context");
1720                     }
1721                 }
1722             }
1723         }
1724     }
1725 
1726     private void validateTransactionalSettings() {
1727         boolean transactional = transactionalMode.isTransactional();
1728         if (copyOnRead == null) {
1729             if (terracottaConfiguration != null && terracottaConfiguration.isCopyOnReadSet()) {
1730                 copyOnRead = terracottaConfiguration.isCopyOnRead();
1731             } else {
1732                 copyOnRead = transactional;
1733             }
1734         }
1735         if (copyOnWrite == null) {
1736             copyOnWrite = transactional;
1737         }
1738 
1739         if (transactional) {
1740             if (!copyOnRead || !copyOnWrite) {
1741                 throw new InvalidConfigurationException("A transactional cache has to be copyOnRead and copyOnWrite!");
1742             }
1743         }
1744     }
1745 
1746     /***
1747      * Accessor
1748      */
1749     public String getName() {
1750         return name;
1751     }
1752 
1753     /***
1754      * Accessor
1755      *
1756      * @deprecated use {@link #getMaxEntriesLocalHeap()}
1757      */
1758     @Deprecated
1759     public int getMaxElementsInMemory() {
1760         return maxEntriesLocalHeap;
1761     }
1762 
1763     /***
1764      * Accessor
1765      */
1766     public long getCacheLoaderTimeoutMillis() {
1767         return cacheLoaderTimeoutMillis;
1768     }
1769 
1770     /***
1771      * Accessor
1772      *
1773      * @deprecated use {@link #getMaxEntriesLocalDisk()}
1774      */
1775     @Deprecated
1776     public int getMaxElementsOnDisk() {
1777         return maxElementsOnDisk;
1778     }
1779 
1780     /***
1781      * Configured maximum number of entries for the local disk store.
1782      */
1783     public long getMaxEntriesLocalDisk() {
1784         return maxElementsOnDisk;
1785     }
1786 
1787     /***
1788      * Configured maximum number of entries for the local memory heap.
1789      */
1790     public long getMaxEntriesLocalHeap() {
1791         return maxEntriesLocalHeap;
1792     }
1793 
1794     /***
1795      * Accessor
1796      */
1797     public MemoryStoreEvictionPolicy getMemoryStoreEvictionPolicy() {
1798         return memoryStoreEvictionPolicy;
1799     }
1800 
1801     /***
1802      * Accessor
1803      */
1804     public boolean isClearOnFlush() {
1805         return clearOnFlush;
1806     }
1807 
1808     /***
1809      * Accessor
1810      */
1811     public boolean isEternal() {
1812         return eternal;
1813     }
1814 
1815     /***
1816      * Accessor
1817      */
1818     public long getTimeToIdleSeconds() {
1819         return timeToIdleSeconds;
1820     }
1821 
1822     /***
1823      * Accessor
1824      */
1825     public long getTimeToLiveSeconds() {
1826         return timeToLiveSeconds;
1827     }
1828 
1829     /***
1830      * Accessor
1831      */
1832     public boolean isOverflowToDisk() {
1833         return overflowToDisk;
1834     }
1835 
1836     /***
1837      * Accessor
1838      */
1839     public boolean isDiskPersistent() {
1840         return diskPersistent;
1841     }
1842 
1843     /***
1844      * Accessor
1845      */
1846     public boolean isSearchable() {
1847         return searchable != null;
1848     }
1849 
1850     /***
1851      * Accessor
1852      */
1853     public String getDiskStorePath() {
1854         return diskStorePath;
1855     }
1856 
1857     /***
1858      * Accessor
1859      */
1860     public int getDiskSpoolBufferSizeMB() {
1861         return diskSpoolBufferSizeMB;
1862     }
1863 
1864     /***
1865      * Accessor
1866      */
1867     public long getDiskExpiryThreadIntervalSeconds() {
1868         return diskExpiryThreadIntervalSeconds;
1869     }
1870 
1871     /***
1872      * Accessor
1873      */
1874     public int getDiskAccessStripes() {
1875         return diskAccessStripes;
1876     }
1877 
1878     /***
1879      * Only used when cache is clustered with Terracotta
1880      *
1881      * @return true if logging is enabled otherwise false
1882      */
1883     public boolean getLogging() {
1884         return logging;
1885     }
1886 
1887     /***
1888      * Accessor
1889      *
1890      * @return true if offheap store is enabled, otherwise false.
1891      */
1892     public boolean isOverflowToOffHeap() {
1893         return overflowToOffHeap;
1894     }
1895 
1896     /***
1897      * Accessor
1898      *
1899      * @return the max memory of the offheap store for this cache.
1900      */
1901     public String getMaxMemoryOffHeap() {
1902         return Long.toString(getMaxMemoryOffHeapInBytes());
1903     }
1904 
1905     /***
1906      * Accessor
1907      *
1908      * @return the max memory of the offheap store for this cache, in bytes.
1909      * @see #getMaxMemoryOffHeap()
1910      */
1911     public long getMaxMemoryOffHeapInBytes() {
1912         return getMaxBytesLocalOffHeap();
1913     }
1914 
1915     /***
1916      * Accessor
1917      */
1918     public List getCacheEventListenerConfigurations() {
1919         return cacheEventListenerConfigurations;
1920     }
1921 
1922     /***
1923      * Accessor
1924      *
1925      * @return the configuration
1926      */
1927     public List getCacheExtensionConfigurations() {
1928         return cacheExtensionConfigurations;
1929     }
1930 
1931     /***
1932      * Accessor
1933      *
1934      * @return the configuration
1935      */
1936     public List getCacheLoaderConfigurations() {
1937         return cacheLoaderConfigurations;
1938     }
1939 
1940     /***
1941      * Accessor
1942      *
1943      * @return the configuration
1944      */
1945     public List<CacheDecoratorFactoryConfiguration> getCacheDecoratorConfigurations() {
1946         return cacheDecoratorConfigurations;
1947     }
1948 
1949     /***
1950      * Accessor
1951      *
1952      * @return the configuration
1953      */
1954     public BootstrapCacheLoaderFactoryConfiguration getBootstrapCacheLoaderFactoryConfiguration() {
1955         return bootstrapCacheLoaderFactoryConfiguration;
1956     }
1957 
1958     /***
1959      * Accessor
1960      *
1961      * @return the configuration
1962      */
1963     public CacheExceptionHandlerFactoryConfiguration getCacheExceptionHandlerFactoryConfiguration() {
1964         return cacheExceptionHandlerFactoryConfiguration;
1965     }
1966 
1967     /***
1968      * Accessor
1969      *
1970      * @return the terracotta configuration
1971      */
1972     public TerracottaConfiguration getTerracottaConfiguration() {
1973         return terracottaConfiguration;
1974     }
1975 
1976     /***
1977      * Accessor
1978      *
1979      * @return the pinning configuration
1980      */
1981     public PinningConfiguration getPinningConfiguration() {
1982         return pinningConfiguration;
1983     }
1984 
1985     /***
1986      * Accessor
1987      *
1988      * @return the writer configuration
1989      */
1990     public CacheWriterConfiguration getCacheWriterConfiguration() {
1991         return cacheWriterConfiguration;
1992     }
1993 
1994     /***
1995      * Helper method to compute whether the cache is clustered or not
1996      *
1997      * @return True if the &lt;terracotta/&gt; element exists with {@code clustered="true"}
1998      */
1999     public boolean isTerracottaClustered() {
2000         return terracottaConfiguration != null && terracottaConfiguration.isClustered();
2001     }
2002 
2003     /***
2004      * Accessor
2005      *
2006      * @return the CoherenceMode if Terracotta-clustered or null
2007      */
2008     public Consistency getTerracottaConsistency() {
2009         return terracottaConfiguration != null ? terracottaConfiguration.getConsistency() : null;
2010     }
2011 
2012     /***
2013      * Accessor
2014      *
2015      * @return the StorageStrategy if Terracotta-clustered or null
2016      */
2017     public StorageStrategy getTerracottaStorageStrategy() {
2018         return terracottaConfiguration != null ? terracottaConfiguration.getStorageStrategy() : null;
2019     }
2020 
2021     /***
2022      * To what transactionalMode was the Cache set
2023      *
2024      * @return transactionaMode
2025      */
2026     public final TransactionalMode getTransactionalMode() {
2027         return transactionalMode;
2028     }
2029 
2030     /***
2031      * Helper method to compute whether the cache is XA transactional or not
2032      *
2033      * @return true if transactionalMode="xa_strict"
2034      */
2035     public boolean isXaStrictTransactional() {
2036         validateTransactionalSettings();
2037         return transactionalMode.equals(TransactionalMode.XA_STRICT);
2038     }
2039 
2040     /***
2041      * Helper method to compute whether the cache is local transactional or not
2042      *
2043      * @return true if transactionalMode="local"
2044      */
2045     public boolean isLocalTransactional() {
2046         validateTransactionalSettings();
2047         return transactionalMode.equals(TransactionalMode.LOCAL);
2048     }
2049 
2050     /***
2051      * Helper method to compute whether the cache is local_jta transactional or not
2052      *
2053      * @return true if transactionalMode="xa"
2054      */
2055     public boolean isXaTransactional() {
2056         validateTransactionalSettings();
2057         return transactionalMode.equals(TransactionalMode.XA);
2058     }
2059 
2060     /***
2061      * Represents whether the Cache is transactional or not.
2062      *
2063      * @author alexsnaps
2064      */
2065     public static enum TransactionalMode {
2066 
2067         /***
2068          * No Transactions
2069          */
2070         OFF(false),
2071 
2072         /***
2073          * Local Transactions
2074          */
2075         LOCAL(true),
2076 
2077         /***
2078          * XA Transactions
2079          */
2080         XA(true),
2081 
2082         /***
2083          * XA Strict (true 2PC) Transactions
2084          */
2085         XA_STRICT(true);
2086 
2087         private final boolean transactional;
2088 
2089         /***
2090          * @param transactional
2091          */
2092         TransactionalMode(final boolean transactional) {
2093             this.transactional = transactional;
2094         }
2095 
2096         /***
2097          * @return transactional
2098          */
2099         public boolean isTransactional() {
2100             return transactional;
2101         }
2102     }
2103 
2104     /***
2105      * Add a listener to this cache configuration
2106      *
2107      * @param listener listener instance to add
2108      * @return true if a listener was added
2109      */
2110     public boolean addConfigurationListener(CacheConfigurationListener listener) {
2111         boolean added = listeners.add(listener);
2112         if (added) {
2113             listener.registered(this);
2114         }
2115         return added;
2116     }
2117 
2118     /***
2119      * Remove the supplied cache configuration listener.
2120      *
2121      * @param listener listener to remove
2122      * @return true if a listener was removed
2123      */
2124     public boolean removeConfigurationListener(CacheConfigurationListener listener) {
2125         boolean removed = listeners.remove(listener);
2126         if (removed) {
2127             listener.deregistered(this);
2128         }
2129         return removed;
2130     }
2131 
2132     private void fireTtiChanged(long oldTti, long newTti) {
2133         if (oldTti != newTti) {
2134             for (CacheConfigurationListener l : listeners) {
2135                 l.timeToIdleChanged(oldTti, newTti);
2136             }
2137         }
2138     }
2139 
2140     private void fireTtlChanged(long oldTtl, long newTtl) {
2141         if (oldTtl != newTtl) {
2142             for (CacheConfigurationListener l : listeners) {
2143                 l.timeToLiveChanged(oldTtl, newTtl);
2144             }
2145         }
2146     }
2147 
2148     private void fireLoggingChanged(boolean oldValue, boolean newValue) {
2149         if (oldValue != newValue) {
2150             for (CacheConfigurationListener l : listeners) {
2151                 l.loggingChanged(oldValue, newValue);
2152             }
2153         }
2154     }
2155 
2156     private void fireDiskCapacityChanged(int oldCapacity, int newCapacity) {
2157         if (oldCapacity != newCapacity) {
2158             for (CacheConfigurationListener l : listeners) {
2159                 l.diskCapacityChanged(oldCapacity, newCapacity);
2160             }
2161         }
2162     }
2163 
2164     private void fireMemoryCapacityChanged(int oldCapacity, int newCapacity) {
2165         if (oldCapacity != newCapacity) {
2166             for (CacheConfigurationListener l : listeners) {
2167                 l.memoryCapacityChanged(oldCapacity, newCapacity);
2168             }
2169         }
2170     }
2171 
2172     private void checkDynamicChange() {
2173         if (frozen) {
2174             throw new CacheException("Dynamic configuration changes are disabled for this cache");
2175         }
2176     }
2177 
2178     /***
2179      * Intended for internal use only, and subject to change.
2180      * This is required so that changes in store implementation's config
2181      * (probably from other nodes) can propagate up to here
2182      */
2183     public void internalSetTimeToIdle(long timeToIdle) {
2184         this.timeToIdleSeconds = timeToIdle;
2185     }
2186 
2187     /***
2188      * Intended for internal use only, and subject to change.
2189      */
2190     public void internalSetTimeToLive(long timeToLive) {
2191         this.timeToLiveSeconds = timeToLive;
2192     }
2193 
2194     /***
2195      * Intended for internal use only, and subject to change.
2196      */
2197     public void internalSetMemCapacity(int capacity) {
2198         this.maxEntriesLocalHeap = capacity;
2199     }
2200 
2201     /***
2202      * Intended for internal use only, and subject to change.
2203      */
2204     public void internalSetDiskCapacity(int capacity) {
2205         this.maxElementsOnDisk = capacity;
2206     }
2207 
2208     /***
2209      * Intended for internal use only, and subject to change.
2210      */
2211     public void internalSetLogging(boolean logging) {
2212         this.logging = logging;
2213     }
2214 
2215     /***
2216      * Get the defined search attributes indexed by attribute name
2217      *
2218      * @return search attributes
2219      */
2220     public Map<String, SearchAttribute> getSearchAttributes() {
2221         if (searchable == null) {
2222             return Collections.EMPTY_MAP;
2223         }
2224         return searchable.getSearchAttributes();
2225     }
2226 
2227     /***
2228      * Get the search configuration for this cache (if any)
2229      *
2230      * @return search config (may be null)
2231      */
2232     public Searchable getSearchable() {
2233         return searchable;
2234     }
2235 }