SOLR-9524: SolrIndexSearcher.getIndexFingerprint uses dubious synchronization

This commit is contained in:
Noble Paul 2016-09-21 11:29:53 +05:30
parent 3d130097b7
commit afc57347b4
2 changed files with 16 additions and 9 deletions

View File

@ -137,6 +137,8 @@ Bug Fixes
* SOLR-9512: CloudSolrClient will try and keep up with leader changes if its * SOLR-9512: CloudSolrClient will try and keep up with leader changes if its
state cache points to a down server (Alan Woodward, noble) state cache points to a down server (Alan Woodward, noble)
* SOLR-9524: SolrIndexSearcher.getIndexFingerprint uses dubious synchronization (Mike Drob, noble)
Optimizations Optimizations
---------------------- ----------------------

View File

@ -36,6 +36,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects; import com.google.common.base.Objects;
@ -2384,15 +2385,19 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
* gets a cached version of the IndexFingerprint for this searcher * gets a cached version of the IndexFingerprint for this searcher
**/ **/
public IndexFingerprint getIndexFingerprint(long maxVersion) throws IOException { public IndexFingerprint getIndexFingerprint(long maxVersion) throws IOException {
IndexFingerprint fingerprint = maxVersionFingerprintCache.get(maxVersion); final SolrIndexSearcher searcher = this;
if (fingerprint != null) return fingerprint; final AtomicReference<IOException> exception = new AtomicReference<>();
// possibly expensive, so prevent more than one thread from calculating it for this searcher try {
synchronized (maxVersionFingerprintCache) { return maxVersionFingerprintCache.computeIfAbsent(maxVersion, key -> {
fingerprint = maxVersionFingerprintCache.get(maxVersionFingerprintCache); try {
if (fingerprint != null) return fingerprint; return IndexFingerprint.getFingerprint(searcher, key);
fingerprint = IndexFingerprint.getFingerprint(this, maxVersion); } catch (IOException e) {
maxVersionFingerprintCache.put(maxVersion, fingerprint); exception.set(e);
return fingerprint; return null;
}
});
} finally {
if (exception.get() != null) throw exception.get();
} }
} }