You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by vj...@apache.org on 2020/04/16 14:09:46 UTC

[hbase] branch branch-1 updated: HBASE-24194 : Refactor anonymous inner classes of BufferedEncodedSeeker to named inner classes (#1522)

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

vjasani pushed a commit to branch branch-1
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-1 by this push:
     new d4b64c2  HBASE-24194 : Refactor anonymous inner classes of BufferedEncodedSeeker to named inner classes (#1522)
d4b64c2 is described below

commit d4b64c2545b2dbf14f779bfff3c8d63552236049
Author: Viraj Jasani <vj...@apache.org>
AuthorDate: Thu Apr 16 19:34:42 2020 +0530

    HBASE-24194 : Refactor anonymous inner classes of BufferedEncodedSeeker to named inner classes (#1522)
    
    Signed-off-by: Peter Somogyi <ps...@apache.org>
    Signed-off-by: binlijin <bi...@gmail.com>
---
 .../hbase/io/encoding/CopyKeyDataBlockEncoder.java |  67 +++---
 .../hbase/io/encoding/DiffKeyDeltaEncoder.java     | 261 +++++++++++----------
 .../hbase/io/encoding/FastDiffDeltaEncoder.java    | 239 ++++++++++---------
 .../hbase/io/encoding/PrefixKeyDeltaEncoder.java   |  65 ++---
 4 files changed, 334 insertions(+), 298 deletions(-)

diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/CopyKeyDataBlockEncoder.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/CopyKeyDataBlockEncoder.java
index 8941345..5d27f08 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/CopyKeyDataBlockEncoder.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/CopyKeyDataBlockEncoder.java
@@ -84,35 +84,7 @@ public class CopyKeyDataBlockEncoder extends BufferedDataBlockEncoder {
   @Override
   public EncodedSeeker createSeeker(KVComparator comparator,
       final HFileBlockDecodingContext decodingCtx) {
-    return new BufferedEncodedSeeker<SeekerState>(comparator, decodingCtx) {
-      @Override
-      protected void decodeNext() {
-        current.keyLength = currentBuffer.getInt();
-        current.valueLength = currentBuffer.getInt();
-        current.ensureSpaceForKey();
-        currentBuffer.get(current.keyBuffer, 0, current.keyLength);
-        current.valueOffset = currentBuffer.position();
-        ByteBufferUtils.skip(currentBuffer, current.valueLength);
-        if (includesTags()) {
-          // Read short as unsigned, high byte first
-          current.tagsLength = ((currentBuffer.get() & 0xff) << 8) ^ (currentBuffer.get() & 0xff);
-          ByteBufferUtils.skip(currentBuffer, current.tagsLength);
-        }
-        if (includesMvcc()) {
-          current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
-        } else {
-          current.memstoreTS = 0;
-        }
-        current.nextKvOffset = currentBuffer.position();
-      }
-
-      @Override
-      protected void decodeFirst() {
-        ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
-        current.lastCommonPrefix = 0;
-        decodeNext();
-      }
-    };
+    return new SeekerStateBufferedEncodedSeeker(comparator, decodingCtx);
   }
 
   @Override
@@ -126,4 +98,41 @@ public class CopyKeyDataBlockEncoder extends BufferedDataBlockEncoder {
 
     return buffer;
   }
+
+  private static class SeekerStateBufferedEncodedSeeker
+      extends BufferedEncodedSeeker<SeekerState> {
+
+    public SeekerStateBufferedEncodedSeeker(KVComparator comparator,
+      HFileBlockDecodingContext decodingCtx) {
+      super(comparator, decodingCtx);
+    }
+
+    @Override
+    protected void decodeNext() {
+      current.keyLength = currentBuffer.getInt();
+      current.valueLength = currentBuffer.getInt();
+      current.ensureSpaceForKey();
+      currentBuffer.get(current.keyBuffer, 0, current.keyLength);
+      current.valueOffset = currentBuffer.position();
+      ByteBufferUtils.skip(currentBuffer, current.valueLength);
+      if (includesTags()) {
+        // Read short as unsigned, high byte first
+        current.tagsLength = ((currentBuffer.get() & 0xff) << 8) ^ (currentBuffer.get() & 0xff);
+        ByteBufferUtils.skip(currentBuffer, current.tagsLength);
+      }
+      if (includesMvcc()) {
+        current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
+      } else {
+        current.memstoreTS = 0;
+      }
+      current.nextKvOffset = currentBuffer.position();
+    }
+
+    @Override
+    protected void decodeFirst() {
+      ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
+      current.lastCommonPrefix = 0;
+      decodeNext();
+    }
+  }
 }
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/DiffKeyDeltaEncoder.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/DiffKeyDeltaEncoder.java
index f28100d..0cc1bc0 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/DiffKeyDeltaEncoder.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/DiffKeyDeltaEncoder.java
@@ -378,132 +378,7 @@ public class DiffKeyDeltaEncoder extends BufferedDataBlockEncoder {
   @Override
   public EncodedSeeker createSeeker(KVComparator comparator,
       HFileBlockDecodingContext decodingCtx) {
-    return new BufferedEncodedSeeker<DiffSeekerState>(comparator, decodingCtx) {
-      private byte[] familyNameWithSize;
-      private static final int TIMESTAMP_WITH_TYPE_LENGTH =
-          Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE;
-
-      private void decode(boolean isFirst) {
-        byte flag = currentBuffer.get();
-        byte type = 0;
-        if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
-          if (!isFirst) {
-            type = current.keyBuffer[current.keyLength - Bytes.SIZEOF_BYTE];
-          }
-          current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
-        }
-        if ((flag & FLAG_SAME_VALUE_LENGTH) == 0) {
-          current.valueLength =
-              ByteBufferUtils.readCompressedInt(currentBuffer);
-        }
-        current.lastCommonPrefix =
-            ByteBufferUtils.readCompressedInt(currentBuffer);
-
-        current.ensureSpaceForKey();
-
-        if (current.lastCommonPrefix < Bytes.SIZEOF_SHORT) {
-          // length of row is different, copy everything except family
-
-          // copy the row size
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              Bytes.SIZEOF_SHORT - current.lastCommonPrefix);
-          current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
-              Bytes.SIZEOF_SHORT;
-
-          // copy the rest of row
-          currentBuffer.get(current.keyBuffer, Bytes.SIZEOF_SHORT,
-              current.rowLengthWithSize - Bytes.SIZEOF_SHORT);
-
-          // copy the column family
-          System.arraycopy(familyNameWithSize, 0, current.keyBuffer,
-              current.rowLengthWithSize, familyNameWithSize.length);
-
-          // copy the qualifier
-          currentBuffer.get(current.keyBuffer,
-              current.rowLengthWithSize + familyNameWithSize.length,
-              current.keyLength - current.rowLengthWithSize -
-              familyNameWithSize.length - TIMESTAMP_WITH_TYPE_LENGTH);
-        } else if (current.lastCommonPrefix < current.rowLengthWithSize) {
-          // we have to copy part of row and qualifier,
-          // but column family is in right place
-
-          // before column family (rest of row)
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              current.rowLengthWithSize - current.lastCommonPrefix);
-
-          // after column family (qualifier)
-          currentBuffer.get(current.keyBuffer,
-              current.rowLengthWithSize + familyNameWithSize.length,
-              current.keyLength - current.rowLengthWithSize -
-              familyNameWithSize.length - TIMESTAMP_WITH_TYPE_LENGTH);
-        } else {
-          // copy just the ending
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              current.keyLength - TIMESTAMP_WITH_TYPE_LENGTH -
-              current.lastCommonPrefix);
-        }
-
-        // timestamp
-        int pos = current.keyLength - TIMESTAMP_WITH_TYPE_LENGTH;
-        int timestampFitInBytes = 1 +
-            ((flag & MASK_TIMESTAMP_LENGTH) >>> SHIFT_TIMESTAMP_LENGTH);
-        long timestampOrDiff =
-            ByteBufferUtils.readLong(currentBuffer, timestampFitInBytes);
-        if ((flag & FLAG_TIMESTAMP_SIGN) != 0) {
-          timestampOrDiff = -timestampOrDiff;
-        }
-        if ((flag & FLAG_TIMESTAMP_IS_DIFF) == 0) { // it is timestamp
-          current.timestamp = timestampOrDiff;
-        } else { // it is diff
-          current.timestamp = current.timestamp - timestampOrDiff;
-        }
-        Bytes.putLong(current.keyBuffer, pos, current.timestamp);
-        pos += Bytes.SIZEOF_LONG;
-
-        // type
-        if ((flag & FLAG_SAME_TYPE) == 0) {
-          currentBuffer.get(current.keyBuffer, pos, Bytes.SIZEOF_BYTE);
-        } else if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
-          current.keyBuffer[pos] = type;
-        }
-
-        current.valueOffset = currentBuffer.position();
-        ByteBufferUtils.skip(currentBuffer, current.valueLength);
-
-        if (includesTags()) {
-          decodeTags();
-        }
-        if (includesMvcc()) {
-          current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
-        } else {
-          current.memstoreTS = 0;
-        }
-        current.nextKvOffset = currentBuffer.position();
-      }
-
-      @Override
-      protected void decodeFirst() {
-        ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
-
-        // read column family
-        byte familyNameLength = currentBuffer.get();
-        familyNameWithSize = new byte[familyNameLength + Bytes.SIZEOF_BYTE];
-        familyNameWithSize[0] = familyNameLength;
-        currentBuffer.get(familyNameWithSize, Bytes.SIZEOF_BYTE,
-            familyNameLength);
-        decode(true);
-      }
-
-      @Override
-      protected void decodeNext() {
-        decode(false);
-      }
-
-      @Override
-      protected DiffSeekerState createSeekerState() {
-        return new DiffSeekerState();
-      }
-    };
+    return new DiffSeekerStateBufferedEncodedSeeker(comparator, decodingCtx);
   }
 
   @Override
