2020-12-07 22:15:18 +01:00
|
|
|
package it.cavallium.dbengine.database.disk;
|
|
|
|
|
2021-12-16 16:14:44 +01:00
|
|
|
import static it.cavallium.dbengine.client.UninterruptibleScheduler.uninterruptibleScheduler;
|
2021-09-10 12:13:52 +02:00
|
|
|
import static it.cavallium.dbengine.database.LLUtils.MARKER_LUCENE;
|
2021-12-17 02:18:30 +01:00
|
|
|
import static it.cavallium.dbengine.database.LLUtils.toDocument;
|
|
|
|
import static it.cavallium.dbengine.database.LLUtils.toFields;
|
2022-01-28 21:12:10 +01:00
|
|
|
import static it.cavallium.dbengine.lucene.searcher.GlobalQueryRewrite.NO_REWRITE;
|
2022-06-08 16:45:54 +02:00
|
|
|
import static java.util.Objects.requireNonNull;
|
2022-03-13 11:01:51 +01:00
|
|
|
import static reactor.core.scheduler.Schedulers.DEFAULT_BOUNDED_ELASTIC_QUEUESIZE;
|
|
|
|
import static reactor.core.scheduler.Schedulers.DEFAULT_BOUNDED_ELASTIC_SIZE;
|
2021-09-10 12:13:52 +02:00
|
|
|
|
2022-01-28 19:31:25 +01:00
|
|
|
import com.google.common.collect.Multimap;
|
2021-12-30 17:28:06 +01:00
|
|
|
import io.micrometer.core.instrument.Counter;
|
2021-10-30 11:13:46 +02:00
|
|
|
import io.micrometer.core.instrument.MeterRegistry;
|
2022-06-13 23:25:43 +02:00
|
|
|
import io.micrometer.core.instrument.Tag;
|
2021-12-30 17:28:06 +01:00
|
|
|
import io.micrometer.core.instrument.Timer;
|
2022-08-15 23:07:17 +02:00
|
|
|
import it.cavallium.dbengine.client.Backuppable;
|
|
|
|
import it.cavallium.dbengine.client.IBackuppable;
|
2021-11-19 19:03:31 +01:00
|
|
|
import it.cavallium.dbengine.client.query.QueryParser;
|
|
|
|
import it.cavallium.dbengine.client.query.current.data.Query;
|
2021-03-02 01:53:36 +01:00
|
|
|
import it.cavallium.dbengine.client.query.current.data.QueryParams;
|
2022-07-02 11:44:13 +02:00
|
|
|
import it.cavallium.dbengine.client.query.current.data.TotalHitsCount;
|
2021-11-07 17:46:40 +01:00
|
|
|
import it.cavallium.dbengine.database.LLIndexRequest;
|
2020-12-31 12:04:53 +01:00
|
|
|
import it.cavallium.dbengine.database.LLLuceneIndex;
|
2021-03-27 03:35:27 +01:00
|
|
|
import it.cavallium.dbengine.database.LLSearchResultShard;
|
2020-12-31 12:04:53 +01:00
|
|
|
import it.cavallium.dbengine.database.LLSnapshot;
|
2021-12-30 17:28:06 +01:00
|
|
|
import it.cavallium.dbengine.database.LLSoftUpdateDocument;
|
2020-12-31 12:04:53 +01:00
|
|
|
import it.cavallium.dbengine.database.LLTerm;
|
2021-12-30 17:28:06 +01:00
|
|
|
import it.cavallium.dbengine.database.LLUpdateDocument;
|
2021-11-07 17:46:40 +01:00
|
|
|
import it.cavallium.dbengine.database.LLUpdateFields;
|
2020-12-31 12:04:53 +01:00
|
|
|
import it.cavallium.dbengine.database.LLUtils;
|
2022-07-23 02:42:48 +02:00
|
|
|
import it.cavallium.dbengine.lucene.LuceneCloseable;
|
|
|
|
import it.cavallium.dbengine.lucene.LuceneConcurrentMergeScheduler;
|
2021-12-30 17:28:06 +01:00
|
|
|
import it.cavallium.dbengine.lucene.LuceneHacks;
|
2022-03-05 15:46:40 +01:00
|
|
|
import it.cavallium.dbengine.lucene.LuceneRocksDBManager;
|
2021-02-04 22:42:57 +01:00
|
|
|
import it.cavallium.dbengine.lucene.LuceneUtils;
|
2021-11-19 19:03:31 +01:00
|
|
|
import it.cavallium.dbengine.lucene.collector.Buckets;
|
2022-04-30 21:56:42 +02:00
|
|
|
import it.cavallium.dbengine.lucene.directory.Lucene91CodecWithNoFieldCompression;
|
2022-01-28 19:31:25 +01:00
|
|
|
import it.cavallium.dbengine.lucene.mlt.MoreLikeThisTransformer;
|
2021-10-13 12:25:32 +02:00
|
|
|
import it.cavallium.dbengine.lucene.searcher.AdaptiveLocalSearcher;
|
2021-11-18 17:13:53 +01:00
|
|
|
import it.cavallium.dbengine.lucene.searcher.BucketParams;
|
|
|
|
import it.cavallium.dbengine.lucene.searcher.DecimalBucketMultiSearcher;
|
2021-07-06 01:30:37 +02:00
|
|
|
import it.cavallium.dbengine.lucene.searcher.LocalQueryParams;
|
2021-10-13 12:25:32 +02:00
|
|
|
import it.cavallium.dbengine.lucene.searcher.LocalSearcher;
|
2022-07-02 11:44:13 +02:00
|
|
|
import it.cavallium.dbengine.lucene.searcher.LuceneSearchResult;
|
2022-03-05 15:46:40 +01:00
|
|
|
import it.cavallium.dbengine.rpc.current.data.IndicizerAnalyzers;
|
|
|
|
import it.cavallium.dbengine.rpc.current.data.IndicizerSimilarities;
|
|
|
|
import it.cavallium.dbengine.rpc.current.data.LuceneOptions;
|
2022-06-30 13:54:55 +02:00
|
|
|
import it.cavallium.dbengine.utils.SimpleResource;
|
2020-12-07 22:15:18 +01:00
|
|
|
import java.io.IOException;
|
2022-06-30 13:54:55 +02:00
|
|
|
import java.io.UncheckedIOException;
|
2022-03-30 23:44:55 +02:00
|
|
|
import java.time.Duration;
|
2021-11-19 19:03:31 +01:00
|
|
|
import java.util.ArrayList;
|
2021-11-18 17:13:53 +01:00
|
|
|
import java.util.List;
|
2021-05-11 21:59:05 +02:00
|
|
|
import java.util.Map.Entry;
|
2022-03-19 00:08:23 +01:00
|
|
|
import java.util.Objects;
|
2021-10-30 11:13:46 +02:00
|
|
|
import java.util.concurrent.Callable;
|
2021-09-06 18:52:21 +02:00
|
|
|
import java.util.concurrent.Phaser;
|
2020-12-07 22:15:18 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2021-10-07 00:53:38 +02:00
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
2021-12-17 02:18:30 +01:00
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
2022-03-19 00:08:23 +01:00
|
|
|
import java.util.logging.Level;
|
2021-12-31 00:58:47 +01:00
|
|
|
import org.apache.commons.lang3.time.StopWatch;
|
2021-12-17 01:48:49 +01:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.Logger;
|
2021-09-20 11:52:21 +02:00
|
|
|
import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper;
|
2021-06-25 20:06:58 +02:00
|
|
|
import org.apache.lucene.index.ConcurrentMergeScheduler;
|
2022-06-28 13:52:21 +02:00
|
|
|
import org.apache.lucene.index.IndexDeletionPolicy;
|
2020-12-07 22:15:18 +01:00
|
|
|
import org.apache.lucene.index.IndexWriter;
|
|
|
|
import org.apache.lucene.index.IndexWriterConfig;
|
2021-07-06 14:33:47 +02:00
|
|
|
import org.apache.lucene.index.MergeScheduler;
|
2022-06-21 14:35:07 +02:00
|
|
|
import org.apache.lucene.index.NoMergePolicy;
|
2021-06-25 20:06:58 +02:00
|
|
|
import org.apache.lucene.index.SerialMergeScheduler;
|
2020-12-07 22:15:18 +01:00
|
|
|
import org.apache.lucene.index.SnapshotDeletionPolicy;
|
2021-02-04 22:42:57 +01:00
|
|
|
import org.apache.lucene.search.similarities.Similarity;
|
2020-12-07 22:15:18 +01:00
|
|
|
import org.apache.lucene.store.Directory;
|
2021-04-30 19:15:04 +02:00
|
|
|
import org.apache.lucene.store.MMapDirectory;
|
2021-11-19 19:03:31 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2020-12-07 22:15:18 +01:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
2022-05-10 00:31:16 +02:00
|
|
|
import it.cavallium.dbengine.utils.ShortNamedThreadFactory;
|
2020-12-07 22:15:18 +01:00
|
|
|
import reactor.core.publisher.Flux;
|
|
|
|
import reactor.core.publisher.Mono;
|
2022-03-19 00:08:23 +01:00
|
|
|
import reactor.core.publisher.SignalType;
|
2021-02-01 02:21:53 +01:00
|
|
|
import reactor.core.scheduler.Scheduler;
|
2020-12-07 22:15:18 +01:00
|
|
|
import reactor.core.scheduler.Schedulers;
|
|
|
|
|
2022-08-15 23:07:17 +02:00
|
|
|
public class LLLocalLuceneIndex extends SimpleResource implements IBackuppable, LLLuceneIndex, LuceneCloseable {
|
2020-12-07 22:15:18 +01:00
|
|
|
|
2021-12-17 01:48:49 +01:00
|
|
|
protected static final Logger logger = LogManager.getLogger(LLLocalLuceneIndex.class);
|
2022-01-26 14:22:54 +01:00
|
|
|
|
2022-04-10 20:15:05 +02:00
|
|
|
private final ReentrantLock shutdownLock = new ReentrantLock();
|
2020-12-12 23:41:09 +01:00
|
|
|
/**
|
|
|
|
* Global lucene index scheduler.
|
|
|
|
* There is only a single thread globally to not overwhelm the disk with
|
2021-02-03 14:37:02 +01:00
|
|
|
* concurrent commits or concurrent refreshes.
|
2020-12-12 23:41:09 +01:00
|
|
|
*/
|
2022-03-30 23:44:55 +02:00
|
|
|
private static final Scheduler luceneHeavyTasksScheduler = uninterruptibleScheduler(Schedulers.newBoundedElastic(
|
|
|
|
DEFAULT_BOUNDED_ELASTIC_SIZE,
|
|
|
|
DEFAULT_BOUNDED_ELASTIC_QUEUESIZE,
|
2022-07-23 02:42:48 +02:00
|
|
|
new LuceneThreadFactory("heavy-tasks").setDaemon(true).withGroup(new ThreadGroup("lucene-heavy-tasks")),
|
2022-04-04 17:52:49 +02:00
|
|
|
Math.toIntExact(Duration.ofHours(1).toSeconds())
|
2022-03-30 23:44:55 +02:00
|
|
|
));
|
2022-04-05 00:37:44 +02:00
|
|
|
private static final Scheduler luceneWriteScheduler = uninterruptibleScheduler(Schedulers.newBoundedElastic(
|
|
|
|
DEFAULT_BOUNDED_ELASTIC_SIZE,
|
|
|
|
DEFAULT_BOUNDED_ELASTIC_QUEUESIZE,
|
2022-07-23 02:42:48 +02:00
|
|
|
new LuceneThreadFactory("lucene-write").setDaemon(true).withGroup(new ThreadGroup("lucene-write")),
|
2022-04-05 00:37:44 +02:00
|
|
|
Math.toIntExact(Duration.ofHours(1).toSeconds())
|
|
|
|
));
|
|
|
|
private static final Scheduler bulkScheduler = luceneWriteScheduler;
|
2021-12-17 02:18:30 +01:00
|
|
|
|
2022-06-29 01:14:05 +02:00
|
|
|
private static final boolean ENABLE_SNAPSHOTS
|
|
|
|
= Boolean.parseBoolean(System.getProperty("it.cavallium.dbengine.lucene.snapshot.enable", "true"));
|
|
|
|
|
|
|
|
private static final boolean CACHE_SEARCHER_MANAGER
|
|
|
|
= Boolean.parseBoolean(System.getProperty("it.cavallium.dbengine.lucene.cachedsearchermanager.enable", "true"));
|
|
|
|
|
|
|
|
private static final LLSnapshot DUMMY_SNAPSHOT = new LLSnapshot(-1);
|
|
|
|
|
2022-01-26 14:22:54 +01:00
|
|
|
static {
|
|
|
|
LLUtils.initHooks();
|
|
|
|
}
|
|
|
|
|
|
|
|
private final LocalSearcher localSearcher;
|
|
|
|
private final DecimalBucketMultiSearcher decimalBucketMultiSearcher = new DecimalBucketMultiSearcher();
|
|
|
|
|
2021-12-30 17:28:06 +01:00
|
|
|
private final Counter startedDocIndexings;
|
|
|
|
private final Counter endeddDocIndexings;
|
|
|
|
private final Timer docIndexingTime;
|
|
|
|
private final Timer snapshotTime;
|
|
|
|
private final Timer flushTime;
|
|
|
|
private final Timer commitTime;
|
|
|
|
private final Timer mergeTime;
|
|
|
|
private final Timer refreshTime;
|
2020-12-12 23:41:09 +01:00
|
|
|
|
2022-03-05 15:46:40 +01:00
|
|
|
private final String shardName;
|
2020-12-07 22:15:18 +01:00
|
|
|
private final IndexWriter indexWriter;
|
2021-09-06 15:06:51 +02:00
|
|
|
private final SnapshotsManager snapshotsManager;
|
2021-09-18 18:34:21 +02:00
|
|
|
private final IndexSearcherManager searcherManager;
|
2021-09-20 11:52:21 +02:00
|
|
|
private final PerFieldAnalyzerWrapper luceneAnalyzer;
|
|
|
|
private final Similarity luceneSimilarity;
|
2022-03-05 15:46:40 +01:00
|
|
|
private final LuceneRocksDBManager rocksDBManager;
|
2020-12-07 22:15:18 +01:00
|
|
|
private final Directory directory;
|
2022-08-15 23:07:17 +02:00
|
|
|
private final LuceneBackuppable backuppable;
|
2020-12-07 22:15:18 +01:00
|
|
|
private final boolean lowMemory;
|
|
|
|
|
2021-09-06 18:52:21 +02:00
|
|
|
private final Phaser activeTasks = new Phaser(1);
|
2020-12-12 23:41:09 +01:00
|
|
|
|
2022-04-06 02:41:32 +02:00
|
|
|
public LLLocalLuceneIndex(LLTempHugePqEnv env,
|
2021-10-30 11:13:46 +02:00
|
|
|
MeterRegistry meterRegistry,
|
2022-03-05 15:46:40 +01:00
|
|
|
@NotNull String clusterName,
|
|
|
|
int shardIndex,
|
2021-05-28 16:04:59 +02:00
|
|
|
IndicizerAnalyzers indicizerAnalyzers,
|
|
|
|
IndicizerSimilarities indicizerSimilarities,
|
2021-10-13 00:23:56 +02:00
|
|
|
LuceneOptions luceneOptions,
|
2022-03-05 15:46:40 +01:00
|
|
|
@Nullable LuceneHacks luceneHacks,
|
|
|
|
@Nullable LuceneRocksDBManager rocksDBManager) throws IOException {
|
2021-12-30 17:28:06 +01:00
|
|
|
|
2022-03-05 15:46:40 +01:00
|
|
|
if (clusterName.isBlank()) {
|
2020-12-07 22:15:18 +01:00
|
|
|
throw new IOException("Empty lucene database name");
|
|
|
|
}
|
2021-05-25 01:12:24 +02:00
|
|
|
if (!MMapDirectory.UNMAP_SUPPORTED) {
|
|
|
|
logger.error("Unmap is unsupported, lucene will run slower: {}", MMapDirectory.UNMAP_NOT_SUPPORTED_REASON);
|
|
|
|
} else {
|
|
|
|
logger.debug("Lucene MMap is supported");
|
|
|
|
}
|
2022-02-26 22:51:22 +01:00
|
|
|
this.lowMemory = luceneOptions.lowMemory();
|
2022-03-19 00:08:23 +01:00
|
|
|
this.shardName = LuceneUtils.getStandardName(clusterName, shardIndex);
|
2022-03-05 15:46:40 +01:00
|
|
|
this.directory = LuceneUtils.createLuceneDirectory(luceneOptions.directoryOptions(),
|
2022-03-19 00:08:23 +01:00
|
|
|
shardName,
|
2022-03-05 15:46:40 +01:00
|
|
|
rocksDBManager);
|
2022-03-11 17:59:46 +01:00
|
|
|
boolean isFilesystemCompressed = LuceneUtils.getIsFilesystemCompressed(luceneOptions.directoryOptions());
|
2021-06-06 02:23:51 +02:00
|
|
|
|
2021-09-20 11:52:21 +02:00
|
|
|
this.luceneAnalyzer = LuceneUtils.toPerFieldAnalyzerWrapper(indicizerAnalyzers);
|
|
|
|
this.luceneSimilarity = LuceneUtils.toPerFieldSimilarityWrapper(indicizerSimilarities);
|
2022-03-05 15:46:40 +01:00
|
|
|
this.rocksDBManager = rocksDBManager;
|
2021-12-12 16:41:49 +01:00
|
|
|
|
2022-04-06 02:41:32 +02:00
|
|
|
var useHugePq = luceneOptions.allowNonVolatileCollection();
|
2021-12-12 23:40:30 +01:00
|
|
|
var maxInMemoryResultEntries = luceneOptions.maxInMemoryResultEntries();
|
2021-10-13 00:23:56 +02:00
|
|
|
if (luceneHacks != null && luceneHacks.customLocalSearcher() != null) {
|
|
|
|
localSearcher = luceneHacks.customLocalSearcher().get();
|
|
|
|
} else {
|
2022-04-06 02:41:32 +02:00
|
|
|
localSearcher = new AdaptiveLocalSearcher(env, useHugePq, maxInMemoryResultEntries);
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
2021-06-06 02:23:51 +02:00
|
|
|
|
2021-09-20 11:52:21 +02:00
|
|
|
var indexWriterConfig = new IndexWriterConfig(luceneAnalyzer);
|
2022-06-28 13:52:21 +02:00
|
|
|
IndexDeletionPolicy deletionPolicy;
|
|
|
|
deletionPolicy = requireNonNull(indexWriterConfig.getIndexDeletionPolicy());
|
2022-06-29 01:14:05 +02:00
|
|
|
if (ENABLE_SNAPSHOTS) {
|
|
|
|
deletionPolicy = new SnapshotDeletionPolicy(deletionPolicy);
|
|
|
|
}
|
2022-06-28 13:52:21 +02:00
|
|
|
indexWriterConfig.setIndexDeletionPolicy(deletionPolicy);
|
2020-12-07 22:15:18 +01:00
|
|
|
indexWriterConfig.setCommitOnClose(true);
|
2021-09-07 11:26:10 +02:00
|
|
|
int writerSchedulerMaxThreadCount;
|
2021-07-06 14:33:47 +02:00
|
|
|
MergeScheduler mergeScheduler;
|
2020-12-07 22:15:18 +01:00
|
|
|
if (lowMemory) {
|
2021-07-06 14:33:47 +02:00
|
|
|
mergeScheduler = new SerialMergeScheduler();
|
2021-09-07 11:26:10 +02:00
|
|
|
writerSchedulerMaxThreadCount = 1;
|
2020-12-07 22:15:18 +01:00
|
|
|
} else {
|
2022-07-23 02:42:48 +02:00
|
|
|
//noinspection resource
|
|
|
|
ConcurrentMergeScheduler concurrentMergeScheduler = new LuceneConcurrentMergeScheduler();
|
2022-06-08 16:45:54 +02:00
|
|
|
// false means SSD, true means HDD
|
|
|
|
boolean spins = false;
|
|
|
|
concurrentMergeScheduler.setDefaultMaxMergesAndThreads(spins);
|
|
|
|
// It's true by default, but this makes sure it's true if it's a managed path
|
|
|
|
if (LuceneUtils.getManagedPath(luceneOptions.directoryOptions()).isPresent()) {
|
2021-07-23 15:20:33 +02:00
|
|
|
concurrentMergeScheduler.enableAutoIOThrottle();
|
|
|
|
}
|
2021-09-07 11:26:10 +02:00
|
|
|
writerSchedulerMaxThreadCount = concurrentMergeScheduler.getMaxThreadCount();
|
2021-07-06 14:33:47 +02:00
|
|
|
mergeScheduler = concurrentMergeScheduler;
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
2022-03-11 17:59:46 +01:00
|
|
|
if (isFilesystemCompressed) {
|
|
|
|
indexWriterConfig.setUseCompoundFile(false);
|
2022-04-30 21:56:42 +02:00
|
|
|
indexWriterConfig.setCodec(new Lucene91CodecWithNoFieldCompression());
|
2022-03-11 17:59:46 +01:00
|
|
|
}
|
2021-09-20 11:52:21 +02:00
|
|
|
logger.trace("WriterSchedulerMaxThreadCount: {}", writerSchedulerMaxThreadCount);
|
2021-07-06 14:33:47 +02:00
|
|
|
indexWriterConfig.setMergeScheduler(mergeScheduler);
|
2022-06-20 11:55:41 +02:00
|
|
|
indexWriterConfig.setMergePolicy(LuceneUtils.getMergePolicy(luceneOptions));
|
2022-03-09 02:29:38 +01:00
|
|
|
if (luceneOptions.indexWriterRAMBufferSizeMB().isPresent()) {
|
|
|
|
indexWriterConfig.setRAMBufferSizeMB(luceneOptions.indexWriterRAMBufferSizeMB().get());
|
|
|
|
}
|
|
|
|
if (luceneOptions.indexWriterMaxBufferedDocs().isPresent()) {
|
|
|
|
indexWriterConfig.setMaxBufferedDocs(luceneOptions.indexWriterMaxBufferedDocs().get());
|
|
|
|
}
|
|
|
|
if (luceneOptions.indexWriterReaderPooling().isPresent()) {
|
|
|
|
indexWriterConfig.setReaderPooling(luceneOptions.indexWriterReaderPooling().get());
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
2021-09-20 11:52:21 +02:00
|
|
|
indexWriterConfig.setSimilarity(getLuceneSimilarity());
|
2020-12-07 22:15:18 +01:00
|
|
|
this.indexWriter = new IndexWriter(directory, indexWriterConfig);
|
2022-06-29 01:14:05 +02:00
|
|
|
if (ENABLE_SNAPSHOTS) {
|
|
|
|
this.snapshotsManager = new SnapshotsManager(indexWriter, (SnapshotDeletionPolicy) deletionPolicy);
|
|
|
|
} else {
|
|
|
|
this.snapshotsManager = null;
|
|
|
|
}
|
|
|
|
SimpleIndexSearcherManager searcherManager;
|
|
|
|
if (CACHE_SEARCHER_MANAGER) {
|
|
|
|
searcherManager = new SimpleIndexSearcherManager(indexWriter,
|
|
|
|
snapshotsManager,
|
|
|
|
luceneHeavyTasksScheduler,
|
|
|
|
getLuceneSimilarity(),
|
|
|
|
luceneOptions.applyAllDeletes().orElse(true),
|
|
|
|
luceneOptions.writeAllDeletes().orElse(false),
|
|
|
|
luceneOptions.queryRefreshDebounceTime()
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
searcherManager = new SimpleIndexSearcherManager(indexWriter,
|
|
|
|
snapshotsManager,
|
|
|
|
luceneHeavyTasksScheduler,
|
|
|
|
getLuceneSimilarity(),
|
|
|
|
luceneOptions.applyAllDeletes().orElse(true),
|
|
|
|
luceneOptions.writeAllDeletes().orElse(false),
|
|
|
|
luceneOptions.queryRefreshDebounceTime());
|
|
|
|
}
|
2022-06-13 23:25:43 +02:00
|
|
|
this.searcherManager = searcherManager;
|
2020-12-12 23:41:09 +01:00
|
|
|
|
2022-03-05 15:46:40 +01:00
|
|
|
this.startedDocIndexings = meterRegistry.counter("index.write.doc.started.counter", "index.name", clusterName);
|
|
|
|
this.endeddDocIndexings = meterRegistry.counter("index.write.doc.ended.counter", "index.name", clusterName);
|
|
|
|
this.docIndexingTime = Timer.builder("index.write.doc.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
|
|
|
this.snapshotTime = Timer.builder("index.write.snapshot.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
|
|
|
this.flushTime = Timer.builder("index.write.flush.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
|
|
|
this.commitTime = Timer.builder("index.write.commit.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
|
|
|
this.mergeTime = Timer.builder("index.write.merge.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
|
|
|
this.refreshTime = Timer.builder("index.search.refresh.timer").publishPercentiles(0.2, 0.5, 0.95).publishPercentileHistogram().tag("index.name", clusterName).register(meterRegistry);
|
2022-06-21 14:35:07 +02:00
|
|
|
meterRegistry.gauge("index.snapshot.counter", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getSnapshotsCount);
|
|
|
|
meterRegistry.gauge("index.write.flushing.bytes", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getIndexWriterFlushingBytes);
|
|
|
|
meterRegistry.gauge("index.write.sequence.completed.max", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getIndexWriterMaxCompletedSequenceNumber);
|
|
|
|
meterRegistry.gauge("index.write.doc.pending.counter", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getIndexWriterPendingNumDocs);
|
|
|
|
meterRegistry.gauge("index.write.segment.merging.counter", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getIndexWriterMergingSegmentsSize);
|
|
|
|
meterRegistry.gauge("index.directory.deletion.pending.counter", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getDirectoryPendingDeletionsCount);
|
|
|
|
meterRegistry.gauge("index.doc.counter", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getDocCount);
|
|
|
|
meterRegistry.gauge("index.doc.max", List.of(Tag.of("index.name", clusterName)), this, LLLocalLuceneIndex::getMaxDoc);
|
2022-06-13 23:25:43 +02:00
|
|
|
meterRegistry.gauge("index.searcher.refreshes.active.count",
|
|
|
|
List.of(Tag.of("index.name", clusterName)),
|
|
|
|
searcherManager,
|
2022-06-29 01:14:05 +02:00
|
|
|
SimpleIndexSearcherManager::getActiveRefreshes
|
2022-06-13 23:25:43 +02:00
|
|
|
);
|
|
|
|
meterRegistry.gauge("index.searcher.searchers.active.count",
|
|
|
|
List.of(Tag.of("index.name", clusterName)),
|
|
|
|
searcherManager,
|
2022-06-29 01:14:05 +02:00
|
|
|
SimpleIndexSearcherManager::getActiveSearchers
|
2022-06-13 23:25:43 +02:00
|
|
|
);
|
2021-12-30 17:28:06 +01:00
|
|
|
|
2020-12-12 23:41:09 +01:00
|
|
|
// Start scheduled tasks
|
2021-09-06 18:52:21 +02:00
|
|
|
var commitMillis = luceneOptions.commitDebounceTime().toMillis();
|
|
|
|
luceneHeavyTasksScheduler.schedulePeriodically(this::scheduledCommit, commitMillis, commitMillis,
|
|
|
|
TimeUnit.MILLISECONDS);
|
2022-08-15 23:07:17 +02:00
|
|
|
|
|
|
|
this.backuppable = new LuceneBackuppable();
|
2020-12-12 23:41:09 +01:00
|
|
|
}
|
|
|
|
|
2021-09-20 11:52:21 +02:00
|
|
|
private Similarity getLuceneSimilarity() {
|
|
|
|
return luceneSimilarity;
|
2021-02-04 22:42:57 +01:00
|
|
|
}
|
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
@Override
|
|
|
|
public String getLuceneIndexName() {
|
2022-03-05 15:46:40 +01:00
|
|
|
return shardName;
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-01-30 01:41:04 +01:00
|
|
|
public Mono<LLSnapshot> takeSnapshot() {
|
2022-06-29 01:14:05 +02:00
|
|
|
if (snapshotsManager == null) {
|
|
|
|
return Mono.just(DUMMY_SNAPSHOT);
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
return snapshotsManager.takeSnapshot().elapsed().map(elapsed -> {
|
|
|
|
snapshotTime.record(elapsed.getT1(), TimeUnit.MILLISECONDS);
|
|
|
|
return elapsed.getT2();
|
|
|
|
}).transform(this::ensureOpen);
|
2021-10-07 00:53:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private <V> Mono<V> ensureOpen(Mono<V> mono) {
|
2021-10-30 11:13:46 +02:00
|
|
|
return Mono.<Void>fromCallable(() -> {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2021-10-30 11:13:46 +02:00
|
|
|
throw new IllegalStateException("Lucene index is closed");
|
2021-10-07 00:53:38 +02:00
|
|
|
} else {
|
2021-10-30 11:13:46 +02:00
|
|
|
return null;
|
2021-10-07 00:53:38 +02:00
|
|
|
}
|
2021-10-30 11:13:46 +02:00
|
|
|
}).then(mono).doFirst(activeTasks::register).doFinally(s -> activeTasks.arriveAndDeregister());
|
|
|
|
}
|
|
|
|
|
|
|
|
private <V> Mono<V> runSafe(Callable<V> callable) {
|
2021-12-16 16:14:44 +01:00
|
|
|
return Mono
|
|
|
|
.fromCallable(callable)
|
2022-04-05 00:37:44 +02:00
|
|
|
.subscribeOn(luceneWriteScheduler)
|
2021-12-16 16:14:44 +01:00
|
|
|
.publishOn(Schedulers.parallel());
|
2021-10-30 11:13:46 +02:00
|
|
|
}
|
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
@Override
|
2021-01-30 01:41:04 +01:00
|
|
|
public Mono<Void> releaseSnapshot(LLSnapshot snapshot) {
|
2022-06-29 01:14:05 +02:00
|
|
|
if (snapshotsManager == null) {
|
|
|
|
if (snapshot != null && !Objects.equals(snapshot, DUMMY_SNAPSHOT)) {
|
|
|
|
return Mono.error(new IllegalStateException("Can't release snapshot " + snapshot));
|
|
|
|
}
|
|
|
|
return Mono.empty();
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
return snapshotsManager
|
|
|
|
.releaseSnapshot(snapshot)
|
|
|
|
.elapsed()
|
|
|
|
.doOnNext(elapsed -> snapshotTime.record(elapsed.getT1(), TimeUnit.MILLISECONDS))
|
|
|
|
.then();
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-07 17:46:40 +01:00
|
|
|
public Mono<Void> addDocument(LLTerm key, LLUpdateDocument doc) {
|
2022-03-19 00:08:23 +01:00
|
|
|
return this.<Void>runSafe(() -> {
|
|
|
|
docIndexingTime.recordCallable(() -> {
|
|
|
|
startedDocIndexings.increment();
|
|
|
|
try {
|
|
|
|
indexWriter.addDocument(toDocument(doc));
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
logger.trace(MARKER_LUCENE, "Added document {}: {}", key, doc);
|
2021-12-17 02:18:30 +01:00
|
|
|
return null;
|
2022-03-19 00:08:23 +01:00
|
|
|
}).transform(this::ensureOpen);
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-03-19 00:08:23 +01:00
|
|
|
public Mono<Long> addDocuments(boolean atomic, Flux<Entry<LLTerm, LLUpdateDocument>> documents) {
|
2022-03-12 00:22:41 +01:00
|
|
|
if (!atomic) {
|
|
|
|
return documents
|
2022-03-13 11:01:51 +01:00
|
|
|
.publishOn(bulkScheduler)
|
2022-03-12 00:22:41 +01:00
|
|
|
.handle((document, sink) -> {
|
|
|
|
LLUpdateDocument value = document.getValue();
|
|
|
|
startedDocIndexings.increment();
|
|
|
|
try {
|
|
|
|
docIndexingTime.recordCallable(() -> {
|
|
|
|
indexWriter.addDocument(toDocument(value));
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
} catch (Exception ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
return;
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment();
|
|
|
|
}
|
2022-03-19 00:08:23 +01:00
|
|
|
logger.trace(MARKER_LUCENE, "Added document: {}", document);
|
|
|
|
sink.next(true);
|
2022-03-12 00:22:41 +01:00
|
|
|
})
|
2022-03-19 00:08:23 +01:00
|
|
|
.count()
|
2022-03-12 00:22:41 +01:00
|
|
|
.transform(this::ensureOpen);
|
|
|
|
} else {
|
|
|
|
return documents
|
|
|
|
.collectList()
|
2022-03-13 11:01:51 +01:00
|
|
|
.publishOn(bulkScheduler)
|
2022-03-19 00:08:23 +01:00
|
|
|
.<Long>handle((documentsList, sink) -> {
|
2022-03-12 00:22:41 +01:00
|
|
|
var count = documentsList.size();
|
|
|
|
StopWatch stopWatch = StopWatch.createStarted();
|
|
|
|
try {
|
|
|
|
startedDocIndexings.increment(count);
|
|
|
|
try {
|
|
|
|
indexWriter.addDocuments(LLUtils.toDocumentsFromEntries(documentsList));
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment(count);
|
|
|
|
}
|
|
|
|
} catch (IOException ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
return;
|
|
|
|
} finally {
|
|
|
|
docIndexingTime.record(stopWatch.getTime(TimeUnit.MILLISECONDS) / Math.max(count, 1),
|
|
|
|
TimeUnit.MILLISECONDS
|
|
|
|
);
|
|
|
|
}
|
2022-03-19 00:08:23 +01:00
|
|
|
sink.next((long) documentsList.size());
|
2022-03-12 00:22:41 +01:00
|
|
|
})
|
|
|
|
.transform(this::ensureOpen);
|
|
|
|
}
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
2021-01-30 19:57:50 +01:00
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
@Override
|
2021-01-30 01:41:04 +01:00
|
|
|
public Mono<Void> deleteDocument(LLTerm id) {
|
2021-12-30 17:28:06 +01:00
|
|
|
return this.<Void>runSafe(() -> docIndexingTime.recordCallable(() -> {
|
|
|
|
startedDocIndexings.increment();
|
|
|
|
try {
|
|
|
|
indexWriter.deleteDocuments(LLUtils.toTerm(id));
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment();
|
|
|
|
}
|
2021-12-17 02:18:30 +01:00
|
|
|
return null;
|
2021-12-30 17:28:06 +01:00
|
|
|
})).transform(this::ensureOpen);
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-07 17:46:40 +01:00
|
|
|
public Mono<Void> update(LLTerm id, LLIndexRequest request) {
|
2022-03-19 00:08:23 +01:00
|
|
|
return this.<Void>runSafe(() -> {
|
|
|
|
docIndexingTime.recordCallable(() -> {
|
|
|
|
startedDocIndexings.increment();
|
|
|
|
try {
|
|
|
|
if (request instanceof LLUpdateDocument updateDocument) {
|
|
|
|
indexWriter.updateDocument(LLUtils.toTerm(id), toDocument(updateDocument));
|
|
|
|
} else if (request instanceof LLSoftUpdateDocument softUpdateDocument) {
|
|
|
|
indexWriter.softUpdateDocument(LLUtils.toTerm(id),
|
|
|
|
toDocument(softUpdateDocument.items()),
|
|
|
|
toFields(softUpdateDocument.softDeleteItems())
|
|
|
|
);
|
|
|
|
} else if (request instanceof LLUpdateFields updateFields) {
|
|
|
|
indexWriter.updateDocValues(LLUtils.toTerm(id), toFields(updateFields.items()));
|
|
|
|
} else {
|
|
|
|
throw new UnsupportedOperationException("Unexpected request type: " + request);
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment();
|
2022-02-25 15:46:32 +01:00
|
|
|
}
|
2022-03-19 00:08:23 +01:00
|
|
|
return null;
|
|
|
|
});
|
|
|
|
logger.trace(MARKER_LUCENE, "Updated document {}: {}", id, request);
|
2022-02-25 15:46:32 +01:00
|
|
|
return null;
|
2022-03-19 00:08:23 +01:00
|
|
|
}).transform(this::ensureOpen);
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-03-19 00:08:23 +01:00
|
|
|
public Mono<Long> updateDocuments(Flux<Entry<LLTerm, LLUpdateDocument>> documents) {
|
2022-03-05 15:46:40 +01:00
|
|
|
return documents
|
2022-03-19 00:08:23 +01:00
|
|
|
.log("local-update-documents", Level.FINEST, false, SignalType.ON_NEXT, SignalType.ON_COMPLETE)
|
2022-03-13 11:01:51 +01:00
|
|
|
.publishOn(bulkScheduler)
|
2022-03-12 00:22:41 +01:00
|
|
|
.handle((document, sink) -> {
|
|
|
|
LLTerm key = document.getKey();
|
|
|
|
LLUpdateDocument value = document.getValue();
|
|
|
|
startedDocIndexings.increment();
|
|
|
|
try {
|
|
|
|
docIndexingTime.recordCallable(() -> {
|
|
|
|
indexWriter.updateDocument(LLUtils.toTerm(key), toDocument(value));
|
|
|
|
return null;
|
|
|
|
});
|
2022-03-18 19:16:06 +01:00
|
|
|
logger.trace(MARKER_LUCENE, "Updated document {}: {}", key, value);
|
2022-03-12 00:22:41 +01:00
|
|
|
} catch (Exception ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
return;
|
|
|
|
} finally {
|
|
|
|
endeddDocIndexings.increment();
|
|
|
|
}
|
2022-03-19 00:08:23 +01:00
|
|
|
sink.next(true);
|
2022-03-12 00:22:41 +01:00
|
|
|
})
|
2022-03-19 00:08:23 +01:00
|
|
|
.count()
|
2022-03-12 00:22:41 +01:00
|
|
|
.transform(this::ensureOpen);
|
2021-01-30 19:57:50 +01:00
|
|
|
}
|
2021-01-30 01:41:04 +01:00
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
|
|
|
|
@Override
|
2021-01-30 01:41:04 +01:00
|
|
|
public Mono<Void> deleteAll() {
|
2021-10-30 11:13:46 +02:00
|
|
|
return this.<Void>runSafe(() -> {
|
2021-12-17 02:18:30 +01:00
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
|
|
|
indexWriter.deleteAll();
|
|
|
|
indexWriter.forceMergeDeletes(true);
|
|
|
|
indexWriter.commit();
|
2022-06-23 00:14:36 +02:00
|
|
|
indexWriter.deleteUnusedFiles();
|
2021-12-17 02:18:30 +01:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
return null;
|
2022-04-05 00:37:44 +02:00
|
|
|
}).subscribeOn(luceneHeavyTasksScheduler).publishOn(Schedulers.parallel()).transform(this::ensureOpen);
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-03-05 15:46:40 +01:00
|
|
|
public Flux<LLSearchResultShard> moreLikeThis(@Nullable LLSnapshot snapshot,
|
2021-03-02 01:53:36 +01:00
|
|
|
QueryParams queryParams,
|
2022-02-26 03:28:20 +01:00
|
|
|
@Nullable String keyFieldName,
|
2022-01-28 19:31:25 +01:00
|
|
|
Multimap<String, String> mltDocumentFieldsFlux) {
|
2021-11-16 23:19:23 +01:00
|
|
|
LocalQueryParams localQueryParams = LuceneUtils.toLocalQueryParams(queryParams, luceneAnalyzer);
|
2021-09-20 11:52:21 +02:00
|
|
|
var searcher = this.searcherManager.retrieveSearcher(snapshot);
|
2022-01-28 19:31:25 +01:00
|
|
|
var transformer = new MoreLikeThisTransformer(mltDocumentFieldsFlux, luceneAnalyzer, luceneSimilarity);
|
2021-07-06 01:30:37 +02:00
|
|
|
|
2021-11-08 11:17:52 +01:00
|
|
|
return localSearcher
|
|
|
|
.collect(searcher, localQueryParams, keyFieldName, transformer)
|
2022-07-23 14:25:59 +02:00
|
|
|
.map(result -> LLSearchResultShard.withResource(result.results(), result.totalHitsCount(), result))
|
2022-03-05 15:46:40 +01:00
|
|
|
.flux();
|
2021-07-06 01:30:37 +02:00
|
|
|
}
|
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
@Override
|
2022-03-05 15:46:40 +01:00
|
|
|
public Flux<LLSearchResultShard> search(@Nullable LLSnapshot snapshot, QueryParams queryParams,
|
2022-02-26 03:28:20 +01:00
|
|
|
@Nullable String keyFieldName) {
|
2022-07-02 11:44:13 +02:00
|
|
|
return searchInternal(snapshot, queryParams, keyFieldName)
|
2022-07-23 14:25:59 +02:00
|
|
|
.map(result -> LLSearchResultShard.withResource(result.results(), result.totalHitsCount(), result))
|
2022-07-02 11:44:13 +02:00
|
|
|
.flux();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Mono<LuceneSearchResult> searchInternal(@Nullable LLSnapshot snapshot, QueryParams queryParams,
|
|
|
|
@Nullable String keyFieldName) {
|
2021-11-16 23:19:23 +01:00
|
|
|
LocalQueryParams localQueryParams = LuceneUtils.toLocalQueryParams(queryParams, luceneAnalyzer);
|
2021-09-20 11:52:21 +02:00
|
|
|
var searcher = searcherManager.retrieveSearcher(snapshot);
|
|
|
|
|
2022-07-02 11:44:13 +02:00
|
|
|
return localSearcher.collect(searcher, localQueryParams, keyFieldName, NO_REWRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Mono<TotalHitsCount> count(@Nullable LLSnapshot snapshot, Query query, @Nullable Duration timeout) {
|
|
|
|
var params = LuceneUtils.getCountQueryParams(query);
|
|
|
|
return Mono
|
|
|
|
.usingWhen(this.searchInternal(snapshot, params, null),
|
|
|
|
result -> Mono.just(result.totalHitsCount()),
|
|
|
|
LLUtils::finalizeResource
|
|
|
|
)
|
|
|
|
.defaultIfEmpty(TotalHitsCount.of(0, true));
|
2021-11-18 17:13:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-19 19:03:31 +01:00
|
|
|
public Mono<Buckets> computeBuckets(@Nullable LLSnapshot snapshot,
|
|
|
|
@NotNull List<Query> queries,
|
|
|
|
@Nullable Query normalizationQuery,
|
2021-11-18 17:13:53 +01:00
|
|
|
BucketParams bucketParams) {
|
2021-11-19 19:03:31 +01:00
|
|
|
List<org.apache.lucene.search.Query> localQueries = new ArrayList<>(queries.size());
|
|
|
|
for (Query query : queries) {
|
|
|
|
localQueries.add(QueryParser.toQuery(query, luceneAnalyzer));
|
|
|
|
}
|
|
|
|
var localNormalizationQuery = QueryParser.toQuery(normalizationQuery, luceneAnalyzer);
|
2022-06-14 13:10:38 +02:00
|
|
|
Mono<LLIndexSearchers> searchers = searcherManager
|
2021-11-18 17:13:53 +01:00
|
|
|
.retrieveSearcher(snapshot)
|
2022-07-03 01:32:13 +02:00
|
|
|
.map(indexSearcher -> LLIndexSearchers.unsharded(indexSearcher));
|
2021-11-18 17:13:53 +01:00
|
|
|
|
2022-01-26 14:22:54 +01:00
|
|
|
return decimalBucketMultiSearcher.collectMulti(searchers, bucketParams, localQueries, localNormalizationQuery);
|
2021-02-04 22:42:57 +01:00
|
|
|
}
|
|
|
|
|
2022-06-14 13:10:38 +02:00
|
|
|
public Mono<LLIndexSearcher> retrieveSearcher(@Nullable LLSnapshot snapshot) {
|
2022-01-26 14:22:54 +01:00
|
|
|
return searcherManager.retrieveSearcher(snapshot);
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-06-30 13:54:55 +02:00
|
|
|
protected void onClose() {
|
|
|
|
logger.debug("Waiting IndexWriter tasks...");
|
|
|
|
activeTasks.arriveAndAwaitAdvance();
|
|
|
|
logger.debug("IndexWriter tasks ended");
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
|
|
|
logger.debug("Closing searcher manager...");
|
|
|
|
searcherManager.close();
|
|
|
|
logger.debug("Searcher manager closed");
|
|
|
|
logger.debug("Closing IndexWriter...");
|
|
|
|
indexWriter.close();
|
|
|
|
directory.close();
|
|
|
|
logger.debug("IndexWriter closed");
|
|
|
|
} catch (IOException ex) {
|
|
|
|
throw new UncheckedIOException(ex);
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
|
2021-02-03 13:48:30 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Void> flush() {
|
|
|
|
return Mono
|
|
|
|
.<Void>fromCallable(() -> {
|
2021-10-07 00:53:38 +02:00
|
|
|
if (activeTasks.isTerminated()) return null;
|
2021-12-17 02:18:30 +01:00
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-02-28 00:40:17 +01:00
|
|
|
return null;
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
flushTime.recordCallable(() -> {
|
|
|
|
indexWriter.flush();
|
|
|
|
return null;
|
|
|
|
});
|
2021-12-17 02:18:30 +01:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
2021-02-03 13:48:30 +01:00
|
|
|
return null;
|
|
|
|
})
|
2021-10-07 00:53:38 +02:00
|
|
|
.subscribeOn(luceneHeavyTasksScheduler)
|
|
|
|
.transform(this::ensureOpen);
|
2021-02-03 13:48:30 +01:00
|
|
|
}
|
|
|
|
|
2022-06-21 14:35:07 +02:00
|
|
|
@Override
|
|
|
|
public Mono<Void> waitForMerges() {
|
|
|
|
return Mono
|
|
|
|
.<Void>fromCallable(() -> {
|
|
|
|
if (activeTasks.isTerminated()) return null;
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
var mergeScheduler = indexWriter.getConfig().getMergeScheduler();
|
|
|
|
if (mergeScheduler instanceof ConcurrentMergeScheduler concurrentMergeScheduler) {
|
|
|
|
concurrentMergeScheduler.sync();
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
})
|
|
|
|
.subscribeOn(luceneHeavyTasksScheduler)
|
|
|
|
.transform(this::ensureOpen);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Mono<Void> waitForLastMerges() {
|
|
|
|
return Mono
|
|
|
|
.<Void>fromCallable(() -> {
|
|
|
|
if (activeTasks.isTerminated()) return null;
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
indexWriter.getConfig().setMergePolicy(NoMergePolicy.INSTANCE);
|
|
|
|
var mergeScheduler = indexWriter.getConfig().getMergeScheduler();
|
|
|
|
if (mergeScheduler instanceof ConcurrentMergeScheduler concurrentMergeScheduler) {
|
|
|
|
concurrentMergeScheduler.sync();
|
|
|
|
}
|
2022-06-23 00:14:36 +02:00
|
|
|
indexWriter.deleteUnusedFiles();
|
2022-06-21 14:35:07 +02:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
})
|
|
|
|
.subscribeOn(luceneHeavyTasksScheduler)
|
|
|
|
.transform(this::ensureOpen);
|
|
|
|
}
|
|
|
|
|
2021-02-03 13:48:30 +01:00
|
|
|
@Override
|
2021-07-18 19:37:24 +02:00
|
|
|
public Mono<Void> refresh(boolean force) {
|
2021-02-03 13:48:30 +01:00
|
|
|
return Mono
|
|
|
|
.<Void>fromCallable(() -> {
|
2021-09-06 18:52:21 +02:00
|
|
|
activeTasks.register();
|
2021-02-03 13:48:30 +01:00
|
|
|
try {
|
2021-09-06 18:52:21 +02:00
|
|
|
if (activeTasks.isTerminated()) return null;
|
2021-12-17 02:18:30 +01:00
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-02-28 00:40:17 +01:00
|
|
|
return null;
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
refreshTime.recordCallable(() -> {
|
|
|
|
if (force) {
|
|
|
|
searcherManager.maybeRefreshBlocking();
|
|
|
|
} else {
|
|
|
|
searcherManager.maybeRefresh();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
2021-12-17 02:18:30 +01:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
2021-07-18 19:37:24 +02:00
|
|
|
}
|
2021-02-03 13:48:30 +01:00
|
|
|
} finally {
|
2021-09-06 18:52:21 +02:00
|
|
|
activeTasks.arriveAndDeregister();
|
2021-02-03 13:48:30 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
})
|
2021-03-03 10:57:45 +01:00
|
|
|
.subscribeOn(luceneHeavyTasksScheduler);
|
2021-02-03 13:48:30 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 00:40:17 +01:00
|
|
|
/**
|
|
|
|
* Internal method, do not use
|
|
|
|
*/
|
|
|
|
public void scheduledCommit() {
|
2021-12-17 02:18:30 +01:00
|
|
|
shutdownLock.lock();
|
2020-12-07 22:15:18 +01:00
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-02-28 00:40:17 +01:00
|
|
|
return;
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
commitTime.recordCallable(() -> {
|
|
|
|
indexWriter.commit();
|
2022-06-23 00:14:36 +02:00
|
|
|
indexWriter.deleteUnusedFiles();
|
2021-12-30 17:28:06 +01:00
|
|
|
return null;
|
|
|
|
});
|
|
|
|
} catch (Exception ex) {
|
2021-09-10 12:13:52 +02:00
|
|
|
logger.error(MARKER_LUCENE, "Failed to execute a scheduled commit", ex);
|
2021-12-17 02:18:30 +01:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 00:40:17 +01:00
|
|
|
/**
|
|
|
|
* Internal method, do not use
|
|
|
|
*/
|
|
|
|
public void scheduledMerge() { // Do not use. Merges are done automatically by merge policies
|
2021-12-17 02:18:30 +01:00
|
|
|
shutdownLock.lock();
|
2021-12-15 16:47:59 +01:00
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-02-28 00:40:17 +01:00
|
|
|
return;
|
|
|
|
}
|
2021-12-30 17:28:06 +01:00
|
|
|
mergeTime.recordCallable(() -> {
|
|
|
|
indexWriter.maybeMerge();
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
} catch (Exception ex) {
|
2021-12-15 16:47:59 +01:00
|
|
|
logger.error(MARKER_LUCENE, "Failed to execute a scheduled merge", ex);
|
2021-12-17 02:18:30 +01:00
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
2021-12-15 16:47:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-07 22:15:18 +01:00
|
|
|
@Override
|
|
|
|
public boolean isLowMemoryMode() {
|
|
|
|
return lowMemory;
|
|
|
|
}
|
2021-09-20 11:52:21 +02:00
|
|
|
|
2022-06-21 14:35:07 +02:00
|
|
|
private double getSnapshotsCount() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
2022-06-29 01:14:05 +02:00
|
|
|
if (snapshotsManager == null) return 0d;
|
2022-06-21 14:35:07 +02:00
|
|
|
return snapshotsManager.getSnapshotsCount();
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getIndexWriterFlushingBytes() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
return indexWriter.getFlushingBytes();
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getIndexWriterMaxCompletedSequenceNumber() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
return indexWriter.getMaxCompletedSequenceNumber();
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getIndexWriterPendingNumDocs() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
return indexWriter.getPendingNumDocs();
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getIndexWriterMergingSegmentsSize() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
return indexWriter.getMergingSegments().size();
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getDirectoryPendingDeletionsCount() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
return indexWriter.getDirectory().getPendingDeletions().size();
|
|
|
|
} catch (IOException e) {
|
|
|
|
return 0d;
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getDocCount() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
var docStats = indexWriter.getDocStats();
|
|
|
|
if (docStats != null) {
|
|
|
|
return docStats.numDocs;
|
|
|
|
} else {
|
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getMaxDoc() {
|
|
|
|
shutdownLock.lock();
|
|
|
|
try {
|
2022-06-30 13:54:55 +02:00
|
|
|
if (isClosed()) {
|
2022-06-21 14:35:07 +02:00
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
var docStats = indexWriter.getDocStats();
|
|
|
|
if (docStats != null) {
|
|
|
|
return docStats.maxDoc;
|
|
|
|
} else {
|
|
|
|
return 0d;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
shutdownLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-19 00:08:23 +01:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object o) {
|
|
|
|
if (this == o) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (o == null || getClass() != o.getClass()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLLocalLuceneIndex that = (LLLocalLuceneIndex) o;
|
|
|
|
|
|
|
|
return Objects.equals(shardName, that.shardName);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
return shardName.hashCode();
|
|
|
|
}
|
2022-08-15 23:07:17 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public Mono<Void> pauseForBackup() {
|
|
|
|
return backuppable.pauseForBackup();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Mono<Void> resumeAfterBackup() {
|
|
|
|
return backuppable.resumeAfterBackup();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isPaused() {
|
|
|
|
return backuppable.isPaused();
|
|
|
|
}
|
|
|
|
|
|
|
|
private class LuceneBackuppable extends Backuppable {
|
|
|
|
|
|
|
|
private LLSnapshot snapshot;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Mono<Void> onPauseForBackup() {
|
|
|
|
return LLLocalLuceneIndex.this.takeSnapshot().doOnSuccess(snapshot -> {
|
|
|
|
if (snapshot == null) {
|
|
|
|
logger.error("Can't pause index \"{}\" because snapshots are not enabled!", shardName);
|
|
|
|
}
|
|
|
|
this.snapshot = snapshot;
|
|
|
|
}).then();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Mono<Void> onResumeAfterBackup() {
|
|
|
|
if (snapshot == null) {
|
|
|
|
return Mono.empty();
|
|
|
|
}
|
|
|
|
return LLLocalLuceneIndex.this.releaseSnapshot(snapshot);
|
|
|
|
}
|
|
|
|
}
|
2020-12-07 22:15:18 +01:00
|
|
|
}
|