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

com.eurodyn.qlack2.fuse.caching.impl.memcached.CacheServiceImpl Maven / Gradle / Ivy

/*
* Copyright 2014 EUROPEAN DYNAMICS SA 
*
* Licensed under the EUPL, Version 1.1 only (the "License").
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
package com.eurodyn.qlack2.fuse.caching.impl.memcached;

import com.eurodyn.qlack2.fuse.caching.api.CacheService;
import com.google.common.base.Predicates;
import com.google.common.collect.Sets;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.BinaryConnectionFactory;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.OperationTimeoutException;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A Memcached backed caching client. The caching URL represents the IP address and the port of
 * Memcached, e.g. my-memcached-server:1234.
 */
public class CacheServiceImpl extends CacheService {

  public static final Logger LOGGER = Logger.getLogger(CacheServiceImpl.class.getName());
  private MemcachedClient cache;

  /**
   * As Memcached does not support enlisting of its keys, this is a workaround
   * to allow deleting keys by a regular expression. Note that for very large
   * caches this may not be the most effective usage pattern, however if you
   * *need* to use Memcached this is your only option.
   */
  Set keys;

  public CacheServiceImpl() {
    try {
      if (isActive()) {
        cache = new MemcachedClient(new BinaryConnectionFactory(), AddrUtil
          .getAddresses(getCacheURL()));
        LOGGER.fine(MessageFormat.format("Using cache server {0}.", getCacheURL()));
        keys = Sets.newConcurrentHashSet();
      }
    } catch (IOException e) {
      LOGGER.log(Level.SEVERE, "Cache client could not be initialised.", e);
    }
  }

  public MemcachedClient getCache() {
    return cache;
  }

  public void destroy() {
    if (cache != null) {
      cache.shutdown();
      cache = null;
      keys.clear();
      keys = null;
    }
  }

  @Override
  public void set(String key, Object value) {
    if (isActive()) {
      try {
        /**
         * Memcached expresses EPOCH in seconds, therefore we need to convert the msec passed EPOCH.
         */
        int expiresAtEpochSec =
          getExpiryTime() > 0 ? (int) ((System.currentTimeMillis() + getExpiryTime()) / 1000l) : 0;
        cache.set(key, expiresAtEpochSec, value);
        LOGGER.log(Level.FINEST, "Added to memcached key {0}, with " + "value {1}.",
          new String[]{key, value.toString()});
        keys.add(key);
      } catch (OperationTimeoutException | CancellationException e) {
        LOGGER.log(Level.FINEST, "Could not add the key to the cache.", e);
      }
    }
  }

  @Override
  public void deleteByKeyName(String key) {
    if (isActive()) {
      try {
        cache.delete(key);
        keys.remove(key);
        LOGGER.log(Level.FINEST, "Deleted from memcached key {0}.", key);
      } catch (OperationTimeoutException | CancellationException e) {
        LOGGER.log(Level.FINEST, "Could not delete the key from the cache.", e);
      }
    }
  }

  @Override
  public Object get(String key) {
    Object retVal = null;

    if (isActive()) {
      try {
        if (cache != null) {
          retVal = cache.get(key);
        }
      } catch (OperationTimeoutException | CancellationException e) {
        LOGGER.log(Level.FINEST, "Could not get the key to the cache.", e);
      }
    }

    return retVal;
  }

  @Override
  public void deleteByKeyPattern(String pattern) {
    if (isActive()) {
      Set filter = Sets.filter(keys, Predicates.containsPattern(pattern));
      for (String key : filter) {
        deleteByKeyName(key);
      }
    }
  }

  @Override
  public void deleteByKeyPrefix(String prefix) {
    if (isActive()) {
      deleteByKeyPattern(prefix + ".*");
    }
  }

  @Override
  public Set getKeyNames() {
    Set retVal = new HashSet<>();

    if (isActive()) {
      retVal = keys;
    }

    return retVal;
  }

  @Override
  public void clear() {
    if (isActive()) {
      cache.flush();
      keys.clear();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy