You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by an...@apache.org on 2016/07/25 17:28:50 UTC

hbase git commit: HBASE-16205 When Cells are not copied to MSLAB, deep clone it while adding to Memstore.

Repository: hbase
Updated Branches:
  refs/heads/master 6dbce2a8c -> 2df0ef549


HBASE-16205 When Cells are not copied to MSLAB, deep clone it while adding to Memstore.


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/2df0ef54
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/2df0ef54
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/2df0ef54

Branch: refs/heads/master
Commit: 2df0ef549abe0ee8e58d4290193b5d69b3e8d6c6
Parents: 6dbce2a
Author: anoopsjohn <an...@gmail.com>
Authored: Mon Jul 25 22:58:32 2016 +0530
Committer: anoopsjohn <an...@gmail.com>
Committed: Mon Jul 25 22:58:32 2016 +0530

----------------------------------------------------------------------
 .../apache/hadoop/hbase/ShareableMemory.java    | 39 ++++++++++++++++++++
 .../hadoop/hbase/codec/KeyValueCodec.java       | 33 ++++++++++++++++-
 .../hbase/codec/KeyValueCodecWithTags.java      |  3 +-
 .../hbase/regionserver/AbstractMemStore.java    | 33 +++++++++++++++--
 4 files changed, 101 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/2df0ef54/hbase-common/src/main/java/org/apache/hadoop/hbase/ShareableMemory.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/ShareableMemory.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/ShareableMemory.java
