* make sure to work around all ehcache diskcache problems, unexpected exceptions, inconsistency, etc

This commit is contained in:
Reinhard Pointner 2012-07-25 04:34:20 +00:00
parent 581fd76265
commit 3145245341
9 changed files with 148 additions and 90 deletions

View File

@ -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> T get(Object key, Class<T> 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;
}
}
}

View File

@ -22,9 +22,7 @@ import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
import java.util.Set; import java.util.Set;
import net.sf.ehcache.Cache; import net.sourceforge.filebot.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sourceforge.filebot.WebServices; import net.sourceforge.filebot.WebServices;
import net.sourceforge.filebot.hash.HashType; import net.sourceforge.filebot.hash.HashType;
import net.sourceforge.filebot.mediainfo.MediaInfo; import net.sourceforge.filebot.mediainfo.MediaInfo;
@ -589,15 +587,16 @@ public class MediaBindingBean {
private String crc32(File file) throws IOException, InterruptedException { private String crc32(File file) throws IOException, InterruptedException {
// try to get checksum from cache // try to get checksum from cache
Cache cache = CacheManager.getInstance().getCache("checksum"); Cache cache = Cache.getCache("checksum");
Element element = cache.get(file);
if (element != null)
return (String) element.getValue();
// compute and cache checksum String hash = cache.get(file, String.class);
String hash = computeHash(file, HashType.SFV); if (hash != null) {
cache.put(new Element(file, hash));
return hash; return hash;
} }
// compute and cache checksum
hash = computeHash(file, HashType.SFV);
cache.put(file, hash);
return hash;
}
} }

View File

