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 org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /***
23 * Class to hold the Terracotta configuration - either a pointer to the real config or a
24 * container for embedded config.
25 *
26 * @author Alex Miller
27 * @author Geert Bevin
28 * @author Abhishek Sanoujam
29 */
30 public class TerracottaConfiguration implements Cloneable {
31
32 /***
33 * Default clustered mode
34 */
35 public static final boolean DEFAULT_CLUSTERED = true;
36 /***
37 * Default value mode
38 */
39 public static final ValueMode DEFAULT_VALUE_MODE = ValueMode.SERIALIZATION;
40 /***
41 * Default coherent read behavior
42 */
43 public static final boolean DEFAULT_COHERENT_READS = true;
44 /***
45 * Default xa enabled
46 */
47 public static final boolean DEFAULT_CACHE_XA = false;
48 /***
49 * Default orphan eviction status
50 */
51 public static final boolean DEFAULT_ORPHAN_EVICTION = true;
52 /***
53 * Default orphan eviction period
54 */
55 public static final int DEFAULT_ORPHAN_EVICTION_PERIOD = 4;
56 /***
57 * Default local key cache status
58 */
59 public static final boolean DEFAULT_LOCAL_KEY_CACHE = false;
60 /***
61 * Default local key cache size
62 */
63 public static final int DEFAULT_LOCAL_KEY_CACHE_SIZE = 300000;
64 /***
65 * Default copy on read setting
66 */
67 public static final boolean DEFAULT_COPY_ON_READ = false;
68
69 /***
70 * Default value for {@link NonstopConfiguration}
71 */
72 public static final NonstopConfiguration DEFAULT_NON_STOP_CONFIGURATION = new NonstopConfiguration().enabled(false);
73
74 /***
75 * Default cache coherence setting
76 *
77 * @deprecated since 2.4 Use {@link #DEFAULT_CONSISTENCY_TYPE} instead.
78 */
79 @Deprecated
80 public static final boolean DEFAULT_CACHE_COHERENT = true;
81
82 /***
83 * Default cache consistency setting
84 */
85 public static final Consistency DEFAULT_CONSISTENCY_TYPE = Consistency.EVENTUAL;
86
87 /***
88 * Default setting for synchronous-write
89 */
90 public static final boolean DEFAULT_SYNCHRONOUS_WRITES = false;
91
92 /***
93 * Default setting for storageStrategy
94 */
95 public static final StorageStrategy DEFAULT_STORAGE_STRATEGY = StorageStrategy.DCV2;
96
97 /***
98 * Default value for concurrency of the internal Store.
99 */
100 public static final int DEFAULT_CONCURRENCY = 0;
101
102
103 /***
104 * Default value for whether local cache is enabled or not
105 */
106 public static final boolean DEFAULT_LOCAL_CACHE_ENABLED = true;
107
108 /***
109 * Represents whether values are stored with serialization in the clustered store
110 * or through Terracotta clustered identity.
111 *
112 * @author amiller
113 */
114 public static enum ValueMode {
115 /***
116 * When a key or value is put in the cache, serialize the data for sending around the cluster
117 */
118 SERIALIZATION,
119
120 /***
121 * Use Terracotta clustered identity to preserve object identity without serialization
122 */
123 IDENTITY,
124 }
125
126 /***
127 * Represents whether keys/values are to be stored in the local vm or the Terracotta server
128 *
129 * @author Abhishek Sanoujam
130 */
131 public static enum StorageStrategy {
132 /***
133 * Store the key/values in the local vm
134 */
135 CLASSIC,
136
137 /***
138 * Store the key/values in the Terracotta Server
139 */
140 DCV2,
141 }
142
143 private static final Logger LOG = LoggerFactory.getLogger(TerracottaConfiguration.class.getName());
144
145 private boolean clustered = DEFAULT_CLUSTERED;
146 private ValueMode valueMode = DEFAULT_VALUE_MODE;
147 private boolean coherentReads = DEFAULT_COHERENT_READS;
148 private boolean orphanEviction = DEFAULT_ORPHAN_EVICTION;
149 private int orphanEvictionPeriod = DEFAULT_ORPHAN_EVICTION_PERIOD;
150 private boolean localKeyCache = DEFAULT_LOCAL_KEY_CACHE;
151 private int localKeyCacheSize = DEFAULT_LOCAL_KEY_CACHE_SIZE;
152 private boolean isCopyOnRead = DEFAULT_COPY_ON_READ;
153 private boolean cacheXA = DEFAULT_CACHE_XA;
154 private boolean synchronousWrites = DEFAULT_SYNCHRONOUS_WRITES;
155 private StorageStrategy storageStrategy = DEFAULT_STORAGE_STRATEGY;
156 private int concurrency = DEFAULT_CONCURRENCY;
157 private NonstopConfiguration nonStopConfiguration = DEFAULT_NON_STOP_CONFIGURATION;
158
159 private boolean copyOnReadSet;
160 private volatile boolean storageStrategySet;
161 private Consistency consistency = DEFAULT_CONSISTENCY_TYPE;
162 private volatile boolean localCacheEnabled = DEFAULT_LOCAL_CACHE_ENABLED;
163
164 /***
165 * Clones this object, following the usual contract.
166 *
167 * @return a copy, which independent other than configurations than cannot change.
168 */
169 @Override
170 public TerracottaConfiguration clone() {
171 try {
172 TerracottaConfiguration clone = (TerracottaConfiguration) super.clone();
173 if (nonStopConfiguration != null) {
174 clone.nonstop(this.nonStopConfiguration.clone());
175 }
176 return clone;
177 } catch (CloneNotSupportedException e) {
178 throw new RuntimeException(e);
179 }
180 }
181
182 /***
183 * Indicates whether to cluster this cache with Terracotta.
184 * <p/>
185 * Defaults to {@value #DEFAULT_CLUSTERED}.
186 *
187 * @param clustered
188 * {@code true} if the cache should be clustered with Terracotta; {@code false} otherwise
189 */
190 public void setClustered(boolean clustered) {
191 this.clustered = clustered;
192 }
193
194 /***
195 * @return this configuration instance
196 * @see #setClustered(boolean)
197 */
198 public TerracottaConfiguration clustered(boolean clustered) {
199 setClustered(clustered);
200 return this;
201 }
202
203 /***
204 * Check whether clustering is enabled
205 */
206 public boolean isClustered() {
207 return this.clustered;
208 }
209
210 /***
211 * Used by BeanHandler to set the copyOnRead flag during parsing
212 */
213 public void setCopyOnRead(boolean isCopyOnRead) {
214 LOG.warn("copyOnRead is deprecated on the <terracotta /> element, "
215 + "please use the copyOnRead attribute on <cache /> or <defaultCache />");
216 this.copyOnReadSet = true;
217 this.isCopyOnRead = isCopyOnRead;
218 }
219
220 /***
221 * Whether the copyOnRead was explicitly set
222 *
223 * @return true if set by config
224 */
225 boolean isCopyOnReadSet() {
226 return copyOnReadSet;
227 }
228
229 /***
230 * @return this configuration instance
231 * @see #setCopyOnRead(boolean)
232 */
233 public TerracottaConfiguration copyOnRead(boolean isCopyOnRead) {
234 setCopyOnRead(isCopyOnRead);
235 return this;
236 }
237
238 /***
239 * Check whether the [serialized value] cache is an XA enabled cache
240 */
241 public boolean isCacheXA() {
242 return this.cacheXA;
243 }
244
245 /***
246 * Used by BeanHandler to set the cacheXA flag during parsing
247 */
248 public void setCacheXA(boolean cacheXA) {
249 this.cacheXA = cacheXA;
250 }
251
252 /***
253 * @return this configuration instance
254 * @see #setCacheXA(boolean)
255 */
256 public TerracottaConfiguration cacheXA(boolean cacheXA) {
257 setCacheXA(cacheXA);
258 return this;
259 }
260
261 /***
262 * Check whether the [serialized value] cache should use copy on read semantics
263 */
264 public boolean isCopyOnRead() {
265 return this.isCopyOnRead;
266 }
267
268 /***
269 * Sets whether this cache should use coherent reads (usually should be {@value #DEFAULT_COHERENT_READS} unless optimizing for
270 * read-only).
271 * <p/>
272 * Defaults to {@value #DEFAULT_COHERENT_READS}.
273 *
274 * @param coherentReads
275 * {@code true} if coherent reads should be used; {@code false} otherwise
276 */
277 public void setCoherentReads(boolean coherentReads) {
278 LOG.warn("The attribute \"coherentReads\" in \"terracotta\" element is deprecated."
279 + " Please use the new \"coherent\" attribute instead.");
280 this.coherentReads = coherentReads;
281 }
282
283 /***
284 * @return this configuration instance
285 * @see #setCoherentReads(boolean)
286 */
287 public TerracottaConfiguration coherentReads(boolean coherentReads) {
288 setCoherentReads(coherentReads);
289 return this;
290 }
291
292 /***
293 * Check whether coherent reads are enabled
294 */
295 public boolean getCoherentReads() {
296 return this.coherentReads;
297 }
298
299 /***
300 * Converts the {@code valueMode} string argument to uppercase and looks up enum constant in ValueMode.
301 */
302 public void setValueMode(String valueMode) {
303 if (valueMode == null) {
304 throw new IllegalArgumentException("Value mode must be non-null");
305 }
306 this.valueMode = ValueMode.valueOf(ValueMode.class, valueMode.toUpperCase());
307 }
308
309 /***
310 * @return this configuration instance
311 * @see #setValueMode(String)
312 */
313 public TerracottaConfiguration valueMode(String valueMode) {
314 setValueMode(valueMode);
315 return this;
316 }
317
318 /***
319 * @return this configuration instance
320 * @see #setValueMode(String)
321 */
322 public TerracottaConfiguration valueMode(ValueMode valueMode) {
323 if (valueMode == null) {
324 throw new IllegalArgumentException("Value mode must be non-null");
325 }
326 this.valueMode = valueMode;
327 return this;
328 }
329
330 /***
331 * Get the value mode in terms of the mode enum
332 */
333 public ValueMode getValueMode() {
334 return this.valueMode;
335 }
336
337 /***
338 * Sets whether this cache should perform orphan eviction (usually should be {@value #DEFAULT_ORPHAN_EVICTION}).
339 * <p/>
340 * Orphans are elements that are not present on any node in the cluster anymore and hence need additional routines to be detected since
341 * they're not locally available anywhere.
342 * <p/>
343 * Defaults to {@value #DEFAULT_ORPHAN_EVICTION}.
344 *
345 * @param orphanEviction
346 * {@code true} if orphan eviction should be used; {@code false} otherwise
347 */
348 public void setOrphanEviction(boolean orphanEviction) {
349 this.orphanEviction = orphanEviction;
350 }
351
352 /***
353 * @return this configuration instance
354 * @see #setOrphanEviction(boolean)
355 */
356 public TerracottaConfiguration orphanEviction(boolean orphanEviction) {
357 setOrphanEviction(orphanEviction);
358 return this;
359 }
360
361 /***
362 * Check whether orphan eviction is enabled
363 */
364 public boolean getOrphanEviction() {
365 return this.orphanEviction;
366 }
367
368 /***
369 * Set how often this cache should perform orphan eviction (measured in regular eviction periods).
370 * <p/>
371 * Defaults to {@value #DEFAULT_ORPHAN_EVICTION_PERIOD}).
372 *
373 * @param orphanEvictionPeriod
374 * every how many regular evictions an orphan eviction should occur
375 */
376 public void setOrphanEvictionPeriod(int orphanEvictionPeriod) {
377 this.orphanEvictionPeriod = orphanEvictionPeriod;
378 }
379
380 /***
381 * @return this configuration instance
382 * @see #setOrphanEvictionPeriod(int)
383 */
384 public TerracottaConfiguration orphanEvictionPeriod(int orphanEvictionPeriod) {
385 setOrphanEvictionPeriod(orphanEvictionPeriod);
386 return this;
387 }
388
389 /***
390 * Get the number of regular eviction cycles between orphan evictions
391 */
392 public int getOrphanEvictionPeriod() {
393 return this.orphanEvictionPeriod;
394 }
395
396 /***
397 * Sets whether this cache should use an unclustered local key cache (usually should be {@value #DEFAULT_LOCAL_KEY_CACHE} unless
398 * optimizing for a small read-only cache)
399 * <p/>
400 * Defaults to {@value #DEFAULT_LOCAL_KEY_CACHE}.
401 *
402 * @param localKeyCache
403 * {@code true} if a local key cache should be used; {@code false} otherwise
404 */
405 public void setLocalKeyCache(boolean localKeyCache) {
406 this.localKeyCache = localKeyCache;
407 }
408
409 /***
410 * @return this configuration instance
411 * @see #setLocalKeyCache(boolean)
412 */
413 public TerracottaConfiguration localKeyCache(boolean localKeyCache) {
414 setLocalKeyCache(localKeyCache);
415 return this;
416 }
417
418 /***
419 * Check whether the local key cache is enabled
420 */
421 public boolean getLocalKeyCache() {
422 return this.localKeyCache;
423 }
424
425 /***
426 * Sets maximum size of the local key cache (usually the size of the key set of the cache or cache partition).
427 * <p/>
428 * Defaults to {@value #DEFAULT_LOCAL_KEY_CACHE_SIZE}.
429 *
430 * @param localKeyCacheSize
431 * the size of the local key cache in number of keys
432 */
433 public void setLocalKeyCacheSize(int localKeyCacheSize) {
434 this.localKeyCacheSize = localKeyCacheSize;
435 }
436
437 /***
438 * @return this configuration instance
439 * @see #setLocalKeyCacheSize(int)
440 */
441 public TerracottaConfiguration localKeyCacheSize(int localKeyCacheSize) {
442 setLocalKeyCacheSize(localKeyCacheSize);
443 return this;
444 }
445
446 /***
447 * Get the size limit of the local key cache (if enabled)
448 */
449 public int getLocalKeyCacheSize() {
450 return this.localKeyCacheSize;
451 }
452
453 /***
454 * Used by BeanHandler to set the <tt>coherent</tt> during parsing
455 *
456 * @deprecated since 2.4 Use {@link #setConsistency(Consistency)} instead
457 */
458 @Deprecated
459 public void setCoherent(boolean coherent) {
460 Consistency consistencyType = coherent ? Consistency.STRONG : Consistency.EVENTUAL;
461 this.consistency(consistencyType);
462 }
463
464 /***
465 * @return this configuration instance
466 * @deprecated since 2.4 Use {@link #consistency(Consistency)} instead
467 */
468 @Deprecated
469 public TerracottaConfiguration coherent(boolean coherent) {
470 Consistency consistencyType = coherent ? Consistency.STRONG : Consistency.EVENTUAL;
471 this.consistency(consistencyType);
472 return this;
473 }
474
475 /***
476 * Is the cache configured for coherent or incoherent mode.
477 *
478 * @return true if configured in coherent mode.
479 * @deprecated since 2.4 Use {@link #getConsistency()} instead to query the {@link Consistency} or Ehcache#isNodeCoherent()
480 * to query if the node is coherent
481 */
482 @Deprecated
483 public boolean isCoherent() {
484 return consistency == Consistency.STRONG;
485 }
486
487 /***
488 * Is the cache configured for synchronous-write?
489 *
490 * @return true if configured for synchronouse-write, otherwise false. Default is false
491 */
492 public boolean isSynchronousWrites() {
493 return synchronousWrites;
494 }
495
496 /***
497 * Set the value for synchronous-write
498 *
499 * @param synchronousWrites
500 * true for using synchronous-write
501 */
502 public void setSynchronousWrites(boolean synchronousWrites) {
503 this.synchronousWrites = synchronousWrites;
504 }
505
506 /***
507 * @return this configuration instance
508 * @see #setSynchronousWrites(boolean)
509 */
510 public TerracottaConfiguration synchronousWrites(boolean synchronousWrites) {
511 setSynchronousWrites(synchronousWrites);
512 return this;
513 }
514
515 /***
516 * Converts the {@code storageStrategy} string argument to uppercase and looks up enum constant in StorageStrategy.
517 */
518 public void setStorageStrategy(String storageStrategy) {
519 if (storageStrategy == null) {
520 throw new IllegalArgumentException("Storage Strategy must be non-null");
521 }
522 this.storageStrategy(StorageStrategy.valueOf(StorageStrategy.class, storageStrategy.toUpperCase()));
523 }
524
525 /***
526 * @return this configuration instance
527 * @see #setStorageStrategy(String)
528 */
529 public TerracottaConfiguration storageStrategy(String storageStrategy) {
530 setStorageStrategy(storageStrategy);
531 return this;
532 }
533
534 /***
535 * @return this configuration instance
536 * @see #setStorageStrategy(String)
537 */
538 public TerracottaConfiguration storageStrategy(StorageStrategy storageStrategy) {
539 if (storageStrategy == null) {
540 throw new IllegalArgumentException("Storage Strategy must be non-null");
541 }
542 this.storageStrategy = storageStrategy;
543 this.storageStrategySet = true;
544 return this;
545 }
546
547 /***
548 * Returns true is storageStrategy is set explicitly
549 *
550 * @return true is storageStrategy is set explicitly
551 */
552 public boolean isStorageStrategySet() {
553 return storageStrategySet;
554 }
555
556 /***
557 * Get the value mode in terms of the mode enum
558 */
559 public StorageStrategy getStorageStrategy() {
560 return this.storageStrategy;
561 }
562
563 /***
564 * @return this configuration instance
565 * @see #setConcurrency(int)
566 */
567 public TerracottaConfiguration concurrency(final int concurrency) {
568 setConcurrency(concurrency);
569 return this;
570 }
571
572 /***
573 * Sets the value of concurrency. Throws {@link IllegalArgumentException} if the value is less than 0.
574 * This value cannot be changed once cache is initialized.
575 */
576 public void setConcurrency(final int concurrency) {
577 if (concurrency < 0) {
578 throw new IllegalArgumentException("Only non-negative integers allowed");
579 }
580 this.concurrency = concurrency;
581 }
582
583 /***
584 * Get the value of concurrency.
585 * This value cannot be changed once cache is initialized.
586 */
587 public int getConcurrency() {
588 return this.concurrency;
589 }
590
591 /***
592 * Add the {@link NonstopConfiguration}
593 *
594 * @param nonstopConfiguration
595 */
596 public void addNonstop(NonstopConfiguration nonstopConfiguration) {
597 this.nonStopConfiguration = nonstopConfiguration;
598 }
599
600 /***
601 * Set the {@link NonstopConfiguration}
602 *
603 * @param nonstopConfiguration
604 * @return this configuration instance
605 */
606 public TerracottaConfiguration nonstop(NonstopConfiguration nonstopConfiguration) {
607 this.addNonstop(nonstopConfiguration);
608 return this;
609 }
610
611 /***
612 * Get the {@link NonstopConfiguration}, may be null
613 *
614 * @return the {@link NonstopConfiguration}, may be null
615 */
616 public NonstopConfiguration getNonstopConfiguration() {
617 return nonStopConfiguration;
618 }
619
620 /***
621 * Returns true if nonstop is enabled
622 *
623 * @return true if nonstop is enabled
624 */
625 public boolean isNonstopEnabled() {
626 return nonStopConfiguration != null && nonStopConfiguration.isEnabled();
627 }
628
629 /***
630 * Setter for consistency, returns this instance
631 *
632 * @param consistency
633 * @return this instance
634 */
635 public TerracottaConfiguration consistency(Consistency consistency) {
636 setConsistency(consistency);
637 return this;
638 }
639
640 /***
641 * Setter for consistency
642 *
643 * @param consistency
644 */
645 public void setConsistency(Consistency consistency) {
646 this.consistency = consistency;
647 }
648
649 /***
650 * Setter for consistency
651 *
652 * @param consistency
653 */
654 public void setConsistency(String consistency) {
655 if (consistency == null) {
656 throw new IllegalArgumentException("Consistency cannot be null");
657 }
658 this.setConsistency(Consistency.valueOf(consistency.toUpperCase()));
659 }
660
661 /***
662 * Getter for consistency
663 *
664 * @return the consistency
665 */
666 public Consistency getConsistency() {
667 return this.consistency;
668 }
669
670 /***
671 * Returns true if local cache is enabled, otherwise false
672 * @return true if local cache is enabled, otherwise false
673 */
674 public boolean isLocalCacheEnabled() {
675 return localCacheEnabled;
676 }
677
678 /***
679 * Enable or disable the local cache
680 * @param localCacheEnabled
681 */
682 public void setLocalCacheEnabled(final boolean localCacheEnabled) {
683 this.localCacheEnabled = localCacheEnabled;
684 }
685
686
687 /***
688 * Enable or disable the local cache
689 * @param localCacheEnabled
690 * @return this instance
691 */
692 public TerracottaConfiguration localCacheEnabled(final boolean localCacheEnabled) {
693 setLocalCacheEnabled(localCacheEnabled);
694 return this;
695 }
696
697 /***
698 * Enum for various consistency settings
699 *
700 * @author Abhishek Sanoujam
701 *
702 */
703 public static enum Consistency {
704 /***
705 * Strong consistency
706 */
707 STRONG,
708 /***
709 * Eventual consistency
710 */
711 EVENTUAL;
712 }
713 }