1
16
17 package net.sf.ehcache.config;
18
19 import static net.sf.ehcache.config.Configuration.getAllActiveCaches;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.concurrent.CopyOnWriteArraySet;
28
29 import net.sf.ehcache.Cache;
30 import net.sf.ehcache.CacheException;
31 import net.sf.ehcache.CacheManager;
32 import net.sf.ehcache.Element;
33 import net.sf.ehcache.config.PersistenceConfiguration.Strategy;
34 import net.sf.ehcache.config.TerracottaConfiguration.Consistency;
35 import net.sf.ehcache.event.NotificationScope;
36 import net.sf.ehcache.search.attribute.DynamicAttributesExtractor;
37 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
38 import net.sf.ehcache.store.compound.ReadWriteCopyStrategy;
39
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
89 public class CacheConfiguration implements Cloneable {
90
91
94 public static final boolean DEFAULT_CLEAR_ON_FLUSH = true;
95
96
99 public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = 120;
100
101
104 public static final int DEFAULT_SPOOL_BUFFER_SIZE = 30;
105
106
109 public static final int DEFAULT_DISK_ACCESS_STRIPES = 1;
110
111
114 public static final boolean DEFAULT_LOGGING = false;
115
116
119 public static final MemoryStoreEvictionPolicy DEFAULT_MEMORY_STORE_EVICTION_POLICY = MemoryStoreEvictionPolicy.LRU;
120
121
124 public static final CacheWriterConfiguration DEFAULT_CACHE_WRITER_CONFIGURATION = new CacheWriterConfiguration();
125
126
129 public static final boolean DEFAULT_COPY_ON_READ = false;
130
131
134 public static final boolean DEFAULT_COPY_ON_WRITE = false;
135
136
139 public static final long DEFAULT_TTL = 0;
140
141
144 public static final long DEFAULT_TTI = 0;
145
146
149 public static final int DEFAULT_MAX_ELEMENTS_ON_DISK = 0;
150
151
154 public static final TransactionalMode DEFAULT_TRANSACTIONAL_MODE = TransactionalMode.OFF;
155
156
159 public static final boolean DEFAULT_STATISTICS = false;
160
161
166 @Deprecated
167 public static final boolean DEFAULT_DISK_PERSISTENT = false;
168
169
172 public static final CopyStrategyConfiguration DEFAULT_COPY_STRATEGY_CONFIGURATION = new CopyStrategyConfiguration();
173
174
177 public static final long DEFAULT_MAX_BYTES_ON_HEAP = 0;
178
179
182 public static final long DEFAULT_MAX_BYTES_OFF_HEAP = 0;
183
184
187 public static final long DEFAULT_MAX_BYTES_ON_DISK = 0;
188
189
192 public static final boolean DEFAULT_ETERNAL_VALUE = false;
193
194
195 private static final Logger LOG = LoggerFactory.getLogger(CacheConfiguration.class.getName());
196 private static final int HUNDRED_PERCENT = 100;
197 private static final int MINIMUM_RECOMMENDED_IN_MEMORY = 100;
198
199
202 protected volatile String name;
203
204
207 protected volatile long cacheLoaderTimeoutMillis;
208
209
214 protected volatile Integer maxEntriesLocalHeap;
215
216
221 protected volatile int maxElementsOnDisk = DEFAULT_MAX_ELEMENTS_ON_DISK;
222
223
235 protected volatile MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
236
237
241 protected volatile boolean clearOnFlush = DEFAULT_CLEAR_ON_FLUSH;
242
243
247 protected volatile boolean eternal = DEFAULT_ETERNAL_VALUE;
248
249
253 protected volatile long timeToIdleSeconds = DEFAULT_TTI;
254
255
260 protected volatile long timeToLiveSeconds = DEFAULT_TTL;
261
262
268 @Deprecated
269 protected volatile Boolean overflowToDisk;
270
271
276 @Deprecated
277 protected volatile Boolean diskPersistent;
278
279
282 protected volatile int diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
283
284
287 protected volatile int diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
288
289
296 protected volatile long diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
297
298
302 protected volatile boolean logging = DEFAULT_LOGGING;
303
304
308 protected volatile Boolean overflowToOffHeap;
309
310
313 protected volatile List<CacheEventListenerFactoryConfiguration> cacheEventListenerConfigurations =
314 new ArrayList<CacheEventListenerFactoryConfiguration>();
315
316
319 protected volatile List<CacheExtensionFactoryConfiguration> cacheExtensionConfigurations =
320 new ArrayList<CacheExtensionFactoryConfiguration>();
321
322
325 protected BootstrapCacheLoaderFactoryConfiguration bootstrapCacheLoaderFactoryConfiguration;
326
327
330 protected CacheExceptionHandlerFactoryConfiguration cacheExceptionHandlerFactoryConfiguration;
331
332
335 protected TerracottaConfiguration terracottaConfiguration;
336
337
340 protected volatile PinningConfiguration pinningConfiguration;
341
342
345 protected CacheWriterConfiguration cacheWriterConfiguration = DEFAULT_CACHE_WRITER_CONFIGURATION;
346
347
350 protected volatile List<CacheLoaderFactoryConfiguration> cacheLoaderConfigurations = new ArrayList<CacheLoaderFactoryConfiguration>();
351
352
355 protected volatile List<CacheDecoratorFactoryConfiguration> cacheDecoratorConfigurations =
356 new ArrayList<CacheDecoratorFactoryConfiguration>();
357
358
361 protected volatile Set<CacheConfigurationListener> listeners = new CopyOnWriteArraySet<CacheConfigurationListener>();
362
363 private volatile Set<DynamicSearchListener> dynamicSearchListeners = new CopyOnWriteArraySet<DynamicSearchListener>();
364
365 private DynamicAttributesExtractor flexIndexer;
366 private volatile boolean frozen;
367 private volatile TransactionalMode transactionalMode;
368 private volatile boolean statistics = DEFAULT_STATISTICS;
369 private volatile CopyStrategyConfiguration copyStrategyConfiguration = DEFAULT_COPY_STRATEGY_CONFIGURATION.copy();
370 private volatile SizeOfPolicyConfiguration sizeOfPolicyConfiguration;
371 private volatile PersistenceConfiguration persistenceConfiguration;
372 private volatile ElementValueComparatorConfiguration elementValueComparatorConfiguration =
373 new ElementValueComparatorConfiguration();
374 private volatile Boolean copyOnRead;
375 private volatile Boolean copyOnWrite;
376 private volatile boolean conflictingEternalValuesWarningLogged;
377 private volatile Searchable searchable;
378 private String maxBytesLocalHeapInput;
379 private String maxBytesLocalOffHeapInput;
380 private String maxBytesLocalDiskInput;
381 private Long maxBytesLocalHeap;
382 private Long maxBytesLocalOffHeap;
383 private Long maxBytesLocalDisk;
384 private Integer maxBytesLocalHeapPercentage;
385 private Integer maxBytesLocalOffHeapPercentage;
386 private Integer maxBytesLocalDiskPercentage;
387 private PoolUsage onHeapPoolUsage;
388 private PoolUsage offHeapPoolUsage;
389 private PoolUsage onDiskPoolUsage;
390 private volatile boolean maxEntriesLocalDiskExplicitlySet;
391 private volatile boolean maxBytesLocalDiskExplicitlySet;
392 private volatile boolean maxBytesLocalOffHeapExplicitlySet;
393
394
402 public CacheConfiguration() {
403
404 }
405
406
416 public CacheConfiguration(String name, int maxEntriesLocalHeap) {
417 this.name = name;
418 this.maxEntriesLocalHeap = maxEntriesLocalHeap;
419 }
420
421
426 @Override
427 public CacheConfiguration clone() {
428 CacheConfiguration config;
429 try {
430 config = (CacheConfiguration) super.clone();
431 } catch (CloneNotSupportedException e) {
432 throw new RuntimeException(e);
433 }
434
435 cloneCacheEventListenerConfigurations(config);
436
437 cloneCacheExtensionConfigurations(config);
438
439 if (bootstrapCacheLoaderFactoryConfiguration != null) {
440 config.bootstrapCacheLoaderFactoryConfiguration = bootstrapCacheLoaderFactoryConfiguration.clone();
441 }
442
443 if (cacheExceptionHandlerFactoryConfiguration != null) {
444 config.cacheExceptionHandlerFactoryConfiguration = cacheExceptionHandlerFactoryConfiguration.clone();
445 }
446
447 if (terracottaConfiguration != null) {
448 config.terracottaConfiguration = terracottaConfiguration.clone();
449 }
450
451 if (cacheWriterConfiguration != null) {
452 config.cacheWriterConfiguration = cacheWriterConfiguration.clone();
453 }
454
455 cloneCacheLoaderConfigurations(config);
456
457 cloneCacheDecoratorConfigurations(config);
458
459 config.listeners = new CopyOnWriteArraySet<CacheConfigurationListener>();
460 config.dynamicSearchListeners = new CopyOnWriteArraySet<DynamicSearchListener>();
461
462 return config;
463 }
464
465 private void cloneCacheEventListenerConfigurations(CacheConfiguration config) {
466 if (cacheEventListenerConfigurations.size() > 0) {
467 List<CacheEventListenerFactoryConfiguration> copy = new ArrayList<CacheEventListenerFactoryConfiguration>();
468 for (CacheEventListenerFactoryConfiguration item : cacheEventListenerConfigurations) {
469 copy.add(item.clone());
470 }
471 config.cacheEventListenerConfigurations = copy;
472 }
473 }
474
475 private void cloneCacheExtensionConfigurations(CacheConfiguration config) {
476 if (cacheExtensionConfigurations.size() > 0) {
477 List<CacheExtensionFactoryConfiguration> copy = new ArrayList<CacheExtensionFactoryConfiguration>();
478 for (CacheConfiguration.CacheExtensionFactoryConfiguration item : cacheExtensionConfigurations) {
479 copy.add(item.clone());
480 }
481 config.cacheExtensionConfigurations = copy;
482 }
483 }
484
485 private void cloneCacheLoaderConfigurations(CacheConfiguration config) {
486 if (cacheLoaderConfigurations.size() > 0) {
487 List<CacheLoaderFactoryConfiguration> copy = new ArrayList<CacheLoaderFactoryConfiguration>();
488 for (CacheConfiguration.CacheLoaderFactoryConfiguration item : cacheLoaderConfigurations) {
489 copy.add(item.clone());
490 }
491 config.cacheLoaderConfigurations = copy;
492 }
493 }
494
495 private void cloneCacheDecoratorConfigurations(CacheConfiguration config) {
496 if (cacheDecoratorConfigurations.size() > 0) {
497 List<CacheDecoratorFactoryConfiguration> copy = new ArrayList<CacheDecoratorFactoryConfiguration>();
498 for (CacheDecoratorFactoryConfiguration item : cacheDecoratorConfigurations) {
499 copy.add(item.clone());
500 }
501 config.cacheDecoratorConfigurations = copy;
502 }
503 }
504
505 private void assertArgumentNotNull(String name, Object object) {
506 if (object == null) {
507 throw new IllegalArgumentException(name + " cannot be null");
508 }
509 }
510
511
516 public final void setName(String name) {
517 checkDynamicChange();
518 assertArgumentNotNull("Cache name", name);
519 this.name = name;
520 }
521
522
529 public final CacheConfiguration name(String name) {
530 setName(name);
531 return this;
532 }
533
534
542 public final void setLogging(boolean enable) {
543 checkDynamicChange();
544 boolean oldLoggingEnabled = this.logging;
545 this.logging = enable;
546 fireLoggingChanged(oldLoggingEnabled, enable);
547 }
548
549
554 public final void setOverflowToOffHeap(boolean overflowToOffHeap) {
555 checkDynamicChange();
556 this.overflowToOffHeap = overflowToOffHeap;
557 }
558
559
566 public CacheConfiguration overflowToOffHeap(boolean overflowToOffHeap) {
567 setOverflowToOffHeap(overflowToOffHeap);
568 return this;
569 }
570
571
576 public void addSizeOfPolicy(SizeOfPolicyConfiguration sizeOfPolicyConfiguration) {
577 this.sizeOfPolicyConfiguration = sizeOfPolicyConfiguration;
578 }
579
580
587 public CacheConfiguration sizeOfPolicy(SizeOfPolicyConfiguration sizeOfPolicyConfiguration) {
588 addSizeOfPolicy(sizeOfPolicyConfiguration);
589 return this;
590 }
591
592
597 public void addPersistence(PersistenceConfiguration persistenceConfiguration) {
598 if (diskPersistent != null) {
599 throw new InvalidConfigurationException("Cannot use both <persistence ...> and diskPersistent in a single cache configuration.");
600 }
601 if (Boolean.TRUE.equals(overflowToDisk)) {
602 throw new InvalidConfigurationException("Cannot use both <persistence ...> and overflowToDisk in a single cache configuration.");
603 }
604 this.persistenceConfiguration = persistenceConfiguration;
605 }
606
607
614 public CacheConfiguration persistence(PersistenceConfiguration persistenceConfiguration) {
615 addPersistence(persistenceConfiguration);
616 return this;
617 }
618
619
625 @Deprecated
626 public final void setMaxMemoryOffHeap(String maxMemoryOffHeap) {
627 checkDynamicChange();
628 assertArgumentNotNull("Cache maxMemoryOffHeap", maxMemoryOffHeap);
629 setMaxBytesLocalOffHeap(maxMemoryOffHeap);
630 }
631
632
639 @Deprecated
640 public CacheConfiguration maxMemoryOffHeap(String maxMemoryOffHeap) {
641 setMaxMemoryOffHeap(maxMemoryOffHeap);
642 return this;
643 }
644
645
655 public final CacheConfiguration logging(boolean enable) {
656 setLogging(enable);
657 return this;
658 }
659
660
668 @Deprecated
669 public final void setMaxElementsInMemory(int maxElementsInMemory) {
670 setMaxEntriesLocalHeap(maxElementsInMemory);
671 }
672
673
680 public final void setMaxEntriesLocalHeap(long maxEntriesInMemory) {
681 if (maxEntriesInMemory < 0) {
682 throw new InvalidConfigurationException("Number of entries on local heap cannot be negative");
683 }
684 if (maxEntriesInMemory > Integer.MAX_VALUE) {
685 throw new IllegalArgumentException("Values larger than Integer.MAX_VALUE are not currently supported.");
686 }
687
688 checkDynamicChange();
689 if (onHeapPoolUsage != null && onHeapPoolUsage != PoolUsage.None) {
690 throw new InvalidConfigurationException("MaxEntriesLocalHeap is not compatible with " +
691 "MaxBytesLocalHeap set on cache");
692 }
693 int oldCapacity = maxEntriesLocalHeap == null ? 0 : maxEntriesLocalHeap;
694 int newCapacity = (int) maxEntriesInMemory;
695 this.maxEntriesLocalHeap = (int) maxEntriesInMemory;
696 fireMemoryCapacityChanged(oldCapacity, newCapacity);
697 }
698
699
708 @Deprecated
709 public final CacheConfiguration maxElementsInMemory(int maxElementsInMemory) {
710 setMaxElementsInMemory(maxElementsInMemory);
711 return this;
712 }
713
714
722 public final CacheConfiguration maxEntriesLocalHeap(int maxElementsInMemory) {
723 setMaxEntriesLocalHeap(maxElementsInMemory);
724 return this;
725 }
726
727
732 public final void setCacheLoaderTimeoutMillis(long cacheLoaderTimeoutMillis) {
733 checkDynamicChange();
734 this.cacheLoaderTimeoutMillis = cacheLoaderTimeoutMillis;
735 }
736
737
743 public CacheConfiguration timeoutMillis(long timeoutMillis) {
744 setCacheLoaderTimeoutMillis(timeoutMillis);
745 return this;
746 }
747
748
753 public final void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
754 assertArgumentNotNull("Cache memoryStoreEvictionPolicy", memoryStoreEvictionPolicy);
755 setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy.fromString(memoryStoreEvictionPolicy));
756 }
757
758
765 public final CacheConfiguration memoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
766 setMemoryStoreEvictionPolicy(memoryStoreEvictionPolicy);
767 return this;
768 }
769
770
773 public final void setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
774 checkDynamicChange();
775 if (null == memoryStoreEvictionPolicy) {
776 this.memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
777 } else {
778 this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
779 }
780 }
781
782
788 public final CacheConfiguration memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
789 setMemoryStoreEvictionPolicyFromObject(memoryStoreEvictionPolicy);
790 return this;
791 }
792
793
799 public final void setClearOnFlush(boolean clearOnFlush) {
800 checkDynamicChange();
801 this.clearOnFlush = clearOnFlush;
802 }
803
804
812 public final CacheConfiguration clearOnFlush(boolean clearOnFlush) {
813 setClearOnFlush(clearOnFlush);
814 return this;
815 }
816
817
822 public final void setEternal(boolean eternal) {
823 checkDynamicChange();
824 isEternalValueConflictingWithTTIOrTTL(eternal, getTimeToLiveSeconds(), getTimeToIdleSeconds());
825 this.eternal = eternal;
826 if (eternal) {
827 setTimeToIdleSeconds(0);
828 setTimeToLiveSeconds(0);
829 }
830 }
831
832 private boolean isEternalValueConflictingWithTTIOrTTL(boolean newEternalValue, long newTTLValue, long newTTIValue) {
833 boolean conflicting = false;
834
835 if (newEternalValue && (newTTLValue != 0 || newTTIValue != 0)) {
836 conflicting = true;
837 }
838
839 if (conflicting && !conflictingEternalValuesWarningLogged) {
840 conflictingEternalValuesWarningLogged = true;
841 LOG.warn("Cache '" + getName() + "' is set to eternal but also has TTI/TTL set. "
842 + " To avoid this warning, clean up the config " + "removing conflicting values of eternal,"
843 + " TTI and TTL. Effective configuration for Cache '" + getName() + "' will be eternal='" + newEternalValue
844 + "', timeToIdleSeconds='0', timeToLiveSeconds='0'.");
845 }
846 return conflicting;
847 }
848
849
856 public final CacheConfiguration eternal(boolean eternal) {
857 setEternal(eternal);
858 return this;
859 }
860
861
869 public final void setTimeToIdleSeconds(long timeToIdleSeconds) {
870 checkDynamicChange();
871 if (!isEternalValueConflictingWithTTIOrTTL(eternal, 0, timeToIdleSeconds)) {
872 long oldTti = this.timeToIdleSeconds;
873 long newTti = timeToIdleSeconds;
874 this.timeToIdleSeconds = timeToIdleSeconds;
875 fireTtiChanged(oldTti, newTti);
876 }
877 }
878
879
889 public final CacheConfiguration timeToIdleSeconds(long timeToIdleSeconds) {
890 setTimeToIdleSeconds(timeToIdleSeconds);
891 return this;
892 }
893
894
902 public final void setTimeToLiveSeconds(long timeToLiveSeconds) {
903 checkDynamicChange();
904 if (!isEternalValueConflictingWithTTIOrTTL(eternal, timeToLiveSeconds, 0)) {
905 long oldTtl = this.timeToLiveSeconds;
906 long newTtl = timeToLiveSeconds;
907 this.timeToLiveSeconds = timeToLiveSeconds;
908 fireTtlChanged(oldTtl, newTtl);
909 }
910 }
911
912
922 public final CacheConfiguration timeToLiveSeconds(long timeToLiveSeconds) {
923 setTimeToLiveSeconds(timeToLiveSeconds);
924 return this;
925 }
926
927
933 @Deprecated
934 public final void setOverflowToDisk(boolean overflowToDisk) {
935 checkDynamicChange();
936 if (persistenceConfiguration != null && Boolean.TRUE.equals(overflowToDisk)) {
937 throw new InvalidConfigurationException("Cannot use both <persistence ...> and overflowToDisk in a single cache configuration.");
938 }
939 this.overflowToDisk = overflowToDisk;
940 validateConfiguration();
941 }
942
943
951 @Deprecated
952 public final CacheConfiguration overflowToDisk(boolean overflowToDisk) {
953 setOverflowToDisk(overflowToDisk);
954 return this;
955 }
956
957
963 @Deprecated
964 public final void setDiskPersistent(boolean diskPersistent) {
965 checkDynamicChange();
966 if (persistenceConfiguration != null) {
967 throw new InvalidConfigurationException("Cannot use both <persistence ...> and diskPersistent in a single cache configuration.");
968 }
969 this.diskPersistent = diskPersistent;
970 validateConfiguration();
971 }
972
973
981 @Deprecated
982 public final CacheConfiguration diskPersistent(boolean diskPersistent) {
983 setDiskPersistent(diskPersistent);
984 return this;
985 }
986
987
993 public void setDiskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
994 checkDynamicChange();
995 if (diskSpoolBufferSizeMB <= 0) {
996 this.diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
997 } else {
998 this.diskSpoolBufferSizeMB = diskSpoolBufferSizeMB;
999 }
1000 }
1001
1002
1010 public final CacheConfiguration diskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
1011 setDiskSpoolBufferSizeMB(diskSpoolBufferSizeMB);
1012 return this;
1013 }
1014
1015
1021 public void setDiskAccessStripes(int stripes) {
1022 checkDynamicChange();
1023 if (stripes <= 0) {
1024 this.diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
1025 } else {
1026 this.diskAccessStripes = stripes;
1027 }
1028 }
1029
1030
1037 public final CacheConfiguration diskAccessStripes(int stripes) {
1038 setDiskAccessStripes(stripes);
1039 return this;
1040 }
1041
1042
1049 public void setMaxElementsOnDisk(int maxElementsOnDisk) {
1050 if (onDiskPoolUsage != null && onDiskPoolUsage != PoolUsage.None) {
1051 throw new InvalidConfigurationException("MaxEntriesLocalDisk is not compatible with " +
1052 "MaxBytesLocalDisk set on cache");
1053 }
1054 checkDynamicChange();
1055 int oldCapacity = this.maxElementsOnDisk;
1056 this.maxElementsOnDisk = maxElementsOnDisk;
1057 fireDiskCapacityChanged(oldCapacity, this.maxElementsOnDisk);
1058 }
1059
1060
1067 public void setMaxEntriesLocalDisk(long maxEntriesOnDisk) {
1068 if (maxEntriesOnDisk < 0) {
1069 throw new InvalidConfigurationException("Number of entries on disk cannot be negative");
1070 }
1071 if (maxEntriesOnDisk > Integer.MAX_VALUE) {
1072 throw new IllegalArgumentException("Values greater than Integer.MAX_VALUE are not currently supported.");
1073 }
1074
1075 if (onDiskPoolUsage != null && isTerracottaClustered()) {
1076 throw new IllegalStateException("Can't use local disks with Terracotta clustered caches!");
1077 }
1078 maxEntriesLocalDiskExplicitlySet = true;
1079 setMaxElementsOnDisk((int)maxEntriesOnDisk);
1080 }
1081
1082
1091 public final CacheConfiguration maxElementsOnDisk(int maxElementsOnDisk) {
1092 setMaxElementsOnDisk(maxElementsOnDisk);
1093 return this;
1094 }
1095
1096
1105 public final CacheConfiguration maxEntriesLocalDisk(int maxElementsOnDisk) {
1106 setMaxEntriesLocalDisk(maxElementsOnDisk);
1107 return this;
1108 }
1109
1110
1117 public final void setDiskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
1118 checkDynamicChange();
1119 if (diskExpiryThreadIntervalSeconds <= 0) {
1120 this.diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
1121 } else {
1122 this.diskExpiryThreadIntervalSeconds = diskExpiryThreadIntervalSeconds;
1123 }
1124 }
1125
1126
1136 public final CacheConfiguration diskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
1137 setDiskExpiryThreadIntervalSeconds(diskExpiryThreadIntervalSeconds);
1138 return this;
1139 }
1140
1141
1144 public void freezeConfiguration() {
1145 frozen = true;
1146 if (searchable != null) {
1147 searchable.freezeConfiguration();
1148 }
1149 }
1150
1151
1154 public boolean isFrozen() {
1155 return frozen;
1156 }
1157
1158
1164 public ReadWriteCopyStrategy<Element> getCopyStrategy() {
1165
1166 return copyStrategyConfiguration.getCopyStrategyInstance();
1167 }
1168
1169
1174 public CacheConfiguration copyOnRead(boolean copyOnRead) {
1175 this.setCopyOnRead(copyOnRead);
1176 return this;
1177 }
1178
1179
1184 public boolean isCopyOnRead() {
1185 validateTransactionalSettings();
1186 return copyOnRead;
1187 }
1188
1189
1194 public void setCopyOnRead(final boolean copyOnRead) {
1195 this.copyOnRead = copyOnRead;
1196 }
1197
1198
1203 public CacheConfiguration copyOnWrite(boolean copyOnWrite) {
1204 this.copyOnWrite = copyOnWrite;
1205 return this;
1206 }
1207
1208
1213 public boolean isCopyOnWrite() {
1214 validateTransactionalSettings();
1215 return copyOnWrite;
1216 }
1217
1218
1223 public void setCopyOnWrite(final boolean copyOnWrite) {
1224 this.copyOnWrite = copyOnWrite;
1225 }
1226
1227
1232 public void addCopyStrategy(CopyStrategyConfiguration copyStrategyConfiguration) {
1233 this.copyStrategyConfiguration = copyStrategyConfiguration;
1234 }
1235
1236
1241 public void addElementValueComparator(ElementValueComparatorConfiguration elementValueComparatorConfiguration) {
1242 this.elementValueComparatorConfiguration = elementValueComparatorConfiguration;
1243 }
1244
1245
1250 public final void addSearchable(Searchable searchable) {
1251 checkDynamicChange();
1252 this.searchable = searchable;
1253 }
1254
1255
1259 public long getMaxBytesLocalHeap() {
1260 return maxBytesLocalHeap == null ? DEFAULT_MAX_BYTES_ON_HEAP : maxBytesLocalHeap;
1261 }
1262
1263
1267 public void setMaxBytesLocalHeap(final String maxBytesHeap) {
1268 assertArgumentNotNull("Cache maxBytesLocalHeap", maxBytesHeap);
1269 if (isPercentage(maxBytesHeap)) {
1270 maxBytesLocalHeapPercentage = parsePercentage(maxBytesHeap);
1271 } else {
1272 setMaxBytesLocalHeap(MemoryUnit.parseSizeInBytes(maxBytesHeap));
1273 }
1274 maxBytesLocalHeapInput = maxBytesHeap;
1275 }
1276
1277
1281 public void setMaxBytesLocalHeap(final Long maxBytesHeap) {
1282 if (onHeapPoolUsage != null && getMaxEntriesLocalHeap() > 0) {
1283 throw new InvalidConfigurationException("MaxEntriesLocalHeap is not compatible with " +
1284 "MaxBytesLocalHeap set on cache");
1285 }
1286 if (onHeapPoolUsage != null && onHeapPoolUsage != PoolUsage.Cache) {
1287 throw new IllegalStateException("A Cache can't switch memory pool!");
1288 }
1289 verifyGreaterThanZero(maxBytesHeap, "maxBytesLocalHeap");
1290 Long oldValue = this.maxBytesLocalHeap;
1291 this.maxBytesLocalHeap = maxBytesHeap;
1292 fireMaxBytesOnLocalHeapChanged(oldValue, maxBytesHeap);
1293 }
1294
1295 private void fireMaxBytesOnLocalHeapChanged(final Long oldValue, final Long newValue) {
1296 if ((oldValue != null && !oldValue.equals(newValue)) || (newValue != null && !newValue.equals(oldValue))) {
1297 for (CacheConfigurationListener listener : listeners) {
1298 listener.maxBytesLocalHeapChanged(oldValue != null ? oldValue : 0, newValue);
1299 }
1300 }
1301 }
1302
1303 private void fireMaxBytesOnLocalDiskChanged(final Long oldValue, final Long newValue) {
1304 if ((oldValue != null && !oldValue.equals(newValue)) || (newValue != null && !newValue.equals(oldValue))) {
1305 for (CacheConfigurationListener listener : listeners) {
1306 listener.maxBytesLocalDiskChanged(oldValue != null ? oldValue : 0, newValue);
1307 }
1308 }
1309 }
1310
1311 private void fireDynamicAttributesExtractorAdded(DynamicAttributesExtractor oldValue, DynamicAttributesExtractor newValue) {
1312 if (oldValue != newValue) {
1313 for (DynamicSearchListener lsnr : dynamicSearchListeners) {
1314 lsnr.extractorChanged(oldValue, newValue);
1315 }
1316 }
1317 }
1318
1319
1325
1326 public CacheConfiguration maxBytesLocalHeap(final long amount, final MemoryUnit memoryUnit) {
1327 setMaxBytesLocalHeap(memoryUnit.toBytes(amount));
1328 return this;
1329 }
1330
1331
1335 public long getMaxBytesLocalOffHeap() {
1336 return maxBytesLocalOffHeap == null ? DEFAULT_MAX_BYTES_OFF_HEAP : maxBytesLocalOffHeap;
1337 }
1338
1339
1343 public String getMaxBytesLocalOffHeapAsString() {
1344 return maxBytesLocalOffHeapInput != null ? maxBytesLocalOffHeapInput : Long.toString(getMaxBytesLocalOffHeap());
1345 }
1346
1347
1351 public void setMaxBytesLocalOffHeap(final String maxBytesOffHeap) {
1352 assertArgumentNotNull("Cache maxBytesLocalOffHeap", maxBytesOffHeap);
1353 if (isPercentage(maxBytesOffHeap)) {
1354 maxBytesLocalOffHeapPercentage = parsePercentage(maxBytesOffHeap);
1355 } else {
1356 setMaxBytesLocalOffHeap(MemoryUnit.parseSizeInBytes(maxBytesOffHeap));
1357 }
1358 maxBytesLocalOffHeapInput = maxBytesOffHeap;
1359 maxBytesLocalOffHeapExplicitlySet = true;
1360 }
1361
1362
1366 public Integer getMaxBytesLocalOffHeapPercentage() {
1367 return maxBytesLocalOffHeapPercentage;
1368 }
1369
1370
1374 public Integer getMaxBytesLocalHeapPercentage() {
1375 return maxBytesLocalHeapPercentage;
1376 }
1377
1378
1382 public String getMaxBytesLocalHeapAsString() {
1383 return maxBytesLocalHeapInput != null ? maxBytesLocalHeapInput : Long.toString(getMaxBytesLocalHeap());
1384 }
1385
1386
1390 public Integer getMaxBytesLocalDiskPercentage() {
1391 return maxBytesLocalDiskPercentage;
1392 }
1393
1394 private int parsePercentage(final String stringValue) {
1395 String trimmed = stringValue.trim();
1396 int percentage = Integer.parseInt(trimmed.substring(0, trimmed.length() - 1));
1397 if (percentage > HUNDRED_PERCENT || percentage < 0) {
1398 throw new IllegalArgumentException("Percentage need values need to be between 0 and 100 inclusive, but got : " + percentage);
1399 }
1400 return percentage;
1401 }
1402
1403 private boolean isPercentage(final String stringValue) {
1404 String trimmed = stringValue.trim();
1405 return trimmed.charAt(trimmed.length() - 1) == '%';
1406 }
1407
1408
1412 public void setMaxBytesLocalOffHeap(final Long maxBytesOffHeap) {
1413 if (offHeapPoolUsage != null) {
1414 throw new IllegalStateException("OffHeap can't be set dynamically!");
1415 }
1416 verifyGreaterThanZero(maxBytesOffHeap, "maxBytesLocalOffHeap");
1417 this.maxBytesLocalOffHeapExplicitlySet = true;
1418 this.maxBytesLocalOffHeap = maxBytesOffHeap;
1419 }
1420
1421
1427 public CacheConfiguration maxBytesLocalOffHeap(final long amount, final MemoryUnit memoryUnit) {
1428 setMaxBytesLocalOffHeap(memoryUnit.toBytes(amount));
1429 return this;
1430 }
1431
1432
1436 public long getMaxBytesLocalDisk() {
1437 return maxBytesLocalDisk == null ? DEFAULT_MAX_BYTES_ON_DISK : maxBytesLocalDisk;
1438 }
1439
1440
1444 public String getMaxBytesLocalDiskAsString() {
1445 return maxBytesLocalDiskInput != null ? maxBytesLocalDiskInput : Long.toString(getMaxBytesLocalDisk());
1446 }
1447
1448
1452 public void setMaxBytesLocalDisk(final String maxBytesDisk) {
1453 assertArgumentNotNull("Cache maxBytesLocalDisk", maxBytesDisk);
1454 if (isPercentage(maxBytesDisk)) {
1455 maxBytesLocalDiskPercentage = parsePercentage(maxBytesDisk);
1456 } else {
1457 setMaxBytesLocalDisk(MemoryUnit.parseSizeInBytes(maxBytesDisk));
1458 }
1459 maxBytesLocalDiskExplicitlySet = true;
1460 maxBytesLocalDiskInput = maxBytesDisk;
1461 }
1462
1463
1467 public void setMaxBytesLocalDisk(final Long maxBytesDisk) {
1468 if (onDiskPoolUsage != null && getMaxEntriesLocalDisk() > 0) {
1469 throw new InvalidConfigurationException("MaxEntriesLocalDisk is not compatible with " +
1470 "MaxBytesLocalDisk set on cache");
1471 }
1472 if (onDiskPoolUsage != null && onDiskPoolUsage != PoolUsage.Cache) {
1473 throw new IllegalStateException("A Cache can't switch disk pool!");
1474 }
1475 verifyGreaterThanZero(maxBytesDisk, "maxBytesLocalDisk");
1476 maxBytesLocalDiskExplicitlySet = true;
1477 Long oldValue = this.maxBytesLocalDisk;
1478 this.maxBytesLocalDisk = maxBytesDisk;
1479 fireMaxBytesOnLocalDiskChanged(oldValue, maxBytesDisk);
1480 }
1481
1482
1488 public CacheConfiguration maxBytesLocalDisk(final long amount, final MemoryUnit memoryUnit) {
1489 setMaxBytesLocalDisk(memoryUnit.toBytes(amount));
1490 return this;
1491 }
1492
1493
1497 public void setDynamicAttributesExtractor(DynamicAttributesExtractor extractor) {
1498 if (searchable == null || !searchable.isDynamicIndexingAllowed()) {
1499 throw new IllegalArgumentException("Dynamic search attribute extraction not supported");
1500 }
1501 if (extractor == null && this.flexIndexer != null) {
1502 throw new IllegalArgumentException("Dynamic search attributes extractor cannot be set to null by user");
1503 }
1504 DynamicAttributesExtractor old = this.flexIndexer;
1505 this.flexIndexer = extractor;
1506 fireDynamicAttributesExtractorAdded(old, this.flexIndexer);
1507 }
1508
1509
1514 public CacheConfiguration dynamicAttributeExtractor(DynamicAttributesExtractor extractor) {
1515 setDynamicAttributesExtractor(extractor);
1516 return this;
1517 }
1518
1519 private void verifyGreaterThanZero(final Long maxBytesOnHeap, final String field) {
1520 if (maxBytesOnHeap != null && maxBytesOnHeap < 1) {
1521 throw new IllegalArgumentException(field + " has to be larger than 0");
1522 }
1523 }
1524
1525
1530 public CopyStrategyConfiguration getCopyStrategyConfiguration() {
1531 return this.copyStrategyConfiguration;
1532 }
1533
1534
1539 public ElementValueComparatorConfiguration getElementValueComparatorConfiguration() {
1540 return elementValueComparatorConfiguration;
1541 }
1542
1543
1548 public boolean isMaxBytesLocalHeapPercentageSet() {
1549 return maxBytesLocalHeapPercentage != null;
1550 }
1551
1552
1557 public boolean isMaxBytesLocalOffHeapPercentageSet() {
1558 return maxBytesLocalOffHeapPercentage != null;
1559 }
1560
1561
1566 public boolean isMaxBytesLocalDiskPercentageSet() {
1567 return maxBytesLocalDiskPercentage != null;
1568 }
1569
1570
1574 public void setupFor(final CacheManager cacheManager) {
1575 setupFor(cacheManager, true);
1576 }
1577
1578
1583 public void setupFor(final CacheManager cacheManager, final boolean register) {
1584 final Collection<ConfigError> errors = validate(cacheManager.getConfiguration());
1585 configCachePools(cacheManager.getConfiguration());
1586 errors.addAll(verifyPoolAllocationsBeforeAddingTo(cacheManager,
1587 cacheManager.getConfiguration().getMaxBytesLocalHeap(),
1588 cacheManager.getConfiguration().getMaxBytesLocalOffHeap(),
1589 cacheManager.getConfiguration().getMaxBytesLocalDisk()));
1590 if (!errors.isEmpty()) {
1591 throw new InvalidConfigurationException(errors);
1592 }
1593
1594
1595 if (!isTerracottaClustered()) {
1596 updateCacheManagerPoolSizes(cacheManager);
1597 }
1598
1599 if (register) {
1600 registerCacheConfiguration(cacheManager);
1601 }
1602 if (cacheManager.getConfiguration().isMaxBytesLocalHeapSet() || cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
1603 addConfigurationListener(new AbstractCacheConfigurationListener() {
1604 @Override
1605 public void maxBytesLocalHeapChanged(final long oldValue, final long newValue) {
1606 if (getMaxBytesLocalHeap() > 0
1607 && cacheManager.getConfiguration().getCacheConfigurations().keySet().contains(getName())
1608 && cacheManager.getConfiguration().isMaxBytesLocalHeapSet()) {
1609 long previous = cacheManager.getOnHeapPool().getMaxSize();
1610 cacheManager.getOnHeapPool().setMaxSize(previous + oldValue - newValue);
1611 }
1612 }
1613
1614 @Override
1615 public void maxBytesLocalDiskChanged(final long oldValue, final long newValue) {
1616 if (getMaxBytesLocalDisk() > 0
1617 && cacheManager.getConfiguration().getCacheConfigurations().keySet().contains(getName())
1618 && cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
1619 long previous = cacheManager.getOnDiskPool().getMaxSize();
1620 cacheManager.getOnDiskPool().setMaxSize(previous + oldValue - newValue);
1621 }
1622 }
1623 });
1624 }
1625
1626 consolidatePersistenceSettings(cacheManager);
1627
1628 if (overflowToOffHeap == null && (cacheManager.getConfiguration().isMaxBytesLocalOffHeapSet() || getMaxBytesLocalOffHeap() > 0)) {
1629 overflowToOffHeap = true;
1630 }
1631 if ((persistenceConfiguration != null && Strategy.LOCALTEMPSWAP.equals(persistenceConfiguration.getStrategy()))) {
1632 overflowToDisk = true;
1633 }
1634 if (overflowToDisk == null && cacheManager.getConfiguration().isMaxBytesLocalDiskSet() || getMaxBytesLocalDisk() > 0) {
1635 if (persistenceConfiguration != null && Strategy.LOCALRESTARTABLE.equals(persistenceConfiguration.getStrategy())) {
1636 throw new InvalidConfigurationException("Cannot use localRestartable persistence and disk overflow in the same cache");
1637 } else {
1638 overflowToDisk = true;
1639 }
1640 }
1641 warnMaxEntriesLocalHeap(register, cacheManager);
1642 warnMaxEntriesForOverflowToOffHeap(register);
1643 warnSizeOfPolicyConfiguration();
1644 freezePoolUsages(cacheManager);
1645 }
1646
1647 private void consolidatePersistenceSettings(CacheManager manager) {
1648 if (persistenceConfiguration == null) {
1649 if (diskPersistent == Boolean.TRUE) {
1650 persistenceConfiguration = new PersistenceConfiguration().strategy(Strategy.LOCALTEMPSWAP);
1651 }
1652 } else {
1653 switch (persistenceConfiguration.getStrategy()) {
1654 case DISTRIBUTED:
1655 case NONE:
1656 diskPersistent = Boolean.FALSE;
1657 break;
1658 case LOCALTEMPSWAP:
1659 if (diskPersistent == null) {
1660 diskPersistent = Boolean.FALSE;
1661 }
1662 break;
1663 case LOCALRESTARTABLE:
1664 diskPersistent = Boolean.TRUE;
1665 break;
1666 default:
1667 break;
1668 }
1669 }
1670
1671 if (persistenceConfiguration != null && persistenceConfiguration.getSynchronousWrites()) {
1672 switch (persistenceConfiguration.getStrategy()) {
1673 case NONE:
1674 case LOCALTEMPSWAP:
1675 throw new InvalidConfigurationException("Persistence: synchronousWrites=\"true\" is not supported "
1676 + "with strategy \"localTempSwap\" or \"none\"");
1677 default:
1678 break;
1679 }
1680 }
1681 }
1682
1683 private void warnMaxEntriesForOverflowToOffHeap(final boolean register) {
1684 if (overflowToOffHeap != null && overflowToOffHeap && register) {
1685 if (getMaxEntriesLocalHeap() > 0 && getMaxEntriesLocalHeap() < MINIMUM_RECOMMENDED_IN_MEMORY) {
1686 LOG.warn("The " + getName() + " cache is configured for off-heap and has a maxEntriesLocalHeap/maxElementsInMemory of "
1687 + getMaxEntriesLocalHeap() + ". It is recommended to set maxEntriesLocalHeap/maxElementsInMemory to at least "
1688 + MINIMUM_RECOMMENDED_IN_MEMORY + " elements when using an off-heap store, otherwise performance "
1689 + "will be seriously degraded.");
1690 }
1691 }
1692 }
1693
1694 private void warnMaxEntriesLocalHeap(final boolean register, CacheManager cacheManager) {
1695 if (getMaxEntriesLocalHeap() == 0 && register) {
1696 if (getMaxBytesLocalHeap() == 0 && (!cacheManager.getConfiguration().isMaxBytesLocalHeapSet())) {
1697 LOG.warn("Cache: " + getName() +
1698 " has a maxElementsInMemory of 0. This might lead to performance degradation or OutOfMemoryError at Terracotta client." +
1699 "From Ehcache 2.0 onwards this has been changed to mean a store" +
1700 " with no capacity limit. Set it to 1 if you want" +
1701 " no elements cached in memory");
1702 }
1703 }
1704 }
1705
1706 private void warnSizeOfPolicyConfiguration() {
1707 if (isTerracottaClustered() && getSizeOfPolicyConfiguration() != null) {
1708 LOG.warn("Terracotta clustered cache: " + getName() + " has a sizeOf policy configuration specificed. " +
1709 "SizeOfPolicyConfiguration is unsupported for Terracotta clustered caches.");
1710 }
1711 }
1712
1713 private void freezePoolUsages(final CacheManager cacheManager) {
1714 if (getMaxBytesLocalHeap() > 0) {
1715 onHeapPoolUsage = CacheConfiguration.PoolUsage.Cache;
1716 } else if (cacheManager.getConfiguration().isMaxBytesLocalHeapSet()) {
1717 onHeapPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
1718 } else {
1719 onHeapPoolUsage = CacheConfiguration.PoolUsage.None;
1720 }
1721
1722 if (getMaxBytesLocalOffHeap() > 0) {
1723 offHeapPoolUsage = CacheConfiguration.PoolUsage.Cache;
1724 } else if (cacheManager.getConfiguration().isMaxBytesLocalOffHeapSet()) {
1725 offHeapPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
1726 } else {
1727 offHeapPoolUsage = CacheConfiguration.PoolUsage.None;
1728 }
1729
1730 if (isTerracottaClustered()) {
1731 onDiskPoolUsage = CacheConfiguration.PoolUsage.None;
1732 } else {
1733 if (getMaxBytesLocalDisk() > 0) {
1734 onDiskPoolUsage = CacheConfiguration.PoolUsage.Cache;
1735 } else if (cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
1736 onDiskPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
1737 } else {
1738 onDiskPoolUsage = CacheConfiguration.PoolUsage.None;
1739 }
1740 }
1741 }
1742
1743 private void registerCacheConfiguration(final CacheManager cacheManager) {
1744 Map<String, CacheConfiguration> configMap = cacheManager.getConfiguration().getCacheConfigurations();
1745 if (!configMap.containsKey(getName())) {
1746 cacheManager.getConfiguration().addCache(this, false);
1747 }
1748 }
1749
1750 private void updateCacheManagerPoolSizes(final CacheManager cacheManager) {
1751 if (cacheManager.getOnHeapPool() != null) {
1752 cacheManager.getOnHeapPool().setMaxSize(cacheManager.getOnHeapPool().getMaxSize() - getMaxBytesLocalHeap());
1753 }
1754 if (cacheManager.getOnDiskPool() != null) {
1755 cacheManager.getOnDiskPool().setMaxSize(cacheManager.getOnDiskPool().getMaxSize() - getMaxBytesLocalDisk());
1756 }
1757 }
1758
1759
1767 List<ConfigError> verifyPoolAllocationsBeforeAddingTo(CacheManager cacheManager,
1768 long managerMaxBytesLocalHeap,
1769 long managerMaxBytesLocalOffHeap,
1770 long managerMaxBytesLocalDisk) {
1771 final List<ConfigError> configErrors = new ArrayList<ConfigError>();
1772
1773 long totalOnHeapAssignedMemory = 0;
1774 long totalOffHeapAssignedMemory = 0;
1775 long totalOnDiskAssignedMemory = 0;
1776
1777 boolean isUpdate = false;
1778 for (Cache cache : getAllActiveCaches(cacheManager)) {
1779 isUpdate = cache.getName().equals(getName()) || isUpdate;
1780 final CacheConfiguration config = cache.getCacheConfiguration();
1781 totalOnHeapAssignedMemory += config.getMaxBytesLocalHeap();
1782 totalOffHeapAssignedMemory += config.getMaxBytesLocalOffHeap();
1783 totalOnDiskAssignedMemory += config.getMaxBytesLocalDisk();
1784 }
1785
1786 if (!isUpdate) {
1787 totalOnHeapAssignedMemory += getMaxBytesLocalHeap();
1788 totalOffHeapAssignedMemory += getMaxBytesLocalOffHeap();
1789 totalOnDiskAssignedMemory += getMaxBytesLocalDisk();
1790 }
1791
1792 verifyLocalHeap(managerMaxBytesLocalHeap, configErrors, totalOnHeapAssignedMemory);
1793 verifyLocalOffHeap(managerMaxBytesLocalOffHeap, configErrors, totalOffHeapAssignedMemory);
1794 verifyLocalDisk(managerMaxBytesLocalDisk, configErrors, totalOnDiskAssignedMemory);
1795
1796 if (managerMaxBytesLocalHeap > 0 && managerMaxBytesLocalHeap - totalOnHeapAssignedMemory == 0) {
1797 LOG.warn("All the onHeap memory has been assigned, there is none left for dynamically added caches");
1798 }
1799
1800 if (Runtime.getRuntime().maxMemory() - totalOnHeapAssignedMemory < 0) {
1801
1802 configErrors.add(new ConfigError("You've assigned more memory to the on-heap than the VM can sustain, " +
1803 "please adjust your -Xmx setting accordingly"));
1804 }
1805
1806 if (totalOnHeapAssignedMemory / (float) Runtime.getRuntime().maxMemory() > CacheManager.ON_HEAP_THRESHOLD) {
1807 LOG.warn("You've assigned over 80% of your VM's heap to be used by the cache!");
1808 }
1809
1810 return configErrors;
1811 }
1812
1813 private void verifyLocalDisk(final long managerMaxBytesLocalDisk,
1814 final List<ConfigError> configErrors, final long totalOnDiskAssignedMemory) {
1815 if ((isMaxBytesLocalDiskPercentageSet() || getMaxBytesLocalDisk() > 0)
1816 && managerMaxBytesLocalDisk > 0 && managerMaxBytesLocalDisk - totalOnDiskAssignedMemory < 0) {
1817 configErrors.add(new ConfigError("Cache '" + getName()
1818 + "' over-allocates CacheManager's localOnDisk limit!"));
1819 }
1820 }
1821
1822 private void verifyLocalOffHeap(final long managerMaxBytesLocalOffHeap,
1823 final List<ConfigError> configErrors, final long totalOffHeapAssignedMemory) {
1824 if ((isMaxBytesLocalOffHeapPercentageSet() || getMaxBytesLocalOffHeap() > 0)
1825 && managerMaxBytesLocalOffHeap > 0 && managerMaxBytesLocalOffHeap - totalOffHeapAssignedMemory < 0) {
1826 configErrors.add(new ConfigError("Cache '" + getName()
1827 + "' over-allocates CacheManager's localOffHeap limit!"));
1828 }
1829 }
1830
1831 private void verifyLocalHeap(final long managerMaxBytesLocalHeap,
1832 final List<ConfigError> configErrors, final long totalOnHeapAssignedMemory) {
1833 if ((isMaxBytesLocalHeapPercentageSet() || getMaxBytesLocalHeap() > 0)
1834 && managerMaxBytesLocalHeap > 0 && managerMaxBytesLocalHeap - totalOnHeapAssignedMemory < 0) {
1835 configErrors.add(new ConfigError("Cache '" + getName()
1836 + "' over-allocates CacheManager's localOnHeap limit!"));
1837 }
1838 }
1839
1840
1844 void configCachePools(Configuration configuration) {
1845
1846 long cacheAssignedMem;
1847 if (getMaxBytesLocalHeapPercentage() != null) {
1848 cacheAssignedMem = configuration.getMaxBytesLocalHeap() * getMaxBytesLocalHeapPercentage() / HUNDRED_PERCENT;
1849 setMaxBytesLocalHeap(cacheAssignedMem);
1850 }
1851
1852 if (offHeapPoolUsage == null && getMaxBytesLocalOffHeapPercentage() != null) {
1853 cacheAssignedMem = configuration.getMaxBytesLocalOffHeap() * getMaxBytesLocalOffHeapPercentage() / HUNDRED_PERCENT;
1854 setMaxBytesLocalOffHeap(cacheAssignedMem);
1855 }
1856
1857 if (getMaxBytesLocalDiskPercentage() != null) {
1858 cacheAssignedMem = configuration.getMaxBytesLocalDisk() * getMaxBytesLocalDiskPercentage() / HUNDRED_PERCENT;
1859 setMaxBytesLocalDisk(cacheAssignedMem);
1860 }
1861
1862 }
1863
1864
1869 public Collection<ConfigError> validate(final Configuration configuration) {
1870
1871 final Collection<ConfigError> errors = new ArrayList<ConfigError>();
1872
1873 verifyClusteredCacheConfiguration(configuration, errors);
1874
1875 if (maxEntriesLocalHeap == null && !configuration.isMaxBytesLocalHeapSet() && maxBytesLocalHeap == null) {
1876 errors.add(new CacheConfigError("If your CacheManager has no maxBytesLocalHeap set, you need to either set " +
1877 "maxEntriesLocalHeap or maxBytesLocalHeap at the Cache level", getName()));
1878 }
1879
1880 if (configuration.isMaxBytesLocalHeapSet() && Runtime.getRuntime().maxMemory() - configuration.getMaxBytesLocalHeap() < 0) {
1881 errors.add(new ConfigError("You've assigned more memory to the on-heap than the VM can sustain, " +
1882 "please adjust your -Xmx setting accordingly"));
1883 }
1884
1885
1886
1887
1888
1889
1890 if (persistenceConfiguration != null && persistenceConfiguration.getStrategy() == null) {
1891 errors.add(new ConfigError("Persistence configuration found with no strategy set."));
1892 }
1893
1894 errors.addAll(validateCachePools(configuration));
1895
1896 return errors;
1897 }
1898
1899 private void verifyClusteredCacheConfiguration(final Configuration configuration, final Collection<ConfigError> errors) {
1900 if (!isTerracottaClustered()) { return; }
1901
1902 if (getPinningConfiguration() != null && getPinningConfiguration().getStore() == PinningConfiguration.Store.INCACHE
1903 && getMaxElementsOnDisk() != 0) {
1904 errors.add(new CacheConfigError("maxElementsOnDisk may not be used on a pinned cache.", getName()));
1905 }
1906
1907 if (maxEntriesLocalDiskExplicitlySet) {
1908 errors.add(new CacheConfigError("You can't set maxEntriesLocalDisk when clustering your cache with Terracotta, " +
1909 "local disks won't be used! To control elements going in the cache cluster wide, " +
1910 "use maxElementsOnDisk instead", getName()));
1911 }
1912
1913
1914 if (maxBytesLocalDiskExplicitlySet) {
1915 errors.add(new CacheConfigError("You can't set maxBytesLocalDisk when clustering your cache with Terracotta",
1916 getName()));
1917 }
1918
1919 validateTerracottaConfig(configuration, errors);
1920 }
1921
1922
1927 List<CacheConfigError> validateCachePools(final Configuration configuration) {
1928 List<CacheConfigError> errors = new ArrayList<CacheConfigError>();
1929
1930 if (configuration.isMaxBytesLocalHeapSet()
1931 && getMaxEntriesLocalHeap() > 0) {
1932 errors.add(new CacheConfigError("MaxElementsInMemory is not compatible with " +
1933 "MaxBytesLocalHeap set on cache manager", getName()));
1934 }
1935 if (getMaxBytesLocalHeap() > 0 && getMaxEntriesLocalHeap() > 0) {
1936 errors.add(new CacheConfigError("MaxElementsInMemory is not compatible with " +
1937 "MaxBytesLocalHeap set on cache", getName()));
1938 }
1939 if (isMaxBytesLocalHeapPercentageSet() && !configuration.isMaxBytesLocalHeapSet()) {
1940 errors.add(new CacheConfigError("Defines a percentage maxBytesOnHeap value but no CacheManager " +
1941 "wide value was configured", getName()));
1942 }
1943 if (isMaxBytesLocalOffHeapPercentageSet() && !configuration.isMaxBytesLocalOffHeapSet()) {
1944 errors.add(new CacheConfigError("Defines a percentage maxBytesOffHeap value but no CacheManager " +
1945 "wide value was configured", getName()));
1946 }
1947 if (isMaxBytesLocalDiskPercentageSet() && !configuration.isMaxBytesLocalDiskSet()) {
1948 errors.add(new CacheConfigError("Defines a percentage maxBytesOnDisk value but no CacheManager " +
1949 "wide value was configured", getName()));
1950 }
1951 return errors;
1952 }
1953
1954 private void validateTerracottaConfig(final Configuration configuration, final Collection<ConfigError> errors) {
1955 final TerracottaClientConfiguration clientConfiguration = configuration.getTerracottaConfiguration();
1956 if (clientConfiguration != null && clientConfiguration.isRejoin() && !getTerracottaConfiguration().isNonstopEnabled()) {
1957 errors.add(new CacheConfigError("Terracotta clustered caches must be nonstop when rejoin is enabled.", getName()));
1958 }
1959 }
1960
1961
1965 public boolean isCountBasedTuned() {
1966 return (maxEntriesLocalHeap != null && maxEntriesLocalHeap > 0) || maxElementsOnDisk > 0;
1967 }
1968
1969
1973 public boolean isOverflowToOffHeapSet() {
1974 return overflowToOffHeap != null;
1975 }
1976
1977
1978
1981 public static final class CacheEventListenerFactoryConfiguration extends FactoryConfiguration<CacheEventListenerFactoryConfiguration> {
1982 private NotificationScope notificationScope = NotificationScope.ALL;
1983
1984
1988 public void setListenFor(String listenFor) {
1989 if (listenFor == null) {
1990 throw new IllegalArgumentException("listenFor must be non-null");
1991 }
1992 this.notificationScope = NotificationScope.valueOf(NotificationScope.class, listenFor.toUpperCase());
1993 }
1994
1995
1999 public final CacheEventListenerFactoryConfiguration listenFor(String listenFor) {
2000 setListenFor(listenFor);
2001 return this;
2002 }
2003
2004
2007 public NotificationScope getListenFor() {
2008 return this.notificationScope;
2009 }
2010 }
2011
2012
2015 public final void addCacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
2016 checkDynamicChange();
2017 cacheEventListenerConfigurations.add(factory);
2018 validateConfiguration();
2019 }
2020
2021
2025 public final CacheConfiguration cacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
2026 addCacheEventListenerFactory(factory);
2027 return this;
2028 }
2029
2030
2033 public static final class CacheExtensionFactoryConfiguration extends FactoryConfiguration<CacheExtensionFactoryConfiguration> {
2034 }
2035
2036
2039 public final void addCacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
2040 checkDynamicChange();
2041 cacheExtensionConfigurations.add(factory);
2042 }
2043
2044
2048 public final CacheConfiguration cacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
2049
2052 addCacheExtensionFactory(factory);
2053 return this;
2054 }
2055
2056
2059 public static final class BootstrapCacheLoaderFactoryConfiguration extends
2060 FactoryConfiguration<BootstrapCacheLoaderFactoryConfiguration> {
2061 }
2062
2063
2066 public final void addBootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
2067 checkDynamicChange();
2068 this.bootstrapCacheLoaderFactoryConfiguration = factory;
2069 }
2070
2071
2075 public final CacheConfiguration bootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
2076 addBootstrapCacheLoaderFactory(factory);
2077 return this;
2078 }
2079
2080
2083 public static final class CacheExceptionHandlerFactoryConfiguration extends
2084 FactoryConfiguration<CacheExceptionHandlerFactoryConfiguration> {
2085 }
2086
2087
2094 public final void addCacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
2095 checkDynamicChange();
2096 this.cacheExceptionHandlerFactoryConfiguration = factory;
2097 }
2098
2099
2103 public final CacheConfiguration cacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
2104 addCacheExceptionHandlerFactory(factory);
2105 return this;
2106 }
2107
2108
2111 public static final class CacheLoaderFactoryConfiguration extends FactoryConfiguration<CacheLoaderFactoryConfiguration> {
2112 }
2113
2114
2119 public final void addCacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
2120 checkDynamicChange();
2121 cacheLoaderConfigurations.add(factory);
2122 }
2123
2124
2127 public static final class CacheDecoratorFactoryConfiguration extends FactoryConfiguration<CacheDecoratorFactoryConfiguration> {
2128 }
2129
2130
2135 public final void addCacheDecoratorFactory(CacheDecoratorFactoryConfiguration factory) {
2136 checkDynamicChange();
2137 cacheDecoratorConfigurations.add(factory);
2138 }
2139
2140
2144 public final CacheConfiguration cacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
2145 addCacheLoaderFactory(factory);
2146 return this;
2147 }
2148
2149
2152 public final void addTerracotta(TerracottaConfiguration terracottaConfiguration) {
2153 this.terracottaConfiguration = terracottaConfiguration;
2154 validateConfiguration();
2155 }
2156
2157
2160 public final void addPinning(PinningConfiguration pinningConfiguration) {
2161 this.pinningConfiguration = pinningConfiguration;
2162 validateConfiguration();
2163 }
2164
2165
2169 public final CacheConfiguration pinning(PinningConfiguration pinningConfiguration) {
2170 addPinning(pinningConfiguration);
2171 return this;
2172 }
2173
2174
2178 public final CacheConfiguration terracotta(TerracottaConfiguration terracottaConfiguration) {
2179 addTerracotta(terracottaConfiguration);
2180 return this;
2181 }
2182
2183
2188 public final CacheConfiguration searchable(Searchable searchable) {
2189 addSearchable(searchable);
2190 return this;
2191 }
2192
2193
2196 public final void addCacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
2197 if (null == cacheWriterConfiguration) {
2198 this.cacheWriterConfiguration = new CacheWriterConfiguration();
2199 } else {
2200 this.cacheWriterConfiguration = cacheWriterConfiguration;
2201 }
2202 }
2203
2204
2208 public final CacheConfiguration cacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
2209 addCacheWriter(cacheWriterConfiguration);
2210 return this;
2211 }
2212
2213
2218 public final void setTransactionalMode(final String transactionalMode) {
2219 assertArgumentNotNull("Cache transactionalMode", transactionalMode);
2220 transactionalMode(TransactionalMode.valueOf(transactionalMode.toUpperCase()));
2221 }
2222
2223
2230 public final CacheConfiguration transactionalMode(String transactionalMode) {
2231 setTransactionalMode(transactionalMode);
2232 return this;
2233 }
2234
2235
2242 public final CacheConfiguration transactionalMode(TransactionalMode transactionalMode) {
2243 if (transactionalMode == null) {
2244 throw new IllegalArgumentException("TransactionalMode value must be non-null");
2245 }
2246 if (this.transactionalMode != null) {
2247 throw new InvalidConfigurationException("transactionalMode cannot be changed once set");
2248 }
2249 this.transactionalMode = transactionalMode;
2250 return this;
2251 }
2252
2253
2256 public final void setStatistics(boolean enabled) {
2257 this.statistics = enabled;
2258 }
2259
2260
2266 public final CacheConfiguration statistics(boolean statistics) {
2267 setStatistics(statistics);
2268 return this;
2269 }
2270
2271
2274 public final boolean getStatistics() {
2275 return statistics;
2276 }
2277
2278
2281 public void validateCompleteConfiguration() {
2282
2283 validateConfiguration();
2284
2285
2286
2287 if (name == null) {
2288 throw new InvalidConfigurationException("Caches must be named.");
2289 }
2290 }
2291
2292
2295 public void validateConfiguration() {
2296 if (terracottaConfiguration != null && terracottaConfiguration.isClustered()) {
2297 if (overflowToDisk != null && overflowToDisk) {
2298 throw new InvalidConfigurationException("overflowToDisk isn't supported for a clustered Terracotta cache");
2299 }
2300 if (diskPersistent == Boolean.TRUE) {
2301 throw new InvalidConfigurationException("diskPersistent isn't supported for a clustered Terracotta cache");
2302 }
2303 if (persistenceConfiguration != null && !Strategy.DISTRIBUTED.equals(persistenceConfiguration.getStrategy())) {
2304 throw new InvalidConfigurationException(persistenceConfiguration.getStrategy() +
2305 " persistence strategy isn't supported for a clustered Terracotta cache");
2306 }
2307 if (cacheEventListenerConfigurations != null) {
2308 for (CacheEventListenerFactoryConfiguration listenerConfig : cacheEventListenerConfigurations) {
2309 if (null == listenerConfig.getFullyQualifiedClassPath()) {
2310 continue;
2311 }
2312 if (!listenerConfig.getFullyQualifiedClassPath().startsWith("net.sf.ehcache.") &&
2313 LOG.isWarnEnabled()) {
2314 LOG.warn("The non-standard CacheEventListenerFactory '" + listenerConfig.getFullyQualifiedClassPath() +
2315 "' is used with a clustered Terracotta cache, " +
2316 "if the purpose of this listener is replication it is not supported in a clustered context");
2317 }
2318 }
2319 }
2320 }
2321 if (cacheWriterConfiguration != null) {
2322 if (!cacheWriterConfiguration.getWriteBatching() && cacheWriterConfiguration.getWriteBatchSize() != 1) {
2323 throw new InvalidConfigurationException("CacheWriter Batch Size !=1 and CacheWriter Batching " +
2324 "turned off");
2325 }
2326 }
2327 }
2328
2329 private void validateTransactionalSettings() {
2330 boolean transactional = getTransactionalMode().isTransactional();
2331 if (copyOnRead == null) {
2332 if (terracottaConfiguration != null && terracottaConfiguration.isCopyOnReadSet()) {
2333 copyOnRead = terracottaConfiguration.isCopyOnRead();
2334 } else {
2335 copyOnRead = transactional;
2336 }
2337 }
2338 if (copyOnWrite == null) {
2339 copyOnWrite = transactional;
2340 }
2341
2342 if (transactional) {
2343 if (!copyOnRead || !copyOnWrite) {
2344 throw new InvalidConfigurationException("A transactional cache has to be copyOnRead and copyOnWrite!");
2345 }
2346 }
2347 }
2348
2349
2352 public String getName() {
2353 return name;
2354 }
2355
2356
2361 @Deprecated
2362 public int getMaxElementsInMemory() {
2363 return (int)getMaxEntriesLocalHeap();
2364 }
2365
2366
2369 public long getCacheLoaderTimeoutMillis() {
2370 return cacheLoaderTimeoutMillis;
2371 }
2372
2373
2377 public int getMaxElementsOnDisk() {
2378 return maxElementsOnDisk;
2379 }
2380
2381
2384 public long getMaxEntriesLocalDisk() {
2385 return maxElementsOnDisk;
2386 }
2387
2388
2391 public long getMaxEntriesLocalHeap() {
2392 return maxEntriesLocalHeap == null ? 0 : maxEntriesLocalHeap;
2393 }
2394
2395
2398 public MemoryStoreEvictionPolicy getMemoryStoreEvictionPolicy() {
2399 return memoryStoreEvictionPolicy;
2400 }
2401
2402
2405 public boolean isClearOnFlush() {
2406 return clearOnFlush;
2407 }
2408
2409
2412 public boolean isEternal() {
2413 return eternal;
2414 }
2415
2416
2419 public long getTimeToIdleSeconds() {
2420 return timeToIdleSeconds;
2421 }
2422
2423
2426 public long getTimeToLiveSeconds() {
2427 return timeToLiveSeconds;
2428 }
2429
2430
2435 @Deprecated
2436 public boolean isOverflowToDisk() {
2437 return overflowToDisk == null ? false : overflowToDisk;
2438 }
2439
2440
2445 @Deprecated
2446 public boolean isDiskPersistent() {
2447 Boolean persistent = diskPersistent;
2448 return diskPersistent == null ? DEFAULT_DISK_PERSISTENT : persistent;
2449 }
2450
2451
2454 public boolean isSearchable() {
2455 return searchable != null;
2456 }
2457
2458
2461 public int getDiskSpoolBufferSizeMB() {
2462 return diskSpoolBufferSizeMB;
2463 }
2464
2465
2468 public long getDiskExpiryThreadIntervalSeconds() {
2469 return diskExpiryThreadIntervalSeconds;
2470 }
2471
2472
2475 public int getDiskAccessStripes() {
2476 return diskAccessStripes;
2477 }
2478
2479
2482 public DynamicAttributesExtractor getDynamicExtractor() {
2483 return flexIndexer;
2484 }
2485
2490 public boolean getLogging() {
2491 return logging;
2492 }
2493
2494
2499 public boolean isOverflowToOffHeap() {
2500 return overflowToOffHeap == null ? false : overflowToOffHeap;
2501 }
2502
2503
2508 public SizeOfPolicyConfiguration getSizeOfPolicyConfiguration() {
2509 return sizeOfPolicyConfiguration;
2510 }
2511
2512
2517 public PersistenceConfiguration getPersistenceConfiguration() {
2518 return persistenceConfiguration;
2519 }
2520
2521
2527 @Deprecated
2528 public String getMaxMemoryOffHeap() {
2529 return maxBytesLocalOffHeapInput;
2530 }
2531
2532
2538 @Deprecated
2539 public long getMaxMemoryOffHeapInBytes() {
2540 return getMaxBytesLocalOffHeap();
2541 }
2542
2543
2546 public List getCacheEventListenerConfigurations() {
2547 return cacheEventListenerConfigurations;
2548 }
2549
2550
2555 public List getCacheExtensionConfigurations() {
2556 return cacheExtensionConfigurations;
2557 }
2558
2559
2564 public List getCacheLoaderConfigurations() {
2565 return cacheLoaderConfigurations;
2566 }
2567
2568
2573 public List<CacheDecoratorFactoryConfiguration> getCacheDecoratorConfigurations() {
2574 return cacheDecoratorConfigurations;
2575 }
2576
2577
2582 public BootstrapCacheLoaderFactoryConfiguration getBootstrapCacheLoaderFactoryConfiguration() {
2583 return bootstrapCacheLoaderFactoryConfiguration;
2584 }
2585
2586
2591 public CacheExceptionHandlerFactoryConfiguration getCacheExceptionHandlerFactoryConfiguration() {
2592 return cacheExceptionHandlerFactoryConfiguration;
2593 }
2594
2595
2600 public TerracottaConfiguration getTerracottaConfiguration() {
2601 return terracottaConfiguration;
2602 }
2603
2604
2609 public PinningConfiguration getPinningConfiguration() {
2610 return pinningConfiguration;
2611 }
2612
2613
2618 public CacheWriterConfiguration getCacheWriterConfiguration() {
2619 return cacheWriterConfiguration;
2620 }
2621
2622
2627 public boolean isTerracottaClustered() {
2628 return terracottaConfiguration != null && terracottaConfiguration.isClustered();
2629 }
2630
2631
2636 public Consistency getTerracottaConsistency() {
2637 return terracottaConfiguration != null ? terracottaConfiguration.getConsistency() : null;
2638 }
2639
2640
2645 public final TransactionalMode getTransactionalMode() {
2646 if (transactionalMode == null) {
2647 return DEFAULT_TRANSACTIONAL_MODE;
2648 }
2649 return transactionalMode;
2650 }
2651
2652
2657 public boolean isXaStrictTransactional() {
2658 validateTransactionalSettings();
2659 return getTransactionalMode().equals(TransactionalMode.XA_STRICT);
2660 }
2661
2662
2667 public boolean isLocalTransactional() {
2668 validateTransactionalSettings();
2669 return getTransactionalMode().equals(TransactionalMode.LOCAL);
2670 }
2671
2672
2677 public boolean isXaTransactional() {
2678 validateTransactionalSettings();
2679 return getTransactionalMode().equals(TransactionalMode.XA);
2680 }
2681
2682
2685 private static enum PoolUsage {
2686
2687 CacheManager(true), Cache(true), None(false);
2688
2689 private final boolean usingPool;
2690 private PoolUsage(final boolean poolUser) {
2691 this.usingPool = poolUser;
2692 }
2693
2694 public boolean isUsingPool() {
2695 return usingPool;
2696 }
2697 }
2698
2703 public static enum TransactionalMode {
2704
2705
2708 OFF(false),
2709
2710
2713 LOCAL(true),
2714
2715
2718 XA(true),
2719
2720
2723 XA_STRICT(true);
2724
2725 private final boolean transactional;
2726
2727
2730 TransactionalMode(final boolean transactional) {
2731 this.transactional = transactional;
2732 }
2733
2734
2737 public boolean isTransactional() {
2738 return transactional;
2739 }
2740 }
2741
2742
2748 public boolean addConfigurationListener(CacheConfigurationListener listener) {
2749 boolean added = listeners.add(listener);
2750 if (added) {
2751 listener.registered(this);
2752 }
2753 return added;
2754 }
2755
2756
2761 public boolean addDynamicSearchListener(DynamicSearchListener listener) {
2762 return dynamicSearchListeners.add(listener);
2763 }
2764
2765
2771 public boolean removeConfigurationListener(CacheConfigurationListener listener) {
2772 boolean removed = listeners.remove(listener);
2773 if (removed) {
2774 listener.deregistered(this);
2775 }
2776 return removed;
2777 }
2778
2779 private void fireTtiChanged(long oldTti, long newTti) {
2780 if (oldTti != newTti) {
2781 for (CacheConfigurationListener l : listeners) {
2782 l.timeToIdleChanged(oldTti, newTti);
2783 }
2784 }
2785 }
2786
2787 private void fireTtlChanged(long oldTtl, long newTtl) {
2788 if (oldTtl != newTtl) {
2789 for (CacheConfigurationListener l : listeners) {
2790 l.timeToLiveChanged(oldTtl, newTtl);
2791 }
2792 }
2793 }
2794
2795 private void fireLoggingChanged(boolean oldValue, boolean newValue) {
2796 if (oldValue != newValue) {
2797 for (CacheConfigurationListener l : listeners) {
2798 l.loggingChanged(oldValue, newValue);
2799 }
2800 }
2801 }
2802
2803 private void fireDiskCapacityChanged(int oldCapacity, int newCapacity) {
2804 if (oldCapacity != newCapacity) {
2805 for (CacheConfigurationListener l : listeners) {
2806 l.diskCapacityChanged(oldCapacity, newCapacity);
2807 }
2808 }
2809 }
2810
2811 private void fireMemoryCapacityChanged(int oldCapacity, int newCapacity) {
2812 if (oldCapacity != newCapacity) {
2813 for (CacheConfigurationListener l : listeners) {
2814 l.memoryCapacityChanged(oldCapacity, newCapacity);
2815 }
2816 }
2817 }
2818
2819 private void checkDynamicChange() {
2820 if (frozen) {
2821 throw new CacheException("Dynamic configuration changes are disabled for this cache");
2822 }
2823 }
2824
2825
2830 public void internalSetTimeToIdle(long timeToIdle) {
2831 this.timeToIdleSeconds = timeToIdle;
2832 }
2833
2834
2837 public void internalSetTimeToLive(long timeToLive) {
2838 this.timeToLiveSeconds = timeToLive;
2839 }
2840
2841
2844 public void internalSetMemCapacity(int capacity) {
2845 this.maxEntriesLocalHeap = capacity;
2846 }
2847
2848
2851 public void internalSetMemCapacityInBytes(long capacity) {
2852 this.maxBytesLocalHeap = capacity;
2853 }
2854
2855
2858 public void internalSetDiskCapacity(int capacity) {
2859 this.maxElementsOnDisk = capacity;
2860 }
2861
2862
2865 public void internalSetLogging(boolean logging) {
2866 this.logging = logging;
2867 }
2868
2869
2874 public Map<String, SearchAttribute> getSearchAttributes() {
2875 if (searchable == null) {
2876 return Collections.emptyMap();
2877 }
2878 return searchable.getSearchAttributes();
2879 }
2880
2881
2886 public Searchable getSearchable() {
2887 return searchable;
2888 }
2889
2890 }
2891