This is an automated email from the ASF dual-hosted git repository.

gabor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/parquet-java.git


The following commit(s) were added to refs/heads/master by this push:
     new 9db623654 GH-3224: Make ParquetProperties.valuesWriterFactory thread 
safe (#3308)
9db623654 is described below

commit 9db62365453e3f08082162b92598b7ee56e38e0b
Author: Arnav Balyan <[email protected]>
AuthorDate: Tue Sep 16 18:21:34 2025 +0530

    GH-3224: Make ParquetProperties.valuesWriterFactory thread safe (#3308)
---
 .../apache/parquet/column/ParquetProperties.java   |  7 +++-
 .../column/ParquetPropertiesThreadSafetyTest.java  | 46 ++++++++++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git 
a/parquet-column/src/main/java/org/apache/parquet/column/ParquetProperties.java 
b/parquet-column/src/main/java/org/apache/parquet/column/ParquetProperties.java
index d3dced53d..f29214b45 100644
--- 
a/parquet-column/src/main/java/org/apache/parquet/column/ParquetProperties.java
+++ 
b/parquet-column/src/main/java/org/apache/parquet/column/ParquetProperties.java
@@ -69,6 +69,11 @@ public class ParquetProperties {
 
   public static final boolean DEFAULT_PAGE_WRITE_CHECKSUM_ENABLED = true;
 
+  /**
+   * @deprecated This shared instance can cause thread safety issues when used 
by multiple builders concurrently.
+   * Use {@code new DefaultValuesWriterFactory()} instead to create individual 
instances.
+   */
+  @Deprecated
   public static final ValuesWriterFactory DEFAULT_VALUES_WRITER_FACTORY = new 
DefaultValuesWriterFactory();
 
   private static final int MIN_SLAB_SIZE = 64;
@@ -396,7 +401,7 @@ public class ParquetProperties {
     private int pageValueCountThreshold = DEFAULT_PAGE_VALUE_COUNT_THRESHOLD;
     private boolean estimateNextSizeCheck = 
DEFAULT_ESTIMATE_ROW_COUNT_FOR_PAGE_SIZE_CHECK;
     private ByteBufferAllocator allocator = new HeapByteBufferAllocator();
-    private ValuesWriterFactory valuesWriterFactory = 
DEFAULT_VALUES_WRITER_FACTORY;
+    private ValuesWriterFactory valuesWriterFactory = new 
DefaultValuesWriterFactory();
     private int columnIndexTruncateLength = 
DEFAULT_COLUMN_INDEX_TRUNCATE_LENGTH;
     private int statisticsTruncateLength = DEFAULT_STATISTICS_TRUNCATE_LENGTH;
     private boolean statisticsEnabled = DEFAULT_STATISTICS_ENABLED;
diff --git 
a/parquet-column/src/test/java/org/apache/parquet/column/ParquetPropertiesThreadSafetyTest.java
 
b/parquet-column/src/test/java/org/apache/parquet/column/ParquetPropertiesThreadSafetyTest.java
new file mode 100644
index 000000000..bb622f1c1
--- /dev/null
+++ 
b/parquet-column/src/test/java/org/apache/parquet/column/ParquetPropertiesThreadSafetyTest.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.parquet.column;
+
+import static org.junit.Assert.assertNotSame;
+
+import java.lang.reflect.Field;
+import org.apache.parquet.column.values.factory.ValuesWriterFactory;
+import org.junit.Test;
+
+public class ParquetPropertiesThreadSafetyTest {
+
+  @Test
+  public void testBuilderValuesWriterFactoryNotShared() throws Exception {
+    ParquetProperties.Builder builder1 = ParquetProperties.builder();
+    ParquetProperties.Builder builder2 = ParquetProperties.builder();
+    ParquetProperties.Builder builder3 = ParquetProperties.builder();
+
+    Field factoryField = 
ParquetProperties.Builder.class.getDeclaredField("valuesWriterFactory");
+    factoryField.setAccessible(true);
+
+    ValuesWriterFactory factory1 = (ValuesWriterFactory) 
factoryField.get(builder1);
+    ValuesWriterFactory factory2 = (ValuesWriterFactory) 
factoryField.get(builder2);
+    ValuesWriterFactory factory3 = (ValuesWriterFactory) 
factoryField.get(builder3);
+
+    assertNotSame("Builder instances should not share ValuesWriterFactory 
instances", factory1, factory2);
+    assertNotSame("Builder instances should not share ValuesWriterFactory 
instances", factory2, factory3);
+    assertNotSame("Builder instances should not share ValuesWriterFactory 
instances", factory1, factory3);
+  }
+}

Reply via email to