diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java index 9162962..c792a6c 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java @@ -1652,6 +1652,16 @@ public final class CellUtil { } } + public static Cell deepCopy(Cell cell) { + // TODO, when we add ExtendedCell, it will have clone method and we can ask cell to clone. + int len = KeyValueUtil.length(cell); + byte[] b = new byte[len]; + KeyValueUtil.appendToByteArray(cell, b, 0); + KeyValue newKv = new KeyValue(b, 0, len); + newKv.setSequenceId(cell.getSequenceId()); + return newKv; + } + @InterfaceAudience.Private /** * These cells are used in reseeks/seeks to improve the read performance. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java index adb101e..e2d0d41 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java @@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; import org.apache.hadoop.hbase.Cell; 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.classification.InterfaceAudience; @@ -251,6 +252,18 @@ public abstract class Segment { } protected long internalAdd(Cell cell, boolean useMSLAB) { + // 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 (!useMSLAB) { + cell = CellUtil.deepCopy(cell); + } boolean succ = getCellSet().add(cell); long s = AbstractMemStore.heapSizeChange(cell, succ); // If there's already a same cell in the CellSet and we are using MSLAB, we must count in the