This commit is contained in:
Andrea Cavalli 2021-09-21 02:01:02 +02:00
parent bd97704a0b
commit 0fee105f0b
9 changed files with 100 additions and 21 deletions

View File

@ -18,7 +18,7 @@ public final class SearchResult<T, U> extends ResourceSupport<SearchResult<T, U>
public SearchResult(Flux<SearchResultItem<T, U>> results, TotalHitsCount totalHitsCount,
Drop<SearchResult<T, U>> drop) {
super(new SearchResult.CloseOnDrop<>(drop));
super(new CloseOnDrop<>(drop));
this.results = results;
this.totalHitsCount = totalHitsCount;
}
@ -68,7 +68,11 @@ public final class SearchResult<T, U> extends ResourceSupport<SearchResult<T, U>
@Override
public void drop(SearchResult<V, W> obj) {
delegate.drop(obj);
try {
delegate.drop(obj);
} finally {
obj.makeInaccessible();
}
}
}
}

View File

@ -80,7 +80,11 @@ public final class SearchResultKeys<T> extends ResourceSupport<SearchResultKeys<
@Override
public void drop(SearchResultKeys<U> obj) {
delegate.drop(obj);
try {
delegate.drop(obj);
} finally {
obj.makeInaccessible();
}
}
}

View File

@ -84,7 +84,11 @@ public final class LLSearchResultShard extends ResourceSupport<LLSearchResultSha
@Override
public void drop(LLSearchResultShard obj) {
delegate.drop(obj);
try {
delegate.drop(obj);
} finally {
obj.makeInaccessible();
}
}
}
}

View File

@ -136,15 +136,22 @@ public class CachedIndexSearcherManager implements IndexSearcherManager {
activeSearchers.register();
IndexSearcher indexSearcher;
SearcherManager associatedSearcherManager;
boolean ownsIndexSearcher;
if (snapshot == null) {
indexSearcher = searcherManager.acquire();
indexSearcher.setSimilarity(similarity);
associatedSearcherManager = searcherManager;
ownsIndexSearcher = true;
} else {
indexSearcher = snapshotsManager.resolveSnapshot(snapshot).getIndexSearcher();
associatedSearcherManager = null;
ownsIndexSearcher = false;
}
return new LLIndexSearcher(indexSearcher, associatedSearcherManager, this::dropCachedIndexSearcher);
return new LLIndexSearcher(indexSearcher,
associatedSearcherManager,
ownsIndexSearcher,
this::dropCachedIndexSearcher
);
})
.cacheInvalidateWhen(indexSearcher -> onInvalidateCache, ResourceSupport::close)
.map(searcher -> searcher.copy(this::dropCachedIndexSearcher).send())

View File

