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

richardantal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/master by this push:
     new 27d6b1b251 PHOENIX-7474 Migrate IndexTool tables and make sure they 
are created (#2031)
27d6b1b251 is described below

commit 27d6b1b251b2ea771b75f4b6d992e8fae97ec50d
Author: richardantal <[email protected]>
AuthorDate: Thu Jan 29 09:43:58 2026 +0100

    PHOENIX-7474 Migrate IndexTool tables and make sure they are created (#2031)
---
 .../mapreduce/index/IndexToolTableUtil.java        | 168 +++++++++++
 .../phoenix/query/ConnectionQueryServicesImpl.java |  14 +
 .../apache/phoenix/mapreduce/index/IndexTool.java  |  12 +
 .../index/IndexVerificationOutputRepository.java   |  41 +--
 .../index/IndexVerificationResultRepository.java   |  49 +--
 .../phoenix/end2end/AsyncIndexPermissionIT.java    | 331 +++++++++++++++++++++
 .../apache/phoenix/end2end/BasePermissionsIT.java  |   8 +-
 .../org/apache/phoenix/end2end/IndexToolIT.java    |  48 ++-
 .../end2end/LoadSystemTableSnapshotBase.java       |  37 +--
 .../MigrateSystemTablesToSystemNamespaceIT.java    |  19 +-
 .../end2end/SkipSystemTablesExistenceCheckIT.java  |   3 +-
 .../SystemTablesCreationOnConnectionIT.java        |  12 +-
 .../phoenix/end2end/UpgradeIndexToolTablesIT.java  |  99 ++++++
 ...eIndexToolTablesNameSpaceMappingDisabledIT.java |  31 ++
 .../indexToolsnapshot.tar.gz                       | Bin 0 -> 20480 bytes
 15 files changed, 761 insertions(+), 111 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/mapreduce/index/IndexToolTableUtil.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/mapreduce/index/IndexToolTableUtil.java
new file mode 100644
index 0000000000..fd03a5c18e
--- /dev/null
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/mapreduce/index/IndexToolTableUtil.java
@@ -0,0 +1,168 @@
+/*
+ * 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.mapreduce.index;
+
+
+
+import java.io.IOException;
+import java.sql.Connection;
+
+import java.sql.SQLException;
+import java.util.UUID;
+
+
+import org.apache.hadoop.hbase.NamespaceDescriptor;
+import 
org.apache.phoenix.thirdparty.com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.hbase.TableExistsException;
+import org.apache.hadoop.hbase.client.*;
+import org.apache.phoenix.coprocessorclient.MetaDataProtocol;
+import org.apache.phoenix.query.QueryConstants;
+
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.hbase.TableName;
+
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import org.apache.phoenix.query.ConnectionQueryServices;
+
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.util.ClientUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.phoenix.query.QueryConstants.SYSTEM_SCHEMA_NAME;
+
+/**
+ * Utility class to create index tables and/or migrate them.
+ *
+ */
+public class IndexToolTableUtil extends Configured {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(IndexToolTableUtil.class);
+
+    public final static String OUTPUT_TABLE_NAME = "PHOENIX_INDEX_TOOL";
+    public static String OUTPUT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME,
+            OUTPUT_TABLE_NAME);
+
+    public final static String RESULT_TABLE_NAME = "PHOENIX_INDEX_TOOL_RESULT";
+    public static String RESULT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME,
+            RESULT_TABLE_NAME);
+
+    public static void setIndexToolTableName(Connection connection) throws 
Exception {
+        ConnectionQueryServices queryServices = 
connection.unwrap(PhoenixConnection.class).getQueryServices();
+        if (SchemaUtil.isNamespaceMappingEnabled(PTableType.SYSTEM, 
queryServices.getConfiguration())) {
+            OUTPUT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME, OUTPUT_TABLE_NAME).replace(
+                QueryConstants.NAME_SEPARATOR,
+                QueryConstants.NAMESPACE_SEPARATOR);
+            RESULT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME, RESULT_TABLE_NAME).replace(
+                QueryConstants.NAME_SEPARATOR,
+                QueryConstants.NAMESPACE_SEPARATOR);
+        } else {
+            OUTPUT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME, OUTPUT_TABLE_NAME);
+            RESULT_TABLE_FULL_NAME = 
SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME, RESULT_TABLE_NAME);
+        }
+    }
+
+    public static Table createResultTable(Connection connection) throws 
IOException, SQLException {
+        ConnectionQueryServices queryServices = 
connection.unwrap(PhoenixConnection.class).getQueryServices();
+        try (Admin admin = queryServices.getAdmin()) {
+            TableName resultTableName = 
TableName.valueOf(RESULT_TABLE_FULL_NAME);
+            if 
(RESULT_TABLE_FULL_NAME.contains(QueryConstants.NAMESPACE_SEPARATOR)) {
+                createSystemNamespaceTable(connection);
+            }
+            return createTable(admin, resultTableName);
+        }
+    }
+
+    public static Table createOutputTable(Connection connection) throws 
IOException, SQLException {
+        ConnectionQueryServices queryServices = 
connection.unwrap(PhoenixConnection.class).getQueryServices();
+        try (Admin admin = queryServices.getAdmin()) {
+            TableName outputTableName = 
TableName.valueOf(OUTPUT_TABLE_FULL_NAME);
+            if 
(OUTPUT_TABLE_FULL_NAME.contains(QueryConstants.NAMESPACE_SEPARATOR)) {
+                createSystemNamespaceTable(connection);
+            }
+            return  createTable(admin, outputTableName);
+        }
+    }
+
+    public static void createSystemNamespaceTable(Connection connection) 
throws IOException, SQLException {
+        ConnectionQueryServices queryServices = 
connection.unwrap(PhoenixConnection.class).getQueryServices();
+        if (SchemaUtil.isNamespaceMappingEnabled(PTableType.SYSTEM, 
queryServices.getConfiguration())) {
+            try (Admin admin = queryServices.getAdmin()) {
+                if (!ClientUtil.isHBaseNamespaceAvailable(admin, 
SYSTEM_SCHEMA_NAME)) {
+                    NamespaceDescriptor namespaceDescriptor =
+                            
NamespaceDescriptor.create(SYSTEM_SCHEMA_NAME).build();
+                    admin.createNamespace(namespaceDescriptor);
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    private static Table createTable(Admin admin, TableName tableName) throws 
IOException {
+        if (!admin.tableExists(tableName)) {
+            ColumnFamilyDescriptor columnDescriptor =
+                    ColumnFamilyDescriptorBuilder
+                            
.newBuilder(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES)
+                            .setTimeToLive(MetaDataProtocol.DEFAULT_LOG_TTL)
+                            .build();
+            TableDescriptor tableDescriptor = 
TableDescriptorBuilder.newBuilder(tableName)
+                    .setColumnFamily(columnDescriptor).build();
+            try {
+                admin.createTable(tableDescriptor);
+            } catch (TableExistsException e) {
+                LOGGER.warn("Table exists, ignoring", e);
+            }
+        }
+        return admin.getConnection().getTable(tableName);
+    }
+
+
+    public static void createNewIndexToolTables(Connection connection) throws 
Exception {
+        setIndexToolTableName(connection);
+
+        migrateTable(connection, OUTPUT_TABLE_NAME);
+        migrateTable(connection, RESULT_TABLE_NAME);
+    }
+
+    private static void migrateTable(Connection connection, String tableName) 
throws Exception {
+        if (!tableName.equals(OUTPUT_TABLE_NAME) && 
!tableName.equals(RESULT_TABLE_NAME)) {
+            LOGGER.info("Only migrating PHOENIX_INDEX_TOOL tables!");
+        } else {
+            ConnectionQueryServices queryServices = 
connection.unwrap(PhoenixConnection.class).getQueryServices();
+            try (Admin admin = queryServices.getAdmin()) {
+                TableName oldTableName = TableName.valueOf(tableName);
+                String newTableNameString = 
tableName.equals(OUTPUT_TABLE_NAME) ?
+                        OUTPUT_TABLE_FULL_NAME : RESULT_TABLE_FULL_NAME;
+
+                TableName newTableName = TableName.valueOf(newTableNameString);
+
+                if (admin.tableExists(oldTableName)) {
+                    String snapshotName = tableName + "_" + UUID.randomUUID();
+                    admin.disableTable(oldTableName);
+                    admin.snapshot(snapshotName, oldTableName);
+                    admin.cloneSnapshot(snapshotName, newTableName);
+                    admin.deleteSnapshot(snapshotName);
+                    admin.deleteTable(oldTableName);
+                } else {
+                    createTable(admin, newTableName);
+                }
+            }
+        }
+    }
+}
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index cd141e1182..4ab5b6336b 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -259,6 +259,7 @@ import org.apache.phoenix.log.ConnectionLimiter;
 import org.apache.phoenix.log.DefaultConnectionLimiter;
 import org.apache.phoenix.log.LoggingConnectionLimiter;
 import org.apache.phoenix.log.QueryLoggerDisruptor;
+import org.apache.phoenix.mapreduce.index.IndexToolTableUtil;
 import org.apache.phoenix.monitoring.HTableThreadPoolHistograms;
 import org.apache.phoenix.monitoring.TableMetricsManager;
 import org.apache.phoenix.parse.PFunction;
@@ -4434,6 +4435,12 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices
       metaConnection.createStatement().executeUpdate(getCDCStreamDDL());
     } catch (TableAlreadyExistsException ignore) {
     }
+    try {
+      // check if we have old PHOENIX_INDEX_TOOL tables
+      // move data to the new tables under System, or simply create the new 
tables
+      IndexToolTableUtil.createNewIndexToolTables(metaConnection);
+    } catch (Exception ignore) {
+    }
   }
 
   /**
@@ -4936,6 +4943,13 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices
       // with SYSTEM Namespace
       createSchemaIfNotExistsSystemNSMappingEnabled(metaConnection);
 
+      try {
+        // check if we have old PHOENIX_INDEX_TOOL tables
+        // move data to the new tables under System, or simply create the new 
tables
+        IndexToolTableUtil.createNewIndexToolTables(metaConnection);
+
+      } catch (Exception ignore) {}
+
       clearUpgradeRequired();
       success = true;
     } catch (UpgradeInProgressException | UpgradeNotRequiredException e) {
diff --git 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
index 92d4d01c55..c3f0d1aa81 100644
--- 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
+++ 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
@@ -83,10 +83,12 @@ import 
org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
 import org.apache.phoenix.mapreduce.util.PhoenixMapReduceUtil;
 import org.apache.phoenix.parse.HintNode.Hint;
 import org.apache.phoenix.query.ConnectionQueryServices;
+import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.query.QueryServicesOptions;
 import org.apache.phoenix.schema.PIndexState;
 import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.PTable.IndexType;
 import org.apache.phoenix.schema.TableRef;
 import org.apache.phoenix.schema.types.PVarchar;
@@ -1002,10 +1004,20 @@ public class IndexTool extends Configured implements 
Tool {
         .format(" %s is not an index table for %s for this connection", 
indexTable, qDataTable));
     }
     qSchemaName = SchemaUtil.normalizeIdentifier(schemaName);
+
     pIndexTable = connection.unwrap(PhoenixConnection.class)
       .getTable(SchemaUtil.getQualifiedTableName(schemaName, indexTable));
+    if (SchemaUtil.isNamespaceMappingEnabled(PTableType.SYSTEM, getConf())) {
+      pIndexTable = connection.unwrap(PhoenixConnection.class).getTable(
+        SchemaUtil.getQualifiedTableName(schemaName, indexTable).replace(
+          QueryConstants.NAME_SEPARATOR,
+          QueryConstants.NAMESPACE_SEPARATOR));
+    }
     indexType = pIndexTable.getIndexType();
     qIndexTable = SchemaUtil.getQualifiedTableName(schemaName, indexTable);
+    if (SchemaUtil.isNamespaceMappingEnabled(PTableType.SYSTEM, getConf())) {
+      qIndexTable = qIndexTable.replace(QueryConstants.NAME_SEPARATOR, 
QueryConstants.NAMESPACE_SEPARATOR);
+    }
     if (IndexType.LOCAL.equals(indexType)) {
       isLocalIndexBuild = true;
       if (useSnapshot) {
diff --git 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationOutputRepository.java
 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationOutputRepository.java
index b5331febde..00d389b069 100644
--- 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationOutputRepository.java
+++ 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationOutputRepository.java
@@ -18,25 +18,19 @@
 package org.apache.phoenix.mapreduce.index;
 
 import java.io.IOException;
-import java.sql.Connection;
 import java.sql.SQLException;
+import java.sql.Connection;
+
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
-import org.apache.hadoop.hbase.TableExistsException;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.Admin;
-import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
-import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
+import java.util.Iterator;
+
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.ResultScanner;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.client.Table;
-import org.apache.hadoop.hbase.client.TableDescriptor;
-import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.coprocessorclient.MetaDataProtocol;
 import org.apache.phoenix.hbase.index.table.HTableFactory;
 import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
 import org.apache.phoenix.jdbc.PhoenixConnection;
@@ -60,10 +54,9 @@ public class IndexVerificationOutputRepository implements 
AutoCloseable {
     IndexTool.IndexDisableLoggingType.NONE;
   private boolean shouldLogBeyondMaxLookback = true;
 
-  public final static String OUTPUT_TABLE_NAME = "PHOENIX_INDEX_TOOL";
-  public final static byte[] OUTPUT_TABLE_NAME_BYTES = 
Bytes.toBytes(OUTPUT_TABLE_NAME);
-  public final static byte[] OUTPUT_TABLE_COLUMN_FAMILY =
-    QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES;
+  public final static String OUTPUT_TABLE_NAME = 
IndexToolTableUtil.OUTPUT_TABLE_FULL_NAME;
+  public final static byte[] OUTPUT_TABLE_NAME_BYTES = 
Bytes.toBytes(IndexToolTableUtil.OUTPUT_TABLE_FULL_NAME);
+  public final static byte[] OUTPUT_TABLE_COLUMN_FAMILY = 
QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES;
 
   public final static String DATA_TABLE_NAME = "DTName";
   public final static byte[] DATA_TABLE_NAME_BYTES = 
Bytes.toBytes(DATA_TABLE_NAME);
@@ -180,25 +173,7 @@ public class IndexVerificationOutputRepository implements 
AutoCloseable {
   }
 
   public void createOutputTable(Connection connection) throws IOException, 
SQLException {
-    ConnectionQueryServices queryServices =
-      connection.unwrap(PhoenixConnection.class).getQueryServices();
-    try (Admin admin = queryServices.getAdmin()) {
-      TableName outputTableName = TableName.valueOf(OUTPUT_TABLE_NAME);
-      if (!admin.tableExists(outputTableName)) {
-        ColumnFamilyDescriptor columnDescriptor =
-          ColumnFamilyDescriptorBuilder.newBuilder(OUTPUT_TABLE_COLUMN_FAMILY)
-            .setTimeToLive(MetaDataProtocol.DEFAULT_LOG_TTL).build();
-        TableDescriptor tableDescriptor =
-          
TableDescriptorBuilder.newBuilder(TableName.valueOf(OUTPUT_TABLE_NAME))
-            .setColumnFamily(columnDescriptor).build();
-        try {
-          admin.createTable(tableDescriptor);
-        } catch (TableExistsException e) {
-          LOGGER.warn("Table exists, ignoring", e);
-        }
-        outputTable = admin.getConnection().getTable(outputTableName);
-      }
-    }
+    outputTable = IndexToolTableUtil.createOutputTable(connection);
   }
 
   @VisibleForTesting
diff --git 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationResultRepository.java
 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationResultRepository.java
index 1481f8cf0a..ec63f825aa 100644
--- 
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationResultRepository.java
+++ 
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexVerificationResultRepository.java
@@ -21,35 +21,23 @@ import java.io.IOException;
 import java.sql.Connection;
 import java.sql.SQLException;
 import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.TableExistsException;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.Admin;
-import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
-import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
+
 import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.ResultScanner;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.client.Table;
-import org.apache.hadoop.hbase.client.TableDescriptor;
-import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
 import org.apache.hadoop.hbase.regionserver.Region;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.coprocessor.IndexToolVerificationResult;
-import org.apache.phoenix.coprocessorclient.MetaDataProtocol;
 import org.apache.phoenix.hbase.index.table.HTableFactory;
 import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
 import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.query.ConnectionQueryServices;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.util.ByteUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class IndexVerificationResultRepository implements AutoCloseable {
-  private static final Logger LOGGER =
-    LoggerFactory.getLogger(IndexVerificationResultRepository.class);
 
   public static final String RUN_STATUS_SKIPPED = "Skipped";
   public static final String RUN_STATUS_EXECUTED = "Executed";
@@ -57,8 +45,8 @@ public class IndexVerificationResultRepository implements 
AutoCloseable {
   private Table indexTable;
   public static final String ROW_KEY_SEPARATOR = "|";
   public static final byte[] ROW_KEY_SEPARATOR_BYTE = 
Bytes.toBytes(ROW_KEY_SEPARATOR);
-  public final static String RESULT_TABLE_NAME = "PHOENIX_INDEX_TOOL_RESULT";
-  public final static byte[] RESULT_TABLE_NAME_BYTES = 
Bytes.toBytes(RESULT_TABLE_NAME);
+  public static String RESULT_TABLE_NAME = 
IndexToolTableUtil.RESULT_TABLE_FULL_NAME;
+  public static byte[] RESULT_TABLE_NAME_BYTES = 
Bytes.toBytes(IndexToolTableUtil.RESULT_TABLE_FULL_NAME);
   public final static byte[] RESULT_TABLE_COLUMN_FAMILY =
     QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES;
   public final static String SCANNED_DATA_ROW_COUNT = "ScannedDataRowCount";
@@ -172,37 +160,18 @@ public class IndexVerificationResultRepository implements 
AutoCloseable {
 
   }
 
-  public IndexVerificationResultRepository(Connection conn, byte[] 
indexNameBytes)
-    throws SQLException {
-    resultTable = getTable(conn, RESULT_TABLE_NAME_BYTES);
+  public IndexVerificationResultRepository(Connection conn, byte[] 
indexNameBytes) throws SQLException {
+    resultTable = getTable(conn, 
Bytes.toBytes(IndexToolTableUtil.RESULT_TABLE_FULL_NAME));
     indexTable = getTable(conn, indexNameBytes);
   }
 
-  public IndexVerificationResultRepository(byte[] indexName, HTableFactory 
hTableFactory)
-    throws IOException {
-    resultTable = hTableFactory.getTable(new 
ImmutableBytesPtr(RESULT_TABLE_NAME_BYTES));
+  public IndexVerificationResultRepository(byte[] indexName, HTableFactory 
hTableFactory) throws IOException {
+    resultTable = hTableFactory.getTable(new 
ImmutableBytesPtr(Bytes.toBytes(IndexToolTableUtil.RESULT_TABLE_FULL_NAME)));
     indexTable = hTableFactory.getTable(new ImmutableBytesPtr(indexName));
   }
 
   public void createResultTable(Connection connection) throws IOException, 
SQLException {
-    ConnectionQueryServices queryServices =
-      connection.unwrap(PhoenixConnection.class).getQueryServices();
-    try (Admin admin = queryServices.getAdmin()) {
-      TableName resultTableName = TableName.valueOf(RESULT_TABLE_NAME);
-      if (!admin.tableExists(resultTableName)) {
-        ColumnFamilyDescriptor columnDescriptor =
-          ColumnFamilyDescriptorBuilder.newBuilder(RESULT_TABLE_COLUMN_FAMILY)
-            .setTimeToLive(MetaDataProtocol.DEFAULT_LOG_TTL).build();
-        TableDescriptor tableDescriptor = 
TableDescriptorBuilder.newBuilder(resultTableName)
-          .setColumnFamily(columnDescriptor).build();
-        try {
-          admin.createTable(tableDescriptor);
-        } catch (TableExistsException e) {
-          LOGGER.warn("Table exists, ignoring", e);
-        }
-        resultTable = admin.getConnection().getTable(resultTableName);
-      }
-    }
+    resultTable = IndexToolTableUtil.createResultTable(connection);
   }
 
   private static byte[] generatePartialResultTableRowKey(long ts, byte[] 
indexTableName) {
@@ -387,7 +356,7 @@ public class IndexVerificationResultRepository implements 
AutoCloseable {
 
   public IndexToolVerificationResult getVerificationResult(Connection conn, 
long ts,
     byte[] indexTableName) throws IOException, SQLException {
-    try (Table hTable = getTable(conn, RESULT_TABLE_NAME_BYTES)) {
+    try (Table hTable = getTable(conn, 
Bytes.toBytes(IndexToolTableUtil.RESULT_TABLE_FULL_NAME))) {
       byte[] startRowKey = generatePartialResultTableRowKey(ts, 
indexTableName);
       byte[] stopRowKey = 
ByteUtil.calculateTheClosestNextRowKeyForPrefix(startRowKey);
       IndexToolVerificationResult verificationResult = new 
IndexToolVerificationResult(ts);
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AsyncIndexPermissionIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AsyncIndexPermissionIT.java
new file mode 100644
index 0000000000..692e65f032
--- /dev/null
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AsyncIndexPermissionIT.java
@@ -0,0 +1,331 @@
+/*
+ * 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.end2end;
+
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.permission.FsPermission;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.LocalHBaseCluster;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Admin;
+import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
+import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
+import org.apache.hadoop.hbase.client.TableDescriptor;
+import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
+import org.apache.hadoop.hbase.security.AccessDeniedException;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.AccessControlClient;
+import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.BaseTest;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.apache.phoenix.util.SchemaUtil;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+
+import java.util.Collections;
+import java.util.Properties;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import static org.apache.phoenix.end2end.BasePermissionsIT.updateACLs;
+import static 
org.apache.phoenix.end2end.BasePermissionsIT.enablePhoenixHBaseAuthorization;
+import static 
org.apache.phoenix.end2end.BasePermissionsIT.configureNamespacesOnServer;
+import static 
org.apache.phoenix.end2end.BasePermissionsIT.configureStatsConfigurations;
+import static 
org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+@Category(NeedsOwnMiniClusterTest.class)
+public class AsyncIndexPermissionIT extends BaseTest{
+
+//    static HBaseTestingUtility testUtil;
+
+    private static final String SUPER_USER = System.getProperty("user.name");
+
+    boolean isNamespaceMapped;
+
+    // Super User has all the access
+    protected static User superUser1 = null;
+
+    // Regular users are granted and revoked permissions as needed
+    protected User regularUser1 = null;
+
+    public AsyncIndexPermissionIT() throws Exception {
+        isNamespaceMapped = true;
+    }
+
+    @BeforeClass
+    public static synchronized void doSetup() throws Exception {
+        if (null != utility) {
+            utility.shutdownMiniCluster();
+            utility = null;
+        }
+
+        enablePhoenixHBaseAuthorization(config, false);
+        configureNamespacesOnServer(config, true);
+        configureStatsConfigurations(config);
+        config.setBoolean(LocalHBaseCluster.ASSIGN_RANDOM_PORTS, true);
+
+
+        Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(2);
+        serverProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
Boolean.toString(true));
+
+        Map<String, String> clientProps = Maps.newHashMapWithExpectedSize(2);
+        clientProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
Boolean.toString(true));
+
+        utility = new HBaseTestingUtility(config);
+
+        setUpTestDriver(new ReadOnlyProps(serverProps.entrySet().iterator()),
+                new ReadOnlyProps(clientProps.entrySet().iterator()));
+
+        superUser1 = User.createUserForTesting(config, SUPER_USER, new 
String[0]);
+    }
+
+    @Before
+    public void initUsersAndTables() {
+        regularUser1 = User.createUserForTesting(config, "regularUser1_"
+                + generateUniqueName(), new String[0]);
+    }
+
+    private BasePermissionsIT.AccessTestAction createIndex(final String 
indexName, final String dataTable, final String columns) throws SQLException {
+        return new BasePermissionsIT.AccessTestAction() {
+            @Override
+            public Object run() throws Exception {
+                try (Connection conn = DriverManager.getConnection(getUrl()); 
Statement stmt = conn.createStatement();) {
+                    String indexStmtSQL = "CREATE index " + indexName + " on " 
+ dataTable + " (" + columns +")";
+                    assertFalse(stmt.execute(indexStmtSQL));
+                }
+                return null;
+            }
+        };
+    }
+
+    private BasePermissionsIT.AccessTestAction createIndexAsync(final String 
indexName, final String schema, final String tableName, final String columns, 
final int status) throws SQLException {
+        return new BasePermissionsIT.AccessTestAction() {
+            @Override
+            public Object run() throws Exception {
+                final String dataTable = SchemaUtil.getTableName(schema, 
tableName);
+                try (Connection conn = DriverManager.getConnection(getUrl()); 
Statement stmt = conn.createStatement();) {
+                    String indexStmtSQL = "CREATE index " + indexName + " on " 
+ dataTable + " (" + columns +") ASYNC";
+                    assertFalse(stmt.execute(indexStmtSQL));
+                }
+                try {
+                    IndexToolIT.runIndexTool(false, schema, tableName, 
indexName, null, status, "-op", "/tmp/regular_User1_dir");
+                } catch (Exception ignored) {
+                    // Running the indexTool might fail because of 
AccessDeniedException
+                }
+                return null;
+            }
+        };
+    }
+
+    @Test(timeout = 80000)
+    public void testCreateIndex() throws Throwable {
+        final String schema = generateUniqueName();
+        final String tableName = generateUniqueName();
+        verifyAllowed(createSchema(schema), superUser1);
+        grantPermissions(regularUser1.getShortName(), schema, 
Permission.Action.WRITE,
+                Permission.Action.READ, Permission.Action.EXEC, 
Permission.Action.ADMIN);
+        grantPermissions(regularUser1.getShortName(), "SYSTEM", 
Permission.Action.READ, Permission.Action.EXEC);
+        grantPermissions(regularUser1.getShortName(), 
Collections.singleton("SYSTEM:CATALOG"), Permission.Action.EXEC, 
Permission.Action.WRITE, Permission.Action.READ);
+
+        Path workDir = new Path("/tmp/regular_User1_dir");
+        FileSystem fs = workDir.getFileSystem(config);
+
+        fs.mkdirs(workDir, FsPermission.valueOf("-rwxrwxrwx"));
+
+        fs.setOwner(workDir, regularUser1.getShortName(), "");
+
+        superUser1.runAs(new PrivilegedExceptionAction<Void>() {
+            @Override
+            public Void run() throws Exception {
+                Admin admin = utility.getAdmin();
+                TableDescriptorBuilder tdb = 
TableDescriptorBuilder.newBuilder(TableName.valueOf(schema + ":" + tableName));
+                ColumnFamilyDescriptor cfd = 
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("0")).build();
+                tdb.setColumnFamily(cfd);
+                TableDescriptor td = tdb.build();
+                admin.createTable(td);
+                return null;
+            }
+        });
+
+        List<UserPermission> perms = 
AccessControlClient.getUserPermissions(getUtility().getConnection(), 
SYSTEM_CATALOG_NAME, regularUser1.getShortName());
+        for (UserPermission perm : perms) {
+            Assert.assertEquals(perm.getUser(), regularUser1.getShortName() );
+            Permission.Action[] actions = { Permission.Action.READ, 
Permission.Action.WRITE, Permission.Action.EXEC };
+            Assert.assertEquals(perm.getPermission().getActions(), actions );
+        }
+
+        verifyAllowed(createTable(SchemaUtil.getTableName(schema, tableName), 
2), regularUser1);
+        verifyAllowed(createIndex("ind1", SchemaUtil.getTableName(schema, 
tableName), "PK"), regularUser1);
+
+        String ind3name = "IND3";
+        regularUser1.runAs(createIndexAsync(ind3name, schema, tableName, "PK", 
0));
+
+        validateIndex(ind3name, schema, "a");
+    }
+
+    private void validateIndex(String ind3name, String schema, String 
expectedStatus) throws SQLException {
+        String sql = "SELECT " + 
"TABLE_SCHEM,TABLE_NAME,TABLE_TYPE,INDEX_STATE" + " FROM " + SYSTEM_CATALOG_NAME
+                + " WHERE TABLE_SCHEM = '%s' AND TABLE_NAME = '%s' and 
TABLE_TYPE = 'i'";
+        ResultSet rs = 
getConnection().createStatement().executeQuery(String.format(sql, schema, 
ind3name));
+        assertTrue(rs.next());
+        assertEquals(expectedStatus, rs.getString(4));
+    }
+
+    public Connection getConnection() throws SQLException {
+        return getConnection(null);
+    }
+
+    public Connection getConnection(String tenantId) throws SQLException {
+        return DriverManager.getConnection(getUrl(), 
getClientProperties(tenantId));
+    }
+
+    private Properties getClientProperties(String tenantId) {
+        Properties props = new Properties();
+        if(tenantId != null) {
+            props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+        }
+        props.setProperty(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
Boolean.toString(isNamespaceMapped));
+        return props;
+    }
+
+    public BasePermissionsIT.AccessTestAction createSchema(final String 
schemaName) throws SQLException {
+        return new BasePermissionsIT.AccessTestAction() {
+            @Override
+            public Object run() throws Exception {
+                if (isNamespaceMapped) {
+                    try (Connection conn = getConnection(); Statement stmt = 
conn.createStatement();) {
+                        assertFalse(stmt.execute("CREATE SCHEMA " + 
schemaName));
+                    }
+                }
+                return null;
+            }
+        };
+    }
+
+    BasePermissionsIT.AccessTestAction createTable(final String tableName, int 
numRecordsToInsert) throws SQLException {
+        return new BasePermissionsIT.AccessTestAction() {
+            @Override
+            public Object run() throws Exception {
+                try (Connection conn = DriverManager.getConnection(getUrl()); 
Statement stmt = conn.createStatement();) {
+                    assertFalse(stmt.execute("CREATE TABLE " + tableName + 
"(pk INTEGER not null primary key, data VARCHAR, val integer)"));
+                    try (PreparedStatement pstmt = 
conn.prepareStatement("UPSERT INTO " + tableName + " values(?, ?, ?)")) {
+                        for (int i = 0; i < numRecordsToInsert; i++) {
+                            pstmt.setInt(1, i);
+                            pstmt.setString(2, Integer.toString(i));
+                            pstmt.setInt(3, i);
+                            assertEquals(1, pstmt.executeUpdate());
+                        }
+                    }
+                    conn.commit();
+                }
+                return null;
+            }
+        };
+    }
+
+    /** This fails only in case of ADE or empty list for any of the users. */
+    public void verifyAllowed(BasePermissionsIT.AccessTestAction action, 
User... users) throws Exception {
+        if(users.length == 0) {
+            throw new Exception("Action needs at least one user to run");
+        }
+        for (User user : users) {
+            verifyAllowed(user, action);
+        }
+    }
+
+    private void verifyAllowed(User user, 
BasePermissionsIT.AccessTestAction... actions) throws Exception {
+        for (BasePermissionsIT.AccessTestAction action : actions) {
+            try {
+                Object obj = user.runAs(action);
+                if (obj != null && obj instanceof List<?>) {
+                    List<?> results = (List<?>) obj;
+                    if (results.isEmpty()) {
+                        fail("Empty non null results from action for user '" + 
user.getShortName() + "'");
+                    }
+                }
+            } catch (AccessDeniedException ade) {
+                fail("Expected action to pass for user '" + 
user.getShortName() + "' but was denied");
+            }
+        }
+    }
+
+    void grantPermissions(String toUser, String namespace, 
Permission.Action... actions) throws Throwable {
+        updateACLs(getUtility(), new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                try {
+                    AccessControlClient.grant(getUtility().getConnection(), 
namespace, toUser, actions);
+
+                    return null;
+                } catch (Throwable t) {
+                    if (t instanceof Exception) {
+                        throw (Exception) t;
+                    } else {
+                        throw new Exception(t);
+                    }
+                }
+            }
+        });
+    }
+
+    void grantPermissions(String toUser, Set<String> tablesToGrant, 
Permission.Action... actions)
+            throws Throwable {
+        updateACLs(getUtility(), new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                try {
+                    for (String table : tablesToGrant) {
+                        
AccessControlClient.grant(getUtility().getConnection(), 
TableName.valueOf(table),
+                                toUser, null, null, actions);
+                    }
+                    return null;
+                } catch (Throwable t) {
+                    if (t instanceof Exception) {
+                        throw (Exception) t;
+                    } else {
+                        throw new Exception(t);
+                    }
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BasePermissionsIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BasePermissionsIT.java
index e0d3bc1b35..53d6d146d6 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BasePermissionsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BasePermissionsIT.java
@@ -224,8 +224,8 @@ public abstract class BasePermissionsIT extends BaseTest {
     view2TableName = tableName + "_V2";
   }
 
-  private static void enablePhoenixHBaseAuthorization(Configuration config,
-    boolean useCustomAccessController) {
+  static void enablePhoenixHBaseAuthorization(Configuration config,
+                                              boolean 
useCustomAccessController) {
     config.set("hbase.superuser", SUPER_USER + "," + "superUser2");
     config.set("hbase.security.authorization", Boolean.TRUE.toString());
     config.set("hbase.security.exec.permission.checks", 
Boolean.TRUE.toString());
@@ -247,11 +247,11 @@ public abstract class BasePermissionsIT extends BaseTest {
       "org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec");
   }
 
-  private static void configureNamespacesOnServer(Configuration conf, boolean 
isNamespaceMapped) {
+  static void configureNamespacesOnServer(Configuration conf, boolean 
isNamespaceMapped) {
     conf.set(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
Boolean.toString(isNamespaceMapped));
   }
 
-  private static void configureStatsConfigurations(Configuration conf) {
+  static void configureStatsConfigurations(Configuration conf) {
     conf.set(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, 
Long.toString(20));
     conf.set(QueryServices.STATS_UPDATE_FREQ_MS_ATTRIB, Long.toString(5));
     conf.set(QueryServices.MAX_SERVER_METADATA_CACHE_TIME_TO_LIVE_MS_ATTRIB, 
Long.toString(5));
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
index 3d03378dbb..c658210832 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
@@ -867,6 +867,14 @@ public class IndexToolIT extends BaseTest {
     String indxTable, String tenantId, IndexTool.IndexVerifyType verifyType, 
Long startTime,
     Long endTime, IndexTool.IndexDisableLoggingType disableLoggingType, Long 
incrementalVerify,
     boolean useIndexTableAsSource) {
+        return getArgList(useSnapshot, schemaName, dataTable, indxTable, 
tenantId,verifyType, startTime,
+                endTime, disableLoggingType, incrementalVerify, 
useIndexTableAsSource, "/tmp/" + UUID.randomUUID().toString());
+    }
+
+  private static List<String> getArgList (boolean useSnapshot, String 
schemaName, String dataTable,
+    String indxTable, String tenantId, IndexTool.IndexVerifyType verifyType, 
Long startTime,
+    Long endTime, IndexTool.IndexDisableLoggingType disableLoggingType, Long 
incrementalVerify,
+    boolean useIndexTableAsSource, String outputPath) {
     List<String> args = Lists.newArrayList();
     if (schemaName != null) {
       args.add("--schema=" + schemaName);
@@ -911,7 +919,7 @@ public class IndexToolIT extends BaseTest {
     }
 
     args.add("-op");
-    args.add("/tmp/" + UUID.randomUUID().toString());
+    args.add(outputPath);
     return args;
   }
 
@@ -930,6 +938,14 @@ public class IndexToolIT extends BaseTest {
     return args.toArray(new String[0]);
   }
 
+  public static String[] getArgValues(boolean useSnapshot, String schemaName, 
String dataTable,
+    String indexTable, String tenantId, IndexTool.IndexVerifyType verifyType,
+    IndexTool.IndexDisableLoggingType disableLoggingType, String outputPath) {
+    List<String> args = getArgList(useSnapshot, schemaName, dataTable, 
indexTable,
+      tenantId, verifyType, null, null, disableLoggingType, null, false, 
outputPath);
+    return args.toArray(new String[0]);
+    }
+
   public static String[] getArgValues(boolean useSnapshot, String schemaName, 
String dataTable,
     String indexTable, String tenantId, IndexTool.IndexVerifyType verifyType, 
Long startTime,
     Long endTime) {
@@ -1018,12 +1034,34 @@ public class IndexToolIT extends BaseTest {
     IndexTool indexingTool = new IndexTool();
     conf.set(QueryServices.TRANSACTIONS_ENABLED, Boolean.TRUE.toString());
     indexingTool.setConf(conf);
-    final String[] cmdArgs = getArgValues(useSnapshot, schemaName, 
dataTableName, indexTableName,
-      tenantId, verifyType, disableLoggingType);
+    boolean additionalArgsContainPath = false;
+    String path = "";
+    List<String> newadditionalArgs = Lists.newArrayList();
+    for (String arg : additionalArgs){
+      if (additionalArgsContainPath == true) {
+        path = arg;
+      }
+      else if ( arg.equals("-op") || arg.equals("-output-path")) {
+         additionalArgsContainPath = true;
+      }
+      else {
+        newadditionalArgs.add(arg);
+      }
+    }
+    additionalArgs = newadditionalArgs.toArray(new String[0]);
+
+    String[] cmdArgs;
+    if (additionalArgsContainPath) {
+      cmdArgs = getArgValues(useSnapshot, schemaName, dataTableName,
+         indexTableName, tenantId, verifyType, disableLoggingType, path);
+    }
+    else {
+      cmdArgs = getArgValues(useSnapshot, schemaName, dataTableName,
+        indexTableName, tenantId, verifyType, disableLoggingType);
+    }
     List<String> cmdArgList = new ArrayList<>(Arrays.asList(cmdArgs));
     cmdArgList.addAll(Arrays.asList(additionalArgs));
-    LOGGER.info("Running IndexTool with {}", 
Arrays.toString(cmdArgList.toArray()),
-      new Exception("Stack Trace"));
+    LOGGER.info("Running IndexTool with {}", 
Arrays.toString(cmdArgList.toArray()), new Exception("Stack Trace"));
     int status = indexingTool.run(cmdArgList.toArray(new 
String[cmdArgList.size()]));
 
     if (expectedStatus == 0) {
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LoadSystemTableSnapshotBase.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LoadSystemTableSnapshotBase.java
index e54f9715e9..56adb57673 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LoadSystemTableSnapshotBase.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LoadSystemTableSnapshotBase.java
@@ -73,22 +73,13 @@ public abstract class LoadSystemTableSnapshotBase extends 
BaseTest {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(LoadSystemTableSnapshotBase.class);
 
-  public static final String SNAPSHOT_DIR = "snapshots4_7/";
-  public static String rootDir;
+    public static String SNAPSHOT_DIR;
+    public static String rootDir;
 
-  private static final HashMap<String, String> SNAPSHOTS_TO_LOAD;
+    private static HashMap<String, String> SNAPSHOTS_TO_LOAD;
 
   public static final byte[] MUTEX_LOCKED = 
"MUTEX_LOCKED".getBytes(StandardCharsets.UTF_8);
 
-  static {
-    SNAPSHOTS_TO_LOAD = new HashMap<>();
-    // Add any HBase tables, including Phoenix System tables
-
-    SNAPSHOTS_TO_LOAD.put("SYSTEM.CATALOG_SNAPSHOT", "SYSTEM.CATALOG");
-    SNAPSHOTS_TO_LOAD.put("SYSTEM.FUNCTION_SNAPSHOT", "SYSTEM.FUNCTION");
-    SNAPSHOTS_TO_LOAD.put("SYSTEM.SEQUENCE_SNAPSHOT", "SYSTEM.SEQUENCE");
-    SNAPSHOTS_TO_LOAD.put("SYSTEM.STATS_SNAPSHOT", "SYSTEM.STATS");
-  }
 
   private static void decompress(String in, File out) throws IOException {
     try (TarArchiveInputStream fin = new TarArchiveInputStream(new 
FileInputStream(in))) {
@@ -108,12 +99,24 @@ public abstract class LoadSystemTableSnapshotBase extends 
BaseTest {
   }
 
   public static synchronized void setupCluster(boolean 
createBlockUpgradeMutex) throws Exception {
+    //Add any HBase tables, including Phoenix System tables
+    HashMap<String, String> snapshotsToLoad = new HashMap<>();
+    snapshotsToLoad.put("SYSTEM.CATALOG_SNAPSHOT", "SYSTEM.CATALOG");
+    snapshotsToLoad.put("SYSTEM.FUNCTION_SNAPSHOT", "SYSTEM.FUNCTION");
+    snapshotsToLoad.put("SYSTEM.SEQUENCE_SNAPSHOT", "SYSTEM.SEQUENCE");
+    snapshotsToLoad.put("SYSTEM.STATS_SNAPSHOT", "SYSTEM.STATS");
+
+    setupCluster(createBlockUpgradeMutex, "snapshots47.tar.gz", 
"snapshots4_7/", snapshotsToLoad, "true");
+  }
+
+  public static synchronized void setupCluster(boolean 
createBlockUpgradeMutex, String tarName, String snapshotDir, HashMap<String, 
String> snapshotsToLoad, String nameSpaceMapping) throws Exception {
+    SNAPSHOT_DIR = snapshotDir;
+    SNAPSHOTS_TO_LOAD = snapshotsToLoad;
     Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(2);
-    serverProps.put(QueryServices.EXTRA_JDBC_ARGUMENTS_ATTRIB,
-      QueryServicesOptions.DEFAULT_EXTRA_JDBC_ARGUMENTS);
-    serverProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, "true");
+    serverProps.put(QueryServices.EXTRA_JDBC_ARGUMENTS_ATTRIB, 
QueryServicesOptions.DEFAULT_EXTRA_JDBC_ARGUMENTS);
+    serverProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
nameSpaceMapping);
     Map<String, String> clientProps = Maps.newHashMapWithExpectedSize(2);
-    clientProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, "true");
+    clientProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
nameSpaceMapping);
 
     // Start minicluster without Phoenix first
     checkClusterInitialized(new 
ReadOnlyProps(serverProps.entrySet().iterator()));
@@ -121,7 +124,7 @@ public abstract class LoadSystemTableSnapshotBase extends 
BaseTest {
     URL folderUrl = 
LoadSystemTableSnapshotBase.class.getClassLoader().getResource(SNAPSHOT_DIR);
 
     // extract the tar
-    File archive = new File(folderUrl.getFile() + "snapshots47.tar.gz");
+    File archive = new File(folderUrl.getFile() + tarName);
     File destination = new File(folderUrl.getFile());
 
     decompress(archive.toString(), destination);
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MigrateSystemTablesToSystemNamespaceIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MigrateSystemTablesToSystemNamespaceIT.java
index 9109e837f5..3436026410 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MigrateSystemTablesToSystemNamespaceIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MigrateSystemTablesToSystemNamespaceIT.java
@@ -63,6 +63,11 @@ import org.junit.experimental.categories.Category;
 @Category(NeedsOwnMiniClusterTest.class)
 public class MigrateSystemTablesToSystemNamespaceIT extends BaseTest {
 
+  private static final Set<String> HBASE_SYSTEM_TABLES = new 
HashSet<>(Arrays.asList(
+    "SYSTEM.PHOENIX_INDEX_TOOL_RESULT", "SYSTEM.PHOENIX_INDEX_TOOL"));
+  private static final Set<String> HBASE_NAMESPACE_MAPPED_SYSTEM_TABLES = new 
HashSet<>(
+    Arrays.asList("SYSTEM:PHOENIX_INDEX_TOOL_RESULT", 
"SYSTEM:PHOENIX_INDEX_TOOL"));
+
   private static final Set<String> PHOENIX_SYSTEM_TABLES =
     new HashSet<>(Arrays.asList("SYSTEM.CATALOG", "SYSTEM.SEQUENCE", 
"SYSTEM.STATS",
       "SYSTEM.FUNCTION", "SYSTEM.MUTEX", "SYSTEM.LOG", "SYSTEM.CHILD_LINK", 
"SYSTEM.TASK",
@@ -191,7 +196,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     });
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size() + 
HBASE_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
     
assertTrue(hbaseTables.containsAll(PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES));
 
     try {
@@ -209,7 +214,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     }
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size() + 
HBASE_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
     
assertTrue(hbaseTables.containsAll(PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES));
   }
 
@@ -227,7 +232,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     });
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size() + 
HBASE_SYSTEM_TABLES.size());
     assertTrue(hbaseTables.containsAll(PHOENIX_SYSTEM_TABLES));
 
     user2.doAs(new PrivilegedExceptionAction<Void>() {
@@ -240,7 +245,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     });
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size() + 
HBASE_SYSTEM_TABLES.size());
     assertTrue(hbaseTables.containsAll(PHOENIX_SYSTEM_TABLES));
 
     try {
@@ -260,7 +265,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     }
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size() + 
HBASE_SYSTEM_TABLES.size());
     assertTrue(hbaseTables.containsAll(PHOENIX_SYSTEM_TABLES));
 
     user2.doAs(new PrivilegedExceptionAction<Void>() {
@@ -273,7 +278,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     });
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == PHOENIX_SYSTEM_TABLES.size() + 
HBASE_SYSTEM_TABLES.size());
     assertTrue(hbaseTables.containsAll(PHOENIX_SYSTEM_TABLES));
 
     user3.doAs(new PrivilegedExceptionAction<Void>() {
@@ -285,7 +290,7 @@ public class MigrateSystemTablesToSystemNamespaceIT extends 
BaseTest {
     });
 
     hbaseTables = getHBaseTables();
-    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
+    assertTrue(hbaseTables.size() == 
PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES.size() + 
HBASE_NAMESPACE_MAPPED_SYSTEM_TABLES.size());
     
assertTrue(hbaseTables.containsAll(PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES));
   }
 
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipSystemTablesExistenceCheckIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipSystemTablesExistenceCheckIT.java
index 4541a51054..4f3b2ea625 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipSystemTablesExistenceCheckIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipSystemTablesExistenceCheckIT.java
@@ -67,7 +67,8 @@ public class SkipSystemTablesExistenceCheckIT {
   private static final Set<String> PHOENIX_SYSTEM_TABLES =
     new HashSet<>(Arrays.asList("SYSTEM.CATALOG", "SYSTEM.SEQUENCE", 
"SYSTEM.STATS",
       "SYSTEM.FUNCTION", "SYSTEM.MUTEX", "SYSTEM.LOG", "SYSTEM.CHILD_LINK", 
"SYSTEM.TASK",
-      "SYSTEM.TRANSFORM", "SYSTEM.CDC_STREAM_STATUS", "SYSTEM.CDC_STREAM"));
+      "SYSTEM.TRANSFORM","SYSTEM.CDC_STREAM_STATUS", "SYSTEM.CDC_STREAM",
+      "SYSTEM.PHOENIX_INDEX_TOOL_RESULT", "SYSTEM.PHOENIX_INDEX_TOOL"));
 
   private static class PhoenixSystemTablesCreationTestDriver extends 
PhoenixTestDriver {
     private static ConnectionQueryServices cqs;
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SystemTablesCreationOnConnectionIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SystemTablesCreationOnConnectionIT.java
index 819feebcaa..52fa0d953a 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SystemTablesCreationOnConnectionIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SystemTablesCreationOnConnectionIT.java
@@ -70,12 +70,15 @@ import org.apache.phoenix.util.UpgradeUtil;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Category(NeedsOwnMiniClusterTest.class)
 public class SystemTablesCreationOnConnectionIT {
 
@@ -104,12 +107,14 @@ public class SystemTablesCreationOnConnectionIT {
   private static final Set<String> PHOENIX_SYSTEM_TABLES =
     new HashSet<>(Arrays.asList("SYSTEM.CATALOG", "SYSTEM.SEQUENCE", 
"SYSTEM.STATS",
       "SYSTEM.FUNCTION", "SYSTEM.MUTEX", "SYSTEM.LOG", "SYSTEM.CHILD_LINK", 
"SYSTEM.TASK",
-      "SYSTEM.TRANSFORM", "SYSTEM.CDC_STREAM_STATUS", "SYSTEM.CDC_STREAM"));
+      "SYSTEM.TRANSFORM","SYSTEM.CDC_STREAM_STATUS", "SYSTEM.CDC_STREAM",
+      "SYSTEM.PHOENIX_INDEX_TOOL_RESULT", "SYSTEM.PHOENIX_INDEX_TOOL"));
 
-  private static final Set<String> PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES =
+    private static final Set<String> PHOENIX_NAMESPACE_MAPPED_SYSTEM_TABLES =
     new HashSet<>(Arrays.asList("SYSTEM:CATALOG", "SYSTEM:SEQUENCE", 
"SYSTEM:STATS",
       "SYSTEM:FUNCTION", "SYSTEM:MUTEX", "SYSTEM:LOG", "SYSTEM:CHILD_LINK", 
"SYSTEM:TASK",
-      "SYSTEM:TRANSFORM", "SYSTEM:CDC_STREAM_STATUS", "SYSTEM:CDC_STREAM"));
+      "SYSTEM:TRANSFORM", "SYSTEM:CDC_STREAM_STATUS", "SYSTEM:CDC_STREAM",
+      "SYSTEM:PHOENIX_INDEX_TOOL_RESULT", "SYSTEM:PHOENIX_INDEX_TOOL"));
 
   private static class PhoenixSysCatCreationServices extends 
ConnectionQueryServicesImpl {
 
@@ -781,7 +786,6 @@ public class SystemTablesCreationOnConnectionIT {
     hbaseTables = getHBaseTables();
     assertEquals(PHOENIX_SYSTEM_TABLES, hbaseTables);
     assertEquals(0, countUpgradeAttempts);
-    assertFalse(isSystemNamespaceCreated());
     return driver;
   }
 
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesIT.java
new file mode 100644
index 0000000000..ed36b1c840
--- /dev/null
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesIT.java
@@ -0,0 +1,99 @@
+/*
+ * 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.end2end;
+
+
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Admin;
+
+import org.apache.phoenix.mapreduce.index.IndexToolTableUtil;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.query.QueryServicesOptions;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.apache.phoenix.util.SchemaUtil;
+import org.junit.Before;
+import org.junit.Test;
+import java.util.HashMap;
+import java.util.Map;
+
+import static 
org.apache.phoenix.mapreduce.index.IndexToolTableUtil.RESULT_TABLE_NAME;
+import static org.apache.phoenix.query.QueryConstants.SYSTEM_SCHEMA_NAME;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+
+public class UpgradeIndexToolTablesIT extends LoadSystemTableSnapshotBase {
+    protected String nameSpaceMapping = "true";
+
+    @Before
+    public synchronized void doSetup() throws Exception {
+        setupCluster(nameSpaceMapping);
+    }
+
+    public synchronized void setupCluster(String nameSpaceMappingEnabled) 
throws Exception {
+        HashMap<String, String> snapshotsToLoad = new HashMap<>();
+        snapshotsToLoad.put("phoenixtoolresultsnapshot", 
"PHOENIX_INDEX_TOOL_RESULT");
+        setupCluster(false, "indexToolsnapshot.tar.gz", 
"indexToolResultSnapshot/",  snapshotsToLoad, nameSpaceMappingEnabled);
+    }
+
+    @Test
+    public void testPhoenixUpgradeIndexToolTables() throws Exception {
+        try (Admin admin = utility.getAdmin()) {
+            // we load the  RESULT_TABLE_NAME from snapshot
+            
assertTrue(admin.tableExists(TableName.valueOf(IndexToolTableUtil.RESULT_TABLE_NAME)));
+            
assertFalse(admin.tableExists(TableName.valueOf(IndexToolTableUtil.RESULT_TABLE_FULL_NAME)));
+            // we don't load the OUTPUT_TABLE_NAME
+            
assertFalse(admin.tableExists(TableName.valueOf(IndexToolTableUtil.OUTPUT_TABLE_NAME)));
+            
assertFalse(admin.tableExists(TableName.valueOf(IndexToolTableUtil.OUTPUT_TABLE_FULL_NAME)));
+        }
+
+        Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(2);
+        serverProps.put(QueryServices.EXTRA_JDBC_ARGUMENTS_ATTRIB, 
QueryServicesOptions.DEFAULT_EXTRA_JDBC_ARGUMENTS);
+        serverProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
nameSpaceMapping);
+        Map<String, String> clientProps = Maps.newHashMapWithExpectedSize(2);
+        clientProps.put(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, 
nameSpaceMapping);
+
+
+        //Now we can start Phoenix
+        setUpTestDriver(new ReadOnlyProps(serverProps.entrySet().iterator()), 
new ReadOnlyProps(clientProps.entrySet()
+                .iterator()));
+        assertTrue(true);
+
+
+        // Check the IndexTool Tables after upgrade
+        try (Admin admin = utility.getAdmin()) {
+            
assertFalse(admin.tableExists(TableName.valueOf(IndexToolTableUtil.OUTPUT_TABLE_NAME)));
+            
assertFalse(admin.tableExists(TableName.valueOf(IndexToolTableUtil.RESULT_TABLE_NAME)));
+            
assertTrue(admin.tableExists(TableName.valueOf(IndexToolTableUtil.OUTPUT_TABLE_FULL_NAME)));
+            
assertTrue(admin.tableExists(TableName.valueOf(IndexToolTableUtil.RESULT_TABLE_FULL_NAME)));
+        }
+
+        String tableName = SchemaUtil.getTableName(SYSTEM_SCHEMA_NAME, 
RESULT_TABLE_NAME);
+        if (nameSpaceMapping.equals("true")) {
+            assertEquals(IndexToolTableUtil.RESULT_TABLE_FULL_NAME, 
tableName.replace(QueryConstants.NAME_SEPARATOR,
+                    QueryConstants.NAMESPACE_SEPARATOR));
+        } else {
+            assertEquals(IndexToolTableUtil.RESULT_TABLE_FULL_NAME, tableName);
+        }
+
+    }
+
+}
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesNameSpaceMappingDisabledIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesNameSpaceMappingDisabledIT.java
new file mode 100644
index 0000000000..f339550d61
--- /dev/null
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIndexToolTablesNameSpaceMappingDisabledIT.java
@@ -0,0 +1,31 @@
+/*
+ * 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.end2end;
+
+import org.junit.Before;
+
+
+public class UpgradeIndexToolTablesNameSpaceMappingDisabledIT extends 
UpgradeIndexToolTablesIT {
+
+    @Override
+    @Before
+    public synchronized void doSetup() throws Exception {
+        nameSpaceMapping = "false";
+        setupCluster(nameSpaceMapping);
+    }
+}
diff --git 
a/phoenix-core/src/it/resources/indexToolResultSnapshot/indexToolsnapshot.tar.gz
 
b/phoenix-core/src/it/resources/indexToolResultSnapshot/indexToolsnapshot.tar.gz
new file mode 100644
index 0000000000..9d75746276
Binary files /dev/null and 
b/phoenix-core/src/it/resources/indexToolResultSnapshot/indexToolsnapshot.tar.gz
 differ

Reply via email to