Skip to content

Commit 2ce17f1

Browse files
SivagurunathanVdakrone
authored andcommitted
Adding best_compression (elastic#49974)
This commit adds a `codec` parameter to the ILM `forcemerge` action. When setting the codec to `best_compression` ILM will close the index, then update the codec setting, re-open the index, and finally perform a force merge.
1 parent 8aaca45 commit 2ce17f1

File tree

11 files changed

+926
-30
lines changed

11 files changed

+926
-30
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.ilm;
8+
9+
import org.elasticsearch.ElasticsearchException;
10+
import org.elasticsearch.action.ActionListener;
11+
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
12+
import org.elasticsearch.client.Client;
13+
import org.elasticsearch.cluster.ClusterState;
14+
import org.elasticsearch.cluster.ClusterStateObserver;
15+
import org.elasticsearch.cluster.metadata.IndexMetaData;
16+
17+
/**
18+
* Invokes a close step on a single index.
19+
*/
20+
21+
public class CloseIndexStep extends AsyncActionStep {
22+
public static final String NAME = "close-index";
23+
24+
CloseIndexStep(StepKey key, StepKey nextStepKey, Client client) {
25+
super(key, nextStepKey, client);
26+
}
27+
28+
@Override
29+
public void performAction(IndexMetaData indexMetaData, ClusterState currentClusterState,
30+
ClusterStateObserver observer, Listener listener) {
31+
if (indexMetaData.getState() == IndexMetaData.State.OPEN) {
32+
CloseIndexRequest request = new CloseIndexRequest(indexMetaData.getIndex().getName());
33+
getClient().admin().indices()
34+
.close(request, ActionListener.wrap(closeIndexResponse -> {
35+
if (closeIndexResponse.isAcknowledged() == false) {
36+
throw new ElasticsearchException("close index request failed to be acknowledged");
37+
}
38+
listener.onResponse(true);
39+
}, listener::onFailure));
40+
}
41+
else {
42+
listener.onResponse(true);
43+
}
44+
}
45+
46+
@Override
47+
public boolean isRetryable() {
48+
return true;
49+
}
50+
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/ForceMergeAction.java

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
*/
66
package org.elasticsearch.xpack.core.ilm;
77

8+
import org.elasticsearch.Version;
89
import org.elasticsearch.client.Client;
10+
import org.elasticsearch.cluster.health.ClusterHealthStatus;
911
import org.elasticsearch.cluster.metadata.IndexMetaData;
12+
import org.elasticsearch.common.Nullable;
1013
import org.elasticsearch.common.ParseField;
1114
import org.elasticsearch.common.Strings;
1215
import org.elasticsearch.common.io.stream.StreamInput;
@@ -15,10 +18,12 @@
1518
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
1619
import org.elasticsearch.common.xcontent.XContentBuilder;
1720
import org.elasticsearch.common.xcontent.XContentParser;
21+
import org.elasticsearch.index.codec.CodecService;
22+
import org.elasticsearch.index.engine.EngineConfig;
1823
import org.elasticsearch.xpack.core.ilm.Step.StepKey;
1924

2025
import java.io.IOException;
21-
import java.util.Arrays;
26+
import java.util.ArrayList;
2227
import java.util.List;
2328
import java.util.Objects;
2429

@@ -28,42 +33,62 @@
2833
public class ForceMergeAction implements LifecycleAction {
2934
public static final String NAME = "forcemerge";
3035
public static final ParseField MAX_NUM_SEGMENTS_FIELD = new ParseField("max_num_segments");
36+
public static final ParseField CODEC = new ParseField("index_codec");
3137

3238
private static final ConstructingObjectParser<ForceMergeAction, Void> PARSER = new ConstructingObjectParser<>(NAME,
3339
false, a -> {
3440
int maxNumSegments = (int) a[0];
35-
return new ForceMergeAction(maxNumSegments);
41+
String codec = a[1] != null ? (String) a[1] : null;
42+
return new ForceMergeAction(maxNumSegments, codec);
3643
});
3744

3845
static {
3946
PARSER.declareInt(ConstructingObjectParser.constructorArg(), MAX_NUM_SEGMENTS_FIELD);
47+
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), CODEC);
4048
}
4149

4250
private final int maxNumSegments;
51+
private final String codec;
4352

4453
public static ForceMergeAction parse(XContentParser parser) {
4554
return PARSER.apply(parser, null);
4655
}
4756

48-
public ForceMergeAction(int maxNumSegments) {
57+
public ForceMergeAction(int maxNumSegments, @Nullable String codec) {
4958
if (maxNumSegments <= 0) {
5059
throw new IllegalArgumentException("[" + MAX_NUM_SEGMENTS_FIELD.getPreferredName()
5160
+ "] must be a positive integer");
5261
}
5362
this.maxNumSegments = maxNumSegments;
63+
if (codec != null && CodecService.BEST_COMPRESSION_CODEC.equals(codec) == false) {
64+
throw new IllegalArgumentException("unknown index codec: [" + codec + "]");
65+
}
66+
this.codec = codec;
5467
}
5568

5669
public ForceMergeAction(StreamInput in) throws IOException {
5770
this.maxNumSegments = in.readVInt();
71+
if (in.getVersion().onOrAfter(Version.V_8_0_0)) {
72+
this.codec = in.readOptionalString();
73+
} else {
74+
this.codec = null;
75+
}
5876
}
5977

6078
public int getMaxNumSegments() {
6179
return maxNumSegments;
6280
}
6381

82+
public String getCodec() {
83+
return this.codec;
84+
}
85+
6486
@Override
6587
public void writeTo(StreamOutput out) throws IOException {
6688
out.writeVInt(maxNumSegments);
89+
if (out.getVersion().onOrAfter(Version.V_8_0_0)) {
90+
out.writeOptionalString(codec);
91+
}
6792
}
6893

6994
@Override
@@ -80,27 +105,58 @@ public boolean isSafeAction() {
80105
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
81106
builder.startObject();
82107
builder.field(MAX_NUM_SEGMENTS_FIELD.getPreferredName(), maxNumSegments);
108+
if (codec != null) {
109+
builder.field(CODEC.getPreferredName(), codec);
110+
}
83111
builder.endObject();
84112
return builder;
85113
}
86114

87115
@Override
88116
public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey) {
89117
Settings readOnlySettings = Settings.builder().put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build();
118+
Settings bestCompressionSettings = Settings.builder()
119+
.put(EngineConfig.INDEX_CODEC_SETTING.getKey(), CodecService.BEST_COMPRESSION_CODEC).build();
90120

91121
StepKey readOnlyKey = new StepKey(phase, NAME, ReadOnlyAction.NAME);
92122
StepKey forceMergeKey = new StepKey(phase, NAME, ForceMergeStep.NAME);
93123
StepKey countKey = new StepKey(phase, NAME, SegmentCountStep.NAME);
94124

125+
StepKey closeKey = new StepKey(phase, NAME, CloseIndexStep.NAME);
126+
StepKey openKey = new StepKey(phase, NAME, OpenIndexStep.NAME);
127+
StepKey waitForGreenIndexKey = new StepKey(phase, NAME, WaitForIndexColorStep.NAME);
128+
StepKey updateCompressionKey = new StepKey(phase, NAME, UpdateSettingsStep.NAME);
129+
95130
UpdateSettingsStep readOnlyStep = new UpdateSettingsStep(readOnlyKey, forceMergeKey, client, readOnlySettings);
96131
ForceMergeStep forceMergeStep = new ForceMergeStep(forceMergeKey, countKey, client, maxNumSegments);
132+
CloseIndexStep closeIndexStep = new CloseIndexStep(closeKey, updateCompressionKey, client);
133+
ForceMergeStep forceMergeStepForBestCompression = new ForceMergeStep(forceMergeKey, closeKey, client, maxNumSegments);
134+
UpdateSettingsStep updateBestCompressionSettings = new UpdateSettingsStep(updateCompressionKey,
135+
openKey, client, bestCompressionSettings);
136+
OpenIndexStep openIndexStep = new OpenIndexStep(openKey, waitForGreenIndexKey, client);
137+
WaitForIndexColorStep waitForIndexGreenStep = new WaitForIndexColorStep(waitForGreenIndexKey,
138+
forceMergeKey, ClusterHealthStatus.GREEN);
97139
SegmentCountStep segmentCountStep = new SegmentCountStep(countKey, nextStepKey, client, maxNumSegments);
98-
return Arrays.asList(readOnlyStep, forceMergeStep, segmentCountStep);
140+
141+
List<Step> mergeSteps = new ArrayList<>();
142+
mergeSteps.add(readOnlyStep);
143+
144+
if (codec != null && codec.equals(CodecService.BEST_COMPRESSION_CODEC)) {
145+
mergeSteps.add(forceMergeStepForBestCompression);
146+
mergeSteps.add(closeIndexStep);
147+
mergeSteps.add(updateBestCompressionSettings);
148+
mergeSteps.add(openIndexStep);
149+
mergeSteps.add(waitForIndexGreenStep);
150+
}
151+
152+
mergeSteps.add(forceMergeStep);
153+
mergeSteps.add(segmentCountStep);
154+
return mergeSteps;
99155
}
100156

101157
@Override
102158
public int hashCode() {
103-
return Objects.hash(maxNumSegments);
159+
return Objects.hash(maxNumSegments, codec);
104160
}
105161

106162
@Override
@@ -112,7 +168,8 @@ public boolean equals(Object obj) {
112168
return false;
113169
}
114170
ForceMergeAction other = (ForceMergeAction) obj;
115-
return Objects.equals(maxNumSegments, other.maxNumSegments);
171+
return Objects.equals(this.maxNumSegments, other.maxNumSegments)
172+
&& Objects.equals(this.codec, other.codec);
116173
}
117174

