/* * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ package com.l2jserver.gameserver.cache; import javolution.context.ObjectFactory; import javolution.lang.Reusable; import javolution.util.FastCollection; import javolution.util.FastComparator; import javolution.util.FastList; import javolution.util.FastMap; /** * @author Layane * @param * @param */ @SuppressWarnings({ "rawtypes" }) public class FastMRUCache extends FastCollection implements Reusable { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1L; private static final int DEFAULT_CAPACITY = 50; private static final int DEFAULT_FORGET_TIME = 300000; //5 Minutes private FastMap _cache = new FastMap().setKeyComparator(FastComparator.DIRECT); private FastMap _map; private FastList _mruList = new FastList<>(); private int _cacheSize; private int _forgetTime; class CacheNode { long _lastModified; V _node; public CacheNode(V object) { _lastModified = System.currentTimeMillis(); _node = object; } @Override public boolean equals(Object object) { return _node == object; } } /** * Holds the set factory. */ private static final ObjectFactory FACTORY = new ObjectFactory() { @Override public Object create() { return new FastMRUCache(); } @Override public void cleanup(Object obj) { ((FastMRUCache) obj).reset(); } }; /** * Returns a set allocated from the stack when executing in a * @return a new, pre-allocated or recycled set instance. */ public static FastMRUCache newInstance() { return (FastMRUCache) FACTORY.object(); } public FastMRUCache() { this(new FastMap(), DEFAULT_CAPACITY, DEFAULT_FORGET_TIME); } public FastMRUCache(FastMap map) { this(map, DEFAULT_CAPACITY, DEFAULT_FORGET_TIME); } public FastMRUCache(FastMap map, int max) { this(map, max, DEFAULT_FORGET_TIME); } public FastMRUCache(FastMap map, int max, int forgetTime) { _map = map; _cacheSize = max; _forgetTime = forgetTime; _map.setKeyComparator(FastComparator.DIRECT); } // Implements Reusable. @Override public synchronized void reset() { _map.reset(); _cache.reset(); _mruList.reset(); _map.setKeyComparator(FastComparator.DIRECT); _cache.setKeyComparator(FastComparator.DIRECT); } public synchronized V get(K key) { V result; if (!_cache.containsKey(key)) { if (_mruList.size() >= _cacheSize) { _cache.remove(_mruList.getLast()); _mruList.removeLast(); } result = _map.get(key); _cache.put(key, new CacheNode(result)); _mruList.addFirst(key); } else { CacheNode current = _cache.get(key); if ((current._lastModified + _forgetTime) <= System.currentTimeMillis()) { current._lastModified = System.currentTimeMillis(); current._node = _map.get(key); _cache.put(key, current); } _mruList.remove(key); _mruList.addFirst(key); result = current._node; } return result; } @Override public synchronized boolean remove(Object key) { _cache.remove(key); _mruList.remove(key); return _map.remove(key) == key; } public FastMap getContentMap() { return _map; } @Override public int size() { return _mruList.size(); } public int capacity() { return _cacheSize; } public int getForgetTime() { return _forgetTime; } @Override public synchronized void clear() { _cache.clear(); _mruList.clear(); _map.clear(); } // Implements FastCollection abstract method. @Override public final Record head() { return _mruList.head(); } @Override public final Record tail() { return _mruList.tail(); } @Override public final Object valueOf(Record record) { return ((FastMap.Entry) record).getKey(); } @Override public final void delete(Record record) { remove(((FastMap.Entry) record).getKey()); } }