All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.terracotta.modules.ehcache.wan.WANUtil Maven / Gradle / Ivy

Go to download

Ehcache is an open source, standards-based cache used to boost performance, offload the database and simplify scalability. Ehcache is robust, proven and full-featured and this has made it the most widely-used Java-based cache.

There is a newer version: 2.10.9.2
Show newest version
/*
 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
 */
package org.terracotta.modules.ehcache.wan;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terracotta.modules.ehcache.ToolkitInstanceFactory;
import org.terracotta.toolkit.concurrent.locks.ToolkitLock;

import java.io.Serializable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

public class WANUtil {
  private static final int             WAIT_INTERVAL_FOR_ORCHESTRATOR_IN_SECONDS = 60;
  private static final Logger          LOGGER                                    = LoggerFactory.getLogger(WANUtil.class);
  private static final String          WAN_PREFIX                                = "__WAN__";
  private static final String          LOCK_PREFIX                               = WAN_PREFIX + "LOCK";
  private static final String          WAN_ENABLED_CACHE_ENTRY                   = WAN_PREFIX + "ENABLED_CACHE";
  private static final String          REPLICA_CACHE_FLAG                        = "IS_REPLICA";
  private static final String          META_DATA_AVAILABLE_FLAG                  = "WAN_META_DATA_AVAILABLE";
  private static final String          BIDIRECTIONAL_FLAG                        = "IS_BIDIRECTIONAL";
  private static final String          WAN_CURRENT_ORCHESTRATOR                  = WAN_PREFIX + "CURRENT_ORCHESTRATOR";

  private final ToolkitInstanceFactory factory;

  public WANUtil(ToolkitInstanceFactory factory) {
    this.factory = factory;
  }

  /**
   * This method marks that WAN meta-data is available for the given cacheManager
   * 
   * @param cacheManagerName name of the CacheManager
   */
  public void markWANReady(String cacheManagerName) {
    getCacheManagerConfigMap(cacheManagerName).put(META_DATA_AVAILABLE_FLAG, Boolean.TRUE);
    notifyClients(cacheManagerName);
  }

  /**
   * This method clears the WAN meta-data available status for the given cacheManager
   * 
   * @param cacheManagerName name of the CacheManager
   */
  public void clearWANReady(String cacheManagerName) {
    getCacheManagerConfigMap(cacheManagerName).put(META_DATA_AVAILABLE_FLAG, Boolean.FALSE);
  }

  /**
   * This method is used to check whether the WAN meta-data is available or not.
   * 
   * @param cacheManagerName
   * @return true if meta-data is available else false.
   */
  public boolean isWANReady(String cacheManagerName) {
    Boolean value = (Boolean) getCacheManagerConfigMap(cacheManagerName).get(META_DATA_AVAILABLE_FLAG);
    return (value == null) ? false : value;
  }

  /**
   * This method is used to wait until the Orchestrator is running.
   * 
   * @param cacheManagerName
   */
  public void waitForOrchestrator(String cacheManagerName) {
    if (!isWANReady(cacheManagerName)) {
      LOGGER.info("Waiting for the Orchestrator...");
      ToolkitLock toolkitLock = factory.getToolkit().getLock(LOCK_PREFIX + cacheManagerName);
      toolkitLock.lock();
      try {
        while (!isWANReady(cacheManagerName)) {
          try {
            boolean orchRunning = toolkitLock.getCondition().await(WAIT_INTERVAL_FOR_ORCHESTRATOR_IN_SECONDS,
                                                                 TimeUnit.SECONDS);
            if (!orchRunning) {
              LOGGER.error("No Orchestrator Running. We can not proceed further without an Orchestrator.");
            }
          } catch (InterruptedException e) {
            LOGGER.warn("Interrupted while waiting for the Orchestrator to be running.", e);
          }
        }
      } finally {
        toolkitLock.unlock();
      }
    }

    LOGGER.info("Orchestrator is available for the CacheManager '{}'", cacheManagerName);
  }

  /**
   * This method is used by Orchestrator to mark the cache as wan-enabled.
   * 
   * @param cacheManagerName
   * @param cacheName
   * @throws IllegalConfigurationException if the cache is already marked as wan disabled
   */
  public void markCacheWanEnabled(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    final Boolean existingValue = (Boolean) cacheConfigMap.putIfAbsent(WAN_ENABLED_CACHE_ENTRY, Boolean.TRUE);
    if ((existingValue != null) && (existingValue.equals(Boolean.FALSE))) {
      LOGGER.error("A Client with cache '{}' exists with non WAN configuration. "
                   + "Please check your client's ehcache.xml and add 'wanEnabledTSA = true'", cacheName);
      throw new IllegalConfigurationException("Cache '" + cacheName + "' is already marked as disabled for WAN");
    }
    LOGGER.info("Marked the cache '{}' wan enabled for CacheManager '{}'", cacheName, cacheManagerName);
  }

  public void markCacheAsReplica(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.put(REPLICA_CACHE_FLAG, Boolean.TRUE);
    LOGGER.info("Cache '{}' in CacheManager '{}' has been marked as a Replica", cacheName, cacheManagerName);
  }

