From 3145245341d61a0cf7f164119bfa771fb643aece Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Wed, 25 Jul 2012 04:34:20 +0000 Subject: [PATCH] * make sure to work around all ehcache diskcache problems, unexpected exceptions, inconsistency, etc --- source/net/sourceforge/filebot/Cache.java | 88 +++++++++++++++++++ .../filebot/format/MediaBindingBean.java | 19 ++-- .../web/AbstractEpisodeListProvider.java | 57 ++++-------- .../sourceforge/filebot/web/AnidbClient.java | 8 +- .../filebot/web/CachedResource.java | 6 ++ .../filebot/web/SerienjunkiesClient.java | 8 +- .../filebot/web/SubsceneSubtitleClient.java | 30 +++---- .../sourceforge/filebot/web/TVRageClient.java | 8 +- .../filebot/web/TheTVDBClient.java | 14 ++- 9 files changed, 148 insertions(+), 90 deletions(-) create mode 100644 source/net/sourceforge/filebot/Cache.java diff --git a/source/net/sourceforge/filebot/Cache.java b/source/net/sourceforge/filebot/Cache.java new file mode 100644 index 00000000..67744e49 --- /dev/null +++ b/source/net/sourceforge/filebot/Cache.java @@ -0,0 +1,88 @@ + +package net.sourceforge.filebot; + + +import java.io.Serializable; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Element; + + +public class Cache { + + public static Cache getCache(String name) { + return new Cache(CacheManager.getInstance().getCache(name)); + } + + private final net.sf.ehcache.Cache cache; + + + protected Cache(net.sf.ehcache.Cache cache) { + this.cache = cache; + } + + + public void put(Object key, Object value) { + try { + cache.put(new Element(key, value)); + } catch (Throwable e) { + Logger.getLogger(Cache.class.getName()).log(Level.WARNING, e.getMessage()); + remove(key); // fail-safe + } + } + + + public T get(Object key, Class type) { + try { + Element element = cache.get(key); + if (element != null && key.equals(element.getKey())) { + return type.cast(element.getValue()); + } + } catch (Exception e) { + Logger.getLogger(Cache.class.getName()).log(Level.WARNING, e.getMessage(), e); + remove(key); // fail-safe + } + + return null; + } + + + public void remove(Object key) { + try { + cache.remove(key); + } catch (Exception e) { + Logger.getLogger(Cache.class.getName()).log(Level.WARNING, e.getMessage(), e); + } + } + + + public static class Key implements Serializable { + + protected Object[] fields; + + + public Key(Object... fields) { + this.fields = fields; + } + + + @Override + public int hashCode() { + return Arrays.hashCode(fields); + } + + + @Override + public boolean equals(Object other) { + if (other instanceof Key) { + return Arrays.equals(this.fields, ((Key) other).fields); + } + + return false; + } + } + +} diff --git a/source/net/sourceforge/filebot/format/MediaBindingBean.java b/source/net/sourceforge/filebot/format/MediaBindingBean.java index 1a46de94..6f66e071 100644 --- a/source/net/sourceforge/filebot/format/MediaBindingBean.java +++ b/source/net/sourceforge/filebot/format/MediaBindingBean.java @@ -22,9 +22,7 @@ import java.util.Map; import java.util.Scanner; import java.util.Set; -import net.sf.ehcache.Cache; -import net.sf.ehcache.CacheManager; -import net.sf.ehcache.Element; +import net.sourceforge.filebot.Cache; import net.sourceforge.filebot.WebServices; import net.sourceforge.filebot.hash.HashType; import net.sourceforge.filebot.mediainfo.MediaInfo; @@ -589,15 +587,16 @@ public class MediaBindingBean { private String crc32(File file) throws IOException, InterruptedException { // try to get checksum from cache - Cache cache = CacheManager.getInstance().getCache("checksum"); - Element element = cache.get(file); - if (element != null) - return (String) element.getValue(); + Cache cache = Cache.getCache("checksum"); + + String hash = cache.get(file, String.class); + if (hash != null) { + return hash; + } // compute and cache checksum - String hash = computeHash(file, HashType.SFV); - cache.put(new Element(file, hash)); + hash = computeHash(file, HashType.SFV); + cache.put(file, hash); return hash; } - } diff --git a/source/net/sourceforge/filebot/web/AbstractEpisodeListProvider.java b/source/net/sourceforge/filebot/web/AbstractEpisodeListProvider.java index 531354de..f49c4275 100644 --- a/source/net/sourceforge/filebot/web/AbstractEpisodeListProvider.java +++ b/source/net/sourceforge/filebot/web/AbstractEpisodeListProvider.java @@ -2,15 +2,14 @@ package net.sourceforge.filebot.web; -import java.io.Serializable; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; +import net.sourceforge.filebot.Cache; +import net.sourceforge.filebot.Cache.Key; public abstract class AbstractEpisodeListProvider implements EpisodeListProvider { @@ -38,6 +37,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider } + @Override public List search(String query, Locale locale) throws Exception { ResultCache cache = getCache(); List results = (cache != null) ? cache.getSearchResult(query, locale) : null; @@ -58,6 +58,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider } + @Override public List getEpisodeList(SearchResult searchResult, SortOrder sortOrder, Locale locale) throws Exception { ResultCache cache = getCache(); List episodes = (cache != null) ? cache.getEpisodeList(searchResult, sortOrder, locale) : null; @@ -102,7 +103,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public List putSearchResult(String query, Locale locale, List value) { try { - cache.put(new Element(new Key(id, normalize(query), locale), value.toArray(new SearchResult[0]))); + cache.put(new Key(id, normalize(query), locale), value.toArray(new SearchResult[0])); } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); } @@ -113,9 +114,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public List getSearchResult(String query, Locale locale) { try { - Element element = cache.get(new Key(id, normalize(query), locale)); - if (element != null) { - return Arrays.asList(((SearchResult[]) element.getValue())); + SearchResult[] results = cache.get(new Key(id, normalize(query), locale), SearchResult[].class); + if (results != null) { + return Arrays.asList(results); } } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e); @@ -127,7 +128,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public List putEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale, List episodes) { try { - cache.put(new Element(new Key(id, key, sortOrder, locale), episodes.toArray(new Episode[0]))); + cache.put(new Key(id, key, sortOrder, locale), episodes.toArray(new Episode[0])); } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); } @@ -138,9 +139,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public List getEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale) { try { - Element element = cache.get(new Key(id, key, sortOrder, locale)); - if (element != null) { - return Arrays.asList((Episode[]) element.getValue()); + Episode[] episodes = cache.get(new Key(id, key, sortOrder, locale), Episode[].class); + if (episodes != null) { + return Arrays.asList(episodes); } } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e); @@ -152,7 +153,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public void putData(Object category, Object key, Locale locale, Object object) { try { - cache.put(new Element(new Key(id, category, locale, key), object)); + cache.put(new Key(id, category, locale, key), object); } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); } @@ -161,9 +162,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider public T getData(Object category, Object key, Locale locale, Class type) { try { - Element element = cache.get(new Key(id, category, locale, key)); - if (element != null) { - return type.cast(element.getValue()); + T value = cache.get(new Key(id, category, locale, key), type); + if (value != null) { + return value; } } catch (Exception e) { Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e); @@ -172,32 +173,6 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider return null; } - - private static class Key implements Serializable { - - protected Object[] fields; - - - public Key(Object... fields) { - this.fields = fields; - } - - - @Override - public int hashCode() { - return Arrays.hashCode(fields); - } - - - @Override - public boolean equals(Object other) { - if (other instanceof Key) { - return Arrays.equals(this.fields, ((Key) other).fields); - } - - return false; - } - } } } diff --git a/source/net/sourceforge/filebot/web/AnidbClient.java b/source/net/sourceforge/filebot/web/AnidbClient.java index b77e322e..76503c56 100644 --- a/source/net/sourceforge/filebot/web/AnidbClient.java +++ b/source/net/sourceforge/filebot/web/AnidbClient.java @@ -23,12 +23,12 @@ import java.util.zip.GZIPInputStream; import javax.swing.Icon; +import net.sourceforge.filebot.Cache; +import net.sourceforge.filebot.ResourceManager; + import org.w3c.dom.Document; import org.w3c.dom.Node; -import net.sf.ehcache.CacheManager; -import net.sourceforge.filebot.ResourceManager; - public class AnidbClient extends AbstractEpisodeListProvider { @@ -70,7 +70,7 @@ public class AnidbClient extends AbstractEpisodeListProvider { @Override public ResultCache getCache() { - return new ResultCache(host, CacheManager.getInstance().getCache("web-persistent-datasource")); + return new ResultCache(host, Cache.getCache("web-persistent-datasource")); } diff --git a/source/net/sourceforge/filebot/web/CachedResource.java b/source/net/sourceforge/filebot/web/CachedResource.java index d802beb1..a2806e88 100644 --- a/source/net/sourceforge/filebot/web/CachedResource.java +++ b/source/net/sourceforge/filebot/web/CachedResource.java @@ -53,6 +53,12 @@ public abstract class CachedResource { try { element = getCache().get(cacheKey); + + // sanity check ehcache diskcache problems + if (element != null && !cacheKey.equals(element.getKey().toString())) { + element = null; + } + if (element != null) { lastUpdateTime = element.getLatestOfCreationAndUpdateTime(); } diff --git a/source/net/sourceforge/filebot/web/SerienjunkiesClient.java b/source/net/sourceforge/filebot/web/SerienjunkiesClient.java index fd4d6bca..68e6086a 100644 --- a/source/net/sourceforge/filebot/web/SerienjunkiesClient.java +++ b/source/net/sourceforge/filebot/web/SerienjunkiesClient.java @@ -17,13 +17,13 @@ import java.util.Set; import javax.net.ssl.HttpsURLConnection; import javax.swing.Icon; +import net.sourceforge.filebot.Cache; +import net.sourceforge.filebot.ResourceManager; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; -import net.sf.ehcache.CacheManager; -import net.sourceforge.filebot.ResourceManager; - public class SerienjunkiesClient extends AbstractEpisodeListProvider { @@ -57,7 +57,7 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider { @Override public ResultCache getCache() { - return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource")); + return new ResultCache(host, Cache.getCache("web-datasource")); } diff --git a/source/net/sourceforge/filebot/web/SubsceneSubtitleClient.java b/source/net/sourceforge/filebot/web/SubsceneSubtitleClient.java index 44a3e74d..d30f4095 100644 --- a/source/net/sourceforge/filebot/web/SubsceneSubtitleClient.java +++ b/source/net/sourceforge/filebot/web/SubsceneSubtitleClient.java @@ -20,15 +20,13 @@ import java.util.regex.Pattern; import javax.swing.Icon; +import net.sourceforge.filebot.Cache; +import net.sourceforge.filebot.ResourceManager; + import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; -import net.sf.ehcache.Cache; -import net.sf.ehcache.CacheManager; -import net.sf.ehcache.Element; -import net.sourceforge.filebot.ResourceManager; - public class SubsceneSubtitleClient implements SubtitleProvider { @@ -121,34 +119,28 @@ public class SubsceneSubtitleClient implements SubtitleProvider { } + @SuppressWarnings("unchecked") protected String getLanguageFilter(String languageName) throws IOException, SAXException { if (languageName == null || languageName.isEmpty()) { return null; } // try cache first - Cache cache = CacheManager.getInstance().getCache("web-persistent-datasource"); + Cache cache = Cache.getCache("web-persistent-datasource"); String cacheKey = getClass().getName() + ".languageFilter"; - try { - Element element = cache.get(cacheKey); - if (element != null) { - return (String) ((Map) element.getValue()).get(languageName.toLowerCase()); - } - } catch (Exception e) { - Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage()); + Map filters = cache.get(cacheKey, Map.class); + + if (filters != null) { + return filters.get(languageName.toLowerCase()); } // fetch new language filter data - Map filters = getLanguageFilterMap(); + filters = getLanguageFilterMap(); // update cache after sanity check if (filters.size() > 42) { - try { - cache.put(new Element(cacheKey, filters)); - } catch (Exception e) { - Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage()); - } + cache.put(cacheKey, filters); } else { Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to scrape language filters: " + filters); } diff --git a/source/net/sourceforge/filebot/web/TVRageClient.java b/source/net/sourceforge/filebot/web/TVRageClient.java index 01a8ee03..3a7549be 100644 --- a/source/net/sourceforge/filebot/web/TVRageClient.java +++ b/source/net/sourceforge/filebot/web/TVRageClient.java @@ -15,13 +15,13 @@ import java.util.Locale; import javax.swing.Icon; +import net.sourceforge.filebot.Cache; +import net.sourceforge.filebot.ResourceManager; + import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; -import net.sf.ehcache.CacheManager; -import net.sourceforge.filebot.ResourceManager; - public class TVRageClient extends AbstractEpisodeListProvider { @@ -42,7 +42,7 @@ public class TVRageClient extends AbstractEpisodeListProvider { @Override public ResultCache getCache() { - return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource")); + return new ResultCache(host, Cache.getCache("web-datasource")); } diff --git a/source/net/sourceforge/filebot/web/TheTVDBClient.java b/source/net/sourceforge/filebot/web/TheTVDBClient.java index ad98d8ac..975132a4 100644 --- a/source/net/sourceforge/filebot/web/TheTVDBClient.java +++ b/source/net/sourceforge/filebot/web/TheTVDBClient.java @@ -29,15 +29,15 @@ import java.util.zip.ZipInputStream; import javax.swing.Icon; import javax.xml.parsers.DocumentBuilderFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import net.sf.ehcache.CacheManager; +import net.sourceforge.filebot.Cache; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.web.TheTVDBClient.BannerDescriptor.BannerProperty; import net.sourceforge.filebot.web.TheTVDBClient.SeriesInfo.SeriesProperty; import net.sourceforge.tuned.FileUtilities; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + public class TheTVDBClient extends AbstractEpisodeListProvider { @@ -99,7 +99,7 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { @Override public ResultCache getCache() { - return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource")); + return new ResultCache(host, Cache.getCache("web-datasource")); } @@ -274,7 +274,7 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { // try cache first try { @SuppressWarnings("unchecked") - Map cachedMirrors = (Map) getCache().getData("mirrors", null, null, Map.class); + Map cachedMirrors = getCache().getData("mirrors", null, null, Map.class); if (cachedMirrors != null) { mirrors.putAll(cachedMirrors); return mirrors.get(mirrorType); @@ -479,7 +479,6 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { poster } - protected Map fields; @@ -762,7 +761,6 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { VignettePath } - protected Map fields;