@ -2,15 +2,14 @@
package net.sourceforge.filebot.web; package net.sourceforge.filebot.web;
import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.ehcache.Cache; import net.sourceforge.filebot.Cache;
import net.sf.ehcache.Element; import net.sourceforge.filebot.Cache.Key;
public abstract class AbstractEpisodeListProvider implements EpisodeListProvider { public abstract class AbstractEpisodeListProvider implements EpisodeListProvider {
@ -38,6 +37,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
} }
@Override
public List<SearchResult> search(String query, Locale locale) throws Exception { public List<SearchResult> search(String query, Locale locale) throws Exception {
ResultCache cache = getCache(); ResultCache cache = getCache();
List<SearchResult> results = (cache != null) ? cache.getSearchResult(query, locale) : null; List<SearchResult> results = (cache != null) ? cache.getSearchResult(query, locale) : null;
@ -58,6 +58,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
} }
@Override
public List<Episode> getEpisodeList(SearchResult searchResult, SortOrder sortOrder, Locale locale) throws Exception { public List<Episode> getEpisodeList(SearchResult searchResult, SortOrder sortOrder, Locale locale) throws Exception {
ResultCache cache = getCache(); ResultCache cache = getCache();
List<Episode> episodes = (cache != null) ? cache.getEpisodeList(searchResult, sortOrder, locale) : null; List<Episode> episodes = (cache != null) ? cache.getEpisodeList(searchResult, sortOrder, locale) : null;
@ -102,7 +103,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
public <T extends SearchResult> List<T> putSearchResult(String query, Locale locale, List<T> value) { public <T extends SearchResult> List<T> putSearchResult(String query, Locale locale, List<T> value) {
try { 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) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage());
} }
@ -113,9 +114,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
public List<SearchResult> getSearchResult(String query, Locale locale) { public List<SearchResult> getSearchResult(String query, Locale locale) {
try { try {
Element element = cache.get(new Key(id, normalize(query), locale)); SearchResult[] results = cache.get(new Key(id, normalize(query), locale), SearchResult[].class);
if (element != null) { if (results != null) {
return Arrays.asList(((SearchResult[]) element.getValue())); return Arrays.asList(results);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e); Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e);
@ -127,7 +128,7 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
public List<Episode> putEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale, List<Episode> episodes) { public List<Episode> putEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale, List<Episode> episodes) {
try { 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) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage());
} }
@ -138,9 +139,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
public List<Episode> getEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale) { public List<Episode> getEpisodeList(SearchResult key, SortOrder sortOrder, Locale locale) {
try { try {
Element element = cache.get(new Key(id, key, sortOrder, locale)); Episode[] episodes = cache.get(new Key(id, key, sortOrder, locale), Episode[].class);
if (element != null) { if (episodes != null) {
return Arrays.asList((Episode[]) element.getValue()); return Arrays.asList(episodes);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), 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) { public void putData(Object category, Object key, Locale locale, Object object) {
try { try {
cache.put(new Element(new Key(id, category, locale, key), object)); cache.put(new Key(id, category, locale, key), object);
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage()); Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage());
} }
@ -161,9 +162,9 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
public <T> T getData(Object category, Object key, Locale locale, Class<T> type) { public <T> T getData(Object category, Object key, Locale locale, Class<T> type) {
try { try {
Element element = cache.get(new Key(id, category, locale, key)); T value = cache.get(new Key(id, category, locale, key), type);
if (element != null) { if (value != null) {
return type.cast(element.getValue()); return value;
} }
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e); Logger.getLogger(AbstractEpisodeListProvider.class.getName()).log(Level.WARNING, e.getMessage(), e);
@ -172,32 +173,6 @@ public abstract class AbstractEpisodeListProvider implements EpisodeListProvider
return null; 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;
}
}
} }
} }

View File

@ -23,12 +23,12 @@ import java.util.zip.GZIPInputStream;
import javax.swing.Icon; import javax.swing.Icon;
import net.sourceforge.filebot.Cache;
import net.sourceforge.filebot.ResourceManager;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import net.sf.ehcache.CacheManager;
import net.sourceforge.filebot.ResourceManager;
public class AnidbClient extends AbstractEpisodeListProvider { public class AnidbClient extends AbstractEpisodeListProvider {
@ -70,7 +70,7 @@ public class AnidbClient extends AbstractEpisodeListProvider {
@Override @Override
public ResultCache getCache() { public ResultCache getCache() {
return new ResultCache(host, CacheManager.getInstance().getCache("web-persistent-datasource")); return new ResultCache(host, Cache.getCache("web-persistent-datasource"));
} }

View File

@ -53,6 +53,12 @@ public abstract class CachedResource<T extends Serializable> {
try { try {
element = getCache().get(cacheKey); element = getCache().get(cacheKey);
// sanity check ehcache diskcache problems
if (element != null && !cacheKey.equals(element.getKey().toString())) {
element = null;
}
if (element != null) { if (element != null) {
lastUpdateTime = element.getLatestOfCreationAndUpdateTime(); lastUpdateTime = element.getLatestOfCreationAndUpdateTime();
} }

View File

@ -17,13 +17,13 @@ import java.util.Set;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.swing.Icon; import javax.swing.Icon;
import net.sourceforge.filebot.Cache;
import net.sourceforge.filebot.ResourceManager;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.json.simple.JSONValue; import org.json.simple.JSONValue;
import net.sf.ehcache.CacheManager;
import net.sourceforge.filebot.ResourceManager;
public class SerienjunkiesClient extends AbstractEpisodeListProvider { public class SerienjunkiesClient extends AbstractEpisodeListProvider {
@ -57,7 +57,7 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
@Override @Override
public ResultCache getCache() { public ResultCache getCache() {
return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource")); return new ResultCache(host, Cache.getCache("web-datasource"));
} }

View File

@ -20,15 +20,13 @@ import java.util.regex.Pattern;
import javax.swing.Icon; import javax.swing.Icon;
import net.sourceforge.filebot.Cache;
import net.sourceforge.filebot.ResourceManager;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.SAXException; 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 { public class SubsceneSubtitleClient implements SubtitleProvider {
@ -121,34 +119,28 @@ public class SubsceneSubtitleClient implements SubtitleProvider {
} }
@SuppressWarnings("unchecked")
protected String getLanguageFilter(String languageName) throws IOException, SAXException { protected String getLanguageFilter(String languageName) throws IOException, SAXException {
if (languageName == null || languageName.isEmpty()) { if (languageName == null || languageName.isEmpty()) {
return null; return null;
} }
// try cache first // try cache first
Cache cache = CacheManager.getInstance().getCache("web-persistent-datasource"); Cache cache = Cache.getCache("web-persistent-datasource");
String cacheKey = getClass().getName() + ".languageFilter"; String cacheKey = getClass().getName() + ".languageFilter";
try { Map<String, String> filters = cache.get(cacheKey, Map.class);
Element element = cache.get(cacheKey);
if (element != null) { if (filters != null) {
return (String) ((Map<?, ?>) element.getValue()).get(languageName.toLowerCase()); return filters.get(languageName.toLowerCase());
}
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage());
} }
// fetch new language filter data // fetch new language filter data
Map<String, String> filters = getLanguageFilterMap(); filters = getLanguageFilterMap();
// update cache after sanity check // update cache after sanity check
if (filters.size() > 42) { if (filters.size() > 42) {
try { cache.put(cacheKey, filters);
cache.put(new Element(cacheKey, filters));
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage());
}
} else { } else {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to scrape language filters: " + filters); Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to scrape language filters: " + filters);
} }

View File

@ -15,13 +15,13 @@ import java.util.Locale;
import javax.swing.Icon; import javax.swing.Icon;
import net.sourceforge.filebot.Cache;
import net.sourceforge.filebot.ResourceManager;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import net.sf.ehcache.CacheManager;
import net.sourceforge.filebot.ResourceManager;
public class TVRageClient extends AbstractEpisodeListProvider { public class TVRageClient extends AbstractEpisodeListProvider {
@ -42,7 +42,7 @@ public class TVRageClient extends AbstractEpisodeListProvider {
@Override @Override
public ResultCache getCache() { public ResultCache getCache() {
return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource")); return new ResultCache(host, Cache.getCache("web-datasource"));
} }

View File

@ -29,15 +29,15 @@ import java.util.zip.ZipInputStream;
import javax.swing.Icon; import javax.swing.Icon;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document; import net.sourceforge.filebot.Cache;
import org.w3c.dom.Node;
import net.sf.ehcache.CacheManager;
import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ResourceManager;
import net.sourceforge.filebot.web.TheTVDBClient.BannerDescriptor.BannerProperty; import net.sourceforge.filebot.web.TheTVDBClient.BannerDescriptor.BannerProperty;
import net.sourceforge.filebot.web.TheTVDBClient.SeriesInfo.SeriesProperty; import net.sourceforge.filebot.web.TheTVDBClient.SeriesInfo.SeriesProperty;
import net.sourceforge.tuned.FileUtilities; import net.sourceforge.tuned.FileUtilities;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class TheTVDBClient extends AbstractEpisodeListProvider { public class TheTVDBClient extends AbstractEpisodeListProvider {
@ -99,7 +99,7 @@ public class TheTVDBClient extends AbstractEpisodeListProvider {
@Override @Override
public ResultCache getCache() { 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 cache first
try { try {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<MirrorType, String> cachedMirrors = (Map<MirrorType, String>) getCache().getData("mirrors", null, null, Map.class); Map<MirrorType, String> cachedMirrors = getCache().getData("mirrors", null, null, Map.class);
if (cachedMirrors != null) { if (cachedMirrors != null) {
mirrors.putAll(cachedMirrors); mirrors.putAll(cachedMirrors);
return mirrors.get(mirrorType); return mirrors.get(mirrorType);
@ -479,7 +479,6 @@ public class TheTVDBClient extends AbstractEpisodeListProvider {
poster poster
} }
protected Map<SeriesProperty, String> fields; protected Map<SeriesProperty, String> fields;
@ -762,7 +761,6 @@ public class TheTVDBClient extends AbstractEpisodeListProvider {
VignettePath VignettePath
} }
protected Map<BannerProperty, String> fields; protected Map<BannerProperty, String> fields;