|
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() {
|
@@ -1015,12 +1016,26 @@ private Engine.IndexResult applyIndexOperation(
|
1015 | 1016 | return index(engine, operation);
|
1016 | 1017 | }
|
1017 | 1018 |
|
1018 |
| - public void setFieldInfos(FieldInfos fieldInfos) { |
1019 |
| - this.fieldInfos = fieldInfos; |
| 1019 | + private static final VarHandle FIELD_INFOS; |
| 1020 | + |
| 1021 | + static { |
| 1022 | + try { |
| 1023 | + FIELD_INFOS = MethodHandles.lookup().findVarHandle(IndexShard.class, "fieldInfos", FieldInfos.class); |
| 1024 | + } catch (Exception e) { |
| 1025 | + throw new ExceptionInInitializerError(e); |
| 1026 | + } |
1020 | 1027 | }
|
1021 | 1028 |
|
1022 | 1029 | public FieldInfos getFieldInfos() {
|
1023 |
| - return fieldInfos; |
| 1030 | + var res = fieldInfos; |
| 1031 | + if (res == null) { |
| 1032 | + // don't replace field infos loaded via the refresh listener to avoid overwriting the field with an older version of the |
| 1033 | + // field infos when racing with a refresh |
| 1034 | + var read = loadFieldInfos(); |
| 1035 | + var existing = (FieldInfos) FIELD_INFOS.compareAndExchange(this, null, read); |
| 1036 | + return existing == null ? read : existing; |
| 1037 | + } |
| 1038 | + return res; |
1024 | 1039 | }
|
1025 | 1040 |
|
1026 | 1041 | public static Engine.Index prepareIndex(
|
@@ -4114,16 +4129,21 @@ public void beforeRefresh() {}
|
4114 | 4129 |
|
4115 | 4130 | @Override
|
4116 | 4131 | public void afterRefresh(boolean didRefresh) {
|
4117 |
| - if (enableFieldHasValue && (didRefresh || fieldInfos == FieldInfos.EMPTY)) { |
4118 |
| - try (Engine.Searcher hasValueSearcher = getEngine().acquireSearcher("field_has_value")) { |
4119 |
| - setFieldInfos(FieldInfos.getMergedFieldInfos(hasValueSearcher.getIndexReader())); |
4120 |
| - } catch (AlreadyClosedException ignore) { |
4121 |
| - // engine is closed - no updated FieldInfos is fine |
4122 |
| - } |
| 4132 | + if (enableFieldHasValue && (didRefresh || fieldInfos == null)) { |
| 4133 | + FIELD_INFOS.setRelease(IndexShard.this, loadFieldInfos()); |
4123 | 4134 | }
|
4124 | 4135 | }
|
4125 | 4136 | }
|
4126 | 4137 |
|
| 4138 | + private FieldInfos loadFieldInfos() { |
| 4139 | + try (Engine.Searcher hasValueSearcher = getEngine().acquireSearcher("field_has_value")) { |
| 4140 | + return FieldInfos.getMergedFieldInfos(hasValueSearcher.getIndexReader()); |
| 4141 | + } catch (AlreadyClosedException ignore) { |
| 4142 | + // engine is closed - no update to FieldInfos is fine |
| 4143 | + } |
| 4144 | + return FieldInfos.EMPTY; |
| 4145 | + } |
| 4146 | + |
4127 | 4147 | /**
|
4128 | 4148 | * Returns the shard-level field stats, which includes the number of segments in the latest NRT reader of this shard
|
4129 | 4149 | * and the total number of fields across those segments.
|
|
0 commit comments