From f8bdb8479ee9eae2cf73aab0d4802c488404b538 Mon Sep 17 00:00:00 2001 From: Sebastian Gruza Date: Thu, 17 Sep 2026 12:59:58 +0000 Subject: [PATCH 1/2] fix(core): format the graph space storage percentage with Locale.ROOT GraphSpace.info() formats the storage percentage with String.format and parses it back with Float.parseFloat. Without a Locale the format follows the JVM default, so on pl_PL, de_DE, fr_FR, ru_RU and other decimal-comma locales it yields "0,33", which parseFloat rejects: with usePD=true a fresh PD makes the server exit at startup (Can't write json: For input string: "0,00"), an existing PD lets it start degraded (some graphs never load, every drop fails), and GET /graphspaces/{space} answers 400. Locale.ROOT keeps the arithmetic and the two-digit rounding unchanged. --- .../apache/hugegraph/space/GraphSpace.java | 7 +- .../apache/hugegraph/unit/UnitTestSuite.java | 2 + .../unit/core/GraphSpaceInfoLocaleTest.java | 64 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java index 5d91aa9f28..f821809b63 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java @@ -20,6 +20,7 @@ import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import org.apache.commons.lang.StringUtils; @@ -389,9 +390,11 @@ public Map info() { infos.put("cpu_used", this.cpuUsed); infos.put("memory_used", this.memoryUsed); infos.put("storage_used", this.storageUsed); + // Locale.ROOT: the default locale may format with a decimal comma + // ("0,33" on pl_PL, de_DE, fr_FR, ...), which parseFloat() rejects float storageUserPercent = Float.parseFloat( - String.format("%.2f", (float) this.storageUsed / - ((float) this.storageLimit * 1.0))); + String.format(Locale.ROOT, "%.2f", (float) this.storageUsed / + ((float) this.storageLimit * 1.0))); infos.put("storage_percent", storageUserPercent); infos.put("graph_number_used", this.graphNumberUsed); infos.put("role_number_used", this.roleNumberUsed); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java index b940dadf1d..2e34907bf2 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java @@ -49,6 +49,7 @@ import org.apache.hugegraph.unit.core.ConditionQueryFlattenTest; import org.apache.hugegraph.unit.core.ConditionTest; import org.apache.hugegraph.unit.core.DataTypeTest; +import org.apache.hugegraph.unit.core.GraphSpaceInfoLocaleTest; import org.apache.hugegraph.unit.core.GraphManagerStoresWaitTest; import org.apache.hugegraph.unit.core.DirectionsTest; import org.apache.hugegraph.unit.core.ExceptionTest; @@ -137,6 +138,7 @@ /* types */ DataTypeTest.class, + GraphSpaceInfoLocaleTest.class, GraphManagerStoresWaitTest.class, DirectionsTest.class, SerialEnumTest.class, diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java new file mode 100644 index 0000000000..c9d7b6ddf2 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java @@ -0,0 +1,64 @@ +/* + * 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.hugegraph.unit.core; + +import java.util.Locale; +import java.util.Map; + +import org.apache.hugegraph.space.GraphSpace; +import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.unit.BaseUnitTest; +import org.junit.Test; + +/** + * GraphSpace.info() formats the storage percentage and parses it back; + * that must not depend on the JVM's default locale (a decimal comma on + * pl_PL, de_DE, fr_FR, ... used to fail with NumberFormatException). + */ +public class GraphSpaceInfoLocaleTest extends BaseUnitTest { + + private static float storagePercent(Locale locale) { + Locale saved = Locale.getDefault(); + Locale.setDefault(locale); + try { + GraphSpace space = new GraphSpace("gs_locale"); + space.storageLimit(100); + space.setStorageUsed(33); + Map info = space.info(); + return (Float) info.get("storage_percent"); + } finally { + Locale.setDefault(saved); + } + } + + @Test + public void testInfoWithDecimalCommaLocales() { + for (Locale locale : new Locale[]{new Locale("pl", "PL"), + Locale.GERMANY, Locale.FRANCE, + new Locale("ru", "RU")}) { + Assert.assertEquals(locale.toString(), 0.33f, + storagePercent(locale), 0.0001f); + } + } + + @Test + public void testInfoWithDecimalPointLocales() { + Assert.assertEquals(0.33f, storagePercent(Locale.ROOT), 0.0001f); + Assert.assertEquals(0.33f, storagePercent(Locale.US), 0.0001f); + } +} From c3adb36389ff9da4c3fa09853f13d72c42b29187 Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 18 Sep 2026 00:40:35 +0800 Subject: [PATCH 2/2] test: restore all locale categories after test --- .../hugegraph/unit/core/GraphSpaceInfoLocaleTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java index c9d7b6ddf2..973890df76 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphSpaceInfoLocaleTest.java @@ -33,7 +33,8 @@ public class GraphSpaceInfoLocaleTest extends BaseUnitTest { private static float storagePercent(Locale locale) { - Locale saved = Locale.getDefault(); + Locale savedFormat = Locale.getDefault(Locale.Category.FORMAT); + Locale savedDisplay = Locale.getDefault(Locale.Category.DISPLAY); Locale.setDefault(locale); try { GraphSpace space = new GraphSpace("gs_locale"); @@ -42,7 +43,8 @@ private static float storagePercent(Locale locale) { Map info = space.info(); return (Float) info.get("storage_percent"); } finally { - Locale.setDefault(saved); + Locale.setDefault(Locale.Category.FORMAT, savedFormat); + Locale.setDefault(Locale.Category.DISPLAY, savedDisplay); } }