|
|
@@ -24,6 +24,7 @@ import org.apache.lucene.index.LeafReaderContext;
|
|
|
import org.apache.lucene.index.IndexReader;
|
|
|
import org.apache.lucene.index.SegmentReader;
|
|
|
import org.apache.lucene.util.Accountable;
|
|
|
+import org.elasticsearch.common.Nullable;
|
|
|
import org.elasticsearch.common.component.AbstractComponent;
|
|
|
import org.elasticsearch.common.inject.Inject;
|
|
|
import org.elasticsearch.common.logging.ESLogger;
|
|
|
@@ -35,17 +36,13 @@ import org.elasticsearch.index.fielddata.AtomicFieldData;
|
|
|
import org.elasticsearch.index.fielddata.FieldDataType;
|
|
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
|
|
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
|
|
-import org.elasticsearch.index.IndexService;
|
|
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
|
|
import org.elasticsearch.index.shard.ShardId;
|
|
|
import org.elasticsearch.index.shard.ShardUtils;
|
|
|
-import org.elasticsearch.index.shard.IndexShard;
|
|
|
import org.elasticsearch.threadpool.ThreadPool;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
-import java.util.concurrent.Callable;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
|
*/
|
|
|
@@ -95,8 +92,8 @@ public class IndicesFieldDataCache extends AbstractComponent implements RemovalL
|
|
|
this.closed = true;
|
|
|
}
|
|
|
|
|
|
- public IndexFieldDataCache buildIndexFieldDataCache(IndexService indexService, Index index, MappedFieldType.Names fieldNames, FieldDataType fieldDataType) {
|
|
|
- return new IndexFieldCache(logger, cache, indicesFieldDataCacheListener, indexService, index, fieldNames, fieldDataType);
|
|
|
+ public IndexFieldDataCache buildIndexFieldDataCache(IndexFieldDataCache.Listener listener, Index index, MappedFieldType.Names fieldNames, FieldDataType fieldDataType) {
|
|
|
+ return new IndexFieldCache(logger, cache, index, fieldNames, fieldDataType, indicesFieldDataCacheListener, listener);
|
|
|
}
|
|
|
|
|
|
public Cache<Key, Accountable> getCache() {
|
|
|
@@ -111,7 +108,7 @@ public class IndicesFieldDataCache extends AbstractComponent implements RemovalL
|
|
|
final Accountable value = notification.getValue();
|
|
|
for (IndexFieldDataCache.Listener listener : key.listeners) {
|
|
|
try {
|
|
|
- listener.onUnload(indexCache.fieldNames, indexCache.fieldDataType, notification.wasEvicted(), value.ramBytesUsed());
|
|
|
+ listener.onRemoval(key.shardId, indexCache.fieldNames, indexCache.fieldDataType, notification.wasEvicted(), value.ramBytesUsed());
|
|
|
} catch (Throwable e) {
|
|
|
// load anyway since listeners should not throw exceptions
|
|
|
logger.error("Failed to call listener on field data cache unloading", e);
|
|
|
@@ -133,96 +130,78 @@ public class IndicesFieldDataCache extends AbstractComponent implements RemovalL
|
|
|
*/
|
|
|
static class IndexFieldCache implements IndexFieldDataCache, SegmentReader.CoreClosedListener, IndexReader.ReaderClosedListener {
|
|
|
private final ESLogger logger;
|
|
|
- private final IndexService indexService;
|
|
|
final Index index;
|
|
|
final MappedFieldType.Names fieldNames;
|
|
|
final FieldDataType fieldDataType;
|
|
|
private final Cache<Key, Accountable> cache;
|
|
|
- private final IndicesFieldDataCacheListener indicesFieldDataCacheListener;
|
|
|
+ private final Listener[] listeners;
|
|
|
|
|
|
- IndexFieldCache(ESLogger logger,final Cache<Key, Accountable> cache, IndicesFieldDataCacheListener indicesFieldDataCacheListener, IndexService indexService, Index index, MappedFieldType.Names fieldNames, FieldDataType fieldDataType) {
|
|
|
+ IndexFieldCache(ESLogger logger,final Cache<Key, Accountable> cache, Index index, MappedFieldType.Names fieldNames, FieldDataType fieldDataType, Listener... listeners) {
|
|
|
this.logger = logger;
|
|
|
- this.indexService = indexService;
|
|
|
+ this.listeners = listeners;
|
|
|
this.index = index;
|
|
|
this.fieldNames = fieldNames;
|
|
|
this.fieldDataType = fieldDataType;
|
|
|
this.cache = cache;
|
|
|
- this.indicesFieldDataCacheListener = indicesFieldDataCacheListener;
|
|
|
- assert indexService != null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public <FD extends AtomicFieldData, IFD extends IndexFieldData<FD>> FD load(final LeafReaderContext context, final IFD indexFieldData) throws Exception {
|
|
|
- final Key key = new Key(this, context.reader().getCoreCacheKey());
|
|
|
+ final ShardId shardId = ShardUtils.extractShardId(context.reader());
|
|
|
+ final Key key = new Key(this, context.reader().getCoreCacheKey(), shardId);
|
|
|
//noinspection unchecked
|
|
|
- final Accountable accountable = cache.get(key, new Callable<AtomicFieldData>() {
|
|
|
- @Override
|
|
|
- public AtomicFieldData call() throws Exception {
|
|
|
- context.reader().addCoreClosedListener(IndexFieldCache.this);
|
|
|
-
|
|
|
- key.listeners.add(indicesFieldDataCacheListener);
|
|
|
- final ShardId shardId = ShardUtils.extractShardId(context.reader());
|
|
|
- if (shardId != null) {
|
|
|
- final IndexShard shard = indexService.shard(shardId.id());
|
|
|
- if (shard != null) {
|
|
|
- key.listeners.add(shard.fieldData());
|
|
|
- }
|
|
|
- }
|
|
|
- final AtomicFieldData fieldData = indexFieldData.loadDirect(context);
|
|
|
- for (Listener listener : key.listeners) {
|
|
|
- try {
|
|
|
- listener.onLoad(fieldNames, fieldDataType, fieldData);
|
|
|
- } catch (Throwable e) {
|
|
|
- // load anyway since listeners should not throw exceptions
|
|
|
- logger.error("Failed to call listener on atomic field data loading", e);
|
|
|
- }
|
|
|
+ final Accountable accountable = cache.get(key, () -> {
|
|
|
+ context.reader().addCoreClosedListener(IndexFieldCache.this);
|
|
|
+ for (Listener listener : this.listeners) {
|
|
|
+ key.listeners.add(listener);
|
|
|
+ }
|
|
|
+ final AtomicFieldData fieldData = indexFieldData.loadDirect(context);
|
|
|
+ for (Listener listener : key.listeners) {
|
|
|
+ try {
|
|
|
+ listener.onCache(shardId, fieldNames, fieldDataType, fieldData);
|
|
|
+ } catch (Throwable e) {
|
|
|
+ // load anyway since listeners should not throw exceptions
|
|
|
+ logger.error("Failed to call listener on atomic field data loading", e);
|
|
|
}
|
|
|
- return fieldData;
|
|
|
}
|
|
|
+ return fieldData;
|
|
|
});
|
|
|
return (FD) accountable;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public <FD extends AtomicFieldData, IFD extends IndexFieldData.Global<FD>> IFD load(final IndexReader indexReader, final IFD indexFieldData) throws Exception {
|
|
|
- final Key key = new Key(this, indexReader.getCoreCacheKey());
|
|
|
+ final ShardId shardId = ShardUtils.extractShardId(indexReader);
|
|
|
+ final Key key = new Key(this, indexReader.getCoreCacheKey(), shardId);
|
|
|
//noinspection unchecked
|
|
|
- final Accountable accountable = cache.get(key, new Callable<Accountable>() {
|
|
|
- @Override
|
|
|
- public Accountable call() throws Exception {
|
|
|
- indexReader.addReaderClosedListener(IndexFieldCache.this);
|
|
|
- key.listeners.add(indicesFieldDataCacheListener);
|
|
|
- final ShardId shardId = ShardUtils.extractShardId(indexReader);
|
|
|
- if (shardId != null) {
|
|
|
- IndexShard shard = indexService.shard(shardId.id());
|
|
|
- if (shard != null) {
|
|
|
- key.listeners.add(shard.fieldData());
|
|
|
- }
|
|
|
- }
|
|
|
- final Accountable ifd = (Accountable) indexFieldData.localGlobalDirect(indexReader);
|
|
|
- for (Listener listener : key.listeners) {
|
|
|
- try {
|
|
|
- listener.onLoad(fieldNames, fieldDataType, ifd);
|
|
|
- } catch (Throwable e) {
|
|
|
- // load anyway since listeners should not throw exceptions
|
|
|
- logger.error("Failed to call listener on global ordinals loading", e);
|
|
|
- }
|
|
|
+ final Accountable accountable = cache.get(key, () -> {
|
|
|
+ indexReader.addReaderClosedListener(IndexFieldCache.this);
|
|
|
+ for (Listener listener : this.listeners) {
|
|
|
+ key.listeners.add(listener);
|
|
|
+ }
|
|
|
+ final Accountable ifd = (Accountable) indexFieldData.localGlobalDirect(indexReader);
|
|
|
+ for (Listener listener : key.listeners) {
|
|
|
+ try {
|
|
|
+ listener.onCache(shardId, fieldNames, fieldDataType, ifd);
|
|
|
+ } catch (Throwable e) {
|
|
|
+ // load anyway since listeners should not throw exceptions
|
|
|
+ logger.error("Failed to call listener on global ordinals loading", e);
|
|
|
}
|
|
|
- return ifd;
|
|
|
}
|
|
|
+ return ifd;
|
|
|
});
|
|
|
return (IFD) accountable;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onClose(Object coreKey) {
|
|
|
- cache.invalidate(new Key(this, coreKey));
|
|
|
+ cache.invalidate(new Key(this, coreKey, null));
|
|
|
// don't call cache.cleanUp here as it would have bad performance implications
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onClose(IndexReader reader) {
|
|
|
- cache.invalidate(new Key(this, reader.getCoreCacheKey()));
|
|
|
+ cache.invalidate(new Key(this, reader.getCoreCacheKey(), null));
|
|
|
// don't call cache.cleanUp here as it would have bad performance implications
|
|
|
}
|
|
|
|
|
|
@@ -263,8 +242,8 @@ public class IndicesFieldDataCache extends AbstractComponent implements RemovalL
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void clear(Object coreCacheKey) {
|
|
|
- cache.invalidate(new Key(this, coreCacheKey));
|
|
|
+ public void clear(IndexReader indexReader) {
|
|
|
+ cache.invalidate(new Key(this, indexReader.getCoreCacheKey(), null));
|
|
|
// don't call cache.cleanUp here as it would have bad performance implications
|
|
|
}
|
|
|
}
|
|
|
@@ -272,13 +251,14 @@ public class IndicesFieldDataCache extends AbstractComponent implements RemovalL
|
|
|
public static class Key {
|
|
|
public final IndexFieldCache indexCache;
|
|
|
public final Object readerKey;
|
|
|
+ public final ShardId shardId;
|
|
|
|
|
|
public final List<IndexFieldDataCache.Listener> listeners = new ArrayList<>();
|
|
|
|
|
|
-
|
|
|
- Key(IndexFieldCache indexCache, Object readerKey) {
|
|
|
+ Key(IndexFieldCache indexCache, Object readerKey, @Nullable ShardId shardId) {
|
|
|
this.indexCache = indexCache;
|
|
|
this.readerKey = readerKey;
|
|
|
+ this.shardId = shardId;
|
|
|
}
|
|
|
|
|
|
@Override
|