  public void markCacheAsMaster(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.put(REPLICA_CACHE_FLAG, Boolean.FALSE);
    LOGGER.info("Cache '{}' in CacheManager '{}' has been marked as a Master", cacheName, cacheManagerName);
  }

  public boolean isCacheReplica(String cacheManagerName, String cacheName) {
    if (cacheName == null || cacheManagerName == null) {
      throw new IllegalArgumentException("Invalid arguments: CacheManagerName- " + cacheManagerName
                                         + " and CacheName- " + cacheName);
    }

    return (Boolean) getCacheConfigMap(cacheManagerName, cacheName).get(REPLICA_CACHE_FLAG);
  }

  public void markCacheAsBidirectional(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.put(BIDIRECTIONAL_FLAG, Boolean.TRUE);
    LOGGER.info("Cache '{}' in CacheManager '{}' has been marked as BIDIRECTIONAL", cacheName, cacheManagerName);
  }

  public void markCacheAsUnidirectional(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.put(BIDIRECTIONAL_FLAG, Boolean.FALSE);
    LOGGER.info("Cache '{}' in CacheManager '{}' has been marked as UNIDIRECTIONAL", cacheName, cacheManagerName);
  }

  public void addCurrentOrchestrator(String cacheManagerName, String cacheName, String orchestrator) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.put(WAN_CURRENT_ORCHESTRATOR, orchestrator);
    LOGGER.info("Added '{}' as orchestrator for Cache '{}' in CacheManager '{}'", orchestrator, cacheName, cacheManagerName);
  }

  public boolean isCacheBidirectional(String cacheManagerName, String cacheName) {
    if (cacheName == null || cacheManagerName == null) {
      throw new IllegalArgumentException("Invalid arguments: CacheManagerName- " + cacheManagerName
                                         + " and CacheName- " + cacheName);
    }

    return (Boolean) getCacheConfigMap(cacheManagerName, cacheName).get(BIDIRECTIONAL_FLAG);
  }

  /**
   * This method is used by Client to mark the cache as wan-disabled.
   * 
   * @param cacheName
   * @throws IllegalConfigurationException if the cache is already marked as wan enabled
   */
  public void markCacheWanDisabled(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    final Boolean existingValue = (Boolean) cacheConfigMap.putIfAbsent(WAN_ENABLED_CACHE_ENTRY, Boolean.FALSE);
    if ((existingValue != null) && (existingValue.equals(Boolean.TRUE))) {
      LOGGER.error("A WAN Orchestrator already exists for cache '{}'. This client should be wan-enabled. "
                   + "Please check your client's ehcache.xml and add 'wanEnabledTSA = true'", cacheName);
      throw new IllegalConfigurationException("Cache '" + cacheName + "' is already marked as enabled for WAN");
    }
    LOGGER.debug("Marked the cache '{}' wan disabled for CacheManager '{}'", cacheName, cacheManagerName);
  }

  /**
   * This method returns true if the cache is wan-enabled else false. This method should only be used by Client and not
   * by the Orchestrator.
   * 
   * @param cacheManagerName name of the CacheManager
   * @param cacheName name of the Cache
   */
  public boolean isWanEnabledCache(String cacheManagerName, String cacheName) {
    if (cacheName == null || cacheManagerName == null) {
      throw new IllegalArgumentException("Invalid arguments: CacheManagerName- " + cacheManagerName
                                         + " and CacheName- " + cacheName);
    }

    Boolean value = (Boolean) getCacheConfigMap(cacheManagerName, cacheName).get(WAN_ENABLED_CACHE_ENTRY);
    return (value == null) ? false : value;
  }

  /**
   * This method is used by clean-up scripts to clean the Cache status for WAN.
   * 
   * @param cacheManagerName name of the CacheManager
   * @param cacheName name of the Cache
   */
  public void cleanUpCacheMetaData(String cacheManagerName, String cacheName) {
    final ConcurrentMap cacheConfigMap = getCacheConfigMap(cacheManagerName, cacheName);
    cacheConfigMap.remove(WAN_ENABLED_CACHE_ENTRY);
    cacheConfigMap.remove(REPLICA_CACHE_FLAG);

    LOGGER.info("Cleaned up the metadata for cache '{}' for CacheManager '{}'", cacheName, cacheManagerName);
  }


  void notifyClients(String cacheManagerName) {
    ToolkitLock toolkitLock = factory.getToolkit().getLock(LOCK_PREFIX + cacheManagerName);
    toolkitLock.lock();
    try {
      toolkitLock.getCondition().signalAll();
    } finally {
      toolkitLock.unlock();
    }
  }

  ConcurrentMap getCacheConfigMap(String cacheManagerName, String cacheName) {
    return factory.getOrCreateClusteredStoreConfigMap(cacheManagerName, cacheName);
  }

  ConcurrentMap getCacheManagerConfigMap(String cacheManagerName) {
    return factory.getOrCreateCacheManagerMetaInfoMap(cacheManagerName);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy