Package com.dotmarketing.business

Source Code of com.dotmarketing.business.DotGuavaCacheAdministratorImpl$DotRemoval

/**
*
*/
package com.dotmarketing.business;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

import com.dotcms.cluster.bean.Server;
import com.dotcms.cluster.bean.ServerPort;
import com.dotcms.cluster.business.ServerAPI;
import com.dotcms.enterprise.cluster.ClusterFactory;
import com.dotcms.repackage.com.google.common.cache.Cache;
import com.dotcms.repackage.com.google.common.cache.CacheBuilder;
import com.dotcms.repackage.com.google.common.cache.RemovalListener;
import com.dotcms.repackage.com.google.common.cache.RemovalNotification;
import com.dotcms.repackage.edu.emory.mathcs.backport.java.util.Collections;
import com.dotcms.repackage.org.apache.commons.collections.map.LRUMap;
import com.dotcms.repackage.org.apache.struts.Globals;
import com.dotcms.repackage.org.jboss.cache.Fqn;
import com.dotcms.repackage.org.jgroups.Address;
import com.dotcms.repackage.org.jgroups.ChannelClosedException;
import com.dotcms.repackage.org.jgroups.ChannelNotConnectedException;
import com.dotcms.repackage.org.jgroups.Event;
import com.dotcms.repackage.org.jgroups.JChannel;
import com.dotcms.repackage.org.jgroups.Message;
import com.dotcms.repackage.org.jgroups.PhysicalAddress;
import com.dotcms.repackage.org.jgroups.ReceiverAdapter;
import com.dotcms.repackage.org.jgroups.View;
import com.dotmarketing.cache.H2CacheLoader;
import com.dotmarketing.common.business.journal.DistributedJournalAPI;
import com.dotmarketing.db.DbConnectionFactory;
import com.dotmarketing.db.HibernateUtil;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.menubuilders.RefreshMenus;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import com.dotmarketing.velocity.DotResourceCache;
import com.liferay.portal.struts.MultiMessageResources;

/**
* The Guava cache administrator uses Google's Guave code
* under the covers and gets it's startup params from the dotmarketing-config.properties
* on a put where the non legacy one will not.
*
* @author Jason Tesser
* @version 1.6.5
*
*/
public class DotGuavaCacheAdministratorImpl extends ReceiverAdapter implements DotCacheAdministrator {

  private DistributedJournalAPI journalAPI;
  private final ConcurrentHashMap<String, Cache<String, Object>> groups = new ConcurrentHashMap<String, Cache<String, Object>>();
  private JChannel channel;
  private boolean useJgroups = false;
  private final ConcurrentHashMap<String, Boolean> cacheToDisk = new ConcurrentHashMap<String, Boolean>();
  private final HashSet<String> availableCaches = new HashSet<String>();
  private H2CacheLoader diskCache = null;

  static final String LIVE_CACHE_PREFIX = "livecache";
  static final String WORKING_CACHE_PREFIX = "workingcache";
  static final String DEFAULT_CACHE = "default";
  public static final String TEST_MESSAGE = "HELLO CLUSTER!";
  static final String VALIDATE_CACHE = "validateCacheInCluster-";
  static final String VALIDATE_CACHE_RESPONSE = "validateCacheInCluster-response-";
  static final String VALIDATE_SEPARATOR = "_";
  static final String DUMMY_TEXT_TO_SEND = "DUMMY MSG TO TEST SEND";
 
  private NullCallable nullCallable = new NullCallable();
 
  //Map<DateInMillis, Map<ServerID, True>>
  private Map<String, Map<String, Boolean>> cacheStatus;

  private boolean isDiskCache(String group){
    if(group ==null || diskCache==null){
      return false;
    }
    group = group.toLowerCase();
    Boolean ret = cacheToDisk.get(group);
    if(ret == null) {
      if(Config.containsProperty("cache." + group + ".disk")){
        ret = Config.getBooleanProperty("cache." + group + ".disk", false);
      }
      else if(group.startsWith(LIVE_CACHE_PREFIX) && Config.containsProperty("cache." + LIVE_CACHE_PREFIX + ".disk")){
        ret = Config.getBooleanProperty("cache."+LIVE_CACHE_PREFIX+".disk", false);
      }
      else if(group.startsWith(WORKING_CACHE_PREFIX) && Config.containsProperty("cache." + WORKING_CACHE_PREFIX + ".disk")){
        ret = Config.getBooleanProperty("cache." + WORKING_CACHE_PREFIX + ".disk", false);
      }
      /*
      else if (group.startsWith("velocitymenucache")) {
        ret = false;
      }

      else if (group.startsWith("velocitycache")) {
         ret = false;
      }
      */
      else{
        ret = Config.getBooleanProperty("cache.default.disk", false);
      }
      cacheToDisk.put(group, ret);
    }

    return ret;

  }

