PHOENIX-4074 Race condition in LazyValueGetter (Samarth Jain)

Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/1ca62e4a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/1ca62e4a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/1ca62e4a

Branch: refs/heads/4.x-HBase-1.1
Commit: 1ca62e4a49c890fbec57c529c3cb1fe8a4cb27d1
Parents: ed180c4
Author: James Taylor <[email protected]>
Authored: Mon Aug 7 19:18:20 2017 -0700
Committer: James Taylor <[email protected]>
Committed: Mon Aug 7 23:05:01 2017 -0700

----------------------------------------------------------------------
 .../index/covered/data/LazyValueGetter.java     | 112 ++++++++++---------
 1 file changed, 58 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/1ca62e4a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/data/LazyValueGetter.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/data/LazyValueGetter.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/data/LazyValueGetter.java
index bafefce..1049c89 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/data/LazyValueGetter.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/data/LazyValueGetter.java
@@ -38,66 +38,70 @@ import 
org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
  */
 public class LazyValueGetter implements ValueGetter {
 
-  private CoveredDeleteScanner scan;
-  private volatile Map<ColumnReference, ImmutableBytesWritable> values;
-  private byte[] row;
-  
-  /**
-   * Back the getter with a {@link Scanner} to actually access the local data.
-   * @param scan backing scanner
-   * @param currentRow row key for the row to seek in the scanner
-   */
-  public LazyValueGetter(CoveredDeleteScanner scan, byte[] currentRow) {
-    this.scan = scan;
-    this.row = currentRow;
-  }
+    private CoveredDeleteScanner scan;
+    private volatile Map<ColumnReference, ImmutableBytesWritable> values;
+    private byte[] row;
 
-  @Override
-  public ImmutableBytesWritable getLatestValue(ColumnReference ref, long ts) 
throws IOException {
-    // ensure we have a backing map
-    if (values == null) {
-      synchronized (this) {
-        values = Collections.synchronizedMap(new HashMap<ColumnReference, 
ImmutableBytesWritable>());
-      }
+    /**
+     * Back the getter with a {@link Scanner} to actually access the local 
data.
+     * @param scan backing scanner
+     * @param currentRow row key for the row to seek in the scanner
+     */
+    public LazyValueGetter(CoveredDeleteScanner scan, byte[] currentRow) {
+        this.scan = scan;
+        this.row = currentRow;
     }
 
-    // check the value in the map
-    ImmutableBytesWritable value = values.get(ref);
-    if (value == null) {
-      value = get(ref);
-      DeleteTracker deleteTracker = scan.getDeleteTracker();
-      if (value == null) {
-          // Delete family is used for row deletion. Family won't necessarily 
match as we'll be at
-          // the delete family marker on the last column family if there is 
one.
-          if (deleteTracker.deleteFamily != null && 
deleteTracker.deleteFamily.getTimestamp() == ts) {
-              value = HIDDEN_BY_DELETE;
-          }
-      }
-      values.put(ref, value);
-    }
+    @Override
+    public ImmutableBytesWritable getLatestValue(ColumnReference ref, long ts) 
throws IOException {
+        Map<ColumnReference, ImmutableBytesWritable> v = values;
+        // ensure we have a backing map
+        if (v == null) {
+            synchronized (this) {
+                v = values;
+                if (v == null) {
+                    v = values = Collections.synchronizedMap(new 
HashMap<ColumnReference, ImmutableBytesWritable>());
+                }
+            }
+        }
 
-    return value;
-  }
+        // check the value in the map
+        ImmutableBytesWritable value = v.get(ref);
+        if (value == null) {
+            value = get(ref);
+            DeleteTracker deleteTracker = scan.getDeleteTracker();
+            if (value == null) {
+                // Delete family is used for row deletion. Family won't 
necessarily match as we'll be at
+                // the delete family marker on the last column family if there 
is one.
+                if (deleteTracker.deleteFamily != null && 
deleteTracker.deleteFamily.getTimestamp() == ts) {
+                    value = HIDDEN_BY_DELETE;
+                }
+            }
+            v.put(ref, value);
+        }
 
-  /**
-   * @param ref
-   * @return the first value on the scanner for the given column
-   */
-  private ImmutableBytesPtr get(ColumnReference ref) throws IOException {
-    KeyValue first = ref.getFirstKeyValueForRow(row);
-    if (!scan.seek(first)) {
-      return null;
+        return value;
     }
-    // there is a next value - we only care about the current value, so we can 
just snag that
-    Cell next = scan.next();
-    if (ref.matches(next)) {
-      return new ImmutableBytesPtr(next.getValueArray(), 
next.getValueOffset(), next.getValueLength());
+
+    /**
+     * @param ref
+     * @return the first value on the scanner for the given column
+     */
+    private ImmutableBytesPtr get(ColumnReference ref) throws IOException {
+        KeyValue first = ref.getFirstKeyValueForRow(row);
+        if (!scan.seek(first)) {
+            return null;
+        }
+        // there is a next value - we only care about the current value, so we 
can just snag that
+        Cell next = scan.next();
+        if (ref.matches(next)) {
+            return new ImmutableBytesPtr(next.getValueArray(), 
next.getValueOffset(), next.getValueLength());
+        }
+        return null;
     }
-    return null;
-  }
 
-  @Override
-  public byte[] getRowKey() {
-       return this.row; 
-  }
+    @Override
+    public byte[] getRowKey() {
+        return this.row; 
+    }
 }
\ No newline at end of file

Reply via email to