001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.dataAccess.filtering;
019
020import io.stallion.settings.Settings;
021import net.sf.ehcache.Cache;
022import net.sf.ehcache.CacheManager;
023import net.sf.ehcache.Element;
024import net.sf.ehcache.config.CacheConfiguration;
025import net.sf.ehcache.config.Configuration;
026import net.sf.ehcache.config.PersistenceConfiguration;
027import net.sf.ehcache.config.SizeOfPolicyConfiguration;
028
029import java.util.Timer;
030import java.util.TimerTask;
031
032/**
033 * A cache used by filters to cache the results of filtering queries,
034 * default TTL is 25 seconds, the cache is expired every time there is
035 * any sort of update to an item in the bucket.
036 *
037 */
038public class FilterCache {
039
040    private static CacheManager manager;
041    private static TimerTask evictThread;
042    private static Timer evictThreadTimer;
043
044
045    public static void start() {
046        if (manager == null) {
047            load();
048        }
049
050        // Every 5 minutes, evict all expired elements from the cache so they do not build up over time
051        evictThread = new TimerTask() {
052            public void run() {
053                Thread.currentThread().setName("stallion-ehcache-evict-task");
054                if (manager == null) {
055                    return;
056                }
057                for(String name: manager.getCacheNames()) {
058                    manager.getCache(name).evictExpiredElements();
059                }
060            }
061        };
062
063        evictThreadTimer = new Timer("stallion-ehcache-evict-timer");
064        evictThreadTimer.scheduleAtFixedRate(evictThread, 0, 5 * 60 * 1000);
065    }
066
067    public static void shutdown() {
068        if (evictThreadTimer != null) {
069            evictThreadTimer.cancel();
070            evictThreadTimer = null;
071        }
072        if (evictThread != null) {
073            evictThread.cancel();
074            evictThread = null;
075        }
076        if (manager != null) {
077            manager.shutdown();
078            manager = null;
079        }
080    }
081
082
083    public static void load() {
084
085        Configuration config = new Configuration();
086        config.setName("stallionFilterCache");
087        CacheManager.create(config);
088        manager = CacheManager.create();
089    }
090
091    public static void initCache(String bucket) {
092        if (manager == null) {
093            load();
094        }
095        if (manager.getCache(bucket) != null) {
096            return;
097        }
098        // We have to do this way because there is no way to programmmatically configured the
099        // sizeOfEngine
100        System.setProperty("net.sf.ehcache.sizeofengine.stallionFilterCache." + bucket, "io.stallion.dataAccess.filtering.EstimatedSizeOfEngine");
101
102        CacheConfiguration config = new CacheConfiguration();
103        config.setName(bucket);
104        // Max cache size is very approximately, 50MB
105
106        config.setMaxBytesLocalHeap(Settings.instance().getFilterCacheSize());
107        //config.setDiskPersistent(false);
108        //config.setMaxElementsOnDisk(0);
109        //config.setMaxBytesLocalDisk(0L);
110        config.setOverflowToOffHeap(false);
111        PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration();
112        persistenceConfiguration.strategy(PersistenceConfiguration.Strategy.NONE);
113
114        config.persistence(persistenceConfiguration);
115        //SizeOfPolicyConfiguration sizeOfPolicyConfiguration = new SizeOfPolicyConfiguration();
116        //sizeOfPolicyConfiguration.
117        //config.addSizeOfPolicy();
118        //config.set
119        Cache cache = new Cache(config);
120
121        manager.addCache(cache);
122
123        //Cache cache = manager.getCache(bucket);
124        //CacheConfiguration config = cache.getCacheConfiguration();
125
126
127        //config.setMaxBytesLocalHeap(150000000L);
128    }
129
130
131    public static Object get(String bucket, String key) {
132        if (manager == null) {
133            return null;
134        }
135        Cache cache = manager.getCache(bucket);
136        if (cache == null) {
137            return null;
138        }
139        Element element = cache.get(key);
140        if (element != null) {
141            return element.getObjectValue();
142        }
143        return null;
144
145    }
146
147    public static void set(String bucket, String key, Object value) {
148        if (manager == null) {
149            load();
150        }
151        if (!manager.cacheExists(bucket)) {
152            initCache(bucket);
153        }
154        Element element = new Element(key, value);
155        element.setTimeToLive(60);
156        manager.getCache(bucket).put(element);
157    }
158
159    public static void clearBucket(String bucket) {
160        if (manager.cacheExists(bucket) && manager.getCache(bucket).getSize() > 0) {
161            manager.getCache(bucket).removeAll();
162        }
163    }
164
165}