Skip to content

Commit 650ccce

Browse files
feature flagging of Zstandard
Signed-off-by: Sarthak Aggarwal <sarthagg@amazon.com>
1 parent 9fb86a5 commit 650ccce

File tree

8 files changed

+48
-6
lines changed

8 files changed

+48
-6
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8787
- Make SearchTemplateRequest implement IndicesRequest.Replaceable ([#9122]()https://github.com/opensearch-project/OpenSearch/pull/9122)
8888
- [BWC and API enforcement] Define the initial set of annotations, their meaning and relations between them ([#9223](https://github.com/opensearch-project/OpenSearch/pull/9223))
8989
- [Segment Replication] Support realtime reads for GET requests ([#9212](https://github.com/opensearch-project/OpenSearch/pull/9212))
90+
- Feature flagging of the ZStandard ([#9476](https://github.com/opensearch-project/OpenSearch/pull/9476))
9091

9192
### Dependencies
9293
- Bump `org.apache.logging.log4j:log4j-core` from 2.17.1 to 2.20.0 ([#8307](https://github.com/opensearch-project/OpenSearch/pull/8307))
@@ -162,4 +163,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
162163
### Security
163164

164165
[Unreleased 3.0]: https://github.com/opensearch-project/OpenSearch/compare/2.x...HEAD
165-
[Unreleased 2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.10...2.x
166+
[Unreleased 2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.10...2.x

distribution/src/config/opensearch.yml

+6
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,9 @@ ${path.logs}
129129
# index searcher threadpool.
130130
#
131131
#opensearch.experimental.feature.concurrent_segment_search.enabled: false
132+
#
133+
#
134+
# Gates the visibility of the ZStd compression algorithm features
135+
# for indexing operations.
136+
#
137+
#opensearch.experimental.feature.compression.zstd.enabled: false

server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ protected FeatureFlagSettings(
3737
Arrays.asList(
3838
FeatureFlags.SEGMENT_REPLICATION_EXPERIMENTAL_SETTING,
3939
FeatureFlags.REMOTE_STORE_SETTING,
40+
FeatureFlags.ZSTD_COMPRESSION_SETTING,
4041
FeatureFlags.EXTENSIONS_SETTING,
4142
FeatureFlags.IDENTITY_SETTING,
4243
FeatureFlags.CONCURRENT_SEGMENT_SEARCH_SETTING,

server/src/main/java/org/opensearch/common/util/FeatureFlags.java

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
*/
2222
public class FeatureFlags {
2323

24+
/**
25+
* Gates the visibility of the index settings that allows the utilization of ZStd compression algorithm features for indexing operations.
26+
*/
27+
public static final String ZSTD_COMPRESSION = "opensearch.experimental.feature.compression.zstd.enabled";
28+
2429
/**
2530
* Gates the visibility of the segment replication experimental features that allows users to test unreleased beta features.
2631
*/
@@ -96,6 +101,8 @@ public static boolean isEnabled(String featureFlagName) {
96101
Property.NodeScope
97102
);
98103

104+
public static final Setting<Boolean> ZSTD_COMPRESSION_SETTING = Setting.boolSetting(ZSTD_COMPRESSION, false, Property.NodeScope);
105+
99106
public static final Setting<Boolean> REMOTE_STORE_SETTING = Setting.boolSetting(REMOTE_STORE, false, Property.NodeScope);
100107

101108
public static final Setting<Boolean> EXTENSIONS_SETTING = Setting.boolSetting(EXTENSIONS, false, Property.NodeScope);

server/src/main/java/org/opensearch/index/codec/CodecService.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
import org.apache.lucene.codecs.lucene95.Lucene95Codec;
3838
import org.apache.lucene.codecs.lucene95.Lucene95Codec.Mode;
3939
import org.opensearch.common.Nullable;
40+
import org.opensearch.common.annotation.ExperimentalApi;
4041
import org.opensearch.common.collect.MapBuilder;
42+
import org.opensearch.common.util.FeatureFlags;
4143
import org.opensearch.index.IndexSettings;
4244
import org.opensearch.index.codec.customcodecs.ZstdCodec;
4345
import org.opensearch.index.codec.customcodecs.ZstdNoDictCodec;
@@ -67,7 +69,9 @@ public class CodecService {
6769
* the raw unfiltered lucene default. useful for testing
6870
*/
6971
public static final String LUCENE_DEFAULT_CODEC = "lucene_default";
72+
@ExperimentalApi
7073
public static final String ZSTD_CODEC = "zstd";
74+
@ExperimentalApi
7175
public static final String ZSTD_NO_DICT_CODEC = "zstd_no_dict";
7276

7377
public CodecService(@Nullable MapperService mapperService, IndexSettings indexSettings, Logger logger) {
@@ -79,15 +83,19 @@ public CodecService(@Nullable MapperService mapperService, IndexSettings indexSe
7983
codecs.put(LZ4, new Lucene95Codec());
8084
codecs.put(BEST_COMPRESSION_CODEC, new Lucene95Codec(Mode.BEST_COMPRESSION));
8185
codecs.put(ZLIB, new Lucene95Codec(Mode.BEST_COMPRESSION));
82-
codecs.put(ZSTD_CODEC, new ZstdCodec(compressionLevel));
83-
codecs.put(ZSTD_NO_DICT_CODEC, new ZstdNoDictCodec(compressionLevel));
86+
if (FeatureFlags.isEnabled(FeatureFlags.ZSTD_COMPRESSION)) {
87+
codecs.put(ZSTD_CODEC, new ZstdCodec(compressionLevel));
88+
codecs.put(ZSTD_NO_DICT_CODEC, new ZstdNoDictCodec(compressionLevel));
89+
}
8490
} else {
8591
codecs.put(DEFAULT_CODEC, new PerFieldMappingPostingFormatCodec(Mode.BEST_SPEED, mapperService, logger));
8692
codecs.put(LZ4, new PerFieldMappingPostingFormatCodec(Mode.BEST_SPEED, mapperService, logger));
8793
codecs.put(BEST_COMPRESSION_CODEC, new PerFieldMappingPostingFormatCodec(Mode.BEST_COMPRESSION, mapperService, logger));
8894
codecs.put(ZLIB, new PerFieldMappingPostingFormatCodec(Mode.BEST_COMPRESSION, mapperService, logger));
89-
codecs.put(ZSTD_CODEC, new ZstdCodec(mapperService, logger, compressionLevel));
90-
codecs.put(ZSTD_NO_DICT_CODEC, new ZstdNoDictCodec(mapperService, logger, compressionLevel));
95+
if (FeatureFlags.isEnabled(FeatureFlags.ZSTD_COMPRESSION)) {
96+
codecs.put(ZSTD_CODEC, new ZstdCodec(mapperService, logger, compressionLevel));
97+
codecs.put(ZSTD_NO_DICT_CODEC, new ZstdNoDictCodec(mapperService, logger, compressionLevel));
98+
}
9199
}
92100
codecs.put(LUCENE_DEFAULT_CODEC, Codec.getDefault());
93101
for (String codec : Codec.availableCodecs()) {

server/src/main/java/org/opensearch/index/engine/EngineConfig.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.opensearch.common.settings.Setting.Property;
4646
import org.opensearch.common.unit.MemorySizeValue;
4747
import org.opensearch.common.unit.TimeValue;
48+
import org.opensearch.common.util.FeatureFlags;
4849
import org.opensearch.core.common.unit.ByteSizeValue;
4950
import org.opensearch.core.index.shard.ShardId;
5051
import org.opensearch.core.indices.breaker.CircuitBreakerService;
@@ -133,9 +134,13 @@ public Supplier<RetentionLeases> retentionLeasesSupplier() {
133134
case "lz4":
134135
case "best_compression":
135136
case "zlib":
137+
case "lucene_default":
138+
return s;
136139
case "zstd":
137140
case "zstd_no_dict":
138-
case "lucene_default":
141+
if (!FeatureFlags.isEnabled(FeatureFlags.ZSTD_COMPRESSION)) {
142+
throw new IllegalArgumentException("ZStandard feature must be enabled to set " + s + " codec.");
143+
}
139144
return s;
140145
default:
141146
if (Codec.availableCodecs().contains(s) == false) { // we don't error message the not officially supported ones
@@ -183,6 +188,9 @@ private static void doValidateCodecSettings(final String codec) {
183188
switch (codec) {
184189
case "zstd":
185190
case "zstd_no_dict":
191+
if (!FeatureFlags.isEnabled(FeatureFlags.ZSTD_COMPRESSION)) {
192+
throw new IllegalArgumentException("Compression level cannot be set before enabling the ZStandard feature.");
193+
}
186194
return;
187195
case "best_compression":
188196
case "zlib":

server/src/test/java/org/opensearch/index/codec/CodecTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.apache.lucene.tests.util.LuceneTestCase.SuppressCodecs;
4646
import org.opensearch.common.settings.IndexScopedSettings;
4747
import org.opensearch.common.settings.Settings;
48+
import org.opensearch.common.util.FeatureFlags;
4849
import org.opensearch.env.Environment;
4950
import org.opensearch.index.IndexSettings;
5051
import org.opensearch.index.analysis.IndexAnalyzers;
@@ -55,6 +56,7 @@
5556
import org.opensearch.index.similarity.SimilarityService;
5657
import org.opensearch.indices.mapper.MapperRegistry;
5758
import org.opensearch.plugins.MapperPlugin;
59+
import org.opensearch.test.FeatureFlagSetter;
5860
import org.opensearch.test.IndexSettingsModule;
5961
import org.opensearch.test.OpenSearchTestCase;
6062

@@ -96,20 +98,23 @@ public void testZlib() throws Exception {
9698
}
9799

98100
public void testZstd() throws Exception {
101+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
99102
Codec codec = createCodecService(false).codec("zstd");
100103
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD, codec);
101104
Lucene95CustomStoredFieldsFormat storedFieldsFormat = (Lucene95CustomStoredFieldsFormat) codec.storedFieldsFormat();
102105
assertEquals(Lucene95CustomCodec.DEFAULT_COMPRESSION_LEVEL, storedFieldsFormat.getCompressionLevel());
103106
}
104107

105108
public void testZstdNoDict() throws Exception {
109+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
106110
Codec codec = createCodecService(false).codec("zstd_no_dict");
107111
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD_NO_DICT, codec);
108112
Lucene95CustomStoredFieldsFormat storedFieldsFormat = (Lucene95CustomStoredFieldsFormat) codec.storedFieldsFormat();
109113
assertEquals(Lucene95CustomCodec.DEFAULT_COMPRESSION_LEVEL, storedFieldsFormat.getCompressionLevel());
110114
}
111115

112116
public void testZstdWithCompressionLevel() throws Exception {
117+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
113118
int randomCompressionLevel = randomIntBetween(1, 6);
114119
Codec codec = createCodecService(randomCompressionLevel, "zstd").codec("zstd");
115120
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD, codec);
@@ -118,6 +123,7 @@ public void testZstdWithCompressionLevel() throws Exception {
118123
}
119124

120125
public void testZstdNoDictWithCompressionLevel() throws Exception {
126+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
121127
int randomCompressionLevel = randomIntBetween(1, 6);
122128
Codec codec = createCodecService(randomCompressionLevel, "zstd_no_dict").codec("zstd_no_dict");
123129
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD_NO_DICT, codec);
@@ -126,6 +132,7 @@ public void testZstdNoDictWithCompressionLevel() throws Exception {
126132
}
127133

128134
public void testBestCompressionWithCompressionLevel() {
135+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
129136
final Settings zstdSettings = Settings.builder()
130137
.put(INDEX_CODEC_COMPRESSION_LEVEL_SETTING.getKey(), randomIntBetween(1, 6))
131138
.put(EngineConfig.INDEX_CODEC_SETTING.getKey(), randomFrom(CodecService.ZSTD_CODEC, CodecService.ZSTD_NO_DICT_CODEC))
@@ -179,6 +186,7 @@ public void testLuceneCodecsWithCompressionLevel() {
179186
}
180187

181188
public void testZstandardCompressionLevelSupport() throws Exception {
189+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
182190
CodecService codecService = createCodecService(false);
183191
CodecSettings zstdCodec = (CodecSettings) codecService.codec("zstd");
184192
CodecSettings zstdNoDictCodec = (CodecSettings) codecService.codec("zstd_no_dict");
@@ -197,13 +205,15 @@ public void testBestCompressionMapperServiceNull() throws Exception {
197205
}
198206

199207
public void testZstdMapperServiceNull() throws Exception {
208+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
200209
Codec codec = createCodecService(true).codec("zstd");
201210
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD, codec);
202211
Lucene95CustomStoredFieldsFormat storedFieldsFormat = (Lucene95CustomStoredFieldsFormat) codec.storedFieldsFormat();
203212
assertEquals(Lucene95CustomCodec.DEFAULT_COMPRESSION_LEVEL, storedFieldsFormat.getCompressionLevel());
204213
}
205214

206215
public void testZstdNoDictMapperServiceNull() throws Exception {
216+
FeatureFlagSetter.set(FeatureFlags.ZSTD_COMPRESSION);
207217
Codec codec = createCodecService(true).codec("zstd_no_dict");
208218
assertStoredFieldsCompressionEquals(Lucene95CustomCodec.Mode.ZSTD_NO_DICT, codec);
209219
Lucene95CustomStoredFieldsFormat storedFieldsFormat = (Lucene95CustomStoredFieldsFormat) codec.storedFieldsFormat();

test/framework/src/main/java/org/opensearch/test/OpenSearchIntegTestCase.java

+1
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ protected Settings featureFlagSettings() {
787787
}
788788
// Enabling Telemetry setting by default
789789
featureSettings.put(FeatureFlags.TELEMETRY_SETTING.getKey(), true);
790+
featureSettings.put(FeatureFlags.ZSTD_COMPRESSION_SETTING.getKey(), true);
790791
return featureSettings.build();
791792
}
792793

0 commit comments

Comments
 (0)