[Winstone-devel] generator_runtime/src/java/generator/runtime/db/cache DBCache.java,NONE,1.1 DBCache
Status: Beta
Brought to you by:
rickknowles
From: Rick K. <ric...@us...> - 2004-12-07 09:51:51
|
Update of /cvsroot/winstone/generator_runtime/src/java/generator/runtime/db/cache In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18339/src/java/generator/runtime/db/cache Added Files: DBCache.java DBCacheInvalidationServlet.java DBCacheFacade.java Log Message: initial commit to sourceforge --- NEW FILE: DBCacheInvalidationServlet.java --- /* * Generator Runtime Servlet Framework * Copyright (C) 2004 Rick Knowles * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * Version 2 as published by the Free Software Foundation. * * 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 Version 2 for more details. * * You should have received a copy of the GNU Library General Public License * Version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package generator.runtime.db.cache; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import generator.runtime.db.DBContextInitializer; import generator.runtime.db.DBPeerFactory; import generator.runtime.servlet.BaseServlet; import generator.runtime.utils.Logger; /** * This servlet is used to support cache invalidation across multiple * application servers in a farm configuration. It forms the listener * component, which accepts cache invalidation messages and deletes the * requested cache element. * * @author <a href="mailto:ric...@ho...">Rick Knowles</a> * @version $Id: DBCacheInvalidationServlet.java,v 1.1 2004/12/07 09:51:31 rickknowles Exp $ */ public class DBCacheInvalidationServlet extends BaseServlet { /** * Accepts a cache invalidation request, and removes the element. * Note that the operations are done directly on the actual * cache object rather than the DBPeerFactory - this is to avoid * endless loops of propogated invalidation requests. */ protected void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Get the cache name and key String flushAll = request.getParameter("flushAll"); String cacheName = request.getParameter("cacheName"); String cacheKey = request.getParameter("cacheKey"); DBPeerFactory factory = (DBPeerFactory) getServletContext() .getAttribute(DBContextInitializer.ATTR_PEER_FACTORY); DBCacheFacade cacheFacade = factory.getCacheFacade(); DBCache cache = cacheFacade.getCache(); if (flushAll != null) { // Delete from all caches Logger.log(Logger.DEBUG, "Dumping all DB caches via DBCacheInvalidationServlet"); cache.dumpAllCaches(); response.getWriter() .println("OK"); } else if (cacheName == null) { Logger.log(Logger.WARNING, "WARNING: No cacheName supplied in the request, ignoring"); response.getWriter() .println("WARNING: No cacheName supplied in the request, ignoring"); } else if (cacheKey == null) { Logger.log(Logger.WARNING, "WARNING: No cacheKey supplied in the request, ignoring"); response.getWriter() .println("WARNING: No cacheKey supplied in the request, ignoring"); } else { // Delete from the cache Logger.log( Logger.DEBUG, "Dumping cache entry (cache=" + cacheName + ", key=" + cacheKey + ") via DBCacheInvalidationServlet"); cache.invalidateCacheEntry(cacheName, cacheKey); response.getWriter().println("OK"); } } } --- NEW FILE: DBCache.java --- /* * Generator Runtime Servlet Framework * Copyright (C) 2004 Rick Knowles * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * Version 2 as published by the Free Software Foundation. * * 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 Version 2 for more details. * * You should have received a copy of the GNU Library General Public License * Version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package generator.runtime.db.cache; import generator.runtime.utils.ApplicationProperties; import generator.runtime.utils.Logger; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; /** * A set of caches (implemented as simple maps). This abstracts the * caching storage functions into a single class. To ensure data * doesn't become stale, it is recommended all caches be flushed * at a regular interval. * * The cross-server notification mechanisms are implemented in * DBCacheFacade. * * @author <a href="mailto:ric...@ho...">Rick Knowles</a> * @version $Id: DBCache.java,v 1.1 2004/12/07 09:51:31 rickknowles Exp $ */ public class DBCache { private Map cacheSet; private List cacheInvalidationListenerURLs; private String cacheMessageEncoding; public DBCache() { this.cacheInvalidationListenerURLs = new Vector(); this.cacheSet = new Hashtable(); } public void init(ApplicationProperties cacheProps) { this.cacheInvalidationListenerURLs.clear(); dumpAllCaches(); // Get the invalidation url list this.cacheMessageEncoding = cacheProps.stringProperty("@encoding", "UTF-8"); Set invalidationURLKeys = cacheProps.getAll("invalidationURL/", true) .keySet(); for (Iterator i = invalidationURLKeys.iterator(); i.hasNext();) { String key = (String) i.next(); String url = cacheProps.stringProperty(key, ""); if (!url.equals("")) { this.cacheInvalidationListenerURLs.add(url); } } Logger.log(Logger.DEBUG, "Initialised cache listener list: " + this.cacheInvalidationListenerURLs.size() + " urls with encoding " + this.cacheMessageEncoding); } private Set getAllCacheNames() { Set names = null; synchronized (this.cacheSet) { names = new HashSet(this.cacheSet.keySet()); } return names; } private Map getCache(String cacheName) { Map cache = null; synchronized (this.cacheSet) { cache = (Map) this.cacheSet.get(cacheName); if (cache == null) { cache = new Hashtable(); this.cacheSet.put(cacheName, cache); } } return cache; } Object getFromCache(String cacheName, String cacheKey) { Map cache = getCache(cacheName); Object value = null; synchronized (cache) { value = cache.get(cacheKey); } Logger.log(Logger.DEBUG, "Getting from cache: cacheName=" + cacheName + ",cacheKey=" + cacheKey + ((value == null) ? ", not found" : ", found")); return value; } void invalidateCacheEntry(String cacheName, String cacheKey) { Logger.log(Logger.DEBUG, "Invalidating cache entry: cacheName=" + cacheName + ",cacheKey=" + cacheKey); Map cache = getCache(cacheName); synchronized (cache) { cache.remove(cacheKey); } } void addToCache(String cacheName, String cacheKey, Object cacheObject) { if (cacheObject == null) { return; } Logger.log(Logger.DEBUG, "Adding cache entry: cacheName=" + cacheName + ",cacheKey=" + cacheKey); Map cache = getCache(cacheName); synchronized (cache) { cache.put(cacheKey, cacheObject); } } void dumpAllCaches() { Set allCacheKeys = getAllCacheNames(); for (Iterator i = allCacheKeys.iterator(); i.hasNext();) { String cacheName = (String) i.next(); Logger.log(Logger.DEBUG, "Invalidating entire cache: cacheName=" + cacheName); Map cache = getCache(cacheName); synchronized (cache) { cache.clear(); } } } } --- NEW FILE: DBCacheFacade.java --- /* * Generator Runtime Servlet Framework * Copyright (C) 2004 Rick Knowles * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * Version 2 as published by the Free Software Foundation. * * 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 Version 2 for more details. * * You should have received a copy of the GNU Library General Public License * Version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package generator.runtime.db.cache; import generator.runtime.utils.ApplicationProperties; import generator.runtime.utils.Logger; import generator.runtime.utils.ServletUtils; import generator.runtime.utils.SimpleHttpClient; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; /** * This is a wrapper around the DBCache class to manage the cross-server * notification requirements. Except when explicitly requiring access to the * local cache, the external interfaces on this class should be used in * preference to those on the member cache variable, to ensure correct * synchronization messages to be sent between server caches. * * @author <a href="mailto:ric...@ho...">Rick Knowles</a> * @version $Id: DBCacheFacade.java,v 1.1 2004/12/07 09:51:31 rickknowles Exp $ */ public class DBCacheFacade { private DBCache cache; private List cacheInvalidationListenerURLs; private String cacheMessageEncoding; public DBCacheFacade() { this.cacheInvalidationListenerURLs = new Vector(); this.cache = new DBCache(); } public void init(ApplicationProperties cacheProps) { this.cacheInvalidationListenerURLs.clear(); // Get the invalidation url list this.cacheMessageEncoding = cacheProps.stringProperty("@encoding", "UTF-8"); Set invalidationURLKeys = cacheProps.getAll("invalidationURL/", true) .keySet(); for (Iterator i = invalidationURLKeys.iterator(); i.hasNext();) { String key = (String) i.next(); String url = cacheProps.stringProperty(key, ""); if (!url.equals("")) { this.cacheInvalidationListenerURLs.add(url); } } Logger.log(Logger.DEBUG, "Initialised cache listener list: " + this.cacheInvalidationListenerURLs.size() + " urls with encoding " + this.cacheMessageEncoding); this.cache.init(cacheProps); } /** * Send invalidate messages to all the cache invalidation listeners */ void sendInvalidateToListeningCaches(String cacheName, String cacheKey) { for (Iterator i = this.cacheInvalidationListenerURLs.iterator(); i.hasNext();) { String url = ServletUtils.addParamsToURL((String) i.next(), new String[][] {{"cacheName", cacheName}, {"cacheKey", cacheKey} }, cacheMessageEncoding, true); Logger.log(Logger.DEBUG, "Sending cache invalidation message: " + url); SimpleHttpClient http = new SimpleHttpClient(url, false, cacheMessageEncoding); http.getThreaded(); } } public DBCache getCache() { return this.cache; } public Object getFromCache(String cacheName, String cacheKey) { return cache.getFromCache(cacheName, cacheKey); } public void invalidateCacheEntry(String cacheName, String cacheKey) { cache.invalidateCacheEntry(cacheName, cacheKey); sendInvalidateToListeningCaches(cacheName, cacheKey); } public void addToCache(String cacheName, String cacheKey, Object cacheObject) { cache.addToCache(cacheName, cacheKey, cacheObject); } public void dumpAllCaches() { cache.dumpAllCaches(); } } |