This is an automated email from the ASF dual-hosted git repository.
xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 5df2ffbdbc7 Add global pinot.md5.disabled switch and enforce MD5
guards (#17800)
5df2ffbdbc7 is described below
commit 5df2ffbdbc7701f72a72488a7ef7c911ff2895a9
Author: Xiang Fu <[email protected]>
AuthorDate: Tue Mar 3 15:19:15 2026 -0800
Add global pinot.md5.disabled switch and enforce MD5 guards (#17800)
---
.../broker/broker/helix/BaseBrokerStarter.java | 3 +
.../pinot/controller/BaseControllerStarter.java | 3 +
.../org/apache/pinot/minion/BaseMinionStarter.java | 3 +
.../pinot/plugin/filesystem/ADLSGen2PinotFS.java | 13 +++-
.../filesystem/test/ADLSGen2PinotFSTest.java | 29 ++++++++
.../apache/pinot/plugin/filesystem/S3Config.java | 6 ++
.../pinot/plugin/filesystem/S3ConfigTest.java | 13 ++++
.../pinot/segment/local/utils/HashUtils.java | 6 ++
.../segment/local/utils/TableConfigUtils.java | 15 ++++-
.../pinot/segment/local/utils/HashUtilsTest.java | 16 +++++
.../segment/local/utils/TableConfigUtilsTest.java | 77 ++++++++++++++++++++++
.../server/starter/helix/BaseServerStarter.java | 3 +
.../apache/pinot/spi/utils/CommonConstants.java | 1 +
.../org/apache/pinot/spi/utils/PinotMd5Mode.java | 46 +++++++++++++
.../apache/pinot/spi/utils/PinotMd5ModeTest.java | 60 +++++++++++++++++
15 files changed, 291 insertions(+), 3 deletions(-)
diff --git
a/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
b/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
index 02a1e9bca59..52dfca19fc7 100644
---
a/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
+++
b/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
@@ -116,6 +116,7 @@ import org.apache.pinot.spi.utils.CommonConstants.Helix;
import org.apache.pinot.spi.utils.CommonConstants.MultiStageQueryRunner;
import org.apache.pinot.spi.utils.InstanceTypeUtils;
import org.apache.pinot.spi.utils.NetUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.sql.parsers.rewriter.QueryRewriterFactory;
import org.apache.pinot.tsdb.spi.PinotTimeSeriesConfiguration;
import org.slf4j.Logger;
@@ -190,6 +191,8 @@ public abstract class BaseBrokerStarter implements
ServiceStartable {
PinotInsecureMode.setPinotInInsecureMode(
_brokerConf.getProperty(CommonConstants.CONFIG_OF_PINOT_INSECURE_MODE,
false));
+
PinotMd5Mode.setPinotMd5Disabled(_brokerConf.getProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
+ PinotMd5Mode.isPinotMd5Disabled()));
if (_brokerConf.getProperty(MultiStageQueryRunner.KEY_OF_QUERY_RUNNER_PORT,
MultiStageQueryRunner.DEFAULT_QUERY_RUNNER_PORT) == 0) {
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/BaseControllerStarter.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/BaseControllerStarter.java
index d8373ca4486..31ed430eeec 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/BaseControllerStarter.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/BaseControllerStarter.java
@@ -161,6 +161,7 @@ import org.apache.pinot.spi.utils.CommonConstants;
import org.apache.pinot.spi.utils.CommonConstants.Helix;
import org.apache.pinot.spi.utils.InstanceTypeUtils;
import org.apache.pinot.spi.utils.NetUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.sql.parsers.rewriter.QueryRewriterFactory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.slf4j.Logger;
@@ -251,6 +252,8 @@ public abstract class BaseControllerStarter implements
ServiceStartable {
applyCustomConfigs(_config);
PinotInsecureMode.setPinotInInsecureMode(_config.getProperty(CommonConstants.CONFIG_OF_PINOT_INSECURE_MODE,
false));
+
PinotMd5Mode.setPinotMd5Disabled(_config.getProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
+ PinotMd5Mode.isPinotMd5Disabled()));
setupHelixSystemProperties();
IdealStateGroupCommit.setMinNumCharsInISToTurnOnCompression(_config.getMinNumCharsInISToTurnOnCompression());
diff --git
a/pinot-minion/src/main/java/org/apache/pinot/minion/BaseMinionStarter.java
b/pinot-minion/src/main/java/org/apache/pinot/minion/BaseMinionStarter.java
index fbcbff886c8..9941edacee9 100644
--- a/pinot-minion/src/main/java/org/apache/pinot/minion/BaseMinionStarter.java
+++ b/pinot-minion/src/main/java/org/apache/pinot/minion/BaseMinionStarter.java
@@ -77,6 +77,7 @@ import org.apache.pinot.spi.services.ServiceStartable;
import org.apache.pinot.spi.tasks.MinionTaskObserverStorageManager;
import org.apache.pinot.spi.utils.CommonConstants;
import org.apache.pinot.spi.utils.InstanceTypeUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.sql.parsers.rewriter.QueryRewriterFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -113,6 +114,8 @@ public abstract class BaseMinionStarter implements
ServiceStartable {
applyCustomConfigs(_config);
PinotInsecureMode.setPinotInInsecureMode(_config.getProperty(CommonConstants.CONFIG_OF_PINOT_INSECURE_MODE,
false));
+
PinotMd5Mode.setPinotMd5Disabled(_config.getProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
+ PinotMd5Mode.isPinotMd5Disabled()));
setupHelixSystemProperties();
_hostname = _config.getHostName();
diff --git
a/pinot-plugins/pinot-file-system/pinot-adls/src/main/java/org/apache/pinot/plugin/filesystem/ADLSGen2PinotFS.java
b/pinot-plugins/pinot-file-system/pinot-adls/src/main/java/org/apache/pinot/plugin/filesystem/ADLSGen2PinotFS.java
index 0f294f9103e..e3b3cc01baa 100644
---
a/pinot-plugins/pinot-file-system/pinot-adls/src/main/java/org/apache/pinot/plugin/filesystem/ADLSGen2PinotFS.java
+++
b/pinot-plugins/pinot-file-system/pinot-adls/src/main/java/org/apache/pinot/plugin/filesystem/ADLSGen2PinotFS.java
@@ -64,6 +64,8 @@ import org.apache.commons.io.FileUtils;
import org.apache.pinot.spi.env.PinotConfiguration;
import org.apache.pinot.spi.filesystem.BasePinotFS;
import org.apache.pinot.spi.filesystem.FileMetadata;
+import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -123,7 +125,14 @@ public class ADLSGen2PinotFS extends BasePinotFS {
@Override
public void init(PinotConfiguration config) {
- _enableChecksum = config.getProperty(ENABLE_CHECKSUM, false);
+ boolean checksumEnabled = config.getProperty(ENABLE_CHECKSUM, false);
+ if (checksumEnabled && PinotMd5Mode.isPinotMd5Disabled()) {
+ throw new IllegalStateException(String.format(
+ "ADLS checksum requires MD5, but MD5 is disabled via '%s=true'. Set
'%s=false' or '%s=false'.",
+ CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
+ ENABLE_CHECKSUM));
+ }
+ _enableChecksum = checksumEnabled;
// Azure storage account name
String accountName = config.getProperty(ACCOUNT_NAME);
@@ -539,7 +548,7 @@ public class ADLSGen2PinotFS extends BasePinotFS {
public void copyFromLocalFile(File srcFile, URI dstUri)
throws Exception {
LOGGER.debug("copyFromLocalFile is called with srcFile='{}', dstUri='{}'",
srcFile, dstUri);
- byte[] contentMd5 = computeContentMd5(srcFile);
+ byte[] contentMd5 = _enableChecksum ? computeContentMd5(srcFile) : null;
try (InputStream fileInputStream = new FileInputStream(srcFile)) {
copyInputStreamToDst(fileInputStream, dstUri, contentMd5);
}
diff --git
a/pinot-plugins/pinot-file-system/pinot-adls/src/test/java/org/apache/pinot/plugin/filesystem/test/ADLSGen2PinotFSTest.java
b/pinot-plugins/pinot-file-system/pinot-adls/src/test/java/org/apache/pinot/plugin/filesystem/test/ADLSGen2PinotFSTest.java
index 4202ae7fdfd..c7823006520 100644
---
a/pinot-plugins/pinot-file-system/pinot-adls/src/test/java/org/apache/pinot/plugin/filesystem/test/ADLSGen2PinotFSTest.java
+++
b/pinot-plugins/pinot-file-system/pinot-adls/src/test/java/org/apache/pinot/plugin/filesystem/test/ADLSGen2PinotFSTest.java
@@ -47,6 +47,7 @@ import org.apache.pinot.plugin.filesystem.ADLSGen2PinotFS;
import org.apache.pinot.plugin.filesystem.AzurePinotFSUtil;
import org.apache.pinot.spi.env.PinotConfiguration;
import org.apache.pinot.spi.filesystem.FileMetadata;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.AfterMethod;
@@ -141,6 +142,34 @@ public class ADLSGen2PinotFSTest {
assertTrue(sasTokenFS != null);
}
+ @Test
+ public void testChecksumEnabledWithMd5DisabledFails() {
+ PinotConfiguration pinotConfiguration = new PinotConfiguration();
+ pinotConfiguration.setProperty("authenticationType", "SAS_TOKEN");
+ pinotConfiguration.setProperty("sasToken",
"sp=rwdl&se=2025-12-31T23:59:59Z&sv=2022-11-02&sr=c&sig=test");
+ pinotConfiguration.setProperty("accountName", "testaccount");
+ pinotConfiguration.setProperty("fileSystemName", "testcontainer");
+ pinotConfiguration.setProperty("enableChecksum", "true");
+
+ ADLSGen2PinotFS adlsGen2PinotFs = new ADLSGen2PinotFS() {
+ @Override
+ public DataLakeFileSystemClient
getOrCreateClientWithFileSystem(DataLakeServiceClient serviceClient,
+ String fileSystemName) {
+ return _mockFileSystemClient;
+ }
+ };
+
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ IllegalStateException exception =
+ expectThrows(IllegalStateException.class, () ->
adlsGen2PinotFs.init(pinotConfiguration));
+ assertTrue(exception.getMessage().contains("pinot.md5.disabled"));
+ assertTrue(exception.getMessage().contains("enableChecksum"));
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
@Test(expectedExceptions = NullPointerException.class)
public void testSasTokenMissingToken() {
PinotConfiguration pinotConfiguration = new PinotConfiguration();
diff --git
a/pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3Config.java
b/pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3Config.java
index a38db4c9072..8666d888934 100644
---
a/pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3Config.java
+++
b/pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3Config.java
@@ -25,7 +25,9 @@ import java.time.Duration;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.pinot.spi.env.PinotConfiguration;
+import org.apache.pinot.spi.utils.CommonConstants;
import org.apache.pinot.spi.utils.DataSizeUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.spi.utils.TimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -126,6 +128,10 @@ public class S3Config {
_responseChecksumValidationWhenRequired =
ResponseChecksumValidation.fromValue(
pinotConfig.getProperty(RESPONSE_CHECKSUM_VALIDATION,
ResponseChecksumValidation.WHEN_REQUIRED.name()));
_useLegacyMd5Plugin =
Boolean.parseBoolean(pinotConfig.getProperty(USE_LEGACY_MD5_PLUGIN, "false"));
+ if (_useLegacyMd5Plugin && PinotMd5Mode.isPinotMd5Disabled()) {
+ throw new IllegalStateException(String.format("S3 config '%s=true' is
not allowed when '%s=true'",
+ USE_LEGACY_MD5_PLUGIN,
CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ }
_storageClass = pinotConfig.getProperty(STORAGE_CLASS);
if (_storageClass != null) {
diff --git
a/pinot-plugins/pinot-file-system/pinot-s3/src/test/java/org/apache/pinot/plugin/filesystem/S3ConfigTest.java
b/pinot-plugins/pinot-file-system/pinot-s3/src/test/java/org/apache/pinot/plugin/filesystem/S3ConfigTest.java
index 0f4528fd022..3eae446fa51 100644
---
a/pinot-plugins/pinot-file-system/pinot-s3/src/test/java/org/apache/pinot/plugin/filesystem/S3ConfigTest.java
+++
b/pinot-plugins/pinot-file-system/pinot-s3/src/test/java/org/apache/pinot/plugin/filesystem/S3ConfigTest.java
@@ -19,6 +19,7 @@
package org.apache.pinot.plugin.filesystem;
import org.apache.pinot.spi.env.PinotConfiguration;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.testng.Assert;
import org.testng.annotations.Test;
import software.amazon.awssdk.services.s3.model.StorageClass;
@@ -75,4 +76,16 @@ public class S3ConfigTest {
S3Config cfg = new S3Config(pinotConfig);
Assert.assertTrue(cfg.useLegacyMd5Plugin());
}
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testLegacyMd5PluginWhenMd5Disabled() {
+ PinotConfiguration pinotConfig = new PinotConfiguration();
+ pinotConfig.setProperty("useLegacyMd5Plugin", "true");
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ new S3Config(pinotConfig);
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
}
diff --git
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/HashUtils.java
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/HashUtils.java
index 5070bbf9270..578280fb0d2 100644
---
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/HashUtils.java
+++
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/HashUtils.java
@@ -28,6 +28,8 @@ import net.jpountz.xxhash.XXHashFactory;
import org.apache.pinot.spi.config.table.HashFunction;
import org.apache.pinot.spi.data.readers.PrimaryKey;
import org.apache.pinot.spi.utils.ByteArray;
+import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
public class HashUtils {
@@ -94,6 +96,10 @@ public class HashUtils {
case NONE:
return primaryKey;
case MD5:
+ if (PinotMd5Mode.isPinotMd5Disabled()) {
+ throw new IllegalStateException(String.format("Hash function MD5 is
disabled via '%s=true'",
+ CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ }
return new ByteArray(HashUtils.hashMD5(primaryKey.asBytes()));
case MURMUR3:
return new ByteArray(HashUtils.hashMurmur3(primaryKey.asBytes()));
diff --git
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
index 97623115c3c..a8453a1c3bf 100644
---
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
+++
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
@@ -62,6 +62,7 @@ import
org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.DedupConfig;
import org.apache.pinot.spi.config.table.FieldConfig;
import org.apache.pinot.spi.config.table.FieldConfig.EncodingType;
+import org.apache.pinot.spi.config.table.HashFunction;
import org.apache.pinot.spi.config.table.IndexingConfig;
import org.apache.pinot.spi.config.table.MultiColumnTextIndexConfig;
import org.apache.pinot.spi.config.table.QuotaConfig;
@@ -104,6 +105,7 @@ import org.apache.pinot.spi.utils.DataSizeUtils;
import org.apache.pinot.spi.utils.Enablement;
import org.apache.pinot.spi.utils.IngestionConfigUtils;
import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.spi.utils.TimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -777,7 +779,8 @@ public final class TableConfigUtils {
}
boolean isUpsertEnabled = tableConfig.getUpsertMode() !=
UpsertConfig.Mode.NONE;
- boolean isDedupEnabled = tableConfig.getDedupConfig() != null &&
tableConfig.getDedupConfig().isDedupEnabled();
+ DedupConfig dedupConfig = tableConfig.getDedupConfig();
+ boolean isDedupEnabled = dedupConfig != null &&
dedupConfig.isDedupEnabled();
// check both upsert and dedup are not enabled simultaneously
Preconditions.checkState(!(isUpsertEnabled && isDedupEnabled),
@@ -807,6 +810,16 @@ public final class TableConfigUtils {
// specifically for upsert
UpsertConfig upsertConfig = tableConfig.getUpsertConfig();
+ if (PinotMd5Mode.isPinotMd5Disabled()) {
+ if (isUpsertEnabled && upsertConfig != null &&
upsertConfig.getHashFunction() == HashFunction.MD5) {
+ throw new IllegalStateException(String.format(
+ "Upsert hash function MD5 is disabled via '%s=true'",
CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ }
+ if (isDedupEnabled && dedupConfig.getHashFunction() == HashFunction.MD5)
{
+ throw new IllegalStateException(String.format(
+ "Dedup hash function MD5 is disabled via '%s=true'",
CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ }
+ }
if (upsertConfig != null) {
// Currently, only one tier is allowed for upsert table, as the
committed segments can't be moved to other tiers.
Preconditions.checkState(tableConfig.getTierConfigsList() == null, "The
upsert table cannot have multi-tiers");
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/HashUtilsTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/HashUtilsTest.java
index 9f4649b162a..8c60ad6f374 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/HashUtilsTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/HashUtilsTest.java
@@ -19,8 +19,11 @@
package org.apache.pinot.segment.local.utils;
import java.util.UUID;
+import org.apache.pinot.spi.config.table.HashFunction;
import org.apache.pinot.spi.data.readers.PrimaryKey;
import org.apache.pinot.spi.utils.BytesUtils;
+import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
@@ -61,6 +64,19 @@ public class HashUtilsTest {
}
}
+ @Test
+ public void testHashPrimaryKeyWithMd5Disabled() {
+ PrimaryKey primaryKey = new PrimaryKey(new Object[]{"hello world"});
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ IllegalStateException exception =
+ expectThrows(IllegalStateException.class, () ->
HashUtils.hashPrimaryKey(primaryKey, HashFunction.MD5));
+
assertTrue(exception.getMessage().contains(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
private void testHashUUID(UUID[] uuids) {
byte[] convertedBytes = HashUtils.hashUUID(new PrimaryKey(uuids));
// After hashing, each UUID should take 16 bytes.
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
index 1488bf81e51..0194c45633c 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
@@ -38,6 +38,7 @@ import
org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.DedupConfig;
import org.apache.pinot.spi.config.table.FieldConfig;
import org.apache.pinot.spi.config.table.FieldConfig.CompressionCodec;
+import org.apache.pinot.spi.config.table.HashFunction;
import org.apache.pinot.spi.config.table.IndexingConfig;
import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
@@ -79,6 +80,7 @@ import org.apache.pinot.spi.stream.StreamMetadataProvider;
import org.apache.pinot.spi.utils.CommonConstants;
import org.apache.pinot.spi.utils.Enablement;
import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
import org.mockito.Mockito;
import org.testng.annotations.DataProvider;
@@ -2025,6 +2027,81 @@ public class TableConfigUtilsTest {
}
}
+ @Test
+ public void testValidateUpsertConfigWithMd5Disabled() {
+ Schema schema = new Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
+ .addSingleValueDimension("myCol", FieldSpec.DataType.STRING)
+ .setPrimaryKeyColumns(Lists.newArrayList("myCol"))
+ .build();
+ UpsertConfig upsertConfig = new UpsertConfig(UpsertConfig.Mode.FULL);
+ upsertConfig.setHashFunction(HashFunction.MD5);
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.REALTIME).setTableName(TABLE_NAME)
+ .setUpsertConfig(upsertConfig)
+ .setRoutingConfig(
+ new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
+ .setStreamConfigs(getStreamConfigs())
+ .build();
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ IllegalStateException exception =
+ expectThrows(IllegalStateException.class, () ->
TableConfigUtils.validateUpsertAndDedupConfig(tableConfig,
+ schema));
+
assertTrue(exception.getMessage().contains(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
+ @Test
+ public void testValidateDedupConfigWithMd5Disabled() {
+ Schema schema = new Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
+ .addSingleValueDimension("myCol", FieldSpec.DataType.STRING)
+ .setPrimaryKeyColumns(Lists.newArrayList("myCol"))
+ .build();
+ DedupConfig dedupConfig = new DedupConfig();
+ dedupConfig.setHashFunction(HashFunction.MD5);
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.REALTIME).setTableName(TABLE_NAME)
+ .setDedupConfig(dedupConfig)
+ .setRoutingConfig(
+ new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
+ .setStreamConfigs(getStreamConfigs())
+ .build();
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ IllegalStateException exception =
+ expectThrows(IllegalStateException.class, () ->
TableConfigUtils.validateUpsertAndDedupConfig(tableConfig,
+ schema));
+
assertTrue(exception.getMessage().contains(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED));
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
+ @Test
+ public void testValidateDedupConfigWithMd5DisabledAllowsUpsertModeNoneMd5() {
+ Schema schema = new Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
+ .addSingleValueDimension("myCol", FieldSpec.DataType.STRING)
+ .setPrimaryKeyColumns(Lists.newArrayList("myCol"))
+ .build();
+ DedupConfig dedupConfig = new DedupConfig();
+ dedupConfig.setHashFunction(HashFunction.NONE);
+ UpsertConfig upsertConfig = new UpsertConfig(UpsertConfig.Mode.NONE);
+ upsertConfig.setHashFunction(HashFunction.MD5);
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.REALTIME).setTableName(TABLE_NAME)
+ .setUpsertConfig(upsertConfig)
+ .setDedupConfig(dedupConfig)
+ .setRoutingConfig(
+ new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
+ .setStreamConfigs(getStreamConfigs())
+ .build();
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ TableConfigUtils.validateUpsertAndDedupConfig(tableConfig, schema);
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
@Test
public void testValidateUpsertConfig() {
Schema schema = new Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
diff --git
a/pinot-server/src/main/java/org/apache/pinot/server/starter/helix/BaseServerStarter.java
b/pinot-server/src/main/java/org/apache/pinot/server/starter/helix/BaseServerStarter.java
index 7340d76b33f..7010bd16032 100644
---
a/pinot-server/src/main/java/org/apache/pinot/server/starter/helix/BaseServerStarter.java
+++
b/pinot-server/src/main/java/org/apache/pinot/server/starter/helix/BaseServerStarter.java
@@ -134,6 +134,7 @@ import org.apache.pinot.spi.utils.CommonConstants.Server;
import
org.apache.pinot.spi.utils.CommonConstants.Server.SegmentCompletionProtocol;
import org.apache.pinot.spi.utils.InstanceTypeUtils;
import org.apache.pinot.spi.utils.NetUtils;
+import org.apache.pinot.spi.utils.PinotMd5Mode;
import org.apache.pinot.spi.utils.builder.TableNameBuilder;
import org.apache.pinot.sql.parsers.rewriter.QueryRewriterFactory;
import org.slf4j.Logger;
@@ -204,6 +205,8 @@ public abstract class BaseServerStarter implements
ServiceStartable {
PinotInsecureMode.setPinotInInsecureMode(
_serverConf.getProperty(CommonConstants.CONFIG_OF_PINOT_INSECURE_MODE,
false));
+
PinotMd5Mode.setPinotMd5Disabled(_serverConf.getProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
+ PinotMd5Mode.isPinotMd5Disabled()));
String tarCompressionCodecName =
_serverConf.getProperty(CommonConstants.CONFIG_OF_PINOT_TAR_COMPRESSION_CODEC_NAME);
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
index f5c9e45b537..88b9bc30520 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
@@ -63,6 +63,7 @@ public class CommonConstants {
public static final String DATABASE = "database";
public static final String DEFAULT_DATABASE = "default";
public static final String CONFIG_OF_PINOT_INSECURE_MODE =
"pinot.insecure.mode";
+ public static final String CONFIG_OF_PINOT_MD5_DISABLED =
"pinot.md5.disabled";
@Deprecated
public static final String DEFAULT_PINOT_INSECURE_MODE = "false";
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/PinotMd5Mode.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/PinotMd5Mode.java
new file mode 100644
index 00000000000..eb5bd2d5954
--- /dev/null
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/PinotMd5Mode.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.spi.utils;
+
+/**
+ * Global runtime switch for disabling MD5-dependent code paths in Pinot.
+ */
+public class PinotMd5Mode {
+ private static volatile boolean _pinotMd5Disabled = readFromSystemProperty();
+
+ private PinotMd5Mode() {
+ }
+
+ public static void setPinotMd5Disabled(boolean pinotMd5Disabled) {
+ _pinotMd5Disabled = pinotMd5Disabled;
+ }
+
+ public static boolean isPinotMd5Disabled() {
+ return _pinotMd5Disabled;
+ }
+
+ // Visible for tests in the same package.
+ static void resetFromSystemProperty() {
+ _pinotMd5Disabled = readFromSystemProperty();
+ }
+
+ private static boolean readFromSystemProperty() {
+ return Boolean.getBoolean(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED);
+ }
+}
diff --git
a/pinot-spi/src/test/java/org/apache/pinot/spi/utils/PinotMd5ModeTest.java
b/pinot-spi/src/test/java/org/apache/pinot/spi/utils/PinotMd5ModeTest.java
new file mode 100644
index 00000000000..f6bcbb894c7
--- /dev/null
+++ b/pinot-spi/src/test/java/org/apache/pinot/spi/utils/PinotMd5ModeTest.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.spi.utils;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+
+public class PinotMd5ModeTest {
+ @Test
+ public void testSetterGetter() {
+ try {
+ PinotMd5Mode.setPinotMd5Disabled(true);
+ assertTrue(PinotMd5Mode.isPinotMd5Disabled());
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ assertFalse(PinotMd5Mode.isPinotMd5Disabled());
+ } finally {
+ PinotMd5Mode.setPinotMd5Disabled(false);
+ }
+ }
+
+ @Test
+ public void testResetFromSystemProperty() {
+ String originalValue =
System.getProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED);
+ try {
+ System.setProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED, "true");
+ PinotMd5Mode.resetFromSystemProperty();
+ assertTrue(PinotMd5Mode.isPinotMd5Disabled());
+
+ System.setProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
"false");
+ PinotMd5Mode.resetFromSystemProperty();
+ assertFalse(PinotMd5Mode.isPinotMd5Disabled());
+ } finally {
+ if (originalValue != null) {
+ System.setProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED,
originalValue);
+ } else {
+ System.clearProperty(CommonConstants.CONFIG_OF_PINOT_MD5_DISABLED);
+ }
+ PinotMd5Mode.resetFromSystemProperty();
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]