2021-09-19 19:59:37 +02:00
|
|
|
package it.cavallium.dbengine.database.disk;
|
|
|
|
|
|
|
|
import io.net5.buffer.api.Drop;
|
|
|
|
import io.net5.buffer.api.Owned;
|
|
|
|
import io.net5.buffer.api.Resource;
|
|
|
|
import io.net5.buffer.api.Send;
|
2021-10-17 17:15:57 +02:00
|
|
|
import io.net5.buffer.api.internal.ResourceSupport;
|
2021-09-19 19:59:37 +02:00
|
|
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.UncheckedIOException;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import java.util.List;
|
2021-12-17 01:48:49 +01:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.Logger;
|
2021-09-19 19:59:37 +02:00
|
|
|
import org.apache.lucene.index.IndexReader;
|
|
|
|
import org.apache.lucene.index.MultiReader;
|
2021-09-22 11:03:39 +02:00
|
|
|
import org.apache.lucene.search.IndexSearcher;
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-09-20 11:35:01 +02:00
|
|
|
public interface LLIndexSearchers extends Resource<LLIndexSearchers> {
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-09-20 11:35:01 +02:00
|
|
|
static LLIndexSearchers of(List<Send<LLIndexSearcher>> indexSearchers) {
|
2021-10-01 19:17:33 +02:00
|
|
|
return new ShardedIndexSearchers(indexSearchers, null);
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
2021-09-20 11:35:01 +02:00
|
|
|
static UnshardedIndexSearchers unsharded(Send<LLIndexSearcher> indexSearcher) {
|
2021-10-01 19:17:33 +02:00
|
|
|
return new UnshardedIndexSearchers(indexSearcher, null);
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
2021-09-22 11:03:39 +02:00
|
|
|
List<IndexSearcher> shards();
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-09-22 11:03:39 +02:00
|
|
|
IndexSearcher shard(int shardIndex);
|
2021-09-19 19:59:37 +02:00
|
|
|
|
|
|
|
IndexReader allShards();
|
|
|
|
|
2021-10-17 17:15:57 +02:00
|
|
|
class UnshardedIndexSearchers extends ResourceSupport<LLIndexSearchers, UnshardedIndexSearchers>
|
2021-09-20 11:35:01 +02:00
|
|
|
implements LLIndexSearchers {
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-12-17 01:48:49 +01:00
|
|
|
private static final Logger logger = LogManager.getLogger(UnshardedIndexSearchers.class);
|
2021-10-01 19:17:33 +02:00
|
|
|
|
|
|
|
private static final Drop<UnshardedIndexSearchers> DROP = new Drop<>() {
|
|
|
|
@Override
|
|
|
|
public void drop(UnshardedIndexSearchers obj) {
|
|
|
|
try {
|
|
|
|
if (obj.indexSearcher != null) {
|
|
|
|
obj.indexSearcher.close();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
logger.error("Failed to close indexSearcher", ex);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (obj.onClose != null) {
|
|
|
|
obj.onClose.run();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
logger.error("Failed to close onClose", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Drop<UnshardedIndexSearchers> fork() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void attach(UnshardedIndexSearchers obj) {
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-09-20 11:35:01 +02:00
|
|
|
private LLIndexSearcher indexSearcher;
|
2021-10-01 19:17:33 +02:00
|
|
|
private Runnable onClose;
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-10-01 19:17:33 +02:00
|
|
|
public UnshardedIndexSearchers(Send<LLIndexSearcher> indexSearcher, Runnable onClose) {
|
|
|
|
super(DROP);
|
2021-09-19 19:59:37 +02:00
|
|
|
this.indexSearcher = indexSearcher.receive();
|
2021-10-01 19:17:33 +02:00
|
|
|
this.onClose = onClose;
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-09-22 11:03:39 +02:00
|
|
|
public List<IndexSearcher> shards() {
|
|
|
|
return List.of(indexSearcher.getIndexSearcher());
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-09-22 11:03:39 +02:00
|
|
|
public IndexSearcher shard(int shardIndex) {
|
2021-09-19 19:59:37 +02:00
|
|
|
if (!isOwned()) {
|
|
|
|
throw attachTrace(new IllegalStateException("UnshardedIndexSearchers must be owned to be used"));
|
|
|
|
}
|
|
|
|
if (shardIndex != -1) {
|
|
|
|
throw new IndexOutOfBoundsException("Shard index " + shardIndex + " is invalid, this is a unsharded index");
|
|
|
|
}
|
2021-09-22 11:03:39 +02:00
|
|
|
return indexSearcher.getIndexSearcher();
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public IndexReader allShards() {
|
|
|
|
return indexSearcher.getIndexReader();
|
|
|
|
}
|
|
|
|
|
2021-09-22 11:03:39 +02:00
|
|
|
public IndexSearcher shard() {
|
2021-09-20 18:20:59 +02:00
|
|
|
return this.shard(-1);
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected RuntimeException createResourceClosedException() {
|
|
|
|
return new IllegalStateException("Closed");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Owned<UnshardedIndexSearchers> prepareSend() {
|
2021-09-20 11:35:01 +02:00
|
|
|
Send<LLIndexSearcher> indexSearcher = this.indexSearcher.send();
|
2021-10-01 19:17:33 +02:00
|
|
|
var onClose = this.onClose;
|
|
|
|
return drop -> {
|
|
|
|
var instance = new UnshardedIndexSearchers(indexSearcher, onClose);
|
|
|
|
drop.attach(instance);
|
|
|
|
return instance;
|
|
|
|
};
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:34:56 +02:00
|
|
|
protected void makeInaccessible() {
|
2021-09-19 19:59:37 +02:00
|
|
|
this.indexSearcher = null;
|
2021-10-01 19:17:33 +02:00
|
|
|
this.onClose = null;
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
2021-10-01 19:17:33 +02:00
|
|
|
}
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-10-17 17:15:57 +02:00
|
|
|
class ShardedIndexSearchers extends ResourceSupport<LLIndexSearchers, ShardedIndexSearchers>
|
2021-10-01 19:17:33 +02:00
|
|
|
implements LLIndexSearchers {
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-12-17 01:48:49 +01:00
|
|
|
private static final Logger logger = LogManager.getLogger(ShardedIndexSearchers.class);
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-10-01 19:17:33 +02:00
|
|
|
private static final Drop<ShardedIndexSearchers> DROP = new Drop<>() {
|
|
|
|
@Override
|
|
|
|
public void drop(ShardedIndexSearchers obj) {
|
|
|
|
try {
|
|
|
|
for (LLIndexSearcher indexSearcher : obj.indexSearchers) {
|
|
|
|
indexSearcher.close();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
logger.error("Failed to close indexSearcher", ex);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (obj.onClose != null) {
|
|
|
|
obj.onClose.run();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
logger.error("Failed to close onClose", ex);
|
2021-09-24 01:59:56 +02:00
|
|
|
}
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-10-01 19:17:33 +02:00
|
|
|
public Drop<ShardedIndexSearchers> fork() {
|
|
|
|
return this;
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
2021-10-01 19:17:33 +02:00
|
|
|
@Override
|
|
|
|
public void attach(ShardedIndexSearchers obj) {
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-09-20 11:35:01 +02:00
|
|
|
private List<LLIndexSearcher> indexSearchers;
|
2021-09-22 11:03:39 +02:00
|
|
|
private List<IndexSearcher> indexSearchersVals;
|
2021-10-01 19:17:33 +02:00
|
|
|
private Runnable onClose;
|
2021-09-19 19:59:37 +02:00
|
|
|
|
2021-10-01 19:17:33 +02:00
|
|
|
public ShardedIndexSearchers(List<Send<LLIndexSearcher>> indexSearchers, Runnable onClose) {
|
|
|
|
super(DROP);
|
2021-09-19 19:59:37 +02:00
|
|
|
this.indexSearchers = new ArrayList<>(indexSearchers.size());
|
2021-09-22 11:03:39 +02:00
|
|
|
this.indexSearchersVals = new ArrayList<>(indexSearchers.size());
|
|
|
|
for (Send<LLIndexSearcher> llIndexSearcher : indexSearchers) {
|
|
|
|
var indexSearcher = llIndexSearcher.receive();
|
|
|
|
this.indexSearchers.add(indexSearcher);
|
|
|
|
this.indexSearchersVals.add(indexSearcher.getIndexSearcher());
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
2021-10-01 19:17:33 +02:00
|
|
|
this.onClose = onClose;
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-09-22 11:03:39 +02:00
|
|
|
public List<IndexSearcher> shards() {
|
|
|
|
if (!isOwned()) {
|
|
|
|
throw attachTrace(new IllegalStateException("ShardedIndexSearchers must be owned to be used"));
|
|
|
|
}
|
|
|
|
return Collections.unmodifiableList(indexSearchersVals);
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-09-22 11:03:39 +02:00
|
|
|
public IndexSearcher shard(int shardIndex) {
|
2021-09-19 19:59:37 +02:00
|
|
|
if (!isOwned()) {
|
|
|
|
throw attachTrace(new IllegalStateException("ShardedIndexSearchers must be owned to be used"));
|
|
|
|
}
|
|
|
|
if (shardIndex < 0) {
|
|
|
|
throw new IndexOutOfBoundsException("Shard index " + shardIndex + " is invalid");
|
|
|
|
}
|
2021-09-22 11:03:39 +02:00
|
|
|
return indexSearchersVals.get(shardIndex);
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public IndexReader allShards() {
|
2021-09-22 11:03:39 +02:00
|
|
|
if (!isOwned()) {
|
|
|
|
throw attachTrace(new IllegalStateException("ShardedIndexSearchers must be owned to be used"));
|
|
|
|
}
|
|
|
|
var irs = new IndexReader[indexSearchersVals.size()];
|
|
|
|
for (int i = 0, s = indexSearchersVals.size(); i < s; i++) {
|
|
|
|
irs[i] = indexSearchersVals.get(i).getIndexReader();
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
Object2IntOpenHashMap<IndexReader> indexes = new Object2IntOpenHashMap<>();
|
|
|
|
for (int i = 0; i < irs.length; i++) {
|
|
|
|
indexes.put(irs[i], i);
|
|
|
|
}
|
|
|
|
try {
|
2021-09-22 11:03:39 +02:00
|
|
|
return new MultiReader(irs, Comparator.comparingInt(indexes::getInt), false);
|
2021-09-19 19:59:37 +02:00
|
|
|
} catch (IOException ex) {
|
|
|
|
// This shouldn't happen
|
|
|
|
throw new UncheckedIOException(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected RuntimeException createResourceClosedException() {
|
|
|
|
return new IllegalStateException("Closed");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Owned<ShardedIndexSearchers> prepareSend() {
|
2021-09-20 11:35:01 +02:00
|
|
|
List<Send<LLIndexSearcher>> indexSearchers = new ArrayList<>(this.indexSearchers.size());
|
|
|
|
for (LLIndexSearcher indexSearcher : this.indexSearchers) {
|
2021-09-19 19:59:37 +02:00
|
|
|
indexSearchers.add(indexSearcher.send());
|
|
|
|
}
|
2021-10-01 19:17:33 +02:00
|
|
|
var onClose = this.onClose;
|
|
|
|
return drop -> {
|
|
|
|
var instance = new ShardedIndexSearchers(indexSearchers, onClose);
|
|
|
|
drop.attach(instance);
|
|
|
|
return instance;
|
|
|
|
};
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:34:56 +02:00
|
|
|
protected void makeInaccessible() {
|
2021-09-19 19:59:37 +02:00
|
|
|
this.indexSearchers = null;
|
2021-09-22 11:03:39 +02:00
|
|
|
this.indexSearchersVals = null;
|
2021-10-01 19:17:33 +02:00
|
|
|
this.onClose = null;
|
2021-09-19 19:59:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|