* make sure shared resources are only fetched once in multi-threaded scenarios
This commit is contained in:
parent
4341922677
commit
4d45826540
@ -49,6 +49,9 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
|
||||
|
||||
private final EpisodeListProvider provider;
|
||||
|
||||
// only allow one fetch session at a time so later requests can make use of cached results
|
||||
private final Object providerLock = new Object();
|
||||
|
||||
|
||||
public EpisodeListMatcher(EpisodeListProvider provider) {
|
||||
this.provider = provider;
|
||||
@ -222,7 +225,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
|
||||
Collection<String> names = detectSeriesNames(files, locale);
|
||||
if (names.size() > 0) {
|
||||
// only allow one fetch session at a time so later requests can make use of cached results
|
||||
synchronized (provider) {
|
||||
synchronized (providerLock) {
|
||||
episodes = fetchEpisodeSet(names, locale, parent);
|
||||
}
|
||||
}
|
||||
@ -246,7 +249,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
|
||||
|
||||
if (input.size() > 0) {
|
||||
// only allow one fetch session at a time so later requests can make use of cached results
|
||||
synchronized (provider) {
|
||||
synchronized (providerLock) {
|
||||
episodes = fetchEpisodeSet(input, locale, parent);
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
@ -37,50 +37,50 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
private final String client;
|
||||
private final int clientver;
|
||||
|
||||
|
||||
|
||||
public AnidbClient(String client, int clientver) {
|
||||
this.client = client;
|
||||
this.clientver = clientver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "AniDB";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return ResourceManager.getIcon("search.anidb");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasSingleSeasonSupport() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasLocaleSupport() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ResultCache getCache() {
|
||||
return new ResultCache(host, CacheManager.getInstance().getCache("web-persistent-datasource"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<SearchResult> search(String query, final Locale locale) throws Exception {
|
||||
// bypass automatic caching since search is based on locally cached data anyway
|
||||
return fetchSearchResult(query, locale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<SearchResult> fetchSearchResult(String query, final Locale locale) throws Exception {
|
||||
LocalSearch<AnidbSearchResult> index = new LocalSearch<AnidbSearchResult>(getAnimeTitles()) {
|
||||
@ -94,7 +94,7 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
return new ArrayList<SearchResult>(index.search(query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<Episode> fetchEpisodeList(SearchResult searchResult, Locale language) throws Exception {
|
||||
AnidbSearchResult anime = (AnidbSearchResult) searchResult;
|
||||
@ -142,7 +142,7 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
return episodes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public URI getEpisodeListLink(SearchResult searchResult) {
|
||||
int aid = ((AnidbSearchResult) searchResult).getAnimeId();
|
||||
@ -154,24 +154,24 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<Episode> getEpisodeList(SearchResult searchResult, int season, Locale locale) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public URI getEpisodeListLink(SearchResult searchResult, int season) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<AnidbSearchResult> getAnimeTitles() throws Exception {
|
||||
|
||||
protected synchronized List<AnidbSearchResult> getAnimeTitles() throws Exception {
|
||||
URL url = new URL("http", host, "/api/animetitles.dat.gz");
|
||||
ResultCache cache = getCache();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<AnidbSearchResult> anime = (List) cache.getSearchResult(null, Locale.ROOT);
|
||||
if (anime != null) {
|
||||
return anime;
|
||||
@ -225,7 +225,7 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
return cache.putSearchResult(null, Locale.ROOT, anime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class AnidbSearchResult extends SearchResult {
|
||||
|
||||
protected int aid;
|
||||
@ -237,41 +237,41 @@ public class AnidbClient extends AbstractEpisodeListProvider {
|
||||
// used by serializer
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AnidbSearchResult(int aid, String primaryTitle, Map<String, String> officialTitle) {
|
||||
this.aid = aid;
|
||||
this.primaryTitle = primaryTitle;
|
||||
this.officialTitle = officialTitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getAnimeId() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return primaryTitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getPrimaryTitle() {
|
||||
return primaryTitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getOfficialTitle(String key) {
|
||||
return officialTitle != null ? officialTitle.get(key) : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof AnidbSearchResult) {
|
||||
|
@ -31,43 +31,43 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
|
||||
private final String apikey;
|
||||
|
||||
|
||||
|
||||
public SerienjunkiesClient(String apikey) {
|
||||
this.apikey = apikey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Serienjunkies";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return ResourceManager.getIcon("search.serienjunkies");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Locale getDefaultLocale() {
|
||||
return Locale.GERMAN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ResultCache getCache() {
|
||||
return new ResultCache(host, CacheManager.getInstance().getCache("web-datasource"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<SearchResult> search(String query, final Locale locale) throws Exception {
|
||||
// bypass automatic caching since search is based on locally cached data anyway
|
||||
return fetchSearchResult(query, locale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<SearchResult> fetchSearchResult(String query, Locale locale) throws Exception {
|
||||
LocalSearch<SerienjunkiesSearchResult> index = new LocalSearch<SerienjunkiesSearchResult>(getSeriesTitles()) {
|
||||
@ -81,8 +81,8 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
return new ArrayList<SearchResult>(index.search(query));
|
||||
}
|
||||
|
||||
|
||||
protected List<SerienjunkiesSearchResult> getSeriesTitles() throws IOException {
|
||||
|
||||
protected synchronized List<SerienjunkiesSearchResult> getSeriesTitles() throws IOException {
|
||||
ResultCache cache = getCache();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -113,7 +113,7 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
return cache.putSearchResult(null, Locale.ROOT, seriesList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<Episode> fetchEpisodeList(SearchResult searchResult, Locale locale) throws IOException {
|
||||
SerienjunkiesSearchResult series = (SerienjunkiesSearchResult) searchResult;
|
||||
@ -142,7 +142,7 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
return episodes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected Object request(String resource) throws IOException {
|
||||
URL url = new URL("https", host, resource);
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
@ -159,24 +159,24 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public URI getEpisodeListLink(SearchResult searchResult) {
|
||||
return getEpisodeListLink(searchResult, "alle-serien-staffeln");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public URI getEpisodeListLink(SearchResult searchResult, int season) {
|
||||
return getEpisodeListLink(searchResult, "season" + season);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public URI getEpisodeListLink(SearchResult searchResult, String page) {
|
||||
return URI.create(String.format("http://www.serienjunkies.de/%s/%s.html", ((SerienjunkiesSearchResult) searchResult).getLink(), page));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class SerienjunkiesSearchResult extends SearchResult {
|
||||
|
||||
protected int sid;
|
||||
@ -185,12 +185,12 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
protected String germanTitle;
|
||||
protected Date startDate;
|
||||
|
||||
|
||||
|
||||
protected SerienjunkiesSearchResult() {
|
||||
// used by serializer
|
||||
}
|
||||
|
||||
|
||||
|
||||
public SerienjunkiesSearchResult(int sid, String link, String mainTitle, String germanTitle, Date startDate) {
|
||||
this.sid = sid;
|
||||
this.link = link;
|
||||
@ -199,44 +199,44 @@ public class SerienjunkiesClient extends AbstractEpisodeListProvider {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return germanTitle != null ? germanTitle : mainTitle; // prefer German title
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getSeriesId() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getMainTitle() {
|
||||
return mainTitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getGermanTitle() {
|
||||
return germanTitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof SerienjunkiesSearchResult) {
|
||||
|
Loading…
Reference in New Issue
Block a user