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.services; 019 020import net.sf.ehcache.Cache; 021import net.sf.ehcache.CacheManager; 022import net.sf.ehcache.Ehcache; 023import net.sf.ehcache.Element; 024import net.sf.ehcache.config.CacheConfiguration; 025import net.sf.ehcache.config.Configuration; 026import net.sf.ehcache.config.PersistenceConfiguration; 027 028import java.util.Timer; 029import java.util.TimerTask; 030 031import static io.stallion.utils.Literals.*; 032import static io.stallion.Context.*; 033 034 035public class LocalMemoryCache { 036 private static CacheManager manager; 037 private static TimerTask evictThread; 038 private static Timer evictThreadTimer; 039 040 041 042 public static void start() { 043 if (manager == null) { 044 load(); 045 } 046 047 // Every 5 minutes, evict all expired elements from the cache so they do not build up over time 048 evictThread = new TimerTask() { 049 public void run() { 050 Thread.currentThread().setName("stallion-ehcache-evict-task"); 051 if (manager == null) { 052 return; 053 } 054 for(String name: manager.getCacheNames()) { 055 manager.getCache(name).evictExpiredElements(); 056 } 057 } 058 }; 059 060 evictThreadTimer = new Timer("stallion-ehcache-evict-timer"); 061 evictThreadTimer.scheduleAtFixedRate(evictThread, 0, 5 * 60 * 1000); 062 } 063 064 public static void shutdown() { 065 066 if (evictThreadTimer != null) { 067 evictThreadTimer.cancel(); 068 evictThreadTimer = null; 069 } 070 if (evictThread != null) { 071 evictThread.cancel(); 072 evictThread = null; 073 } 074 if (manager != null) { 075 manager.shutdown(); 076 manager = null; 077 } 078 } 079 080 public static void load() { 081 082 Configuration config = new Configuration(); 083 config.setName("stallionLocalMemoryCache"); 084 manager = CacheManager.create(); 085 } 086 087 public static void initCache(String bucket) { 088 if (manager == null) { 089 load(); 090 } 091 if (manager.getCache(bucket) != null) { 092 return; 093 } 094 synchronized(manager) { 095 if (manager.getCache(bucket) != null) { 096 return; 097 } 098 CacheConfiguration config = new CacheConfiguration(); 099 config.setName(bucket); 100 // We have to do this way because there is no way to programmatically configure the 101 // sizeOfEngine 102 System.setProperty("net.sf.ehcache.sizeofengine.stallionLocalMemoryCache." + bucket, "io.stallion.dataAccess.filtering.EstimatedSizeOfEngine"); 103 104 // Max cache size is 100MB 105 config.setMaxBytesLocalHeap(100 * 1000 * 1000L); 106 //config.setDiskPersistent(false); 107 //config.setMaxElementsOnDisk(0); 108 //config.setMaxBytesLocalDisk(0L); 109 config.setOverflowToOffHeap(false); 110 PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration(); 111 persistenceConfiguration.strategy(PersistenceConfiguration.Strategy.NONE); 112 config.persistence(persistenceConfiguration); 113 manager.addCache(new Cache(config)); 114 } 115 } 116 117 public static Object get(String key) { 118 return get("default", key); 119 } 120 121 public static Object get(String bucket, String key) { 122 bucket = or(bucket, "default"); 123 if (manager == null) { 124 return null; 125 } 126 if (!manager.cacheExists(bucket)) { 127 return null; 128 } 129 Element element = manager.getCache(bucket).get(key); 130 if (element != null) { 131 return element.getObjectValue(); 132 } 133 return null; 134 } 135 public static void set(String key, Object value, int timeoutSeconds) { 136 set("default", key, value, timeoutSeconds); 137 } 138 public static void set(String bucket, String key, Object value) { 139 set(bucket, key, value, 15); 140 } 141 public static void set(String bucket, String key, Object value, int timeoutSeconds) { 142 bucket = or(bucket, "default"); 143 if (manager == null) { 144 load(); 145 } 146 if (!manager.cacheExists(bucket)) { 147 initCache(bucket); 148 } 149 Element element = new Element(key, value); 150 element.setTimeToLive(timeoutSeconds); 151 manager.getCache(bucket).put(element); 152 } 153 154 public static void clearBucket(String bucket) { 155 if (manager.cacheExists(bucket) && manager.getCache(bucket).getSize() > 0) { 156 manager.getCache(bucket).removeAll(); 157 } 158 } 159 160}