@@ -525,4 +400,138 @@ public class DiffKeyDeltaEncoder extends BufferedDataBlockEncoder {
 
     return buffer;
   }
+
+  private static class DiffSeekerStateBufferedEncodedSeeker
+      extends BufferedEncodedSeeker<DiffSeekerState> {
+
+    private byte[] familyNameWithSize;
+    private static final int TIMESTAMP_WITH_TYPE_LENGTH =
+        Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE;
+
+    private DiffSeekerStateBufferedEncodedSeeker(KVComparator comparator,
+      HFileBlockDecodingContext decodingCtx) {
+      super(comparator, decodingCtx);
+    }
+
+    private void decode(boolean isFirst) {
+      byte flag = currentBuffer.get();
+      byte type = 0;
+      if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
+        if (!isFirst) {
+          type = current.keyBuffer[current.keyLength - Bytes.SIZEOF_BYTE];
+        }
+        current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
+      }
+      if ((flag & FLAG_SAME_VALUE_LENGTH) == 0) {
+        current.valueLength =
+            ByteBufferUtils.readCompressedInt(currentBuffer);
+      }
+      current.lastCommonPrefix =
+          ByteBufferUtils.readCompressedInt(currentBuffer);
+
+      current.ensureSpaceForKey();
+
+      if (current.lastCommonPrefix < Bytes.SIZEOF_SHORT) {
+        // length of row is different, copy everything except family
+
+        // copy the row size
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            Bytes.SIZEOF_SHORT - current.lastCommonPrefix);
+        current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
+            Bytes.SIZEOF_SHORT;
+
+        // copy the rest of row
+        currentBuffer.get(current.keyBuffer, Bytes.SIZEOF_SHORT,
+            current.rowLengthWithSize - Bytes.SIZEOF_SHORT);
+
+        // copy the column family
+        System.arraycopy(familyNameWithSize, 0, current.keyBuffer,
+            current.rowLengthWithSize, familyNameWithSize.length);
+
+        // copy the qualifier
+        currentBuffer.get(current.keyBuffer,
+            current.rowLengthWithSize + familyNameWithSize.length,
+            current.keyLength - current.rowLengthWithSize -
+            familyNameWithSize.length - TIMESTAMP_WITH_TYPE_LENGTH);
+      } else if (current.lastCommonPrefix < current.rowLengthWithSize) {
+        // we have to copy part of row and qualifier,
+        // but column family is in right place
+
+        // before column family (rest of row)
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            current.rowLengthWithSize - current.lastCommonPrefix);
+
+        // after column family (qualifier)
+        currentBuffer.get(current.keyBuffer,
+            current.rowLengthWithSize + familyNameWithSize.length,
+            current.keyLength - current.rowLengthWithSize -
+            familyNameWithSize.length - TIMESTAMP_WITH_TYPE_LENGTH);
+      } else {
+        // copy just the ending
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            current.keyLength - TIMESTAMP_WITH_TYPE_LENGTH -
+            current.lastCommonPrefix);
+      }
+
+      // timestamp
+      int pos = current.keyLength - TIMESTAMP_WITH_TYPE_LENGTH;
+      int timestampFitInBytes = 1 +
+          ((flag & MASK_TIMESTAMP_LENGTH) >>> SHIFT_TIMESTAMP_LENGTH);
+      long timestampOrDiff =
+          ByteBufferUtils.readLong(currentBuffer, timestampFitInBytes);
+      if ((flag & FLAG_TIMESTAMP_SIGN) != 0) {
+        timestampOrDiff = -timestampOrDiff;
+      }
+      if ((flag & FLAG_TIMESTAMP_IS_DIFF) == 0) { // it is timestamp
+        current.timestamp = timestampOrDiff;
+      } else { // it is diff
+        current.timestamp = current.timestamp - timestampOrDiff;
+      }
+      Bytes.putLong(current.keyBuffer, pos, current.timestamp);
+      pos += Bytes.SIZEOF_LONG;
+
+      // type
+      if ((flag & FLAG_SAME_TYPE) == 0) {
+        currentBuffer.get(current.keyBuffer, pos, Bytes.SIZEOF_BYTE);
+      } else if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
+        current.keyBuffer[pos] = type;
+      }
+
+      current.valueOffset = currentBuffer.position();
+      ByteBufferUtils.skip(currentBuffer, current.valueLength);
+
+      if (includesTags()) {
+        decodeTags();
+      }
+      if (includesMvcc()) {
+        current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
+      } else {
+        current.memstoreTS = 0;
+      }
+      current.nextKvOffset = currentBuffer.position();
+    }
+
+    @Override
+    protected void decodeFirst() {
+      ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
+
+      // read column family
+      byte familyNameLength = currentBuffer.get();
+      familyNameWithSize = new byte[familyNameLength + Bytes.SIZEOF_BYTE];
+      familyNameWithSize[0] = familyNameLength;
+      currentBuffer.get(familyNameWithSize, Bytes.SIZEOF_BYTE,
+          familyNameLength);
+      decode(true);
+    }
+
+    @Override
+    protected void decodeNext() {
+      decode(false);
+    }
+
+    @Override
+    protected DiffSeekerState createSeekerState() {
+      return new DiffSeekerState();
+    }
+  }
 }
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/FastDiffDeltaEncoder.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/FastDiffDeltaEncoder.java
index 72b6a5c..468ab6b 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/FastDiffDeltaEncoder.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/FastDiffDeltaEncoder.java
@@ -398,132 +398,141 @@ public class FastDiffDeltaEncoder extends BufferedDataBlockEncoder {
   @Override
   public EncodedSeeker createSeeker(KVComparator comparator,
       final HFileBlockDecodingContext decodingCtx) {
-    return new BufferedEncodedSeeker<FastDiffSeekerState>(comparator, decodingCtx) {
-      private void decode(boolean isFirst) {
-        byte flag = currentBuffer.get();
-        if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
-          if (!isFirst) {
-            System.arraycopy(current.keyBuffer,
-                current.keyLength - current.prevTimestampAndType.length,
-                current.prevTimestampAndType, 0,
-                current.prevTimestampAndType.length);
-          }
-          current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
-        }
-        if ((flag & FLAG_SAME_VALUE_LENGTH) == 0) {
-          current.valueLength =
-              ByteBufferUtils.readCompressedInt(currentBuffer);
-        }
-        current.lastCommonPrefix =
-            ByteBufferUtils.readCompressedInt(currentBuffer);
+    return new FastDiffSeekerStateBufferedEncodedSeeker(comparator, decodingCtx);
+  }
 
-        current.ensureSpaceForKey();
-
-        if (isFirst) {
-          // copy everything
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              current.keyLength - current.prevTimestampAndType.length);
-          current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
-              Bytes.SIZEOF_SHORT;
-          current.familyLengthWithSize =
-              current.keyBuffer[current.rowLengthWithSize] + Bytes.SIZEOF_BYTE;
-        } else if (current.lastCommonPrefix < Bytes.SIZEOF_SHORT) {
-          // length of row is different, copy everything except family
-
-          // copy the row size
-          int oldRowLengthWithSize = current.rowLengthWithSize;
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              Bytes.SIZEOF_SHORT - current.lastCommonPrefix);
-          current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
-              Bytes.SIZEOF_SHORT;
-
-          // move the column family
-          System.arraycopy(current.keyBuffer, oldRowLengthWithSize,
-              current.keyBuffer, current.rowLengthWithSize,
-              current.familyLengthWithSize);
-
-          // copy the rest of row
-          currentBuffer.get(current.keyBuffer, Bytes.SIZEOF_SHORT,
-              current.rowLengthWithSize - Bytes.SIZEOF_SHORT);
-
-          // copy the qualifier
-          currentBuffer.get(current.keyBuffer, current.rowLengthWithSize
-              + current.familyLengthWithSize, current.keyLength
-              - current.rowLengthWithSize - current.familyLengthWithSize
-              - current.prevTimestampAndType.length);
-        } else if (current.lastCommonPrefix < current.rowLengthWithSize) {
-          // We have to copy part of row and qualifier, but the column family
-          // is in the right place.
-
-          // before column family (rest of row)
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              current.rowLengthWithSize - current.lastCommonPrefix);
-
-          // after column family (qualifier)
-          currentBuffer.get(current.keyBuffer, current.rowLengthWithSize
-              + current.familyLengthWithSize, current.keyLength
-              - current.rowLengthWithSize - current.familyLengthWithSize
-              - current.prevTimestampAndType.length);
-        } else {
-          // copy just the ending
-          currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-              current.keyLength - current.prevTimestampAndType.length
-                  - current.lastCommonPrefix);
-        }
+  private class FastDiffSeekerStateBufferedEncodedSeeker
+      extends BufferedEncodedSeeker<FastDiffSeekerState> {
 
-        // timestamp
-        int pos = current.keyLength - current.prevTimestampAndType.length;
-        int commonTimestampPrefix = (flag & MASK_TIMESTAMP_LENGTH) >>>
-          SHIFT_TIMESTAMP_LENGTH;
-        if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
-          System.arraycopy(current.prevTimestampAndType, 0, current.keyBuffer,
-              pos, commonTimestampPrefix);
-        }
-        pos += commonTimestampPrefix;
-        currentBuffer.get(current.keyBuffer, pos,
-            Bytes.SIZEOF_LONG - commonTimestampPrefix);
-        pos += Bytes.SIZEOF_LONG - commonTimestampPrefix;
-
-        // type
-        if ((flag & FLAG_SAME_TYPE) == 0) {
-          currentBuffer.get(current.keyBuffer, pos, Bytes.SIZEOF_BYTE);
-        } else if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
-          current.keyBuffer[pos] =
-              current.prevTimestampAndType[Bytes.SIZEOF_LONG];
-        }
+    private FastDiffSeekerStateBufferedEncodedSeeker(KVComparator comparator,
+      HFileBlockDecodingContext decodingCtx) {
+      super(comparator, decodingCtx);
+    }
 
