Skip to content

Commit a270984

Browse files
authored
backport of: Add rollover-creation-date setting to rolled over index (#31144) (#31413)
This commit introduces a new property to IndexMetaData called RolloverInfo. This object contains a map containing the aliases that were used to rollover the related index, which conditions were met, and at what time the rollover took place. much like the `index.creation_date`, it captures the approximate time that the index was rolled over to a new one. set version serialization check to 6.4
1 parent ee023b2 commit a270984

File tree

11 files changed

+356
-27
lines changed

11 files changed

+356
-27
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxAgeCondition.java

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.common.io.stream.StreamOutput;
2424
import org.elasticsearch.common.unit.TimeValue;
2525
import org.elasticsearch.common.xcontent.XContentBuilder;
26+
import org.elasticsearch.common.xcontent.XContentParser;
2627

2728
import java.io.IOException;
2829

@@ -64,4 +65,12 @@ public void writeTo(StreamOutput out) throws IOException {
6465
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
6566
return builder.field(NAME, value.getStringRep());
6667
}
68+
69+
public static MaxAgeCondition fromXContent(XContentParser parser) throws IOException {
70+
if (parser.nextToken() == XContentParser.Token.VALUE_STRING) {
71+
return new MaxAgeCondition(TimeValue.parseTimeValue(parser.text(), NAME));
72+
} else {
73+
throw new IllegalArgumentException("invalid token: " + parser.currentToken());
74+
}
75+
}
6776
}

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxDocsCondition.java

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.common.io.stream.StreamInput;
2323
import org.elasticsearch.common.io.stream.StreamOutput;
2424
import org.elasticsearch.common.xcontent.XContentBuilder;
25+
import org.elasticsearch.common.xcontent.XContentParser;
2526

2627
import java.io.IOException;
2728

@@ -61,4 +62,12 @@ public void writeTo(StreamOutput out) throws IOException {
6162
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
6263
return builder.field(NAME, value);
6364
}
65+
66+
public static MaxDocsCondition fromXContent(XContentParser parser) throws IOException {
67+
if (parser.nextToken() == XContentParser.Token.VALUE_NUMBER) {
68+
return new MaxDocsCondition(parser.longValue());
69+
} else {
70+
throw new IllegalArgumentException("invalid token: " + parser.currentToken());
71+
}
72+
}
6473
}

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxSizeCondition.java

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.elasticsearch.common.unit.ByteSizeUnit;
2626
import org.elasticsearch.common.unit.ByteSizeValue;
2727
import org.elasticsearch.common.xcontent.XContentBuilder;
28+
import org.elasticsearch.common.xcontent.XContentParser;
2829

2930
import java.io.IOException;
3031