  public DotGuavaCacheAdministratorImpl() {
    journalAPI = APILocator.getDistributedJournalAPI();



        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();


    boolean initDiskCache = false;
    Iterator<String> it = Config.getKeys();
    availableCaches.add(DEFAULT_CACHE);
    while(it.hasNext()){
      String key = it.next();
      if(key ==null){
        continue;
      }
      if(key.startsWith("cache.")){
        String cacheName = key.split("\\.")[1];
        if(key.endsWith(".size")){
          int inMemory = Config.getIntProperty(key, 0);
          availableCaches.add(cacheName.toLowerCase());
          Logger.info(this.getClass(), "***\t Cache Config Memory : " +  cacheName + ": " + inMemory  );
        }
        if(key.endsWith(".disk")){
          boolean useDisk = Config.getBooleanProperty(key, false);
          if(useDisk){
            initDiskCache =true;
            Logger.info(this.getClass(), "***\t Cache Config Disk   : " + cacheName  + ": true");
          }
        }

      }
    }
    if(initDiskCache){
      try{
        diskCache = H2CacheLoader.getInstance();
      }
      catch(Exception e){
        Logger.error(this.getClass(), "***\t Unable to start disk cache: " + e.getMessage(), e);
        cacheToDisk.clear();
      }
    }
   
    cacheStatus = new LRUMap(100);
  }

  public void setCluster(Server localServer) throws Exception {
    setCluster(null, localServer);
  }