-        // handle value
-        if ((flag & FLAG_SAME_VALUE) == 0) {
-          current.valueOffset = currentBuffer.position();
-          ByteBufferUtils.skip(currentBuffer, current.valueLength);
+    private void decode(boolean isFirst) {
+      byte flag = currentBuffer.get();
+      if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
+        if (!isFirst) {
+          System.arraycopy(current.keyBuffer,
+              current.keyLength - current.prevTimestampAndType.length,
+              current.prevTimestampAndType, 0,
+              current.prevTimestampAndType.length);
         }
+        current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
+      }
+      if ((flag & FLAG_SAME_VALUE_LENGTH) == 0) {
+        current.valueLength =
+            ByteBufferUtils.readCompressedInt(currentBuffer);
+      }
+      current.lastCommonPrefix =
+          ByteBufferUtils.readCompressedInt(currentBuffer);
+
+      current.ensureSpaceForKey();
+
+      if (isFirst) {
+        // copy everything
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            current.keyLength - current.prevTimestampAndType.length);
+        current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
+            Bytes.SIZEOF_SHORT;
+        current.familyLengthWithSize =
+            current.keyBuffer[current.rowLengthWithSize] + Bytes.SIZEOF_BYTE;
+      } else if (current.lastCommonPrefix < Bytes.SIZEOF_SHORT) {
+        // length of row is different, copy everything except family
+
+        // copy the row size
+        int oldRowLengthWithSize = current.rowLengthWithSize;
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            Bytes.SIZEOF_SHORT - current.lastCommonPrefix);
+        current.rowLengthWithSize = Bytes.toShort(current.keyBuffer, 0) +
+            Bytes.SIZEOF_SHORT;
+
+        // move the column family
+        System.arraycopy(current.keyBuffer, oldRowLengthWithSize,
+            current.keyBuffer, current.rowLengthWithSize,
+            current.familyLengthWithSize);
 