118175
@Override
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.ilm;
8+
9+
import org.elasticsearch.ElasticsearchException;
10+
import org.elasticsearch.action.ActionListener;
11+
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
12+
import org.elasticsearch.client.Client;
13+
import org.elasticsearch.cluster.ClusterState;
14+
import org.elasticsearch.cluster.ClusterStateObserver;
15+
import org.elasticsearch.cluster.metadata.IndexMetaData;
16+
17+
/**
18+
* Invokes a open step on a single index.
19+
*/
20+
21+
final class OpenIndexStep extends AsyncActionStep {
22+
23+
static final String NAME = "open-index";
24+
25+
OpenIndexStep(StepKey key, StepKey nextStepKey, Client client) {
26+
super(key, nextStepKey, client);
27+
}
28+
29+
@Override
30+
public void performAction(IndexMetaData indexMetaData, ClusterState currentClusterState,
31+
ClusterStateObserver observer, Listener listener) {
32+
if (indexMetaData.getState() == IndexMetaData.State.CLOSE) {
33+
OpenIndexRequest request = new OpenIndexRequest(indexMetaData.getIndex().getName());
34+
getClient().admin().indices()
35+
.open(request,
36+
ActionListener.wrap(openIndexResponse -> {
37+
if (openIndexResponse.isAcknowledged() == false) {
38+
throw new ElasticsearchException("open index request failed to be acknowledged");
39+
}
40+
listener.onResponse(true);
41+
}, listener::onFailure));
42+
43+
} else {
44+
listener.onResponse(true);
45+
}
46+
}
47+
48+
@Override
49+
public boolean isRetryable() {
50+
return true;
51+
}
52+
}

0 commit comments

Comments
 (0)