  public void setCluster(Map<String, String> cacheProperties, Server localServer) throws Exception {
      Logger.info(this, "***\t Starting JGroups Cluster Setup");

      journalAPI = APILocator.getDistributedJournalAPI();

      if(cacheProperties==null) {
        cacheProperties = new HashMap<String, String>();
      }
     
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      ServerAPI serverAPI = APILocator.getServerAPI();
     
      String cacheProtocol, bindAddr, bindPort, cacheTCPInitialHosts, mCastAddr, mCastPort, preferIPv4;
      if(Config.getBooleanProperty("CLUSTER_AUTOWIRE",true)) {
          Logger.info(this, "Using automatic port placement as CLUSTER_AUTOWIRE is ON");
         
          cacheProtocol = UtilMethods.isSet(cacheProperties.get("CACHE_PROTOCOL"))?cacheProperties.get("CACHE_PROTOCOL")
                      :Config.getStringProperty("CACHE_PROTOCOL", "tcp");
         
          String storedBindAddr = (UtilMethods.isSet(localServer.getHost()) && !localServer.getHost().equals("localhost"))
                      ?localServer.getHost():localServer.getIpAddress();
              bindAddr = UtilMethods.isSet(cacheProperties.get("BIND_ADDRESS"))?cacheProperties.get("BIND_ADDRESS")
                      :Config.getStringProperty("CACHE_BINDADDRESS", storedBindAddr );
             
              bindPort = UtilMethods.isSet(cacheProperties.get("CACHE_BINDPORT"))?cacheProperties.get("CACHE_BINDPORT")
                      :localServer!=null&&UtilMethods.isSet(localServer.getCachePort())?Long.toString(localServer.getCachePort())
                      :ClusterFactory.getNextAvailablePort(localServer.getServerId(), ServerPort.CACHE_PORT);
                     
                localServer.setCachePort(Integer.parseInt(bindPort));

                localServer.setHost(Config.getStringProperty("CACHE_BINDADDRESS", null));               

                List<String> myself = new ArrayList<String>();
                myself.add(localServer.getServerId());

                List<Server> aliveServers = serverAPI.getAliveServers(myself);
                aliveServers.add(localServer);

                StringBuilder initialHosts = new StringBuilder();

                int i=0;
                for (Server server : aliveServers) {
                    if(i>0) {
                        initialHosts.append(",");
                    }

                    if(UtilMethods.isSet(server.getHost()) && !server.getHost().equals("localhost")) {
                        initialHosts.append(server.getHost()).append("[").append(server.getCachePort()).append("]");
                    } else {
                        initialHosts.append(server.getIpAddress()).append("[").append(server.getCachePort()).append("]");
                    }
                    i++;
                }

                if(initialHosts.length()==0) {
                    if(bindAddr.equals("localhost")) {
                        initialHosts.append(localServer.getIpAddress()).append("[").append(bindPort).append("]");
                    } else {
                        initialHosts.append(bindAddr).append("[").append(bindPort).append("]");
                    }
                }

                cacheTCPInitialHosts = UtilMethods.isSet(cacheProperties.get("CACHE_TCP_INITIAL_HOSTS"))?cacheProperties.get("CACHE_TCP_INITIAL_HOSTS")
                        :Config.getStringProperty("CACHE_TCP_INITIAL_HOSTS", initialHosts.toString());

                mCastAddr = UtilMethods.isSet(cacheProperties.get("CACHE_MULTICAST_ADDRESS"))?cacheProperties.get("CACHE_MULTICAST_ADDRESS")
                        :Config.getStringProperty("CACHE_MULTICAST_ADDRESS", "228.10.10.10");
                mCastPort = UtilMethods.isSet(cacheProperties.get("CACHE_MULTICAST_PORT"))?cacheProperties.get("CACHE_MULTICAST_PORT")
                        :Config.getStringProperty("CACHE_MULTICAST_PORT", "45588");
                preferIPv4 = UtilMethods.isSet(cacheProperties.get("CACHE_FORCE_IPV4"))?cacheProperties.get("CACHE_FORCE_IPV4")
                        :Config.getStringProperty("CACHE_FORCE_IPV4", "true");
      }
      else {
          Logger.info(this, "Using manual port placement as CLUSTER_AUTOWIRE is OFF");
         
          cacheProtocol = Config.getStringProperty("CACHE_PROTOCOL", "tcp");
          bindAddr = Config.getStringProperty("CACHE_BINDADDRESS", null);
          bindPort = Config.getStringProperty("CACHE_BINDPORT", null);
          cacheTCPInitialHosts = Config.getStringProperty("CACHE_TCP_INITIAL_HOSTS", "localhost[7800]");
          mCastAddr = Config.getStringProperty("CACHE_MULTICAST_ADDRESS", "228.10.10.10");
          mCastPort = Config.getStringProperty("CACHE_MULTICAST_PORT", "45588");
          preferIPv4 = Config.getStringProperty("CACHE_FORCE_IPV4", "true");
      }

      String cacheFile = "cache-jgroups-" + cacheProtocol + ".xml";

      Logger.info(this, "***\t Going to load JGroups with this Classpath file " + cacheFile);

      if (UtilMethods.isSet(bindAddr)) {
          Logger.info(this, "***\t Using " + bindAddr + " as the bindaddress");
        System.setProperty("jgroups.bind_addr", bindAddr);
      }
      else {
                Logger.info(this, "***\t bindaddress is not set");
            }

      if (UtilMethods.isSet(bindPort)) {
          Logger.info(this, "***\t Using " + bindPort + " as the bindport");
        System.setProperty("jgroups.bind_port", bindPort);
      }
      else {
                Logger.info(this, "***\t bindport is not set");
            }
     
      if (cacheProtocol.equals("tcp")) {
        Logger.info(this, "***\t Setting up TCP initial hosts: "+cacheTCPInitialHosts);
        System.setProperty("jgroups.tcpping.initial_hosts",  cacheTCPInitialHosts);
      } else if (cacheProtocol.equals("udp")) {
        Logger.info(this, "***\t Setting up UDP address and port: "+mCastAddr+":"+mCastPort);
        System.setProperty("jgroups.udp.mcast_port", mCastPort);
        System.setProperty("jgroups.udp.mcast_addr", mCastAddr);
      } else {
        Logger.info(this, "Not Setting up any Properties as no protocal was found");
      }

      Logger.info(this, "***\t Prefer IPv4: "+(preferIPv4.equals("true") ? "enabled" : "disabled"));
      System.setProperty("java.net.preferIPv4Stack", preferIPv4);
     
     
      Logger.info(this, "***\t Setting up JChannel");

      if(channel!=null) {
          channel.disconnect();
      }
     
      channel = new JChannel(classLoader.getResource(cacheFile));
      channel.setReceiver(this);
     
      channel.connect(Config.getStringProperty("CACHE_JGROUPS_GROUP_NAME","dotCMSCluster"));
      channel.setOpt(JChannel.LOCAL, false);
      useJgroups = true;
      channel.send(new Message(null, null, TEST_MESSAGE));
      Address channelAddress = channel.getAddress();
      PhysicalAddress physicalAddr = (PhysicalAddress)channel.downcall(new Event(Event.GET_PHYSICAL_ADDRESS, channelAddress));
      String[] addrParts = physicalAddr.toString().split(":");
      String usedPort = addrParts[addrParts.length-1];

      localServer.setCachePort(Integer.parseInt(usedPort));
      serverAPI.updateServer(localServer);

      Logger.info(this, "***\t " + channel.toString(true));
      Logger.info(this, "***\t Ending JGroups Cluster Setup");

  }