-        if (includesTags()) {
-          decodeTags();
-        }
-        if (includesMvcc()) {
-          current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
-        } else {
-          current.memstoreTS = 0;
-        }
-        current.nextKvOffset = currentBuffer.position();
+        // copy the rest of row
+        currentBuffer.get(current.keyBuffer, Bytes.SIZEOF_SHORT,
+            current.rowLengthWithSize - Bytes.SIZEOF_SHORT);
+
+        // copy the qualifier
+        currentBuffer.get(current.keyBuffer, current.rowLengthWithSize
+            + current.familyLengthWithSize, current.keyLength
+            - current.rowLengthWithSize - current.familyLengthWithSize
+            - current.prevTimestampAndType.length);
+      } else if (current.lastCommonPrefix < current.rowLengthWithSize) {
+        // We have to copy part of row and qualifier, but the column family
+        // is in the right place.
+
+        // before column family (rest of row)
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            current.rowLengthWithSize - current.lastCommonPrefix);
+
+        // after column family (qualifier)
+        currentBuffer.get(current.keyBuffer, current.rowLengthWithSize
+            + current.familyLengthWithSize, current.keyLength
+            - current.rowLengthWithSize - current.familyLengthWithSize
+            - current.prevTimestampAndType.length);
+      } else {
+        // copy just the ending
+        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+            current.keyLength - current.prevTimestampAndType.length
+                - current.lastCommonPrefix);
       }
 
