PHOENIX-7731: Add phoenix-hbase-compat module for HBase 2.6.4 (#2291)

diff --git a/phoenix-assembly/pom.xml b/phoenix-assembly/pom.xml
index d7a669e..ae52be7 100644
--- a/phoenix-assembly/pom.xml
+++ b/phoenix-assembly/pom.xml
@@ -252,6 +252,11 @@
           <artifactId>phoenix-hbase-compat-2.6.0</artifactId>
           <version>${project.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.apache.phoenix</groupId>
+          <artifactId>phoenix-hbase-compat-2.6.4</artifactId>
+          <version>${project.version}</version>
+        </dependency>
       </dependencies>
       <build>
         <plugins>
diff --git a/phoenix-core-client/pom.xml b/phoenix-core-client/pom.xml
index e67be38..6c6cea3 100644
--- a/phoenix-core-client/pom.xml
+++ b/phoenix-core-client/pom.xml
@@ -292,6 +292,9 @@
                     || ("${hbase.compat.version}".equals("2.6.0")
                       &amp;&amp; hbaseMinor == 6
                       &amp;&amp; hbasePatch &gt;=0)
+                    || ("${hbase.compat.version}".equals("2.6.4")
+                      &amp;&amp; hbaseMinor == 6
+                      &amp;&amp; hbasePatch &gt;=4)
                   )</condition>
             </evaluateBeanshell>
           </rules>
diff --git a/phoenix-core-server/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReader.java b/phoenix-core-server/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReader.java
index 338991e..cb78e9a 100644
--- a/phoenix-core-server/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReader.java
+++ b/phoenix-core-server/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReader.java
@@ -79,7 +79,7 @@
         ReaderType.STREAM),
       new HFileInfo(new ReaderContext(p, in, size, new HFileSystem(fs), primaryReplicaStoreFile,
         ReaderType.STREAM), conf),
-      p);
+      p, r);
     getHFileReader().getHFileInfo().initMetaAndIndex(getHFileReader());
     this.splitkey = splitKey == null ? r.getSplitKey() : splitKey;
     // Is it top or bottom half?
diff --git a/phoenix-hbase-compat-2.5.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java b/phoenix-hbase-compat-2.5.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
index 58225bd..7c08542 100644
--- a/phoenix-hbase-compat-2.5.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
+++ b/phoenix-hbase-compat-2.5.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
@@ -22,6 +22,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.io.Reference;
 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
 import org.apache.hadoop.hbase.io.hfile.HFileInfo;
 import org.apache.hadoop.hbase.io.hfile.ReaderContext;