@ -14,16 +14,19 @@ import org.slf4j.LoggerFactory;
public class LLIndexSearcher extends ResourceSupport<LLIndexSearcher, LLIndexSearcher> {
private static final Logger logger = LoggerFactory.getLogger(LLIndexSearcher.class);
private final boolean ownsIndexSearcher;
private IndexSearcher indexSearcher;
private SearcherManager associatedSearcherManager;
public LLIndexSearcher(IndexSearcher indexSearcher,
@Nullable SearcherManager associatedSearcherManager,
boolean ownsIndexSearcher,
Drop<LLIndexSearcher> drop) {
super(new LLIndexSearcher.CloseOnDrop(drop));
this.indexSearcher = indexSearcher;
this.associatedSearcherManager = associatedSearcherManager;
this.ownsIndexSearcher = ownsIndexSearcher;
}
public IndexReader getIndexReader() {
@ -45,10 +48,14 @@ public class LLIndexSearcher extends ResourceSupport<LLIndexSearcher, LLIndexSea
throw attachTrace(new IllegalStateException("CachedIndexSearcher must be owned to be used"));
}
var copyIndexSearcher = this.indexSearcher;
if (associatedSearcherManager != null) {
boolean ownsIndexSearcher;
if (this.ownsIndexSearcher && associatedSearcherManager != null) {
copyIndexSearcher.getIndexReader().incRef();
ownsIndexSearcher = true;
} else {
ownsIndexSearcher = false;
}
return new LLIndexSearcher(copyIndexSearcher, associatedSearcherManager, new CloseOnDrop(drop));
return new LLIndexSearcher(copyIndexSearcher, associatedSearcherManager, ownsIndexSearcher, drop);
}
@Override
@ -61,7 +68,7 @@ public class LLIndexSearcher extends ResourceSupport<LLIndexSearcher, LLIndexSea
var indexSearcher = this.indexSearcher;
var associatedSearcherManager = this.associatedSearcherManager;
makeInaccessible();
return drop -> new LLIndexSearcher(indexSearcher, associatedSearcherManager, drop);
return drop -> new LLIndexSearcher(indexSearcher, associatedSearcherManager, ownsIndexSearcher, drop);
}
private void makeInaccessible() {
@ -80,7 +87,7 @@ public class LLIndexSearcher extends ResourceSupport<LLIndexSearcher, LLIndexSea
@Override
public void drop(LLIndexSearcher obj) {
try {
if (obj.associatedSearcherManager != null) {
if (obj.associatedSearcherManager != null && obj.ownsIndexSearcher) {
if (obj.indexSearcher.getIndexReader().getRefCount() > 0) {
obj.associatedSearcherManager.release(obj.indexSearcher);
}

View File

@ -2,33 +2,46 @@ package it.cavallium.dbengine.lucene.searcher;
import it.cavallium.dbengine.lucene.LuceneUtils;
/**
* <pre>y = 2 ^ (x + pageIndexOffset) + firstPageLimit</pre>
*/
public class ExponentialPageLimits implements PageLimits {
private static final int DEFAULT_PAGE_INDEX_OFFSET = 0;
private final int pageIndexOffset;
private final int firstPageLimit;
private final int maxItemsPerPage;
public ExponentialPageLimits() {
this(DEFAULT_MIN_ITEMS_PER_PAGE);
this(DEFAULT_PAGE_INDEX_OFFSET);
}
public ExponentialPageLimits(int firstPageLimit) {
this(firstPageLimit, DEFAULT_MAX_ITEMS_PER_PAGE);
public ExponentialPageLimits(int pageIndexOffset) {
this(pageIndexOffset, DEFAULT_MIN_ITEMS_PER_PAGE);
}
public ExponentialPageLimits(int firstPageLimit, int maxItemsPerPage) {
public ExponentialPageLimits(int pageIndexOffset, int firstPageLimit) {
this(pageIndexOffset, firstPageLimit, DEFAULT_MAX_ITEMS_PER_PAGE);
}
public ExponentialPageLimits(int pageIndexOffset, int firstPageLimit, int maxItemsPerPage) {
this.pageIndexOffset = pageIndexOffset;
this.firstPageLimit = firstPageLimit;
this.maxItemsPerPage = maxItemsPerPage;
}
@Override
public int getPageLimit(int pageIndex) {
if (pageIndex >= 10) { // safety
var offsetedIndex = pageIndex + pageIndexOffset;
var power = 0b1L << offsetedIndex;
if (offsetedIndex >= 30) { // safety
return maxItemsPerPage;
}
var limitedPageIndex = Math.max(1, pageIndex);
var min = Math.max(firstPageLimit, Math.min(maxItemsPerPage,
LuceneUtils.safeLongToInt(limitedPageIndex * (0b1L << limitedPageIndex))));
var min = Math.max(firstPageLimit, Math.min(maxItemsPerPage, firstPageLimit + power));
assert min > 0;
return min;
return LuceneUtils.safeLongToInt(min);
}
}

View File

@ -0,0 +1,40 @@
package it.cavallium.dbengine.lucene.searcher;
import it.cavallium.dbengine.lucene.LuceneUtils;
/**
* <pre>y = (x * factor) + firstPageLimit</pre>
*/
public class LinearPageLimits implements PageLimits {
private static final double DEFAULT_FACTOR = 0.5d;
private final double factor;
private final double firstPageLimit;
private final double maxItemsPerPage;
public LinearPageLimits() {
this(DEFAULT_FACTOR, DEFAULT_MIN_ITEMS_PER_PAGE);
}
public LinearPageLimits(double factor) {
this(factor, DEFAULT_MIN_ITEMS_PER_PAGE);
}
public LinearPageLimits(double factor, int firstPageLimit) {
this(factor, firstPageLimit, DEFAULT_MAX_ITEMS_PER_PAGE);
}
public LinearPageLimits(double factor, int firstPageLimit, int maxItemsPerPage) {
this.factor = factor;
this.firstPageLimit = firstPageLimit;
this.maxItemsPerPage = maxItemsPerPage;
}
@Override
public int getPageLimit(int pageIndex) {
double min = Math.min(maxItemsPerPage, firstPageLimit + (pageIndex * factor));
assert min > 0d;
return (int) min;
}
}

View File

@ -5,7 +5,7 @@ import it.cavallium.dbengine.lucene.LuceneUtils;
public interface PageLimits {
int DEFAULT_MIN_ITEMS_PER_PAGE = 10;
int DEFAULT_MAX_ITEMS_PER_PAGE = 500;
int DEFAULT_MAX_ITEMS_PER_PAGE = 250;
int getPageLimit(int pageIndex);
}

View File

@ -30,11 +30,11 @@ public class SimpleUnsortedUnscoredLuceneMultiSearcher implements LuceneMultiSea
var indexSearchersResource = Mono
.fromRunnable(() -> {
LLUtils.ensureBlocking();
if (!queryParams.isSorted()) {
if (queryParams.isSorted()) {
throw new UnsupportedOperationException("Sorted queries are not supported"
+ " by SimpleUnsortedUnscoredLuceneMultiSearcher");
}
if (!queryParams.isScored()) {
if (queryParams.isScored()) {
throw new UnsupportedOperationException("Scored queries are not supported"
+ " by SimpleUnsortedUnscoredLuceneMultiSearcher");
}