Package com.alu.e3.common.caching

Source Code of com.alu.e3.common.caching.HazelcastCache

/**
* Copyright © 2012 Alcatel-Lucent.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Licensed to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*          http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.alu.e3.common.caching;

import java.security.InvalidParameterException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.alu.e3.common.E3Constant;
import com.alu.e3.common.caching.internal.HandlerPool;
import com.alu.e3.common.caching.internal.MapHandler;
import com.alu.e3.common.logging.Category;
import com.alu.e3.common.logging.CategoryLogger;
import com.alu.e3.common.logging.CategoryLoggerFactory;
import com.alu.e3.common.osgi.api.ITopologyClient;
import com.alu.e3.data.DataEntryEvent;
import com.hazelcast.client.ClientConfig;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.EntryListener;
import com.hazelcast.core.IMap;

public class HazelcastCache<K, V> implements ICacheTable<K, V> {

  protected static final CategoryLogger logger = CategoryLoggerFactory.getLogger(HazelcastCache.class, Category.DMGR);

  protected IMap<K, V> localMap;
  protected boolean isReplicated = false;
  protected String name;

  private Map<IEntryListener<K, V>, EntryListener<K, V>> entryListenersMap;
  protected ITopologyClient topologyClient;
 
  protected HandlerPool<String, MapHandler<K,V>> mapHandlerPool = new HandlerPool<String, MapHandler<K,V>>(E3Constant.HAZELCAST_HANDLER_POOL_MAX_SIZE);


  public void setTopologyClient(ITopologyClient topologyClient) {
    this.topologyClient = topologyClient;
  }

  public IMap<K, V> getMap() {
    return localMap;
  }

  @Override
  public String getName() {
    return name;
  }

  public void setMap(IMap<K, V> map) throws InvalidParameterException {
    if (map == null)
      throw new InvalidParameterException("The parameter map is mandatory");

    this.localMap = map;
    this.name = map.getName();
  }

  public void setIsReplicated(boolean isReplicated) {
    this.isReplicated = isReplicated;
  }

  @Override
  public V get(Object key) {
    if (localMap == null) {
      logger.error("Attempt to get a key on a cache without a map");
    }

    ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(HazelcastCacheManager.class.getClassLoader());

    V retValue = localMap == null ? null : localMap.get(key);

    Thread.currentThread().setContextClassLoader(previousClassLoader);

    return retValue;
  }

  @Override
  public boolean set(K key, V value) {
    if (localMap == null) {
      logger.error("Attempt to put a key in a cache without a map");
      return false;
    }

    ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(HazelcastCacheManager.class.getClassLoader());

    localMap.put(key, value);

    if (isReplicated && topologyClient != null) {
      Set<String> instances = getAllInstanceIPs();

      MapHandler<K, V> mapHandler = null;
      for (String instanceIP : instances) {
        try {
          mapHandler = mapHandlerPool.get(new StringBuffer(instanceIP).append(localMap.getName()).toString());
          if (mapHandler==null)
          {
            mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
            mapHandlerPool.put(new StringBuffer(instanceIP).append(localMap.getName()).toString(), mapHandler);
          }else
          {
            if (!mapHandler.isClientActive())
            {
              mapHandler.dispose();
              String poolKey = new StringBuffer(instanceIP).append(localMap.getName()).toString();
              mapHandlerPool.remove(poolKey);
              mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
              mapHandlerPool.put(poolKey, mapHandler);
            }
          }

          if (!mapHandler.isLocal()) {
            IMap<K, V> map = mapHandler.getMap();
            map.put(key, value);
          }
        } catch (IllegalStateException ise) {
          logger.warn("Was not able to set the entry " + key + " of the cache " + localMap.getName() + " for gateway " + instanceIP + ". This probably means that this instance is down.", ise);
        } catch(Exception e){
          logger.error("Unexpected error updating the entry " + key + " of the cache " + localMap.getName() + " for gateway " + instanceIP, e);
        }

      }
    }

    Thread.currentThread().setContextClassLoader(previousClassLoader);

    return true;
  }

  @Override
  public boolean set(K key, V value, String instanceIP) {
    logger.debug("Setting map:{}, key:{} value:{} on node ip:{}", new Object[]{name, key, value, instanceIP});
   
    if (localMap == null) {
      logger.error("Attempt to put a key in a cache without a map");
      return false;
    }

    ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(HazelcastCacheManager.class.getClassLoader());

    MapHandler<K, V> mapHandler = null;
    try {
      mapHandler = mapHandlerPool.get(new StringBuffer(instanceIP).append(localMap.getName()).toString());
      if (mapHandler==null)
      {
        logger.debug("Creating MapHandler map:{}, key:{} on node ip:{}", new Object[]{name, key, instanceIP});
        mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
        mapHandlerPool.put(new StringBuffer(instanceIP).append(localMap.getName()).toString(), mapHandler);
      }else
      {
        logger.debug("Reusing MapHandler map:{}, key:{} on node ip:{}", new Object[]{name, key, instanceIP});
        if (!mapHandler.isClientActive())
        {
          logger.debug("Recreating MapHandler map:{}, key:{} on node ip:{}", new Object[]{name, key, instanceIP});
          mapHandler.dispose();
          String poolKey = new StringBuffer(instanceIP).append(localMap.getName()).toString();
          mapHandlerPool.remove(poolKey);
          mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
          mapHandlerPool.put(poolKey, mapHandler);
        }
      }

      if (! mapHandler.isLocal()) {
        logger.debug("Pushing value map:{}, key:{} on node ip:{}", new Object[]{name, key, instanceIP});
        IMap<K, V> map = mapHandler.getMap();
        map.put(key, value);
      }
    }
    catch (IllegalStateException ise) {
      logger.error("Was not able to set the entry " + key + " of the cache " + localMap.getName() + " for gateway " + instanceIP + ". This probably means that this instance is down.", ise);
    }

    Thread.currentThread().setContextClassLoader(previousClassLoader);

    return true;
  }

  @Override
  public void reloadSlave(String ip) {
    if (logger.isDebugEnabled()) {
      logger.debug("Reloading table:{} for node ip:{}", name, ip);
    }
   
    if (localMap == null) {
      logger.warn("Attempt to reload a slave cache from a master with no map");
      return;
    }

    MapHandler<K, V> mapHandler = mapHandlerPool.get(new StringBuffer(ip).append(localMap.getName()).toString());
    try {
      if (mapHandler==null)
      {
        if (logger.isDebugEnabled()) {
          logger.debug("Creating mapHandler for table:{} for node ip:{}", name, ip);
        }
        mapHandler = new MapHandler<K, V>(ip, localMap.getName());
        mapHandlerPool.put(new StringBuffer(ip).append(localMap.getName()).toString(), mapHandler);
      }else
      {
        if (logger.isDebugEnabled()) {
          logger.debug("Reusing mapHandler for table:{} for node ip:{}", name, ip);
        }
        if (!mapHandler.isClientActive())
        {
          if (logger.isDebugEnabled()) {
            logger.debug("Recreating mapHandler for table:{} for node ip:{}", name, ip);
          }
          mapHandler.dispose();
          String poolKey = new StringBuffer(ip).append(localMap.getName()).toString();
          mapHandlerPool.remove(poolKey);
          mapHandler = new MapHandler<K, V>(ip, localMap.getName());
          mapHandlerPool.put(poolKey, mapHandler);
        }
      }
      IMap<K, V> map = mapHandler.getMap();
      if (!mapHandler.isLocal()) {
        if (logger.isDebugEnabled()) {
          logger.debug("Pushing allData for table:{} for node ip:{}", name, ip);
        }
        map.putAll(localMap);
      }
    } catch (Exception e) {
      logger.warn("Unable to reload slave", e);
    }
  }

  @Override
  public V remove(Object key) {

    if (localMap == null) {
      logger.error("Attempt to remove a key in a cache without a map");
      return null;
    }

    ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(HazelcastCacheManager.class.getClassLoader());

    V value = localMap.remove(key);

    if (value == null) {
      logger.error("Error removing a key from the master cache");
      Thread.currentThread().setContextClassLoader(previousClassLoader);
      return null;
    }

    if (isReplicated && topologyClient != null) {
      Set<String> instances = getAllInstanceIPs();

      MapHandler<K, V> mapHandler = null;
      for (String instanceIP : instances) {
        try {
          mapHandler = mapHandlerPool.get(new StringBuffer(instanceIP).append(localMap.getName()).toString());
          if (mapHandler==null)
          {
            mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
            mapHandlerPool.put(new StringBuffer(instanceIP).append(localMap.getName()).toString(), mapHandler);
          }else
          {
            if (!mapHandler.isClientActive())
            {
              mapHandler.dispose();
              String poolKey = new StringBuffer(instanceIP).append(localMap.getName()).toString();
              mapHandlerPool.remove(poolKey);
              mapHandler = new MapHandler<K, V>(instanceIP, localMap.getName());
              mapHandlerPool.put(poolKey, mapHandler);
            }
          }
         
          IMap<K, V> map = mapHandler.getMap();
          if (! mapHandler.isLocal()) {
            map.remove(key);
          }
        } catch (IllegalStateException ise) {
          logger.warn("Was not able to set the entry " + key + " of the cache " + localMap.getName() + " for gateway " + instanceIP + ". This probably means that this instance is down.");
        } finally {
          if (mapHandler != null)
            mapHandler.dispose();
        }
      }
    }

    Thread.currentThread().setContextClassLoader(previousClassLoader);

    return value;
  }

  protected Set<String> getAllInstanceIPs() {
    Set<String> instanceIPs = new HashSet<String>();

    // add all gateway internal IPs to use
    instanceIPs.addAll(getInternalIPs(E3Constant.E3GATEWAY));
    // add all gateway external IPs to use
    instanceIPs.addAll(getExternalIPs(E3Constant.E3GATEWAY));

    return instanceIPs;
  }

  private Set<String> getInternalIPs(String type) {
    // get manager area
    String managerArea = topologyClient.getMyArea();
    if (logger.isDebugEnabled()) {
      logger.debug("Current manager area '" + managerArea + "'");
      logger.debug("Adding gateway internal ips for manager area '" + managerArea + "'");
    }
    // use internal ip for gateways having the same area than the manager
    return topologyClient.getInternalIPsOfType(type, managerArea);
  }

  private Set<String> getExternalIPs(String type) {
    // get all other areas than the manager's one
    Set<String> otherAreas = topologyClient.getAllOtherAreas();
    Set<String> externalGatewayIPs = new HashSet<String>();

    // iterate through area list to gather external gateway ips
    for (String area : otherAreas) {
      if (logger.isDebugEnabled()) {
        logger.debug("Adding gateway external ips non manager for area '" + area + "'");
      }
      externalGatewayIPs.addAll(topologyClient.getExternalIPsOfType(type, area));
    }

    return externalGatewayIPs;
  }

  @Override
  public boolean containsKey(Object key) {
    if (localMap == null) {
      logger.error("Attempt to check if a key is contained in a cache without a map");
    }

    return localMap == null ? false : localMap.containsKey(key);
  }

  @Override
  public Set<K> getAllKeys() {
    if (localMap == null) {
      logger.error("Attempt to get all keys of a cache without a map");
    }

    return localMap == null ? new HashSet<K>() : localMap.keySet();
  }

  @Override
  public Collection<V> getAllValues() {
    if (localMap == null) {
      logger.error("Attempt to get all values of a cache without a map");
    }

    return localMap == null ? new HashSet<V>() : localMap.values();
  }

  protected HazelcastClient getHazelcastClient(String ip) {

    ClientConfig clientConfig = new ClientConfig();

    clientConfig.addAddress(ip + ":" + E3Constant.HAZELCAST_PORT);
    HazelcastClient client = HazelcastClient.newHazelcastClient(clientConfig);

    return client;
  }

  @Override
  public void lock(K key) {
    if (localMap == null) {
      logger.error("Attempt to lock a key in a cache without a map");
    } else {
      localMap.lock(key);
    }
  }

  @Override
  public void unlock(K key) {
    if (localMap == null) {
      logger.error("Attempt to unlock a key in a cache without a map");
    } else {
      localMap.unlock(key);
    }
  }

  @Override
  public void clear() {
    if (localMap == null) {
      logger.error("Attempt to clear a cache without a map");
    } else {
      localMap.clear();
    }
  }

  @Override
  public void addEntryListener(final IEntryListener<K, V> listener) {
    EntryListener<K, V> hzListener = new HZListener(listener);

    getEntryListenersMap().put(listener, hzListener);

    localMap.addEntryListener(hzListener, true);
  }

  @Override
  public void removeEntryListener(IEntryListener<K, V> listener) {
    EntryListener<K, V> hzListener = getEntryListenersMap().get(listener);
    getEntryListenersMap().remove(listener);
    localMap.removeEntryListener(hzListener);
  }

  /**
   * @return the entryListenersMap
   */
  protected Map<IEntryListener<K, V>, EntryListener<K, V>> getEntryListenersMap() {
    if (entryListenersMap == null)
      entryListenersMap = new HashMap<IEntryListener<K, V>, EntryListener<K, V>>();
    return entryListenersMap;
  }

  @Override
  public void addEntryListener(IEntryListener<K, V> listener, K key) {
    EntryListener<K, V> hzListener = new HZListener(listener);

    getEntryListenersMap().put(listener, hzListener);

    localMap.addEntryListener(hzListener, key, true);
  }

  @Override
  public void removeEntryListener(IEntryListener<K, V> listener, K key) {
    EntryListener<K, V> hzListener = getEntryListenersMap().get(listener);
    getEntryListenersMap().remove(listener);
    localMap.removeEntryListener(hzListener, key);
  }
 
  public class HZListener implements EntryListener<K, V> {
    protected IEntryListener<K, V> listener;
   
    public HZListener(IEntryListener<K, V> listener) {
      this.listener = listener;
    }
   
    @Override
    public void entryAdded(EntryEvent<K, V> event) {
      DataEntryEvent<K, V> dataEntryEvent = new DataEntryEvent<K, V>(event.getKey(), event.getValue());
      listener.entryAdded(dataEntryEvent);
    }

    @Override
    public void entryRemoved(EntryEvent<K, V> event) {
      DataEntryEvent<K, V> dataEntryEvent = new DataEntryEvent<K, V>(event.getKey(), event.getValue());
      listener.entryRemoved(dataEntryEvent);
    }

    @Override
    public void entryUpdated(EntryEvent<K, V> event) {
      DataEntryEvent<K, V> dataEntryEvent = new DataEntryEvent<K, V>(event.getKey(), event.getValue());
      listener.entryUpdated(dataEntryEvent);
    }

    @Override
    public void entryEvicted(EntryEvent<K, V> event) {

    }

  }
}
TOP

Related Classes of com.alu.e3.common.caching.HazelcastCache

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.