@@ -70,4 +71,12 @@ public void writeTo(StreamOutput out) throws IOException {
7071
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
7172
return builder.field(NAME, value.getStringRep());
7273
}
74+
75+
public static MaxSizeCondition fromXContent(XContentParser parser) throws IOException {
76+
if (parser.nextToken() == XContentParser.Token.VALUE_STRING) {
77+
return new MaxSizeCondition(ByteSizeValue.parseBytesSizeValue(parser.text(), NAME));
78+
} else {
79+
throw new IllegalArgumentException("invalid token: " + parser.currentToken());
80+
}
81+
}
7382
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.action.admin.indices.rollover;
21+
22+
import org.elasticsearch.cluster.AbstractDiffable;
23+
import org.elasticsearch.cluster.Diff;
24+
import org.elasticsearch.common.ParseField;
25+
import org.elasticsearch.common.Strings;
26+
import org.elasticsearch.common.io.stream.StreamInput;
27+
import org.elasticsearch.common.io.stream.StreamOutput;
28+
import org.elasticsearch.common.io.stream.Writeable;
29+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
30+
import org.elasticsearch.common.xcontent.ToXContentFragment;
31+
import org.elasticsearch.common.xcontent.XContentBuilder;
32+
import org.elasticsearch.common.xcontent.XContentParser;
33+
34+
import java.io.IOException;
35+
import java.util.List;
36+
import java.util.Objects;
37+
38+
/**
39+
* Class for holding Rollover related information within an index
40+
*/
41+
public class RolloverInfo extends AbstractDiffable<RolloverInfo> implements Writeable, ToXContentFragment {
42+
43+
public static final ParseField CONDITION_FIELD = new ParseField("met_conditions");
44+
public static final ParseField TIME_FIELD = new ParseField("time");
45+
46+
@SuppressWarnings("unchecked")
47+
public static ConstructingObjectParser<RolloverInfo, String> PARSER = new ConstructingObjectParser<>("rollover_info", false,
48+
(a, alias) -> new RolloverInfo(alias, (List<Condition>) a[0], (Long) a[1]));
49+
static {
50+
PARSER.declareNamedObjects(ConstructingObjectParser.constructorArg(),
51+
(p, c, n) -> p.namedObject(Condition.class, n, c), CONDITION_FIELD);
52+
PARSER.declareLong(ConstructingObjectParser.constructorArg(), TIME_FIELD);
53+
}
54+
55+
private final String alias;
56+
private final List<Condition> metConditions;
57+
private final long time;
58+
59+
public RolloverInfo(String alias, List<Condition> metConditions, long time) {
60+
this.alias = alias;
61+
this.metConditions = metConditions;
62+
this.time = time;
63+
}
64+
65+
public RolloverInfo(StreamInput in) throws IOException {
66+
this.alias = in.readString();
67+
this.time = in.readVLong();
68+
this.metConditions = in.readNamedWriteableList(Condition.class);
69+
}
70+
71+
public static RolloverInfo parse(XContentParser parser, String alias) {
72+
return PARSER.apply(parser, alias);
73+
}
74+
75+
public String getAlias() {
76+
return alias;
77+
}
78+
79+
public List<Condition> getMetConditions() {
80+
return metConditions;
81+
}
82+
83+
public long getTime() {
84+
return time;
85+
}
86+
87+
public static Diff<RolloverInfo> readDiffFrom(StreamInput in) throws IOException {
88+
return readDiffFrom(RolloverInfo::new, in);
89+
}
90+
91+
@Override
92+
public void writeTo(StreamOutput out) throws IOException {
93+
out.writeString(alias);
94+
out.writeVLong(time);
95+
out.writeNamedWriteableList(metConditions);
96+
}
97+
98+
@Override
99+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
100+
builder.startObject(alias);
101+
builder.startObject(CONDITION_FIELD.getPreferredName());
102+
for (Condition condition : metConditions) {
103+
condition.toXContent(builder, params);
104+
}
105+
builder.endObject();
106+
builder.field(TIME_FIELD.getPreferredName(), time);
107+
builder.endObject();
108+
return builder;
109+
}
110+
111+
@Override
112+
public int hashCode() {
113+
return Objects.hash(alias, metConditions, time);
114+
}
115+
116+
@Override
117+
public boolean equals(Object obj) {
118+
if (obj == null) {
119+
return false;
120+
}
121+
if (obj.getClass() != getClass()) {
122+
return false;
123+
}
124+
RolloverInfo other = (RolloverInfo) obj;
125+
return Objects.equals(alias, other.alias) &&
126+
Objects.equals(metConditions, other.metConditions) &&
127+
Objects.equals(time, other.time);
128+
}
129+
130+
@Override
131+
public String toString() {
132+
return Strings.toString(this);
133+
}
134+
}

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java