  /*
   * (non-Javadoc)
   *
   * @see com.dotmarketing.business.DotCacheAdministrator#flushAll()
   */
  public void flushAll() {
    flushAlLocalOnlyl();
    try {
      if (Config.getBooleanProperty("CACHE_CLUSTER_THROUGH_DB", false)) {
        journalAPI.addCacheEntry("0", ROOT_GOUP);
      } else if (useJgroups) {
        Message msg = new Message(null, null, "0:" + ROOT_GOUP);
        try {
          channel.send(msg);
        } catch (Exception e) {
          Logger.error(DotGuavaCacheAdministratorImpl.class, "Unable to send invalidation to cluster : " + e.getMessage(), e);
        }
      }
    } catch (DotDataException e) {
      Logger.error(this, "Unable to add journal entry for cluster", e);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * com.dotmarketing.business.DotCacheAdministrator#flushGroup(java.lang.
   * String)
   */

  public void flushGroup(String group) {

    if(group ==null ){
      return ;
    }
    group = group.toLowerCase();

    groups.remove(group);

    flushGroupLocalOnly(group);

    try {
      if (Config.getBooleanProperty("CACHE_CLUSTER_THROUGH_DB", false)) {
        journalAPI.addCacheEntry("0", group);
      } else if (useJgroups) {
        Message msg = new Message(null, null, "0:" + group);
        try {
          channel.send(msg);
        } catch (Exception e) {
          Logger.error(DotGuavaCacheAdministratorImpl.class, "Unable to send invalidation to cluster : " + e.getMessage(), e);
        }
      }
    } catch (DotDataException e) {
      Logger.error(this, "Unable to add journal entry for cluster", e);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see com.dotmarketing.business.DotCacheAdministrator#flushAll()
   */
  public void flushAlLocalOnlyl() {

    Set<String> myGroups = new HashSet<String>();

    myGroups.addAll(groups.keySet());
    groups.clear();
    if(diskCache != null){
      try {
        myGroups.addAll(H2CacheLoader.getGroups());
      } catch (SQLException e) {
        Logger.error(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
      }
    }

    for(String group : myGroups){
      flushGroupLocalOnly(group);
    }
    if(diskCache != null){
      diskCache.resetCannotCacheCache();
    }
    cacheToDisk.clear();

  }

  public void flushGroupLocalOnly(String group) {

    if(group ==null ){
      return ;
    }
    group = group.toLowerCase();

    Cache cache = getCache(group);


    if(isDiskCache(group)){
      try {
        diskCache.remove(new Fqn(group));
      } catch (Exception e) {
        Logger.debug(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
      }
    }
    cache.invalidateAll();

  }


  private class NullCallable implements Callable{

    public Object call() throws Exception {
      return null;
    }


  }

  public Object getMemory(String key, String group) throws DotCacheException {
    if(key == null || group == null){
      return null;
    }
    key = key.toLowerCase();
    group = group.toLowerCase();
    Cache cache = getCache(group);
    Object j = null;
    try {
      j = cache.get(key, nullCallable);
    } catch (Exception e) {

    }
    return j;
  }

  public Object getDisk(String key, String group) throws DotCacheException {
    if(key == null || group == null){
      return null;
    }

    key = key.toLowerCase();
    group = group.toLowerCase();
    Object j = null;
    if(isDiskCache(group)){
      try {
        Map m=diskCache.get(new Fqn(group, key));
        if(m!=null){
          j = m.get(key);
          if(j != null){
            Cache cache = getCache(group);
            cache.put(key, j);
          }
        }
      } catch (Exception e) {
        Logger.debug(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
      }
    }
    return j;

  }
  /**
   * Gets from Memory, if not in memory, tries disk
   */
  public Object get(String key, String group) throws DotCacheException {
    if(key == null || group == null){
      return null;
    }
    key = key.toLowerCase();
    group = group.toLowerCase();

    Object j = getMemory( key,  group);
    if(j==null){
      j= getDisk( key,  group);
    }

    return j;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * com.dotmarketing.business.DotCacheAdministrator#put(java.lang.String,
   * java.lang.Object, java.lang.String[])
   */
  public void put(String key, final Object content, String group) {
    if(key == null || group == null){
      return;
    }
    key = key.toLowerCase();
    group = group.toLowerCase();



    Cache cache = getCache(group);
    cache.put(key, content);

    if(isDiskCache(group)){
      try {
        diskCache.put(new Fqn(group, key), key, content);
      } catch (Exception e) {
        Logger.debug(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
      }
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * com.dotmarketing.business.DotCacheAdministrator#remove(java.lang.String)
   */
  public void remove(final String key, final String group) {
    if(key == null || group == null){
      return;
    }
    Runnable cacheRemoveRunnable=new Runnable() {
           public void run() {

        String k = key.toLowerCase();
        String g = group.toLowerCase();
        removeLocalOnly(k, g);

        try {
          if (Config.getBooleanProperty("CACHE_CLUSTER_THROUGH_DB", false)) {
            journalAPI.addCacheEntry(k, g);
          } else if (useJgroups) {
            Message msg = new Message(null, null, k + ":" + g);
            try {
              channel.send(msg);
            } catch (Exception e) {
              Logger.error(DotGuavaCacheAdministratorImpl.class, "Unable to send invalidation to cluster : " + e.getMessage(), e);
            }
          }
        } catch (DotDataException e) {
          Logger.error(this, "Unable to add journal entry for cluster", e);
        }
           }
    };
    try {
      if(!DbConnectionFactory.getConnection().getAutoCommit()){
        HibernateUtil.addCommitListener(cacheRemoveRunnable);
      }
    } catch (Exception e) {
      Logger.error(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
    }
    cacheRemoveRunnable.run();
  }

  /*
   * This method should only be called by Jgroups because it doesn't handle any local transaction as the remove does.
   */
  public void removeLocalOnly(final String key, final String group) {
    if(key == null || group == null){
      return;
    }
    Runnable cacheRemoveRunnable=new Runnable() {
           public void run() {
        String k = key.toLowerCase();
        String g = group.toLowerCase();
        Cache<String, Object>  cache = getCache(g);
        cache.invalidate(k);
        if(isDiskCache(g)){
          try {
            if(!UtilMethods.isSet(key)){
              Logger.error(this.getClass(), "Empty key passed in, clearing group " + group + " by mistake");
            }
            diskCache.remove(new Fqn(g, k), k.toLowerCase());
          } catch (Exception e) {
            Logger.error(DotGuavaCacheAdministratorImpl.class,e.getMessage(),e);
          }
        }
           }
    };
    cacheRemoveRunnable.run();
  }

  public Set<String> getKeys(String group) {
    if(group ==null ){
      return null;
    }
    Set<String> keys=new HashSet<String>();

    group = group.toLowerCase();
    Cache<String, Object> cache = getCache(group);
    Map<String, Object> m = cache.asMap();

    if (m!=null) {
      keys.addAll(m.keySet());
    }

    if(diskCache!=null && isDiskCache(group)) {
        try {
            keys.addAll(diskCache.getKeys(group));
        }
        catch(Exception ex) {
            Logger.error(this, "can't get h2 cache keys on group "+group,ex);
        }
    }

    return keys;


  }

  public List<Map<String, Object>> getCacheStatsList() {
    List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();


    Set<String> myGroups = new HashSet<String>();

    myGroups.addAll(groups.keySet());

    if(diskCache != null){
      try {
        for(String s : H2CacheLoader.getGroups()){
          myGroups.add(s.toLowerCase());
        }
      } catch (SQLException e) {
        Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
      }
    }

    Cache dCache = getCache(DEFAULT_CACHE);
    for (String group : myGroups) {
      Map<String, Object> m = new HashMap<String, Object>();
      m.put("cache", getCache(group));
      String region = group.toString();
      m.put("region", region);

      m.put("toDisk", new Boolean(isDiskCache(group)));
      boolean isDefault = false;


      try {
        Cache n = getCache(group);
        m.put("memory", n.size());

        m.put("CacheStats", n.stats());
        isDefault = (!DEFAULT_CACHE.equals(group) && n.equals(dCache));

      } catch (Exception e) {

      }
      m.put("isDefault", isDefault);
      m.put("disk", -1);
      if(diskCache != null){
        if(isDiskCache(group)){
          m.put("disk", H2CacheLoader.getGroupCount(group.toString()));
        }
      }


      int configured = isDefault
        ? Config.getIntProperty("cache."+DEFAULT_CACHE+".size" )
            : (Config.getIntProperty("cache." +region + ".size", -1 ) != -1)
              ? Config.getIntProperty("cache." +region + ".size" )
                : (region.startsWith(WORKING_CACHE_PREFIX) && Config.getIntProperty("cache."+WORKING_CACHE_PREFIX+".size", -1 ) != -1)
                  ? Config.getIntProperty("cache."+WORKING_CACHE_PREFIX+".size" )
                     : (region.startsWith(LIVE_CACHE_PREFIX) && Config.getIntProperty("cache."+LIVE_CACHE_PREFIX+".size", -1 ) != -1)
                       ? Config.getIntProperty("cache."+LIVE_CACHE_PREFIX+".size" )
                           : Config.getIntProperty("cache."+DEFAULT_CACHE+".size" );



         m.put("configuredSize", configured);

      list.add(m);

    }


    Collections.sort(list, new CacheComparator());

    return list;
  }

  private class CacheComparator implements Comparator<Map<String,Object>>{

    public int compare(Map<String,Object> o1, Map<String,Object> o2) {

      if(o1==null && o2!=null) return 1;
      if(o1!=null && o2==null) return -1;
      if(o1==null && o2==null) return 0;

      String group1 = (String) o1.get("region");
      String group2 = (String) o2.get("region");

      if(!UtilMethods.isSet(group1) && !UtilMethods.isSet(group2)) {
        return 0;
      } else if(UtilMethods.isSet(group1) && !UtilMethods.isSet(group2)) {
        return -1;
      } else if(!UtilMethods.isSet(group1) && UtilMethods.isSet(group2)) {
        return 1;
      } else if(group1.equals(group2)) {
        return 0;
      } else if(group1.startsWith(WORKING_CACHE_PREFIX) && group2.startsWith(LIVE_CACHE_PREFIX)) {
        return 1;
      } else if(group1.startsWith(LIVE_CACHE_PREFIX) && group2.startsWith(WORKING_CACHE_PREFIX)) {
        return -1;
      } else if(!group1.startsWith(LIVE_CACHE_PREFIX) && !group1.startsWith(WORKING_CACHE_PREFIX) && (group2.startsWith(LIVE_CACHE_PREFIX) || group2.startsWith(WORKING_CACHE_PREFIX)) ) {
        return -1;
      } else if((group1.startsWith(LIVE_CACHE_PREFIX) || group1.startsWith(WORKING_CACHE_PREFIX)) && !group2.startsWith(LIVE_CACHE_PREFIX) && !group2.startsWith(WORKING_CACHE_PREFIX) ) {
        return 1;
      } else { // neither group1 nor group2 are live or working
        return group1.compareToIgnoreCase(group2);
      }
    }


  }





  public String getCacheStats() {

    return null;
  }

  public void shutdown() {
    if(diskCache != null){
      diskCache.destroy();
    }
  }



  public JChannel getJGroupsChannel() {
    return channel;
  }

  public boolean isClusteringEnabled() {
    return useJgroups;
  }

  /**
   * @param msg
   * @return True if the message was sent without any problem, false otherwise.
   */
  public boolean send(String msg) {
    boolean success = false;
    Message message = new Message(null, null, msg);
    try {
      channel.send(message);
      success = true;
    } catch (Exception e) {
      Logger.warn(DotGuavaCacheAdministratorImpl.class, "Unable to send message to cluster : " + e.getMessage(), e);
      success = false;
    }
    return success;
  }
 
 
 
  /**
   * @param dateInMillis String use as Key on out Map of results.
   * @param numberServers Number of servers to wait for a response.
   * @param maxWaitSeconds seconds to wait for a response.
   * @return Map with DateInMillis, ServerInfo for each cache/live server in Cluster.
   */
  public Map<String, Boolean> validateCacheInCluster(String dateInMillis, int numberServers, int maxWaitSeconds){
   
    cacheStatus = new HashMap<String, Map<String,Boolean>>();
   
    //If we are already in Cluster.
    if(numberServers > 0 && send(DUMMY_TEXT_TO_SEND)){
      //Sends the message to the other servers.
      send(VALIDATE_CACHE + dateInMillis);
     
      //Waits for 2 seconds in order all the servers respond.
      int maxWaitTime = maxWaitSeconds * 1000;
      int passedWaitTime = 0;
     
      //Trying to NOT wait whole 2 seconds for returning the info.
      while (passedWaitTime <= maxWaitTime){
        try {
            Thread.sleep(10);
            passedWaitTime += 10;
           
            Map<String, Boolean> ourMap = (Map<String, Boolean>)cacheStatus.get(dateInMillis);
           
            //No need to wait if we have all server results.
            if(ourMap != null && ourMap.size() == numberServers){
              passedWaitTime = maxWaitTime + 1;
            }
           
        } catch(InterruptedException ex) {
            Thread.currentThread().interrupt();
            passedWaitTime = maxWaitTime + 1;
        }
      }
    }
   
    //Returns the Map with all the info stored by receive() method.
    Map<String, Boolean> mapToReturn = new HashMap<String, Boolean>();
   
    if((Map<String, Boolean>)cacheStatus.get(dateInMillis) != null){
      mapToReturn = (Map<String, Boolean>)cacheStatus.get(dateInMillis);
    }
   
    return mapToReturn;
  }

  @Override
  public void receive(Message msg) {
    if (msg == null) {
      return;
    }
   
    Object v = msg.getObject();
    if (v == null) {
      return;
    }

    if (v.toString().equals(TEST_MESSAGE)) {
      Logger.info(this, "Received Message Ping " + new Date());
      try {
        channel.send(null, null, "ACK");
      } catch (ChannelNotConnectedException e) {
        Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
      } catch (ChannelClosedException e) {
        Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
      }
   
    //Handle when other server is responding to ping. 
    } else if (v.toString().startsWith(VALIDATE_CACHE_RESPONSE)) {
      String message = v.toString();
      //Deletes the first part of the message, no longer needed.
      message = message.replace(VALIDATE_CACHE_RESPONSE, "");
     
      //Gets the part of the message that has the Data in Milli.
      String dateInMillis = message.substring(0, message.indexOf(VALIDATE_SEPARATOR));
      //Gets the last part of the message that has the Server ID.
      String serverID = message.substring(message.lastIndexOf(VALIDATE_SEPARATOR) + 1);
     
      synchronized(this){
        //Creates or updates the Map inside the Map.
        Map<String, Boolean> localMap = cacheStatus.get(dateInMillis);
       
        if(localMap == null){
          localMap = new HashMap<String, Boolean>();
       
       
        localMap.put(serverID, Boolean.TRUE);
       
        //Add the Info with the Date in Millis and the Map with Server Info.
        cacheStatus.put(dateInMillis, localMap);
        }
     
      Logger.debug(this, VALIDATE_CACHE_RESPONSE + " SERVER_ID: " + serverID + " DATE_MILLIS: " + dateInMillis);
         
    //Handle when other server is trying to ping local server.
    } else if (v.toString().startsWith(VALIDATE_CACHE)) {
      String message = v.toString();
      //Deletes the first part of the message, no longer needed.
      message = message.replace(VALIDATE_CACHE, "");
     
      //Gets the part of the message that has the Data in Milli.
      String dateInMillis = message;
      //Sends the message back in order to alert the server we are alive.
      send(VALIDATE_CACHE_RESPONSE + dateInMillis + VALIDATE_SEPARATOR + APILocator.getServerAPI().readServerId());
     
      Logger.debug(this, VALIDATE_CACHE + " DATE_MILLIS: " + dateInMillis);
     
    } else if (v.toString().equals("ACK")) {
      Logger.info(this, "ACK Received " + new Date());
    } else if(v.toString().equals("MultiMessageResources.reload")) {
      MultiMessageResources messages = (MultiMessageResources) Config.CONTEXT.getAttribute( Globals.MESSAGES_KEY );
            messages.reload();
    } else if (v.toString().equals(DUMMY_TEXT_TO_SEND)) {
      //Don't do anything is we are only checking sending.
    } else {
      invalidateCacheFromCluster(v.toString());
    }
  }

  public void viewAccepted(View new_view) {
    super.viewAccepted(new_view);
    Logger.info(this, "Method view: Cluster View is : " + new_view);
    Logger.info(DotGuavaCacheAdministratorImpl.class, "viewAccepted + Cluster View is : " + new_view);
  }

  @Override
  public void suspect(Address mbr) {
    super.suspect(mbr);
    Logger.info(this, "Method suspect: There is a suspected member : " + mbr);
    Logger.info(DotGuavaCacheAdministratorImpl.class, "suspect + There is a suspected member : " + mbr);
  }

  public void testCluster() {
    Message msg = new Message(null, null, TEST_MESSAGE);
    try {
      channel.send(msg);
      Logger.info(this, "Sending Ping to Cluster " + new Date());
    } catch (ChannelNotConnectedException e) {
      Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
    } catch (ChannelClosedException e) {
      Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
    }
  }

  public void testNode(Address nodeAdr) {
    try {
      channel.send(nodeAdr, null, "TESTNODE");
    } catch (ChannelNotConnectedException e) {
      Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
    } catch (ChannelClosedException e) {
      Logger.error(DotGuavaCacheAdministratorImpl.class, e.getMessage(), e);
    }
  }

  private void invalidateCacheFromCluster(String k) {
    boolean flushMenus = false;
    DotResourceCache vc = CacheLocator.getVeloctyResourceCache();
    String menuGroup = vc.getMenuGroup();

    int i = k.lastIndexOf(":");
    if (i > 0) {
      String key = k.substring(0, i);
      String group = k.substring(i + 1, k.length());

      key = key.toLowerCase();
      group = group.toLowerCase();
      if (groups != null) {

        if (groups.containsKey(group)) {
          Logger.debug(this, "Cluster Eviction of Key : " + key + " With Group : " + group + " from cache");
        }
      }
      if (key.contains("dynamic")) {
        if (group.equals(menuGroup)) {
          flushMenus = true;
        }
      }
      if (!flushMenus) {
        if (key.equals("0")) {
          if (group.equalsIgnoreCase(DotCacheAdministrator.ROOT_GOUP)) {
            CacheLocator.getCacheAdministrator().flushAlLocalOnlyl();
          } else if (group.equalsIgnoreCase(menuGroup)) {
            flushMenus = true;
          } else {
            CacheLocator.getCacheAdministrator().flushGroupLocalOnly(group);
          }
        } else {
          CacheLocator.getCacheAdministrator().removeLocalOnly(key, group);
        }
      }
    } else {
      Logger.error(this, "The cache to locally remove key is invalid. The value was " + k);
    }
    if (flushMenus) {
      RefreshMenus.deleteMenusOnFileSystemOnly();
      CacheLocator.getCacheAdministrator().flushGroupLocalOnly(menuGroup);
    }
  }

  private Cache<String, Object> getCache(String cacheName) {
    if (cacheName == null) {
      throw new DotStateException("Null cache region passed in");
    }
    cacheName = cacheName.toLowerCase();
    Cache<String, Object> cache = groups.get(cacheName);

    // init cache if it does not exist
    if (cache == null) {
      synchronized (cacheName.intern()) {
        cache = groups.get(cacheName);
        if (cache == null) {


          boolean separateCache = (availableCaches.contains(cacheName) || DEFAULT_CACHE.equals(cacheName) ||cacheName.startsWith(LIVE_CACHE_PREFIX) || cacheName.startsWith(WORKING_CACHE_PREFIX) );


          if (separateCache) {
            int size = -1;
            boolean toDisk = false;
            if (cacheName.startsWith(LIVE_CACHE_PREFIX)) {
              size = Config.getIntProperty("cache." + cacheName + ".size", -1);
              if(size <0){
                size = Config.getIntProperty("cache."+LIVE_CACHE_PREFIX+".size", -1);
              }
              if(Config.containsProperty("cache." + cacheName + ".disk")){
                toDisk = Config.getBooleanProperty("cache." + cacheName + ".disk", false);
              }
              else{
                toDisk = Config.getBooleanProperty("cache."+LIVE_CACHE_PREFIX+".disk", false);
              }
            }
            else if (cacheName.startsWith(WORKING_CACHE_PREFIX)) {
              size = Config.getIntProperty("cache." + cacheName + ".size", -1);
              if(size <0){
                size = Config.getIntProperty("cache."+WORKING_CACHE_PREFIX+".size", -1);
              }
              if(Config.containsProperty("cache." + cacheName + ".disk")){
                toDisk = Config.getBooleanProperty("cache." + cacheName + ".disk", false);
              }
              else{
                toDisk = Config.getBooleanProperty("cache."+WORKING_CACHE_PREFIX+".disk", false);
              }
            }
            else {
              size = Config.getIntProperty("cache." + cacheName + ".size", -1);
              if(Config.containsProperty("cache." + cacheName + ".disk")){
                toDisk = Config.getBooleanProperty("cache." + cacheName + ".disk", false);
              }
              else{
                toDisk = Config.getBooleanProperty("cache."+DEFAULT_CACHE+".disk", false);
              }
            }

            if (size == -1) {
              size = Config.getIntProperty("cache."+DEFAULT_CACHE+".size", 100);
            }

            Logger.info(this.getClass(), "***\t Building Cache : " + cacheName + ", size:" + size + ", toDisk:" + toDisk + ",Concurrency:" + Config.getIntProperty("cache.concurrencylevel", 32));
            CacheBuilder<Object, Object> cb  = CacheBuilder
                .newBuilder()
                .maximumSize(size)
                .concurrencyLevel(Config.getIntProperty("cache.concurrencylevel", 32));



            cache = cb.build();
            groups.put(cacheName, cache);

          } else {
            Logger.info(this.getClass(), "***\t No Cache for   : " + cacheName + ", using " + DEFAULT_CACHE);
            cache = getCache(DEFAULT_CACHE);
            groups.put(cacheName, cache);
          }
        }
      }
    }

    return cache;

  }

  private class DotRemoval implements RemovalListener {

    public void onRemoval(RemovalNotification removalEvent) {

    }

  }

    @Override
    public Class getImplementationClass() {
        return DotGuavaCacheAdministratorImpl.class;
    }



    @Override
    public DotCacheAdministrator getImplementationObject() {
        return this;
    }

    public View getView() {
      if(channel!=null)
        return channel.getView();
      else
        return null;
    }

    public JChannel getChannel() {
      return channel;
    }
   
    public void shutdownJGroups() {
        synchronized(this) {
            useJgroups=false;
            if(channel!=null) {
                channel.disconnect();
                channel.close();
                channel=null;
            }
        }
    }
}
TOP

Related Classes of com.dotmarketing.business.DotGuavaCacheAdministratorImpl$DotRemoval

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.