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, public SearchResult(Flux<SearchResultItem<T, U>> results, TotalHitsCount totalHitsCount,
Drop<SearchResult<T, U>> drop) { Drop<SearchResult<T, U>> drop) {
super(new SearchResult.CloseOnDrop<>(drop)); super(new CloseOnDrop<>(drop));
this.results = results; this.results = results;
this.totalHitsCount = totalHitsCount; this.totalHitsCount = totalHitsCount;
} }
@ -68,7 +68,11 @@ public final class SearchResult<T, U> extends ResourceSupport<SearchResult<T, U>
@Override @Override
public void drop(SearchResult<V, W> obj) { 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 @Override
public void drop(SearchResultKeys<U> obj) { 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 @Override
public void drop(LLSearchResultShard obj) { 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(); activeSearchers.register();
IndexSearcher indexSearcher; IndexSearcher indexSearcher;
SearcherManager associatedSearcherManager; SearcherManager associatedSearcherManager;
boolean ownsIndexSearcher;
if (snapshot == null) { if (snapshot == null) {
indexSearcher = searcherManager.acquire(); indexSearcher = searcherManager.acquire();
indexSearcher.setSimilarity(similarity); indexSearcher.setSimilarity(similarity);
associatedSearcherManager = searcherManager; associatedSearcherManager = searcherManager;
ownsIndexSearcher = true;
} else { } else {
indexSearcher = snapshotsManager.resolveSnapshot(snapshot).getIndexSearcher(); indexSearcher = snapshotsManager.resolveSnapshot(snapshot).getIndexSearcher();
associatedSearcherManager = null; associatedSearcherManager = null;
ownsIndexSearcher = false;
} }
return new LLIndexSearcher(indexSearcher, associatedSearcherManager, this::dropCachedIndexSearcher); return new LLIndexSearcher(indexSearcher,
associatedSearcherManager,
ownsIndexSearcher,
this::dropCachedIndexSearcher
);
}) })
.cacheInvalidateWhen(indexSearcher -> onInvalidateCache, ResourceSupport::close) .cacheInvalidateWhen(indexSearcher -> onInvalidateCache, ResourceSupport::close)
.map(searcher -> searcher.copy(this::dropCachedIndexSearcher).send()) .map(searcher -> searcher.copy(this::dropCachedIndexSearcher).send())

View File

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

View File

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

View File

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