@Test public void testConfigFileHonorsClusteringOff() { final CacheManager cacheManager = new CacheManager( CacheManager.class.getResourceAsStream("/terracotta/ehcache-event-replication.xml")); try { final Cache cache = cacheManager.getCache("replication"); assertThat(cache, notNullValue()); final TerracottaConfiguration terracottaConfiguration = cache.getCacheConfiguration().getTerracottaConfiguration(); assertThat(terracottaConfiguration, notNullValue()); assertThat(terracottaConfiguration.isClustered(), is(false)); final List eventListenerConfigurations = cache.getCacheConfiguration().getCacheEventListenerConfigurations(); assertThat(eventListenerConfigurations, notNullValue()); assertThat(eventListenerConfigurations.size(), is(1)); assertThat( ((CacheConfiguration.CacheEventListenerFactoryConfiguration) eventListenerConfigurations.get(0)) .getFullyQualifiedClassPath(), equalTo(TerracottaCacheEventReplicationFactory.class.getName())); cache.put(new Element("key", "value")); assertThat((String) cache.get("key").getValue(), equalTo("value")); } finally { cacheManager.shutdown(); } }
/** * Clones this object, following the usual contract. * * @return a copy, which independent other than configurations than cannot change. */ @Override public TerracottaConfiguration clone() { try { TerracottaConfiguration clone = (TerracottaConfiguration) super.clone(); if (nonStopConfiguration != null) { clone.nonstop(this.nonStopConfiguration.clone()); } return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } }
/** * Create a cache given a cache configuration * * @param cacheConfiguration */ final Ehcache createCache(CacheConfiguration cacheConfiguration) { boolean terracottaClustered = false; String terracottaValueMode = null; boolean terracottaCoherentReads = true; TerracottaConfiguration tcConfiguration = cacheConfiguration.getTerracottaConfiguration(); if (tcConfiguration != null) { terracottaClustered = tcConfiguration.isClustered(); terracottaValueMode = tcConfiguration.getValueMode().name(); terracottaCoherentReads = tcConfiguration.getCoherentReads(); } Ehcache cache = new Cache( cacheConfiguration.name, cacheConfiguration.maxElementsInMemory, cacheConfiguration.memoryStoreEvictionPolicy, cacheConfiguration.overflowToDisk, getDiskStorePath(), cacheConfiguration.eternal, cacheConfiguration.timeToLiveSeconds, cacheConfiguration.timeToIdleSeconds, cacheConfiguration.diskPersistent, cacheConfiguration.diskExpiryThreadIntervalSeconds, null, null, cacheConfiguration.maxElementsOnDisk, cacheConfiguration.diskSpoolBufferSizeMB, cacheConfiguration.clearOnFlush, terracottaClustered, terracottaValueMode, terracottaCoherentReads); RegisteredEventListeners listeners = cache.getCacheEventNotificationService(); registerCacheListeners(cacheConfiguration, listeners); registerCacheExtensions(cacheConfiguration, cache); BootstrapCacheLoader bootstrapCacheLoader = createBootstrapCacheLoader( cacheConfiguration.getBootstrapCacheLoaderFactoryConfiguration()); cache.setBootstrapCacheLoader(bootstrapCacheLoader); registerCacheLoaders(cacheConfiguration, cache); cache = applyCacheExceptionHandler(cacheConfiguration, cache); return cache; }
/** * Validates that the supplied Ehcache instance is valid for use as a Hibernate cache. * * @param cache The cache instance * @throws CacheException If any explicit settings on the cache are not validate */ public static void validateEhcache(Ehcache cache) throws CacheException { final CacheConfiguration cacheConfig = cache.getCacheConfiguration(); if (cacheConfig.isTerracottaClustered()) { final TerracottaConfiguration tcConfig = cacheConfig.getTerracottaConfiguration(); switch (tcConfig.getValueMode()) { case IDENTITY: { throw new CacheException( "The clustered Hibernate cache " + cache.getName() + " is using IDENTITY value mode.\n" + "Identity value mode cannot be used with Hibernate cache regions."); } case SERIALIZATION: default: { // this is the recommended valueMode break; } } } }
private void init() { if (tcConfiguration == null) { return; } if (!TerracottaConfiguration.DEFAULT_NON_STOP_CONFIGURATION.equals( tcConfiguration.getNonstopConfiguration())) { this.addChildElement( new NonstopConfigurationElement(this, tcConfiguration.getNonstopConfiguration())); } addAttribute( new SimpleNodeAttribute("clustered", tcConfiguration.isClustered()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_CLUSTERED)); addAttribute( new SimpleNodeAttribute("valueMode", tcConfiguration.getValueMode()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_VALUE_MODE)); addAttribute( new SimpleNodeAttribute("consistency", tcConfiguration.getConsistency().name()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_CONSISTENCY_TYPE.name())); addAttribute( new SimpleNodeAttribute("synchronousWrites", tcConfiguration.isSynchronousWrites()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_SYNCHRONOUS_WRITES)); addAttribute( new SimpleNodeAttribute("copyOnRead", tcConfiguration.isCopyOnRead()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_COPY_ON_READ)); addAttribute( new SimpleNodeAttribute("localKeyCache", tcConfiguration.getLocalKeyCache()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_LOCAL_KEY_CACHE)); addAttribute( new SimpleNodeAttribute("localKeyCacheSize", tcConfiguration.getLocalKeyCacheSize()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_LOCAL_KEY_CACHE_SIZE)); addAttribute( new SimpleNodeAttribute("orphanEviction", tcConfiguration.getOrphanEviction()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_ORPHAN_EVICTION)); addAttribute( new SimpleNodeAttribute("orphanEvictionPeriod", tcConfiguration.getOrphanEvictionPeriod()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_ORPHAN_EVICTION_PERIOD)); addAttribute( new SimpleNodeAttribute("coherentReads", tcConfiguration.getCoherentReads()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_COHERENT_READS)); addAttribute( new SimpleNodeAttribute("concurrency", tcConfiguration.getConcurrency()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_CONCURRENCY)); addAttribute( new SimpleNodeAttribute("localCacheEnabled", tcConfiguration.isLocalCacheEnabled()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_LOCAL_CACHE_ENABLED)); addAttribute( new SimpleNodeAttribute("compressionEnabled", tcConfiguration.isCompressionEnabled()) .optional(true) .defaultValue(TerracottaConfiguration.DEFAULT_COMPRESSION_ENABLED)); }
private void initSupportCache() { // create the support cache // make this cache clustered in the same way as the underlying cache, this.supportConfig = new CacheConfiguration(); supportConfig.name( underlyingCache.getName() + "_" + getClass().getName() + "_refreshAheadSupport"); supportConfig = supportConfig.persistence(new PersistenceConfiguration().strategy(Strategy.NONE)); int activeSize = 2 * refreshAheadConfig.getBatchSize() * refreshAheadConfig.getNumberOfThreads(); supportConfig = supportConfig.maxEntriesLocalHeap(activeSize); supportConfig = supportConfig.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU); supportConfig = supportConfig.timeToLiveSeconds(DEFAULT_SUPPORT_TTL_SECONDS); // TC stuff if (underlyingCache.getCacheConfiguration().isTerracottaClustered()) { supportConfig = supportConfig.persistence(new PersistenceConfiguration().strategy(Strategy.DISTRIBUTED)); TerracottaConfiguration newTerracottaConfig = new TerracottaConfiguration().clustered(true); newTerracottaConfig.consistency(Consistency.STRONG); supportConfig.addTerracotta(newTerracottaConfig); } else { supportConfig.setMaxElementsOnDisk(activeSize); } // here we try to create the support cache. this.supportCache = new Cache(supportConfig); Ehcache prior = underlyingCache.getCacheManager().addCacheIfAbsent(supportCache); if (prior != supportCache) { throw new IllegalStateException( "Unable to add refresh ahead support cache due to name collision: " + refreshAheadConfig.getName()); } // wipe it on startup. might wobble in a clustered case, but clears out orphans. prior.removeAll(); // catch the dispose. not sure this is the best way to do it at all. // we could register a listener alternatively underlyingCache.registerCacheExtension( new CacheExtension() { @Override public void init() {} @Override public Status getStatus() { return underlyingCache.getStatus(); } @Override public void dispose() throws CacheException { RefreshAheadCache.this.localDispose(); } @Override public CacheExtension clone(Ehcache cache) throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }); }