LUCENE-10369: Move DelegatingCacheHelper to FilterDirectoryReader (#596)

This commit is contained in:
Nikola Grcevski 2022-01-11 09:22:06 -05:00 committed by GitHub
parent 308ddd7502
commit bad65c53c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 22 deletions

View File

@ -147,4 +147,37 @@ public abstract class FilterDirectoryReader extends DirectoryReader {
public DirectoryReader getDelegate() {
return in;
}
/**
* A DelegatingCacheHelper is a CacheHelper specialization for implementing long-lived caching
* behaviour for FilterDirectoryReader subclasses. It uses a unique CacheKey for the purpose of
* implementing the onClose listener delegation for the reader.
*/
protected static class DelegatingCacheHelper implements CacheHelper {
private final CacheHelper delegate;
private final CacheKey cacheKey = new CacheKey();
/**
* Create a new DelegatingCacheHelper that delegates the cache onClose listener to another
* CacheHelper, but with its own unique CacheKey.
*
* @param delegate the CacheHelper to delegate the close listener to
*/
protected DelegatingCacheHelper(CacheHelper delegate) {
this.delegate = delegate;
}
@Override
public CacheKey getKey() {
return cacheKey;
}
@Override
public void addClosedListener(ClosedListener listener) {
// here we wrap the listener and call it with our cache key
// this is important since this key will be used to cache the reader and otherwise we won't
// free caches etc.
delegate.addClosedListener(unused -> listener.onClose(cacheKey));
}
}
}

View File

@ -259,26 +259,4 @@ public final class SoftDeletesDirectoryReaderWrapper extends FilterDirectoryRead
return readerCacheHelper;
}
}
private static class DelegatingCacheHelper implements CacheHelper {
private final CacheHelper delegate;
private final CacheKey cacheKey = new CacheKey();
public DelegatingCacheHelper(CacheHelper delegate) {
this.delegate = delegate;
}
@Override
public CacheKey getKey() {
return cacheKey;
}
@Override
public void addClosedListener(ClosedListener listener) {
// here we wrap the listener and call it with our cache key
// this is important since this key will be used to cache the reader and otherwise we won't
// free caches etc.
delegate.addClosedListener(unused -> listener.onClose(cacheKey));
}
}
}

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.FilterDirectoryReader.SubReaderWrapper;
@ -143,4 +144,57 @@ public class TestFilterDirectoryReader extends LuceneTestCase {
directoryReader.close();
dir.close();
}
private static class DummyLastingFilterDirectoryReader extends FilterDirectoryReader {
private final CacheHelper cacheHelper;
public DummyLastingFilterDirectoryReader(DirectoryReader in) throws IOException {
super(in, new DummySubReaderWrapper());
cacheHelper =
(in.getReaderCacheHelper() == null)
? null
: new DelegatingCacheHelper(in.getReaderCacheHelper());
}
@Override
protected DirectoryReader doWrapDirectoryReader(DirectoryReader in) throws IOException {
return new DummyFilterDirectoryReader(in);
}
@Override
public CacheHelper getReaderCacheHelper() {
return cacheHelper;
}
}
public void testDelegatingCacheHelper() throws IOException {
Directory dir = newDirectory();
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
w.addDocument(new Document());
DirectoryReader reader = DirectoryReader.open(w);
DirectoryReader wrapped = new DummyLastingFilterDirectoryReader(reader);
assertNotEquals(reader.getReaderCacheHelper(), wrapped.getReaderCacheHelper());
assertNotEquals(
reader.getReaderCacheHelper().getKey(), wrapped.getReaderCacheHelper().getKey());
AtomicInteger closeCalledCounter = new AtomicInteger(0);
wrapped
.getReaderCacheHelper()
.addClosedListener(
key -> {
closeCalledCounter.incrementAndGet();
assertSame(key, wrapped.getReaderCacheHelper().getKey());
});
reader.close();
assertEquals(1, closeCalledCounter.get());
wrapped.close();
assertEquals(1, closeCalledCounter.get());
w.close();
dir.close();
}
}