You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by bl...@apache.org on 2019/06/18 22:16:31 UTC

[incubator-iceberg] branch master updated: Fix concurrent access to lazy PartitionSpec methods (#219)

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

blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iceberg.git


The following commit(s) were added to refs/heads/master by this push:
     new 33b4db6  Fix concurrent access to lazy PartitionSpec methods (#219)
33b4db6 is described below

commit 33b4db66261d68428a3e7ceb55f0b9b6718e133b
Author: Ryan Blue <rd...@users.noreply.github.com>
AuthorDate: Tue Jun 18 15:16:27 2019 -0700

    Fix concurrent access to lazy PartitionSpec methods (#219)
---
 .../java/org/apache/iceberg/PartitionSpec.java     | 57 ++++++++++++++--------
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/api/src/main/java/org/apache/iceberg/PartitionSpec.java b/api/src/main/java/org/apache/iceberg/PartitionSpec.java
index 3d7475b..5013119 100644
--- a/api/src/main/java/org/apache/iceberg/PartitionSpec.java
+++ b/api/src/main/java/org/apache/iceberg/PartitionSpec.java
@@ -55,10 +55,10 @@ public class PartitionSpec implements Serializable {
   // this is ordered so that DataFile has a consistent schema
   private final int specId;
   private final PartitionField[] fields;
-  private transient ListMultimap<Integer, PartitionField> fieldsBySourceId = null;
-  private transient Map<String, PartitionField> fieldsByName = null;
-  private transient Class<?>[] lazyJavaClasses = null;
-  private transient List<PartitionField> fieldList = null;
+  private transient volatile ListMultimap<Integer, PartitionField> fieldsBySourceId = null;
+  private transient volatile Map<String, PartitionField> fieldsByName = null;
+  private transient volatile Class<?>[] lazyJavaClasses = null;
+  private transient volatile List<PartitionField> fieldList = null;
 
   private PartitionSpec(Schema schema, int specId, List<PartitionField> fields) {
     this.schema = schema;
@@ -118,12 +118,18 @@ public class PartitionSpec implements Serializable {
 
   public Class<?>[] javaClasses() {
     if (lazyJavaClasses == null) {
-      this.lazyJavaClasses = new Class<?>[fields.length];
-      for (int i = 0; i < fields.length; i += 1) {
-        PartitionField field = fields[i];
-        Type sourceType = schema.findType(field.sourceId());
-        Type result = field.transform().getResultType(sourceType);
-        lazyJavaClasses[i] = result.typeId().javaClass();
+      synchronized (this) {
+        if (lazyJavaClasses == null) {
+          Class<?>[] classes = new Class<?>[fields.length];
+          for (int i = 0; i < fields.length; i += 1) {
+            PartitionField field = fields[i];
+            Type sourceType = schema.findType(field.sourceId());
+            Type result = field.transform().getResultType(sourceType);
+            classes[i] = result.typeId().javaClass();
+          }
+
+          this.lazyJavaClasses = classes;
+        }
       }
     }
 
@@ -209,18 +215,26 @@ public class PartitionSpec implements Serializable {
 
   private List<PartitionField> lazyFieldList() {
     if (fieldList == null) {
-      this.fieldList = ImmutableList.copyOf(fields);
+      synchronized (this) {
+        if (fieldList == null) {
+          this.fieldList = ImmutableList.copyOf(fields);
+        }
+      }
     }
     return fieldList;
   }
 
   private Map<String, PartitionField> lazyFieldsByName() {
     if (fieldsByName == null) {
-      ImmutableMap.Builder<String, PartitionField> builder = ImmutableMap.builder();
-      for (PartitionField field : fields) {
-        builder.put(field.name(), field);
+      synchronized (this) {
+        if (fieldsByName == null) {
+          ImmutableMap.Builder<String, PartitionField> builder = ImmutableMap.builder();
+          for (PartitionField field : fields) {
+            builder.put(field.name(), field);
+          }
+          this.fieldsByName = builder.build();
+        }
       }
-      this.fieldsByName = builder.build();
     }
 
     return fieldsByName;
@@ -228,10 +242,15 @@ public class PartitionSpec implements Serializable {
 
   private ListMultimap<Integer, PartitionField> lazyFieldsBySourceId() {
     if (fieldsBySourceId == null) {
-      this.fieldsBySourceId = Multimaps
-          .newListMultimap(Maps.newHashMap(), () -> Lists.newArrayListWithCapacity(fields.length));
-      for (PartitionField field : fields) {
-        fieldsBySourceId.put(field.sourceId(), field);
+      synchronized (this) {
+        if (fieldsBySourceId == null) {
+          ListMultimap<Integer, PartitionField> multiMap = Multimaps
+              .newListMultimap(Maps.newHashMap(), () -> Lists.newArrayListWithCapacity(fields.length));
+          for (PartitionField field : fields) {
+            multiMap.put(field.sourceId(), field);
+          }
+          this.fieldsBySourceId = multiMap;
+        }
       }
     }