Skip to content

Commit 6b14070

Browse files
committed
Introduce index settings version (#34429)
This commit introduces settings version to index metadata. This value is monotonically increasing and is updated on settings updates. This will be useful in cross-cluster replication so that we can request settings updates from the leader only when there is a settings update.
1 parent 6dce0e1 commit 6b14070

File tree

16 files changed

+337
-22
lines changed

16 files changed

+337
-22
lines changed

server/src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,10 @@ public String toString() {
284284
final String TAB = " ";
285285
for (IndexMetaData indexMetaData : metaData) {
286286
sb.append(TAB).append(indexMetaData.getIndex());
287-
sb.append(": v[").append(indexMetaData.getVersion()).append("], mv[").append(indexMetaData.getMappingVersion()).append("]\n");
287+
sb.append(": v[").append(indexMetaData.getVersion())
288+
.append("], mv[").append(indexMetaData.getMappingVersion())
289+
.append("], sv[").append(indexMetaData.getSettingsVersion())
290+
.append("]\n");
288291
for (int shard = 0; shard < indexMetaData.getNumberOfShards(); shard++) {
289292
sb.append(TAB).append(TAB).append(shard).append(": ");
290293
sb.append("p_term [").append(indexMetaData.primaryTerm(shard)).append("], ");

server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ public Iterator<Setting<Integer>> settings() {
244244
public static final String KEY_IN_SYNC_ALLOCATIONS = "in_sync_allocations";
245245
static final String KEY_VERSION = "version";
246246
static final String KEY_MAPPING_VERSION = "mapping_version";
247+
static final String KEY_SETTINGS_VERSION = "settings_version";
247248
static final String KEY_ROUTING_NUM_SHARDS = "routing_num_shards";
248249
static final String KEY_SETTINGS = "settings";
249250
static final String KEY_STATE = "state";
@@ -265,6 +266,8 @@ public Iterator<Setting<Integer>> settings() {
265266

266267
private final long mappingVersion;
267268

269+
private final long settingsVersion;
270+
268271
private final long[] primaryTerms;
269272

270273
private final State state;
@@ -292,7 +295,7 @@ public Iterator<Setting<Integer>> settings() {
292295
private final ActiveShardCount waitForActiveShards;
293296
private final ImmutableOpenMap<String, RolloverInfo> rolloverInfos;
294297

295-
private IndexMetaData(Index index, long version, long mappingVersion, long[] primaryTerms, State state, int numberOfShards, int numberOfReplicas, Settings settings,
298+
private IndexMetaData(Index index, long version, long mappingVersion, long settingsVersion, long[] primaryTerms, State state, int numberOfShards, int numberOfReplicas, Settings settings,
296299
ImmutableOpenMap<String, MappingMetaData> mappings, ImmutableOpenMap<String, AliasMetaData> aliases,
297300
ImmutableOpenMap<String, DiffableStringMap> customData, ImmutableOpenIntMap<Set<String>> inSyncAllocationIds,
298301
DiscoveryNodeFilters requireFilters, DiscoveryNodeFilters initialRecoveryFilters, DiscoveryNodeFilters includeFilters, DiscoveryNodeFilters excludeFilters,
@@ -303,6 +306,8 @@ private IndexMetaData(Index index, long version, long mappingVersion, long[] pri
303306
this.version = version;
304307
assert mappingVersion >= 0 : mappingVersion;
305308
this.mappingVersion = mappingVersion;
309+
assert settingsVersion >= 0 : settingsVersion;
310+
this.settingsVersion = settingsVersion;
306311
this.primaryTerms = primaryTerms;
307312
assert primaryTerms.length == numberOfShards;
308313
this.state = state;
@@ -356,6 +361,10 @@ public long getMappingVersion() {
356361
return mappingVersion;
357362
}
358363

364+
public long getSettingsVersion() {
365+
return settingsVersion;
366+
}
367+
359368
/**
360369
* The term of the current selected primary. This is a non-negative number incremented when
361370
* a primary shard is assigned after a full cluster restart or a replica shard is promoted to a primary.
@@ -605,6 +614,7 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
605614
private final int routingNumShards;
606615
private final long version;
607616
private final long mappingVersion;
617+
private final long settingsVersion;
608618
private final long[] primaryTerms;
609619
private final State state;
610620
private final Settings settings;
@@ -618,6 +628,7 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
618628
index = after.index.getName();
619629
version = after.version;
620630
mappingVersion = after.mappingVersion;
631+
settingsVersion = after.settingsVersion;
621632
routingNumShards = after.routingNumShards;
622633
state = after.state;
623634
settings = after.settings;
@@ -639,6 +650,11 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
639650
} else {
640651
mappingVersion = 1;
641652
}
653+
if (in.getVersion().onOrAfter(Version.V_6_5_0)) {
654+
settingsVersion = in.readVLong();
655+
} else {
656+
settingsVersion = 1;
657+
}
642658
state = State.fromId(in.readByte());
643659
settings = Settings.readSettingsFromStream(in);
644660
primaryTerms = in.readVLongArray();
@@ -667,6 +683,9 @@ public void writeTo(StreamOutput out) throws IOException {
667683
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
668684
out.writeVLong(mappingVersion);
669685
}
686+
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
687+
out.writeVLong(settingsVersion);
688+
}
670689
out.writeByte(state.id);
671690
Settings.writeSettingsToStream(settings, out);
672691
out.writeVLongArray(primaryTerms);
@@ -684,6 +703,7 @@ public IndexMetaData apply(IndexMetaData part) {
684703
Builder builder = builder(index);
685704
builder.version(version);
686705
builder.mappingVersion(mappingVersion);
706+
builder.settingsVersion(settingsVersion);
687707
builder.setRoutingNumShards(routingNumShards);
688708
builder.state(state);
689709
builder.settings(settings);
@@ -705,6 +725,11 @@ public static IndexMetaData readFrom(StreamInput in) throws IOException {
705725
} else {
706726
builder.mappingVersion(1);
707727
}
728+
if (in.getVersion().onOrAfter(Version.V_6_5_0)) {
729+
builder.settingsVersion(in.readVLong());
730+
} else {
731+
builder.settingsVersion(1);
732+
}
708733
builder.setRoutingNumShards(in.readInt());
709734
builder.state(State.fromId(in.readByte()));
710735
builder.settings(readSettingsFromStream(in));
@@ -754,6 +779,9 @@ public void writeTo(StreamOutput out) throws IOException {
754779
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
755780
out.writeVLong(mappingVersion);
756781
}
782+
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
783+
out.writeVLong(settingsVersion);
784+
}
757785
out.writeInt(routingNumShards);
758786
out.writeByte(state.id());
759787
writeSettingsToStream(settings, out);
@@ -802,6 +830,7 @@ public static class Builder {
802830
private State state = State.OPEN;
803831
private long version = 1;
804832
private long mappingVersion = 1;
833+
private long settingsVersion = 1;
805834
private long[] primaryTerms = null;
806835
private Settings settings = Settings.Builder.EMPTY_SETTINGS;
807836
private final ImmutableOpenMap.Builder<String, MappingMetaData> mappings;
@@ -825,6 +854,7 @@ public Builder(IndexMetaData indexMetaData) {
825854
this.state = indexMetaData.state;
826855
this.version = indexMetaData.version;
827856
this.mappingVersion = indexMetaData.mappingVersion;
857+
this.settingsVersion = indexMetaData.settingsVersion;
828858
this.settings = indexMetaData.getSettings();
829859
this.primaryTerms = indexMetaData.primaryTerms.clone();
830860
this.mappings = ImmutableOpenMap.builder(indexMetaData.mappings);
@@ -999,11 +1029,20 @@ public long mappingVersion() {
9991029
return mappingVersion;
10001030
}
10011031

1032+
public long settingsVersion() {
1033+
return settingsVersion;
1034+
}
1035+
10021036
public Builder mappingVersion(final long mappingVersion) {
10031037
this.mappingVersion = mappingVersion;
10041038
return this;
10051039
}
10061040

1041+
public Builder settingsVersion(final long settingsVersion) {
1042+
this.settingsVersion = settingsVersion;
1043+
return this;
1044+
}
1045+
10071046
/**
10081047
* returns the primary term for the given shard.
10091048
* See {@link IndexMetaData#primaryTerm(int)} for more information.
@@ -1131,7 +1170,7 @@ public IndexMetaData build() {
11311170

11321171
final String uuid = settings.get(SETTING_INDEX_UUID, INDEX_UUID_NA_VALUE);
11331172

1134-
return new IndexMetaData(new Index(index, uuid), version, mappingVersion, primaryTerms, state, numberOfShards, numberOfReplicas, tmpSettings, mappings.build(),
1173+
return new IndexMetaData(new Index(index, uuid), version, mappingVersion, settingsVersion, primaryTerms, state, numberOfShards, numberOfReplicas, tmpSettings, mappings.build(),
11351174
tmpAliases.build(), customMetaData.build(), filledInSyncAllocationIds.build(), requireFilters, initialRecoveryFilters, includeFilters, excludeFilters,
11361175
indexCreatedVersion, indexUpgradedVersion, getRoutingNumShards(), routingPartitionSize, waitForActiveShards, rolloverInfos.build());
11371176
}
@@ -1141,6 +1180,7 @@ public static void toXContent(IndexMetaData indexMetaData, XContentBuilder build
11411180

11421181
builder.field(KEY_VERSION, indexMetaData.getVersion());
11431182
builder.field(KEY_MAPPING_VERSION, indexMetaData.getMappingVersion());
1183+
builder.field(KEY_SETTINGS_VERSION, indexMetaData.getSettingsVersion());
11441184
builder.field(KEY_ROUTING_NUM_SHARDS, indexMetaData.getRoutingNumShards());
11451185
builder.field(KEY_STATE, indexMetaData.getState().toString().toLowerCase(Locale.ENGLISH));
11461186

@@ -1214,6 +1254,7 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
12141254
throw new IllegalArgumentException("expected object but got a " + token);
12151255
}
12161256
boolean mappingVersion = false;
1257+
boolean settingsVersion = false;
12171258
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
12181259
if (token == XContentParser.Token.FIELD_NAME) {
12191260
currentFieldName = parser.currentName();
@@ -1308,6 +1349,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
13081349
} else if (KEY_MAPPING_VERSION.equals(currentFieldName)) {
13091350
mappingVersion = true;
13101351
builder.mappingVersion(parser.longValue());
1352+
} else if (KEY_SETTINGS_VERSION.equals(currentFieldName)) {
1353+
settingsVersion = true;
1354+
builder.settingsVersion(parser.longValue());
13111355
} else if (KEY_ROUTING_NUM_SHARDS.equals(currentFieldName)) {
13121356
builder.setRoutingNumShards(parser.intValue());
13131357
} else {
@@ -1320,6 +1364,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
13201364
if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_6_5_0)) {
13211365
assert mappingVersion : "mapping version should be present for indices created on or after 6.5.0";
13221366
}
1367+
if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_6_5_0)) {
1368+
assert settingsVersion : "settings version should be present for indices created on or after 6.5.0";
1369+
}
13231370
return builder.build();
13241371
}
13251372
}

server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataUpdateSettingsService.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.util.Set;
5252

5353
import static org.elasticsearch.action.support.ContextPreservingActionListener.wrapPreservingContext;
54+
import static org.elasticsearch.index.IndexSettings.same;
5455

5556
/**
5657
* Service responsible for submitting update index settings requests
@@ -187,6 +188,14 @@ public ClusterState execute(ClusterState currentState) {
187188
}
188189
}
189190

191+
// increment settings versions
192+
for (final String index : actualIndices) {
193+
if (same(currentState.metaData().index(index).getSettings(), metaDataBuilder.get(index).getSettings()) == false) {
194+
final IndexMetaData.Builder builder = IndexMetaData.builder(metaDataBuilder.get(index));
195+
builder.settingsVersion(1 + builder.settingsVersion());
196+
metaDataBuilder.put(builder);
197+
}
198+
}
190199

191200
ClusterState updatedState = ClusterState.builder(currentState).metaData(metaDataBuilder).routingTable(routingTableBuilder.build()).blocks(blocks).build();
192201

@@ -220,9 +229,9 @@ public ClusterState execute(ClusterState currentState) {
220229
*/
221230
private static void maybeUpdateClusterBlock(String[] actualIndices, ClusterBlocks.Builder blocks, ClusterBlock block, Setting<Boolean> setting, Settings openSettings) {
222231
if (setting.exists(openSettings)) {
223-
final boolean updateReadBlock = setting.get(openSettings);
232+
final boolean updateBlock = setting.get(openSettings);
224233
for (String index : actualIndices) {
225-
if (updateReadBlock) {
234+
if (updateBlock) {
226235
blocks.addIndexBlock(index, block);
227236
} else {
228237
blocks.removeIndexBlock(index, block);

server/src/main/java/org/elasticsearch/cluster/routing/allocation/AllocationService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ private ClusterState adaptAutoExpandReplicas(ClusterState clusterState) {
254254
// operation which make these copies stale
255255
routingTableBuilder.updateNumberOfReplicas(numberOfReplicas, indices);
256256
metaDataBuilder.updateNumberOfReplicas(numberOfReplicas, indices);
257+
// update settings version for each index
258+
for (final String index : indices) {
259+
final IndexMetaData indexMetaData = metaDataBuilder.get(index);
260+
final IndexMetaData.Builder indexMetaDataBuilder =
261+
new IndexMetaData.Builder(indexMetaData).settingsVersion(1 + indexMetaData.getSettingsVersion());
262+
metaDataBuilder.put(indexMetaDataBuilder);
263+
}
257264
logger.info("updating number_of_replicas to [{}] for indices {}", numberOfReplicas, indices);
258265
}
259266
final ClusterState fixedState = ClusterState.builder(clusterState).routingTable(routingTableBuilder.build())

server/src/main/java/org/elasticsearch/index/IndexService.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.apache.lucene.search.Sort;
2525
import org.apache.lucene.store.AlreadyClosedException;
2626
import org.apache.lucene.util.Accountable;
27+
import org.elasticsearch.Assertions;
28+
import org.elasticsearch.Version;
2729
import org.elasticsearch.action.ActionListener;
2830
import org.elasticsearch.client.Client;
2931
import org.elasticsearch.cluster.metadata.IndexMetaData;
@@ -616,9 +618,27 @@ public IndexMetaData getMetaData() {
616618
}
617619

618620
@Override
619-
public synchronized void updateMetaData(final IndexMetaData metadata) {
621+
public synchronized void updateMetaData(final IndexMetaData currentIndexMetaData, final IndexMetaData newIndexMetaData) {
620622
final Translog.Durability oldTranslogDurability = indexSettings.getTranslogDurability();
621-
if (indexSettings.updateIndexMetaData(metadata)) {
623+
624+
final boolean updateIndexMetaData = indexSettings.updateIndexMetaData(newIndexMetaData);
625+
626+
if (Assertions.ENABLED
627+
&& currentIndexMetaData != null
628+
&& currentIndexMetaData.getCreationVersion().onOrAfter(Version.V_6_5_0)) {
629+
final long currentSettingsVersion = currentIndexMetaData.getSettingsVersion();
630+
final long newSettingsVersion = newIndexMetaData.getSettingsVersion();
631+
if (currentSettingsVersion == newSettingsVersion) {
632+
assert updateIndexMetaData == false;
633+
} else {
634+
assert updateIndexMetaData;
635+
assert currentSettingsVersion < newSettingsVersion :
636+
"expected current settings version [" + currentSettingsVersion + "] "
637+
+ "to be less than new settings version [" + newSettingsVersion + "]";
638+
}
639+
}
640+
641+
if (updateIndexMetaData) {
622642
for (final IndexShard shard : this.shards.values()) {
623643
try {
624644
shard.onSettingsChanged();

server/src/main/java/org/elasticsearch/index/IndexSettings.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -633,17 +633,28 @@ public synchronized boolean updateIndexMetaData(IndexMetaData indexMetaData) {
633633
throw new IllegalArgumentException("uuid mismatch on settings update expected: " + getUUID() + " but was: " + newUUID);
634634
}
635635
this.indexMetaData = indexMetaData;
636-
final Settings existingSettings = this.settings;
637-
if (existingSettings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)
638-
.equals(newSettings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE))) {
636+
final Settings newIndexSettings = Settings.builder().put(nodeSettings).put(newSettings).build();
637+
if (same(this.settings, newIndexSettings)) {
639638
// nothing to update, same settings
640639
return false;
641640
}
642641
scopedSettings.applySettings(newSettings);
643-
this.settings = Settings.builder().put(nodeSettings).put(newSettings).build();
642+
this.settings = newIndexSettings;
644643
return true;
645644
}
646645

646+
/**
647+
* Compare the specified settings for equality.
648+
*
649+
* @param left the left settings
650+
* @param right the right settings
651+
* @return true if the settings are the same, otherwise false
652+
*/
653+
public static boolean same(final Settings left, final Settings right) {
654+
return left.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)
655+
.equals(right.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE));
656+
}
657+
647658
/**
648659
* Returns the translog durability for this index.
649660
*/

server/src/main/java/org/elasticsearch/indices/IndicesService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ public synchronized void verifyIndexMetadata(IndexMetaData metaData, IndexMetaDa
559559
closeables.add(() -> service.close("metadata verification", false));
560560
service.mapperService().merge(metaData, MapperService.MergeReason.MAPPING_RECOVERY, true);
561561
if (metaData.equals(metaDataUpdate) == false) {
562-
service.updateMetaData(metaDataUpdate);
562+
service.updateMetaData(metaData, metaDataUpdate);
563563
}
564564
} finally {
565565
IOUtils.close(closeables);

server/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ private void updateIndices(ClusterChangedEvent event) {
488488
final IndexMetaData newIndexMetaData = state.metaData().index(index);
489489
assert newIndexMetaData != null : "index " + index + " should have been removed by deleteIndices";
490490
if (ClusterChangedEvent.indexMetaDataChanged(currentIndexMetaData, newIndexMetaData)) {
491-
indexService.updateMetaData(newIndexMetaData);
491+
indexService.updateMetaData(currentIndexMetaData, newIndexMetaData);
492492
try {
493493
if (indexService.updateMapping(currentIndexMetaData, newIndexMetaData) && sendRefreshMapping) {
494494
nodeMappingRefreshAction.nodeMappingRefresh(state.nodes().getMasterNode(),
@@ -771,9 +771,12 @@ public interface AllocatedIndex<T extends Shard> extends Iterable<T>, IndexCompo
771771
IndexSettings getIndexSettings();
772772

773773
/**
774-
* Updates the meta data of this index. Changes become visible through {@link #getIndexSettings()}
774+
* Updates the metadata of this index. Changes become visible through {@link #getIndexSettings()}.
775+
*
776+
* @param currentIndexMetaData the current index metadata
777+
* @param newIndexMetaData the new index metadata
775778
*/
776-
void updateMetaData(IndexMetaData indexMetaData);
779+
void updateMetaData(IndexMetaData currentIndexMetaData, IndexMetaData newIndexMetaData);
777780

778781
/**
779782
* Checks if index requires refresh from master.

0 commit comments

Comments
 (0)