|
156 | 156 | import java.io.Closeable;
|
157 | 157 | import java.io.IOException;
|
158 | 158 | import java.io.PrintStream;
|
| 159 | +import java.lang.invoke.MethodHandles; |
| 160 | +import java.lang.invoke.VarHandle; |
159 | 161 | import java.nio.channels.ClosedByInterruptException;
|
160 | 162 | import java.nio.charset.StandardCharsets;
|
161 | 163 | import java.util.ArrayList;
|
@@ -413,7 +415,6 @@ public IndexShard(
|
413 | 415 | this.refreshFieldHasValueListener = new RefreshFieldHasValueListener();
|
414 | 416 | this.relativeTimeInNanosSupplier = relativeTimeInNanosSupplier;
|
415 | 417 | this.indexCommitListener = indexCommitListener;
|
416 |
| - this.fieldInfos = FieldInfos.EMPTY; |
417 | 418 | }
|
418 | 419 |
|
419 | 420 | public ThreadPool getThreadPool() {
|
@@ -1011,12 +1012,26 @@ private Engine.IndexResult applyIndexOperation(
|
1011 | 1012 | return index(engine, operation);
|
1012 | 1013 | }
|
1013 | 1014 |
|
1014 |
| - public void setFieldInfos(FieldInfos fieldInfos) { |
1015 |
| - this.fieldInfos = fieldInfos; |
| 1015 | + private static final VarHandle FIELD_INFOS; |
| 1016 | + |
| 1017 | + static { |
| 1018 | + try { |
| 1019 | + FIELD_INFOS = MethodHandles.lookup().findVarHandle(IndexShard.class, "fieldInfos", FieldInfos.class); |
| 1020 | + } catch (Exception e) { |
| 1021 | + throw new ExceptionInInitializerError(e); |
| 1022 | + } |
1016 | 1023 | }
|
1017 | 1024 |
|
1018 | 1025 | public FieldInfos getFieldInfos() {
|
1019 |
| - return fieldInfos; |
| 1026 | + var res = fieldInfos; |
| 1027 | + if (res == null) { |
| 1028 | + // don't replace field infos loaded via the refresh listener to avoid overwriting the field with an older version of the |
| 1029 | + // field infos when racing with a refresh |
| 1030 | + var read = loadFieldInfos(); |
| 1031 | + var existing = (FieldInfos) FIELD_INFOS.compareAndExchange(this, null, read); |
| 1032 | + return existing == null ? read : existing; |
| 1033 | + } |
| 1034 | + return res; |
1020 | 1035 | }
|
1021 | 1036 |
|
1022 | 1037 | public static Engine.Index prepareIndex(
|
@@ -4067,16 +4082,21 @@ public void beforeRefresh() {}
|
4067 | 4082 |
|
4068 | 4083 | @Override
|
4069 | 4084 | public void afterRefresh(boolean didRefresh) {
|
4070 |
| - if (enableFieldHasValue && (didRefresh || fieldInfos == FieldInfos.EMPTY)) { |
4071 |
| - try (Engine.Searcher hasValueSearcher = getEngine().acquireSearcher("field_has_value")) { |
4072 |
| - setFieldInfos(FieldInfos.getMergedFieldInfos(hasValueSearcher.getIndexReader())); |
4073 |
| - } catch (AlreadyClosedException ignore) { |
4074 |
| - // engine is closed - no updated FieldInfos is fine |
4075 |
| - } |
| 4085 | + if (enableFieldHasValue && (didRefresh || fieldInfos == null)) { |
| 4086 | + FIELD_INFOS.setRelease(IndexShard.this, loadFieldInfos()); |
4076 | 4087 | }
|
4077 | 4088 | }
|
4078 | 4089 | }
|
4079 | 4090 |
|
| 4091 | + private FieldInfos loadFieldInfos() { |
| 4092 | + try (Engine.Searcher hasValueSearcher = getEngine().acquireSearcher("field_has_value")) { |
| 4093 | + return FieldInfos.getMergedFieldInfos(hasValueSearcher.getIndexReader()); |
| 4094 | + } catch (AlreadyClosedException ignore) { |
| 4095 | + // engine is closed - no update to FieldInfos is fine |
| 4096 | + } |
| 4097 | + return FieldInfos.EMPTY; |
| 4098 | + } |
| 4099 | + |
4080 | 4100 | /**
|
4081 | 4101 | * Returns the shard-level field stats, which includes the number of segments in the latest NRT reader of this shard
|
4082 | 4102 | * and the total number of fields across those segments.
|
|
0 commit comments