@@ -30,8 +31,8 @@
 public class CompatIndexHalfStoreFileReader extends StoreFileReader {
 
   public CompatIndexHalfStoreFileReader(final FileSystem fs, final CacheConfig cacheConf,
-    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p)
-    throws IOException {
+    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p,
+    Reference r) throws IOException {
     super(readerContext, hFileInfo, cacheConf, new AtomicInteger(0), conf);
   }
 
diff --git a/phoenix-hbase-compat-2.5.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java b/phoenix-hbase-compat-2.5.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
index 58225bd..7c08542 100644
--- a/phoenix-hbase-compat-2.5.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
+++ b/phoenix-hbase-compat-2.5.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
@@ -22,6 +22,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.io.Reference;
 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
 import org.apache.hadoop.hbase.io.hfile.HFileInfo;
 import org.apache.hadoop.hbase.io.hfile.ReaderContext;
@@ -30,8 +31,8 @@
 public class CompatIndexHalfStoreFileReader extends StoreFileReader {
 
   public CompatIndexHalfStoreFileReader(final FileSystem fs, final CacheConfig cacheConf,
-    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p)
-    throws IOException {
+    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p,
+    Reference r) throws IOException {
     super(readerContext, hFileInfo, cacheConf, new AtomicInteger(0), conf);
   }
 
diff --git a/phoenix-hbase-compat-2.6.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java b/phoenix-hbase-compat-2.6.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
index ad39db4..74089af 100644
--- a/phoenix-hbase-compat-2.6.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
+++ b/phoenix-hbase-compat-2.6.0/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
@@ -21,6 +21,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.io.Reference;
 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
 import org.apache.hadoop.hbase.io.hfile.HFileInfo;
 import org.apache.hadoop.hbase.io.hfile.ReaderContext;
@@ -30,8 +31,8 @@
 public class CompatIndexHalfStoreFileReader extends StoreFileReader {
 
   public CompatIndexHalfStoreFileReader(final FileSystem fs, final CacheConfig cacheConf,
-    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p)
-    throws IOException {
+    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p,
+    Reference r) throws IOException {
     super(readerContext, hFileInfo, cacheConf, new StoreFileInfo(conf, fs, p, true), conf);
   }
 
diff --git a/phoenix-hbase-compat-2.6.4/pom.xml b/phoenix-hbase-compat-2.6.4/pom.xml
new file mode 100644
index 0000000..a194418
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.phoenix</groupId>
+    <artifactId>phoenix</artifactId>
+    <version>5.4.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>phoenix-hbase-compat-2.6.4</artifactId>
+  <name>Phoenix Hbase 2.6.4 compatibility</name>
+  <description>Compatibility module for HBase 2.6.4+</description>
+
+  <properties>
+    <hbase26.compat.version>2.6.4-hadoop3</hbase26.compat.version>
+  </properties>
+
+  <dependencies>
+    <!-- HBase dependencies -->
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-client</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-common</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-server</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Override parent dependencyManagement for transitive HBase dependencies -->
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-hadoop-compat</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-hadoop2-compat</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-protocol</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-protocol-shaded</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-zookeeper</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-metrics</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hbase</groupId>
+      <artifactId>hbase-metrics-api</artifactId>
+      <version>${hbase26.compat.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Build with -Dwithout.tephra fails without this -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/ByteStringer.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/ByteStringer.java
new file mode 100644
index 0000000..e8c3f2f
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/ByteStringer.java
@@ -0,0 +1,32 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import com.google.protobuf.ByteString;
+
+// This has different signature in the HBase 2 and 3 modules
+// This only comes together after the maven-replacer plugin relocates all protobuf code.
+public class ByteStringer {
+
+  private ByteStringer() {
+  }
+
+  public static ByteString wrap(final byte[] array) {
+    return org.apache.hadoop.hbase.util.ByteStringer.wrap(array);
+  }
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateFilter.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateFilter.java
new file mode 100644
index 0000000..c1fb96f
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateFilter.java
@@ -0,0 +1,37 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterBase;
+
+public class CompatDelegateFilter extends FilterBase {
+  protected Filter delegate = null;
+
+  public CompatDelegateFilter(Filter delegate) {
+    this.delegate = delegate;
+  }
+
+  @Override
+  public ReturnCode filterKeyValue(Cell v) throws IOException {
+    return delegate.filterKeyValue(v);
+  }
+
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateHTable.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateHTable.java
new file mode 100644
index 0000000..ed634aa
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatDelegateHTable.java
@@ -0,0 +1,141 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.hadoop.hbase.CompareOperator;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.RowMutations;
+import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+public abstract class CompatDelegateHTable implements Table {
+
+  protected final Table delegate;
+
+  public CompatDelegateHTable(Table delegate) {
+    this.delegate = delegate;
+  }
+
+  @Override
+  public HTableDescriptor getTableDescriptor() throws IOException {
+    return delegate.getTableDescriptor();
+  }
+
+  @Override
+  public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, Put put) throws IOException {
+    return delegate.checkAndPut(row, family, qualifier, compareOp, value, put);
+  }
+
+  @Override
+  public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, Delete delete) throws IOException {
+    return delegate.checkAndDelete(row, family, qualifier, compareOp, value, delete);
+  }
+
+  @Override
+  public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, RowMutations mutation) throws IOException {
+    return delegate.checkAndMutate(row, family, qualifier, compareOp, value, mutation);
+  }
+
+  @Override
+  public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put)
+    throws IOException {
+    return delegate.checkAndPut(row, family, qualifier, value, put);
+  }
+
+  @Override
+  public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value,
+    Delete delete) throws IOException {
+    return delegate.checkAndDelete(row, family, qualifier, value, delete);
+  }
+
+  @Override
+  public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOperator op,
+    byte[] value, Put put) throws IOException {
+    return delegate.checkAndPut(row, family, qualifier, op, value, put);
+  }
+
+  @Override
+  public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, CompareOperator op,
+    byte[] value, Delete delete) throws IOException {
+    return delegate.checkAndDelete(row, family, qualifier, op, value, delete);
+  }
+
+  @Override
+  public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareOperator op,
+    byte[] value, RowMutations mutation) throws IOException {
+    return delegate.checkAndMutate(row, family, qualifier, op, value, mutation);
+  }
+
+  @Override
+  public CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) {
+    return delegate.checkAndMutate(row, family);
+  }
+
+  @Override
+  public void setOperationTimeout(int operationTimeout) {
+    delegate.setOperationTimeout(operationTimeout);
+  }
+
+  @Override
+  public int getOperationTimeout() {
+    return delegate.getOperationTimeout();
+  }
+
+  @Override
+  public int getRpcTimeout() {
+    return delegate.getRpcTimeout();
+  }
+
+  @Override
+  public void setRpcTimeout(int rpcTimeout) {
+    delegate.setRpcTimeout(rpcTimeout);
+  }
+
+  @Override
+  public int getReadRpcTimeout() {
+    return delegate.getReadRpcTimeout();
+  }
+
+  @Override
+  public void setReadRpcTimeout(int readRpcTimeout) {
+    delegate.setReadRpcTimeout(readRpcTimeout);
+  }
+
+  @Override
+  public int getWriteRpcTimeout() {
+    return delegate.getWriteRpcTimeout();
+  }
+
+  @Override
+  public void setWriteRpcTimeout(int writeRpcTimeout) {
+    delegate.setWriteRpcTimeout(writeRpcTimeout);
+  }
+
+  @Override
+  public boolean[] existsAll(List<Get> gets) throws IOException {
+    return delegate.existsAll(gets);
+  }
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
new file mode 100644
index 0000000..293fafd
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexHalfStoreFileReader.java
@@ -0,0 +1,40 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.io.Reference;
+import org.apache.hadoop.hbase.io.hfile.CacheConfig;
+import org.apache.hadoop.hbase.io.hfile.HFileInfo;
+import org.apache.hadoop.hbase.io.hfile.ReaderContext;
+import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
+import org.apache.hadoop.hbase.regionserver.StoreFileReader;
+
+public class CompatIndexHalfStoreFileReader extends StoreFileReader {
+
+  public CompatIndexHalfStoreFileReader(final FileSystem fs, final CacheConfig cacheConf,
+    final Configuration conf, final ReaderContext readerContext, final HFileInfo hFileInfo, Path p,
+    Reference r) throws IOException {
+    super(readerContext, hFileInfo, cacheConf, new StoreFileInfo(conf, fs, fs.getFileStatus(p), r),
+      conf);
+  }
+
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexedHLogReader.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexedHLogReader.java
new file mode 100644
index 0000000..c23b0be
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatIndexedHLogReader.java
@@ -0,0 +1,24 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import org.apache.hadoop.hbase.regionserver.wal.ProtobufWALStreamReader;
+
+public abstract class CompatIndexedHLogReader extends ProtobufWALStreamReader {
+
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatLocalIndexStoreFileScanner.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatLocalIndexStoreFileScanner.java
new file mode 100644
index 0000000..62e328a
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatLocalIndexStoreFileScanner.java
@@ -0,0 +1,33 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
+import org.apache.hadoop.hbase.regionserver.StoreFileScanner;
+
+public class CompatLocalIndexStoreFileScanner extends StoreFileScanner {
+
+  public CompatLocalIndexStoreFileScanner(CompatIndexHalfStoreFileReader reader,
+    boolean cacheBlocks, boolean pread, boolean isCompaction, long readPt, long scannerOrder,
+    boolean canOptimizeForNonNullColumn) {
+    super(reader, reader.getScanner(cacheBlocks, pread, isCompaction), !isCompaction,
+      reader.getHFileReader().hasMVCCInfo(), readPt, scannerOrder, canOptimizeForNonNullColumn,
+      reader.getHFileReader().getDataBlockEncoding() == DataBlockEncoding.ROW_INDEX_V1);
+  }
+
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatOmidTransactionTable.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatOmidTransactionTable.java
new file mode 100644
index 0000000..03d12c8
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatOmidTransactionTable.java
@@ -0,0 +1,51 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.RowMutations;
+import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+public abstract class CompatOmidTransactionTable implements Table {
+
+  @Override
+  public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, Put put) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, Delete delete) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
+    byte[] value, RowMutations mutation) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPagingFilter.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPagingFilter.java
new file mode 100644
index 0000000..8410875
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPagingFilter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterBase;
+
+public abstract class CompatPagingFilter extends FilterBase {
+  protected Filter delegate = null;
+
+  public CompatPagingFilter(Filter delegate) {
+    this.delegate = delegate;
+  }
+
+  @Override
+  public ReturnCode filterKeyValue(Cell v) throws IOException {
+
+    if (delegate != null) {
+      return delegate.filterKeyValue(v);
+    }
+    return super.filterKeyValue(v);
+  }
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPhoenixRpcScheduler.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPhoenixRpcScheduler.java
new file mode 100644
index 0000000..a598433
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatPhoenixRpcScheduler.java
@@ -0,0 +1,56 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.ipc.CallRunner;
+import org.apache.hadoop.hbase.ipc.RpcScheduler;
+
+/**
+ * {@link RpcScheduler} that first checks to see if this is an index or metadata update before
+ * passing off the call to the delegate {@link RpcScheduler}.
+ */
+public abstract class CompatPhoenixRpcScheduler extends RpcScheduler {
+  protected RpcScheduler delegate;
+
+  @Override
+  public boolean dispatch(CallRunner task) {
+    try {
+      return compatDispatch(task);
+    } catch (Exception e) {
+      // This never happens with Hbase 2.5
+      throw new RuntimeException(e);
+    }
+  }
+
+  public int getActiveRpcHandlerCount() {
+    return delegate.getActiveRpcHandlerCount();
+  }
+
+  @Override
+  public int getActiveBulkLoadRpcHandlerCount() {
+    return delegate.getActiveBulkLoadRpcHandlerCount();
+  }
+
+  @Override
+  public int getBulkLoadQueueLength() {
+    return delegate.getBulkLoadQueueLength();
+  }
+
+  public abstract boolean compatDispatch(CallRunner task) throws IOException, InterruptedException;
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatUtil.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatUtil.java
new file mode 100644
index 0000000..38a940a
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/CompatUtil.java
@@ -0,0 +1,41 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.hadoop.hbase.MetaTableAccessor;
+import org.apache.hadoop.hbase.client.Connection;
+import org.apache.hadoop.hbase.client.RegionInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CompatUtil {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(CompatUtil.class);
+
+  private CompatUtil() {
+    // Not to be instantiated
+  }
+
+  public static List<RegionInfo> getMergeRegions(Connection conn, RegionInfo regionInfo)
+    throws IOException {
+    return MetaTableAccessor.getMergeRegions(conn, regionInfo);
+  }
+
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/HbaseCompatCapabilities.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/HbaseCompatCapabilities.java
new file mode 100644
index 0000000..ccd416a
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/HbaseCompatCapabilities.java
@@ -0,0 +1,23 @@
+/*
+ * 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.phoenix.compat.hbase;
+
+public class HbaseCompatCapabilities {
+  // Currently every supported HBase version has the same capabilities, so there is
+  // nothing in here.
+}
diff --git a/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/package-info.java b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/package-info.java
new file mode 100644
index 0000000..7c098f4
--- /dev/null
+++ b/phoenix-hbase-compat-2.6.4/src/main/java/org/apache/phoenix/compat/hbase/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * This package contains compatibility classes for bridging differences
+ * between different versions of HBase.
+ */
+package org.apache.phoenix.compat.hbase;
diff --git a/pom.xml b/pom.xml
index 293a1e5..bb8c26d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,6 +45,7 @@
   </licenses>
 
   <modules>
+    <module>phoenix-hbase-compat-2.6.4</module>
     <module>phoenix-hbase-compat-2.6.0</module>
     <module>phoenix-hbase-compat-2.5.4</module>
     <module>phoenix-hbase-compat-2.5.0</module>
@@ -78,7 +79,8 @@
     <hbase-2.5.4.runtime.version>2.5.10-hadoop3</hbase-2.5.4.runtime.version>
     <hbase-2.5.runtime.version>2.5.12-hadoop3</hbase-2.5.runtime.version>
     <hbase-2.6.0.runtime.version>2.6.1-hadoop3</hbase-2.6.0.runtime.version>
-    <hbase-2.6.runtime.version>2.6.3-hadoop3</hbase-2.6.runtime.version>
+    <hbase-2.6.3.runtime.version>2.6.3-hadoop3</hbase-2.6.3.runtime.version>
+    <hbase-2.6.runtime.version>2.6.4-hadoop3</hbase-2.6.runtime.version>
 
     <compileSource>1.8</compileSource>
     <maven.compiler.source>${compileSource}</maven.compiler.source>
@@ -270,6 +272,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.phoenix</groupId>
+        <artifactId>phoenix-client-embedded-hbase-2.6.3</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.phoenix</groupId>
         <artifactId>phoenix-client-lite-hbase-2.5.4</artifactId>
         <version>${project.version}</version>
       </dependency>
@@ -290,6 +297,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.phoenix</groupId>
+        <artifactId>phoenix-client-lite-hbase-2.6.3</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.phoenix</groupId>
         <artifactId>phoenix-client-lite-hbase-2.6</artifactId>
         <version>${project.version}</version>
       </dependency>
@@ -315,6 +327,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.phoenix</groupId>
+        <artifactId>phoenix-server-hbase-2.6.3</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.phoenix</groupId>
         <artifactId>phoenix-server-hbase-2.6</artifactId>
         <version>${project.version}</version>
       </dependency>
@@ -345,6 +362,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.phoenix</groupId>
+        <artifactId>phoenix-mapreduce-byo-shaded-hbase-hbase-2.6.3</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.phoenix</groupId>
         <artifactId>phoenix-pherf</artifactId>
         <version>${project.version}</version>
       </dependency>
@@ -373,6 +395,11 @@
         <artifactId>phoenix-hbase-compat-2.6.0</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.phoenix</groupId>
+        <artifactId>phoenix-hbase-compat-2.6.4</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <!-- Intra-project test dependencies -->
       <dependency>
         <groupId>org.apache.phoenix</groupId>
@@ -2179,7 +2206,7 @@
     </profile>
     <profile>
       <!-- This WILL work with the public -hadoop3 artifacts -->
-      <id>phoenix-hbase-compat-2.6.2</id>
+      <id>phoenix-hbase-compat-2.6.4</id>
       <activation>
         <property>
           <name>hbase.profile</name>
@@ -2188,13 +2215,27 @@
       </activation>
       <properties>
         <hbase.profile>2.6</hbase.profile>
-        <!-- Same compat version as 2.6.0, but different Hadoop version -->
-        <hbase.compat.version>2.6.0</hbase.compat.version>
+        <hbase.compat.version>2.6.4</hbase.compat.version>
         <hbase.version>${hbase-2.6.runtime.version}</hbase.version>
       </properties>
     </profile>
     <profile>
       <!-- This WILL work with the public -hadoop3 artifacts -->
+      <id>phoenix-hbase-compat-2.6.3</id>
+      <activation>
+        <property>
+          <name>hbase.profile</name>
+          <value>2.6.3</value>
+        </property>
+      </activation>
+      <properties>
+        <hbase.profile>2.6.3</hbase.profile>
+        <hbase.compat.version>2.6.0</hbase.compat.version>
+        <hbase.version>${hbase-2.6.3.runtime.version}</hbase.version>
+      </properties>
+    </profile>
+    <profile>
+      <!-- This WILL work with the public -hadoop3 artifacts -->
       <id>phoenix-hbase-compat-2.6.0</id>
       <activation>
         <property>