Skip to content

Commit 4b2052c

Browse files
authored
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 e0b6721 commit 4b2052c

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
@@ -243,6 +243,7 @@ public Iterator<Setting<Integer>> settings() {
243243
public static final String KEY_IN_SYNC_ALLOCATIONS = "in_sync_allocations";
244244
static final String KEY_VERSION = "version";
245245
static final String KEY_MAPPING_VERSION = "mapping_version";
246+
static final String KEY_SETTINGS_VERSION = "settings_version";
246247
static final String KEY_ROUTING_NUM_SHARDS = "routing_num_shards";
247248
static final String KEY_SETTINGS = "settings";
248249
static final String KEY_STATE = "state";
@@ -264,6 +265,8 @@ public Iterator<Setting<Integer>> settings() {
264265

265266
private final long mappingVersion;
266267

268+
private final long settingsVersion;
269+
267270
private final long[] primaryTerms;
268271

269272
private final State state;
@@ -291,7 +294,7 @@ public Iterator<Setting<Integer>> settings() {
291294
private final ActiveShardCount waitForActiveShards;
292295
private final ImmutableOpenMap<String, RolloverInfo> rolloverInfos;
293296

294-
private IndexMetaData(Index index, long version, long mappingVersion, long[] primaryTerms, State state, int numberOfShards, int numberOfReplicas, Settings settings,
297+
private IndexMetaData(Index index, long version, long mappingVersion, long settingsVersion, long[] primaryTerms, State state, int numberOfShards, int numberOfReplicas, Settings settings,
295298
ImmutableOpenMap<String, MappingMetaData> mappings, ImmutableOpenMap<String, AliasMetaData> aliases,
296299
ImmutableOpenMap<String, DiffableStringMap> customData, ImmutableOpenIntMap<Set<String>> inSyncAllocationIds,
297300
DiscoveryNodeFilters requireFilters, DiscoveryNodeFilters initialRecoveryFilters, DiscoveryNodeFilters includeFilters, DiscoveryNodeFilters excludeFilters,
@@ -302,6 +305,8 @@ private IndexMetaData(Index index, long version, long mappingVersion, long[] pri
302305
this.version = version;
303306
assert mappingVersion >= 0 : mappingVersion;
304307
this.mappingVersion = mappingVersion;
308+
assert settingsVersion >= 0 : settingsVersion;
309+
this.settingsVersion = settingsVersion;
305310
this.primaryTerms = primaryTerms;
306311
assert primaryTerms.length == numberOfShards;
307312
this.state = state;
@@ -355,6 +360,10 @@ public long getMappingVersion() {
355360
return mappingVersion;
356361
}
357362

363+
public long getSettingsVersion() {
364+
return settingsVersion;
365+
}
366+
358367
/**
359368
* The term of the current selected primary. This is a non-negative number incremented when
360369
* a primary shard is assigned after a full cluster restart or a replica shard is promoted to a primary.
@@ -596,6 +605,7 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
596605
private final int routingNumShards;
597606
private final long version;
598607
private final long mappingVersion;
608+
private final long settingsVersion;
599609
private final long[] primaryTerms;
600610
private final State state;
601611
private final Settings settings;
@@ -609,6 +619,7 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
609619
index = after.index.getName();
610620
version = after.version;
611621
mappingVersion = after.mappingVersion;
622+
settingsVersion = after.settingsVersion;
612623
routingNumShards = after.routingNumShards;
613624
state = after.state;
614625
settings = after.settings;
@@ -630,6 +641,11 @@ private static class IndexMetaDataDiff implements Diff<IndexMetaData> {
630641
} else {
631642
mappingVersion = 1;
632643
}
644+
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
645+
settingsVersion = in.readVLong();
646+
} else {
647+
settingsVersion = 1;
648+
}
633649
state = State.fromId(in.readByte());
634650
settings = Settings.readSettingsFromStream(in);
635651
primaryTerms = in.readVLongArray();
@@ -658,6 +674,9 @@ public void writeTo(StreamOutput out) throws IOException {
658674
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
659675
out.writeVLong(mappingVersion);
660676
}
677+
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
678+
out.writeVLong(settingsVersion);
679+
}
661680
out.writeByte(state.id);
662681
Settings.writeSettingsToStream(settings, out);
663682
out.writeVLongArray(primaryTerms);
@@ -675,6 +694,7 @@ public IndexMetaData apply(IndexMetaData part) {
675694
Builder builder = builder(index);
676695
builder.version(version);
677696
builder.mappingVersion(mappingVersion);
697+
builder.settingsVersion(settingsVersion);
678698
builder.setRoutingNumShards(routingNumShards);
679699
builder.state(state);
680700
builder.settings(settings);
@@ -696,6 +716,11 @@ public static IndexMetaData readFrom(StreamInput in) throws IOException {
696716
} else {
697717
builder.mappingVersion(1);
698718
}
719+
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
720+
builder.settingsVersion(in.readVLong());
721+
} else {
722+
builder.settingsVersion(1);
723+
}
699724
builder.setRoutingNumShards(in.readInt());
700725
builder.state(State.fromId(in.readByte()));
701726
builder.settings(readSettingsFromStream(in));
@@ -745,6 +770,9 @@ public void writeTo(StreamOutput out) throws IOException {
745770
if (out.getVersion().onOrAfter(Version.V_6_5_0)) {
746771
out.writeVLong(mappingVersion);
747772
}
773+
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
774+
out.writeVLong(settingsVersion);
775+
}
748776
out.writeInt(routingNumShards);
749777
out.writeByte(state.id());
750778
writeSettingsToStream(settings, out);
@@ -793,6 +821,7 @@ public static class Builder {
793821
private State state = State.OPEN;
794822
private long version = 1;
795823
private long mappingVersion = 1;
824+
private long settingsVersion = 1;
796825
private long[] primaryTerms = null;
797826
private Settings settings = Settings.Builder.EMPTY_SETTINGS;
798827
private final ImmutableOpenMap.Builder<String, MappingMetaData> mappings;
@@ -816,6 +845,7 @@ public Builder(IndexMetaData indexMetaData) {
816845
this.state = indexMetaData.state;
817846
this.version = indexMetaData.version;
818847
this.mappingVersion = indexMetaData.mappingVersion;
848+
this.settingsVersion = indexMetaData.settingsVersion;
819849
this.settings = indexMetaData.getSettings();
820850
this.primaryTerms = indexMetaData.primaryTerms.clone();
821851
this.mappings = ImmutableOpenMap.builder(indexMetaData.mappings);
@@ -990,11 +1020,20 @@ public long mappingVersion() {
9901020
return mappingVersion;
9911021
}
9921022

1023+
public long settingsVersion() {
1024+
return settingsVersion;
1025+
}
1026+
9931027
public Builder mappingVersion(final long mappingVersion) {
9941028
this.mappingVersion = mappingVersion;
9951029
return this;
9961030
}
9971031

1032+
public Builder settingsVersion(final long settingsVersion) {
1033+
this.settingsVersion = settingsVersion;
1034+
return this;
1035+
}
1036+
9981037
/**
9991038
* returns the primary term for the given shard.
10001039
* See {@link IndexMetaData#primaryTerm(int)} for more information.
@@ -1122,7 +1161,7 @@ public IndexMetaData build() {
11221161

11231162
final String uuid = settings.get(SETTING_INDEX_UUID, INDEX_UUID_NA_VALUE);
11241163

1125-
return new IndexMetaData(new Index(index, uuid), version, mappingVersion, primaryTerms, state, numberOfShards, numberOfReplicas, tmpSettings, mappings.build(),
1164+
return new IndexMetaData(new Index(index, uuid), version, mappingVersion, settingsVersion, primaryTerms, state, numberOfShards, numberOfReplicas, tmpSettings, mappings.build(),
11261165
tmpAliases.build(), customMetaData.build(), filledInSyncAllocationIds.build(), requireFilters, initialRecoveryFilters, includeFilters, excludeFilters,
11271166
indexCreatedVersion, indexUpgradedVersion, getRoutingNumShards(), routingPartitionSize, waitForActiveShards, rolloverInfos.build());
11281167
}
@@ -1132,6 +1171,7 @@ public static void toXContent(IndexMetaData indexMetaData, XContentBuilder build
11321171

11331172
builder.field(KEY_VERSION, indexMetaData.getVersion());
11341173
builder.field(KEY_MAPPING_VERSION, indexMetaData.getMappingVersion());
1174+
builder.field(KEY_SETTINGS_VERSION, indexMetaData.getSettingsVersion());
11351175
builder.field(KEY_ROUTING_NUM_SHARDS, indexMetaData.getRoutingNumShards());
11361176
builder.field(KEY_STATE, indexMetaData.getState().toString().toLowerCase(Locale.ENGLISH));
11371177

@@ -1205,6 +1245,7 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
12051245
throw new IllegalArgumentException("expected object but got a " + token);
12061246
}
12071247
boolean mappingVersion = false;
1248+
boolean settingsVersion = false;
12081249
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
12091250
if (token == XContentParser.Token.FIELD_NAME) {
12101251
currentFieldName = parser.currentName();
@@ -1299,6 +1340,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
12991340
} else if (KEY_MAPPING_VERSION.equals(currentFieldName)) {
13001341
mappingVersion = true;
13011342
builder.mappingVersion(parser.longValue());
1343+
} else if (KEY_SETTINGS_VERSION.equals(currentFieldName)) {
1344+
settingsVersion = true;
1345+
builder.settingsVersion(parser.longValue());
13021346
} else if (KEY_ROUTING_NUM_SHARDS.equals(currentFieldName)) {
13031347
builder.setRoutingNumShards(parser.intValue());
13041348
} else {
@@ -1311,6 +1355,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti
13111355
if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_6_5_0)) {
13121356
assert mappingVersion : "mapping version should be present for indices created on or after 6.5.0";
13131357
}
1358+
if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_7_0_0_alpha1)) {
1359+
assert settingsVersion : "settings version should be present for indices created on or after 7.0.0";
1360+
}
13141361
return builder.build();
13151362
}
13161363
}

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;
@@ -617,9 +619,27 @@ public IndexMetaData getMetaData() {
617619
}
618620

619621
@Override
620-
public synchronized void updateMetaData(final IndexMetaData metadata) {
622+
public synchronized void updateMetaData(final IndexMetaData currentIndexMetaData, final IndexMetaData newIndexMetaData) {
621623
final Translog.Durability oldTranslogDurability = indexSettings.getTranslogDurability();
622-
if (indexSettings.updateIndexMetaData(metadata)) {
624+
625+
final boolean updateIndexMetaData = indexSettings.updateIndexMetaData(newIndexMetaData);
626+
627+
if (Assertions.ENABLED
628+
&& currentIndexMetaData != null
629+
&& currentIndexMetaData.getCreationVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
630+
final long currentSettingsVersion = currentIndexMetaData.getSettingsVersion();
631+
final long newSettingsVersion = newIndexMetaData.getSettingsVersion();
632+
if (currentSettingsVersion == newSettingsVersion) {
633+
assert updateIndexMetaData == false;
634+
} else {
635+
assert updateIndexMetaData;
636+
assert currentSettingsVersion < newSettingsVersion :
637+
"expected current settings version [" + currentSettingsVersion + "] "
638+
+ "to be less than new settings version [" + newSettingsVersion + "]";
639+
}
640+
}
641+
642+
if (updateIndexMetaData) {
623643
for (final IndexShard shard : this.shards.values()) {
624644
try {
625645
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
@@ -604,17 +604,28 @@ public synchronized boolean updateIndexMetaData(IndexMetaData indexMetaData) {
604604
throw new IllegalArgumentException("uuid mismatch on settings update expected: " + getUUID() + " but was: " + newUUID);
605605
}
606606
this.indexMetaData = indexMetaData;
607-
final Settings existingSettings = this.settings;
608-
if (existingSettings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)
609-
.equals(newSettings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE))) {
607+
final Settings newIndexSettings = Settings.builder().put(nodeSettings).put(newSettings).build();
608+
if (same(this.settings, newIndexSettings)) {
610609
// nothing to update, same settings
611610
return false;
612611
}
613612
scopedSettings.applySettings(newSettings);
614-
this.settings = Settings.builder().put(nodeSettings).put(newSettings).build();
613+
this.settings = newIndexSettings;
615614
return true;
616615
}
617616

617+
/**
618+
* Compare the specified settings for equality.
619+
*
620+
* @param left the left settings
621+
* @param right the right settings
622+
* @return true if the settings are the same, otherwise false
623+
*/
624+
public static boolean same(final Settings left, final Settings right) {
625+
return left.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)
626+
.equals(right.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE));
627+
}
628+
618629
/**
619630
* Returns the translog durability for this index.
620631
*/

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);
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)