-      @Override
-      protected void decodeFirst() {
-        ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
-        decode(true);
+      // timestamp
+      int pos = current.keyLength - current.prevTimestampAndType.length;
+      int commonTimestampPrefix = (flag & MASK_TIMESTAMP_LENGTH) >>>
+        SHIFT_TIMESTAMP_LENGTH;
+      if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
+        System.arraycopy(current.prevTimestampAndType, 0, current.keyBuffer,
+            pos, commonTimestampPrefix);
       }
+      pos += commonTimestampPrefix;
+      currentBuffer.get(current.keyBuffer, pos,
+          Bytes.SIZEOF_LONG - commonTimestampPrefix);
+      pos += Bytes.SIZEOF_LONG - commonTimestampPrefix;
 
-      @Override
-      protected void decodeNext() {
-        decode(false);
+      // type
+      if ((flag & FLAG_SAME_TYPE) == 0) {
+        currentBuffer.get(current.keyBuffer, pos, Bytes.SIZEOF_BYTE);
+      } else if ((flag & FLAG_SAME_KEY_LENGTH) == 0) {
+        current.keyBuffer[pos] =
+            current.prevTimestampAndType[Bytes.SIZEOF_LONG];
       }
 
-      @Override
-      protected FastDiffSeekerState createSeekerState() {
-        return new FastDiffSeekerState();
+      // handle value
+      if ((flag & FLAG_SAME_VALUE) == 0) {
+        current.valueOffset = currentBuffer.position();
+        ByteBufferUtils.skip(currentBuffer, current.valueLength);
       }
-    };
+
+      if (includesTags()) {
+        decodeTags();
+      }
+      if (includesMvcc()) {
+        current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
+      } else {
+        current.memstoreTS = 0;
+      }
+      current.nextKvOffset = currentBuffer.position();
+    }
+
+    @Override
+    protected void decodeFirst() {
+      ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
+      decode(true);
+    }
+
+    @Override
+    protected void decodeNext() {
+      decode(false);
+    }
+
+    @Override
+    protected FastDiffSeekerState createSeekerState() {
+      return new FastDiffSeekerState();
+    }
   }
 }
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/PrefixKeyDeltaEncoder.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/PrefixKeyDeltaEncoder.java
index 8c17102..33f160f 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/PrefixKeyDeltaEncoder.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/PrefixKeyDeltaEncoder.java
@@ -198,35 +198,44 @@ public class PrefixKeyDeltaEncoder extends BufferedDataBlockEncoder {
   @Override
   public EncodedSeeker createSeeker(KVComparator comparator,
       final HFileBlockDecodingContext decodingCtx) {
-    return new BufferedEncodedSeeker<SeekerState>(comparator, decodingCtx) {
-      @Override
-      protected void decodeNext() {
-        current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
-        current.valueLength = ByteBufferUtils.readCompressedInt(currentBuffer);
-        current.lastCommonPrefix =
-            ByteBufferUtils.readCompressedInt(currentBuffer);
-        current.keyLength += current.lastCommonPrefix;
-        current.ensureSpaceForKey();
-        currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
-            current.keyLength - current.lastCommonPrefix);
-        current.valueOffset = currentBuffer.position();
-        ByteBufferUtils.skip(currentBuffer, current.valueLength);
-        if (includesTags()) {
-          decodeTags();
-        }
-        if (includesMvcc()) {
-          current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
-        } else {
-          current.memstoreTS = 0;
-        }
-        current.nextKvOffset = currentBuffer.position();
-      }
+    return new SeekerStateBufferedEncodedSeeker(comparator, decodingCtx);
+  }
+
+  private static class SeekerStateBufferedEncodedSeeker
+      extends BufferedEncodedSeeker<SeekerState> {
+
+    private SeekerStateBufferedEncodedSeeker(KVComparator comparator,
+      HFileBlockDecodingContext decodingCtx) {
+      super(comparator, decodingCtx);
+    }
 
-      @Override
-      protected void decodeFirst() {
-        ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
-        decodeNext();
+    @Override
+    protected void decodeNext() {
+      current.keyLength = ByteBufferUtils.readCompressedInt(currentBuffer);
+      current.valueLength = ByteBufferUtils.readCompressedInt(currentBuffer);
+      current.lastCommonPrefix =
+          ByteBufferUtils.readCompressedInt(currentBuffer);
+      current.keyLength += current.lastCommonPrefix;
+      current.ensureSpaceForKey();
+      currentBuffer.get(current.keyBuffer, current.lastCommonPrefix,
+          current.keyLength - current.lastCommonPrefix);
+      current.valueOffset = currentBuffer.position();
+      ByteBufferUtils.skip(currentBuffer, current.valueLength);
+      if (includesTags()) {
+        decodeTags();
+      }
+      if (includesMvcc()) {
+        current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer);
+      } else {
+        current.memstoreTS = 0;
       }
-    };
+      current.nextKvOffset = currentBuffer.position();
+    }
+
+    @Override
+    protected void decodeFirst() {
+      ByteBufferUtils.skip(currentBuffer, Bytes.SIZEOF_INT);
+      decodeNext();
+    }
   }
 }