new file mode 100644
index 0000000..6a6ae59
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/ShareableMemory.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright The Apache Software Foundation
+ *
+ * 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.hadoop.hbase;
+
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+
+/**
+ * A cell implementing this interface would mean that the memory area backing this cell will refer
+ * to a memory area that could be part of a larger common memory area used by the RegionServer. This
+ * might be the bigger memory chunk where the RPC requests are read into. If an exclusive instance
+ * is required, use the {@link #cloneToCell()} to have the contents of the cell copied to an
+ * exclusive memory area.
+ */
+@InterfaceAudience.Private
+public interface ShareableMemory {
+
+  /**
+   * Does a deep copy of the contents to a new memory area and returns it in the form of a cell.
+   * @return The deep cloned cell
+   */
+  Cell cloneToCell();
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/2df0ef54/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
index df2e740..5165f58 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
@@ -24,10 +24,13 @@ import java.nio.ByteBuffer;
 
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.KeyValueUtil;
 import org.apache.hadoop.hbase.NoTagsKeyValue;
+import org.apache.hadoop.hbase.ShareableMemory;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.util.ByteBufferUtils;
+import org.apache.hadoop.hbase.util.Bytes;
 
 /**
  * Codec that does KeyValue version 1 serialization.
@@ -99,7 +102,35 @@ public class KeyValueCodec implements Codec {
     }
 
     protected Cell createCell(byte[] buf, int offset, int len) {
-      return new NoTagsKeyValue(buf, offset, len);
+      return new ShareableMemoryNoTagsKeyValue(buf, offset, len);
+    }
+
+    static class ShareableMemoryKeyValue extends KeyValue implements ShareableMemory {
+      public ShareableMemoryKeyValue(byte[] bytes, int offset, int length) {
+        super(bytes, offset, length);
+      }
+
+      @Override
+      public Cell cloneToCell() {
+        byte[] copy = Bytes.copy(this.bytes, this.offset, this.length);
+        KeyValue kv = new KeyValue(copy, 0, copy.length);
+        kv.setSequenceId(this.getSequenceId());
+        return kv;
+      }
+    }
+
+    static class ShareableMemoryNoTagsKeyValue extends NoTagsKeyValue implements ShareableMemory {
+      public ShareableMemoryNoTagsKeyValue(byte[] bytes, int offset, int length) {
+        super(bytes, offset, length);
+      }
+
+      @Override
+      public Cell cloneToCell() {
+        byte[] copy = Bytes.copy(this.bytes, this.offset, this.length);
+        KeyValue kv = new NoTagsKeyValue(copy, 0, copy.length);
+        kv.setSequenceId(this.getSequenceId());
+        return kv;
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/2df0ef54/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodecWithTags.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodecWithTags.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodecWithTags.java
index 714cc38..8d2ee99 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodecWithTags.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodecWithTags.java
@@ -24,7 +24,6 @@ import java.nio.ByteBuffer;
 
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
-import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.KeyValueUtil;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 
@@ -85,7 +84,7 @@ public class KeyValueCodecWithTags implements Codec {
     }
 
     protected Cell createCell(byte[] buf, int offset, int len) {
-      return new KeyValue(buf, offset, len);
+      return new ShareableMemoryKeyValue(buf, offset, len);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/2df0ef54/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/AbstractMemStore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/AbstractMemStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/AbstractMemStore.java
index 2b9910f..4716eee 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/AbstractMemStore.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/AbstractMemStore.java
@@ -33,6 +33,7 @@ import org.apache.hadoop.hbase.CellComparator;
 import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.KeyValueUtil;
+import org.apache.hadoop.hbase.ShareableMemory;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.ClassSize;
@@ -110,9 +111,31 @@ public abstract class AbstractMemStore implements MemStore {
   public long add(Cell cell) {
     Cell toAdd = maybeCloneWithAllocator(cell);
     boolean mslabUsed = (toAdd != cell);
+    // This cell data is backed by the same byte[] where we read request in RPC(See HBASE-15180). By
+    // default MSLAB is ON and we might have copied cell to MSLAB area. If not we must do below deep
+    // copy. Or else we will keep referring to the bigger chunk of memory and prevent it from
+    // getting GCed.
+    // Copy to MSLAB would not have happened if
+    // 1. MSLAB is turned OFF. See "hbase.hregion.memstore.mslab.enabled"
+    // 2. When the size of the cell is bigger than the max size supported by MSLAB. See
+    // "hbase.hregion.memstore.mslab.max.allocation". This defaults to 256 KB
+    // 3. When cells are from Append/Increment operation.
+    if (!mslabUsed) {
+      toAdd = deepCopyIfNeeded(toAdd);
+    }
     return internalAdd(toAdd, mslabUsed);
   }
 
+  private static Cell deepCopyIfNeeded(Cell cell) {
+    // When Cell is backed by a shared memory chunk (this can be a chunk of memory where we read the
+    // req into) the Cell instance will be of type ShareableMemory. Later we will add feature to
+    // read the RPC request into pooled direct ByteBuffers.
+    if (cell instanceof ShareableMemory) {
+      return ((ShareableMemory) cell).cloneToCell();
+    }
+    return cell;
+  }
+
   /**
    * Update or insert the specified Cells.
    * <p>
@@ -156,10 +179,8 @@ public abstract class AbstractMemStore implements MemStore {
    */
   @Override
   public long delete(Cell deleteCell) {
-    Cell toAdd = maybeCloneWithAllocator(deleteCell);
-    boolean mslabUsed = (toAdd != deleteCell);
-    long s = internalAdd(toAdd, mslabUsed);
-    return s;
+    // Delete operation just adds the delete marker cell coming here.
+    return add(deleteCell);
   }
 
   /**
@@ -245,6 +266,10 @@ public abstract class AbstractMemStore implements MemStore {
     // hitting OOME - see TestMemStore.testUpsertMSLAB for a
     // test that triggers the pathological case if we don't avoid MSLAB
     // here.
+    // This cell data is backed by the same byte[] where we read request in RPC(See HBASE-15180). We
+    // must do below deep copy. Or else we will keep referring to the bigger chunk of memory and
+    // prevent it from getting GCed.
+    cell = deepCopyIfNeeded(cell);
     long addedSize = internalAdd(cell, false);
 
     // Get the Cells for the row/family/qualifier regardless of timestamp.