+31-8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
3232
import org.elasticsearch.client.Client;
3333
import org.elasticsearch.cluster.ClusterState;
34+
import org.elasticsearch.cluster.ClusterStateUpdateTask;
3435
import org.elasticsearch.cluster.block.ClusterBlockException;
3536
import org.elasticsearch.cluster.block.ClusterBlockLevel;
3637
import org.elasticsearch.cluster.metadata.AliasAction;
@@ -131,7 +132,9 @@ public void onResponse(IndicesStatsResponse statsResponse) {
131132
new RolloverResponse(sourceIndexName, rolloverIndexName, conditionResults, true, false, false, false));
132133
return;
133134
}
134-
if (conditionResults.size() == 0 || conditionResults.values().stream().anyMatch(result -> result)) {
135+
List<Condition> metConditions = rolloverRequest.getConditions().values().stream()
136+
.filter(condition -> conditionResults.get(condition.toString())).collect(Collectors.toList());
137+
if (conditionResults.size() == 0 || metConditions.size() > 0) {
135138
CreateIndexClusterStateUpdateRequest updateRequest = prepareCreateIndexRequest(unresolvedName, rolloverIndexName,
136139
rolloverRequest);
137140
createIndexService.createIndex(updateRequest, ActionListener.wrap(createIndexClusterStateUpdateResponse -> {
@@ -141,13 +144,33 @@ public void onResponse(IndicesStatsResponse statsResponse) {
141144
rolloverRequest),
142145
ActionListener.wrap(aliasClusterStateUpdateResponse -> {
143146
if (aliasClusterStateUpdateResponse.isAcknowledged()) {
144-
activeShardsObserver.waitForActiveShards(new String[]{rolloverIndexName},
145-
rolloverRequest.getCreateIndexRequest().waitForActiveShards(),
146-
rolloverRequest.masterNodeTimeout(),
147-
isShardsAcknowledged -> listener.onResponse(new RolloverResponse(
148-
sourceIndexName, rolloverIndexName, conditionResults, false, true, true,
149-
isShardsAcknowledged)),
150-
listener::onFailure);
147+
clusterService.submitStateUpdateTask("update_rollover_info", new ClusterStateUpdateTask() {
148+
@Override
149+
public ClusterState execute(ClusterState currentState) {
150+
RolloverInfo rolloverInfo = new RolloverInfo(rolloverRequest.getAlias(), metConditions,
151+
threadPool.absoluteTimeInMillis());
152+
return ClusterState.builder(currentState)
153+
.metaData(MetaData.builder(currentState.metaData())
154+
.put(IndexMetaData.builder(currentState.metaData().index(sourceIndexName))
155+
.putRolloverInfo(rolloverInfo))).build();
156+
}
157+
158+
@Override
159+
public void onFailure(String source, Exception e) {
160+
listener.onFailure(e);
161+
}
162+
163+
@Override
164+
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
165+
activeShardsObserver.waitForActiveShards(new String[]{rolloverIndexName},
166+
rolloverRequest.getCreateIndexRequest().waitForActiveShards(),
167+
rolloverRequest.masterNodeTimeout(),
168+
isShardsAcknowledged -> listener.onResponse(new RolloverResponse(
169+
sourceIndexName, rolloverIndexName, conditionResults, false, true, true,
170+
isShardsAcknowledged)),
171+
listener::onFailure);
172+
}
173+
});
151174
} else {
152175
listener.onResponse(new RolloverResponse(sourceIndexName, rolloverIndexName, conditionResults,
153176
false, true, false, false));

server/src/main/java/org/elasticsearch/client/transport/TransportClient.java

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.elasticsearch.common.util.BigArrays;
4747
import org.elasticsearch.common.util.PageCacheRecycler;
4848
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
49+
import org.elasticsearch.indices.IndicesModule;
4950
import org.elasticsearch.indices.breaker.CircuitBreakerService;
5051
import org.elasticsearch.node.InternalSettingsPreparer;
5152
import org.elasticsearch.node.Node;
@@ -149,9 +150,11 @@ private static ClientTemplate buildTemplate(Settings providedSettings, Settings
149150
SettingsModule settingsModule = new SettingsModule(settings, additionalSettings, additionalSettingsFilter);
150151

151152
SearchModule searchModule = new SearchModule(settings, true, pluginsService.filterPlugins(SearchPlugin.class));
153+
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
152154
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
153155
entries.addAll(NetworkModule.getNamedWriteables());
154156
entries.addAll(searchModule.getNamedWriteables());
157+
entries.addAll(indicesModule.getNamedWriteables());
155158
entries.addAll(ClusterModule.getNamedWriteables());
156159
entries.addAll(pluginsService.filterPlugins(Plugin.class).stream()
157160
.flatMap(p -> p.getNamedWriteables().stream())

0 commit comments

Comments
 (0)