Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id EF255200B6A for ; Mon, 22 Aug 2016 19:39:36 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id EDB73160AB3; Mon, 22 Aug 2016 17:39:36 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 742CC160A87 for ; Mon, 22 Aug 2016 19:39:35 +0200 (CEST) Received: (qmail 23505 invoked by uid 500); 22 Aug 2016 17:39:34 -0000 Mailing-List: contact commits-help@phoenix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@phoenix.apache.org Delivered-To: mailing list commits@phoenix.apache.org Received: (qmail 23492 invoked by uid 99); 22 Aug 2016 17:39:34 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 22 Aug 2016 17:39:34 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 86223DFF8D; Mon, 22 Aug 2016 17:39:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: samarth@apache.org To: commits@phoenix.apache.org Message-Id: <925b4305f08c401a8ce85ad95fee0ca7@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: phoenix git commit: PHOENIX-808 Create snapshot of SYSTEM.CATALOG prior to upgrade and restore on any failure Date: Mon, 22 Aug 2016 17:39:34 +0000 (UTC) archived-at: Mon, 22 Aug 2016 17:39:37 -0000 Repository: phoenix Updated Branches: refs/heads/4.x-HBase-0.98 25e79e292 -> 875c701c2 PHOENIX-808 Create snapshot of SYSTEM.CATALOG prior to upgrade and restore on any failure Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/875c701c Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/875c701c Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/875c701c Branch: refs/heads/4.x-HBase-0.98 Commit: 875c701c2c8255a64a463b78140b8dd98763ebaa Parents: 25e79e2 Author: Samarth Authored: Mon Aug 22 10:36:19 2016 -0700 Committer: Samarth Committed: Mon Aug 22 10:36:19 2016 -0700 ---------------------------------------------------------------------- .../phoenix/coprocessor/MetaDataProtocol.java | 19 + .../query/ConnectionQueryServicesImpl.java | 365 ++++++++++++------- .../org/apache/phoenix/util/UpgradeUtil.java | 11 + 3 files changed, 271 insertions(+), 124 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/875c701c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java index 8982fe7..dce89bd 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java @@ -19,7 +19,9 @@ package org.apache.phoenix.coprocessor; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.phoenix.coprocessor.generated.MetaDataProtos; @@ -27,6 +29,7 @@ import org.apache.phoenix.coprocessor.generated.MetaDataProtos.MetaDataResponse; import org.apache.phoenix.coprocessor.generated.MetaDataProtos.MetaDataService; import org.apache.phoenix.coprocessor.generated.PFunctionProtos; import org.apache.phoenix.hbase.index.util.VersionUtil; +import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.parse.PFunction; import org.apache.phoenix.parse.PSchema; import org.apache.phoenix.schema.PColumn; @@ -83,6 +86,22 @@ public abstract class MetaDataProtocol extends MetaDataService { public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0 = MIN_TABLE_TIMESTAMP + 18; // MIN_SYSTEM_TABLE_TIMESTAMP needs to be set to the max of all the MIN_SYSTEM_TABLE_TIMESTAMP_* constants public static final long MIN_SYSTEM_TABLE_TIMESTAMP = MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0; + + // ALWAYS update this map whenever rolling out a new release (major, minor or patch release). + // Key is the SYSTEM.CATALOG timestamp for the version and value is the version string. + public static final Map TIMESTAMP_VERSION_MAP = new HashMap<>(10); + static { + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_1_0, "4.1.x"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_2_0, "4.2.0"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_2_1, "4.2.1"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0, "4.3.x"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0, "4.5.x"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0, "4.6.x"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0, "4.7.x"); + TIMESTAMP_VERSION_MAP.put(MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0, "4.8.x"); + } + public static final String CURRENT_CLIENT_VERSION = PHOENIX_MAJOR_VERSION + "." + PHOENIX_MINOR_VERSION + "." + PHOENIX_PATCH_NUMBER; + // TODO: pare this down to minimum, as we don't need duplicates for both table and column errors, nor should we need // a different code for every type of error. // ENTITY_ALREADY_EXISTS, ENTITY_NOT_FOUND, NEWER_ENTITY_FOUND, ENTITY_NOT_IN_REGION, CONCURRENT_MODIFICATION http://git-wip-us.apache.org/repos/asf/phoenix/blob/875c701c/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java index 7fd35a4..9e4ec53 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java @@ -19,10 +19,15 @@ package org.apache.phoenix.query; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.apache.hadoop.hbase.HColumnDescriptor.TTL; +import static org.apache.phoenix.coprocessor.MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP; import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MAJOR_VERSION; import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MINOR_VERSION; import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_PATCH_NUMBER; +import static org.apache.phoenix.util.UpgradeUtil.getUpgradeSnapshotName; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_SEQUENCE; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_STATS_NAME; import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_DROP_METADATA; import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_RENEW_LEASE_ENABLED; import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_RENEW_LEASE_THREAD_POOL_SIZE; @@ -84,6 +89,8 @@ import org.apache.hadoop.hbase.ipc.ServerRpcController; import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto; import org.apache.hadoop.hbase.regionserver.IndexHalfStoreFileReaderGenerator; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException; +import org.apache.hadoop.hbase.snapshot.SnapshotCreationException; import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; @@ -2298,6 +2305,9 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } checkClosed(); PhoenixConnection metaConnection = null; + boolean success = false; + String snapshotName = null; + String sysCatalogTableName = null; try { openConnection(); String noUpgradeProp = props.getProperty(PhoenixRuntime.NO_UPGRADE_ATTRIB); @@ -2328,148 +2338,150 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement + " is found but client does not have " + IS_NAMESPACE_MAPPING_ENABLED + " enabled") .build().buildException(); } - } - + } try { metaConnection.createStatement().executeUpdate(QueryConstants.CREATE_TABLE_METADATA); - } catch (NewerTableAlreadyExistsException ignore) { // Ignore, as this will happen if the SYSTEM.CATALOG already exists at this fixed timestamp. // A TableAlreadyExistsException is not thrown, since the table only exists *after* this fixed timestamp. } catch (TableAlreadyExistsException e) { if (upgradeSystemTables) { - // This will occur if we have an older SYSTEM.CATALOG and we need to update it to include - // any new columns we've added. long currentServerSideTableTimeStamp = e.getTable().getTimeStamp(); - - String columnsToAdd = ""; - if(currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0) { - // We know that we always need to add the STORE_NULLS column for 4.3 release - columnsToAdd = addColumn(columnsToAdd, PhoenixDatabaseMetaData.STORE_NULLS + " " + PBoolean.INSTANCE.getSqlTypeName()); - try (HBaseAdmin admin = getAdmin()) { - HTableDescriptor[] localIndexTables = admin.listTables(MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX+".*"); - for (HTableDescriptor table : localIndexTables) { - if (table.getValue(MetaDataUtil.PARENT_TABLE_KEY) == null - && table.getValue(MetaDataUtil.IS_LOCAL_INDEX_TABLE_PROP_NAME) != null) { - table.setValue(MetaDataUtil.PARENT_TABLE_KEY, - MetaDataUtil.getUserTableName(table - .getNameAsString())); - // Explicitly disable, modify and enable the table to ensure co-location of data - // and index regions. If we just modify the table descriptor when online schema - // change enabled may reopen the region in same region server instead of following data region. - admin.disableTable(table.getTableName()); - admin.modifyTable(table.getTableName(), table); - admin.enableTable(table.getTableName()); + sysCatalogTableName = e.getTable().getPhysicalName().getString(); + if (currentServerSideTableTimeStamp < MIN_SYSTEM_TABLE_TIMESTAMP) { + snapshotName = getUpgradeSnapshotName(sysCatalogTableName, currentServerSideTableTimeStamp); + createSnapshot(snapshotName, sysCatalogTableName); + } + String columnsToAdd = ""; + // This will occur if we have an older SYSTEM.CATALOG and we need to update it to include + // any new columns we've added. + if(currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0) { + // We know that we always need to add the STORE_NULLS column for 4.3 release + columnsToAdd = addColumn(columnsToAdd, PhoenixDatabaseMetaData.STORE_NULLS + " " + PBoolean.INSTANCE.getSqlTypeName()); + try (HBaseAdmin admin = getAdmin()) { + HTableDescriptor[] localIndexTables = admin.listTables(MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX+".*"); + for (HTableDescriptor table : localIndexTables) { + if (table.getValue(MetaDataUtil.PARENT_TABLE_KEY) == null + && table.getValue(MetaDataUtil.IS_LOCAL_INDEX_TABLE_PROP_NAME) != null) { + table.setValue(MetaDataUtil.PARENT_TABLE_KEY, + MetaDataUtil.getUserTableName(table + .getNameAsString())); + // Explicitly disable, modify and enable the table to ensure co-location of data + // and index regions. If we just modify the table descriptor when online schema + // change enabled may reopen the region in same region server instead of following data region. + admin.disableTable(table.getTableName()); + admin.modifyTable(table.getTableName(), table); + admin.enableTable(table.getTableName()); + } } } } - } - // If the server side schema is before MIN_SYSTEM_TABLE_TIMESTAMP_4_1_0 then - // we need to add INDEX_TYPE and INDEX_DISABLE_TIMESTAMP columns too. - // TODO: Once https://issues.apache.org/jira/browse/PHOENIX-1614 is fixed, - // we should just have a ALTER TABLE ADD IF NOT EXISTS statement with all - // the column names that have been added to SYSTEM.CATALOG since 4.0. - if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_1_0) { - columnsToAdd = addColumn(columnsToAdd, PhoenixDatabaseMetaData.INDEX_TYPE + " " + PUnsignedTinyint.INSTANCE.getSqlTypeName() - + ", " + PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP + " " + PLong.INSTANCE.getSqlTypeName()); - } - - // If we have some new columns from 4.1-4.3 to add, add them now. - if (!columnsToAdd.isEmpty()) { - // Ugh..need to assign to another local variable to keep eclipse happy. - PhoenixConnection newMetaConnection = addColumnsIfNotExists(metaConnection, - PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0, columnsToAdd); - metaConnection = newMetaConnection; - } + // If the server side schema is before MIN_SYSTEM_TABLE_TIMESTAMP_4_1_0 then + // we need to add INDEX_TYPE and INDEX_DISABLE_TIMESTAMP columns too. + // TODO: Once https://issues.apache.org/jira/browse/PHOENIX-1614 is fixed, + // we should just have a ALTER TABLE ADD IF NOT EXISTS statement with all + // the column names that have been added to SYSTEM.CATALOG since 4.0. + if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_1_0) { + columnsToAdd = addColumn(columnsToAdd, PhoenixDatabaseMetaData.INDEX_TYPE + " " + PUnsignedTinyint.INSTANCE.getSqlTypeName() + + ", " + PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP + " " + PLong.INSTANCE.getSqlTypeName()); + } - if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0) { - columnsToAdd = PhoenixDatabaseMetaData.BASE_COLUMN_COUNT + " " - + PInteger.INSTANCE.getSqlTypeName(); - try { - metaConnection = addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0, columnsToAdd, false); - upgradeTo4_5_0(metaConnection); - } catch (ColumnAlreadyExistsException ignored) { - /* - * Upgrade to 4.5 is a slightly special case. We use the fact that the column - * BASE_COLUMN_COUNT is already part of the meta-data schema as the signal that - * the server side upgrade has finished or is in progress. - */ - logger.debug("No need to run 4.5 upgrade"); + // If we have some new columns from 4.1-4.3 to add, add them now. + if (!columnsToAdd.isEmpty()) { + // Ugh..need to assign to another local variable to keep eclipse happy. + PhoenixConnection newMetaConnection = addColumnsIfNotExists(metaConnection, + PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0, columnsToAdd); + metaConnection = newMetaConnection; } - Properties props = PropertiesUtil.deepCopy(metaConnection.getClientInfo()); - props.remove(PhoenixRuntime.CURRENT_SCN_ATTRIB); - props.remove(PhoenixRuntime.TENANT_ID_ATTRIB); - PhoenixConnection conn = new PhoenixConnection(ConnectionQueryServicesImpl.this, metaConnection.getURL(), props, metaConnection.getMetaDataCache()); - try { - List tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescRowKey(conn); - if (!tablesNeedingUpgrade.isEmpty()) { - logger.warn("The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns and ascending BINARY columns (PHOENIX-2067 and PHOENIX-2120):\n" + Joiner.on(' ').join(tablesNeedingUpgrade) + "\nTo upgrade issue the \"bin/psql.py -u\" command."); + + if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0) { + columnsToAdd = PhoenixDatabaseMetaData.BASE_COLUMN_COUNT + " " + + PInteger.INSTANCE.getSqlTypeName(); + try { + metaConnection = addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0, columnsToAdd, false); + upgradeTo4_5_0(metaConnection); + } catch (ColumnAlreadyExistsException ignored) { + /* + * Upgrade to 4.5 is a slightly special case. We use the fact that the column + * BASE_COLUMN_COUNT is already part of the meta-data schema as the signal that + * the server side upgrade has finished or is in progress. + */ + logger.debug("No need to run 4.5 upgrade"); } - List unsupportedTables = UpgradeUtil.getPhysicalTablesWithDescVarbinaryRowKey(conn); - if (!unsupportedTables.isEmpty()) { - logger.warn("The following tables use an unsupported VARBINARY DESC construct and need to be changed:\n" + Joiner.on(' ').join(unsupportedTables)); + Properties props = PropertiesUtil.deepCopy(metaConnection.getClientInfo()); + props.remove(PhoenixRuntime.CURRENT_SCN_ATTRIB); + props.remove(PhoenixRuntime.TENANT_ID_ATTRIB); + PhoenixConnection conn = new PhoenixConnection(ConnectionQueryServicesImpl.this, metaConnection.getURL(), props, metaConnection.getMetaDataCache()); + try { + List tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescRowKey(conn); + if (!tablesNeedingUpgrade.isEmpty()) { + logger.warn("The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns and ascending BINARY columns (PHOENIX-2067 and PHOENIX-2120):\n" + Joiner.on(' ').join(tablesNeedingUpgrade) + "\nTo upgrade issue the \"bin/psql.py -u\" command."); + } + List unsupportedTables = UpgradeUtil.getPhysicalTablesWithDescVarbinaryRowKey(conn); + if (!unsupportedTables.isEmpty()) { + logger.warn("The following tables use an unsupported VARBINARY DESC construct and need to be changed:\n" + Joiner.on(' ').join(unsupportedTables)); + } + } catch (Exception ex) { + logger.error("Unable to determine tables requiring upgrade due to PHOENIX-2067", ex); + } finally { + conn.close(); } - } catch (Exception ex) { - logger.error("Unable to determine tables requiring upgrade due to PHOENIX-2067", ex); - } finally { - conn.close(); } - } - // Add these columns one at a time, each with different timestamps so that if folks have - // run the upgrade code already for a snapshot, we'll still enter this block (and do the - // parts we haven't yet done). - if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0) { - columnsToAdd = PhoenixDatabaseMetaData.IS_ROW_TIMESTAMP + " " + PBoolean.INSTANCE.getSqlTypeName(); - metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0, columnsToAdd); - } - if(currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0) { - // Drop old stats table so that new stats table is created - metaConnection = dropStatsTable(metaConnection, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 4); - metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 3, - PhoenixDatabaseMetaData.TRANSACTIONAL + " " + PBoolean.INSTANCE.getSqlTypeName()); - metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 2, - PhoenixDatabaseMetaData.UPDATE_CACHE_FREQUENCY + " " + PLong.INSTANCE.getSqlTypeName()); - metaConnection = setImmutableTableIndexesImmutable(metaConnection, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 1); - metaConnection = updateSystemCatalogTimestamp(metaConnection, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0); - ConnectionQueryServicesImpl.this.removeTable(null, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME, null, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0); - clearCache(); - } + // Add these columns one at a time, each with different timestamps so that if folks have + // run the upgrade code already for a snapshot, we'll still enter this block (and do the + // parts we haven't yet done). + if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0) { + columnsToAdd = PhoenixDatabaseMetaData.IS_ROW_TIMESTAMP + " " + PBoolean.INSTANCE.getSqlTypeName(); + metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0, columnsToAdd); + } + if(currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0) { + // Drop old stats table so that new stats table is created + metaConnection = dropStatsTable(metaConnection, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 4); + metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 3, + PhoenixDatabaseMetaData.TRANSACTIONAL + " " + PBoolean.INSTANCE.getSqlTypeName()); + metaConnection = addColumnsIfNotExists(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 2, + PhoenixDatabaseMetaData.UPDATE_CACHE_FREQUENCY + " " + PLong.INSTANCE.getSqlTypeName()); + metaConnection = setImmutableTableIndexesImmutable(metaConnection, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 1); + metaConnection = updateSystemCatalogTimestamp(metaConnection, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0); + ConnectionQueryServicesImpl.this.removeTable(null, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME, null, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0); + clearCache(); + } - if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0) { - metaConnection = addColumnsIfNotExists(metaConnection, - PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0 - 2, - PhoenixDatabaseMetaData.IS_NAMESPACE_MAPPED + " " - + PBoolean.INSTANCE.getSqlTypeName()); - metaConnection = addColumnsIfNotExists(metaConnection, - PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0 - 1, - PhoenixDatabaseMetaData.AUTO_PARTITION_SEQ + " " - + PVarchar.INSTANCE.getSqlTypeName()); - metaConnection = addColumnsIfNotExists(metaConnection, - PhoenixDatabaseMetaData.SYSTEM_CATALOG, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0, - PhoenixDatabaseMetaData.APPEND_ONLY_SCHEMA + " " - + PBoolean.INSTANCE.getSqlTypeName()); - metaConnection = UpgradeUtil.disableViewIndexes(metaConnection); - if(getProps().getBoolean(QueryServices.LOCAL_INDEX_CLIENT_UPGRADE_ATTRIB, - QueryServicesOptions.DEFAULT_LOCAL_INDEX_CLIENT_UPGRADE)) { - metaConnection = UpgradeUtil.upgradeLocalIndexes(metaConnection); + if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0) { + metaConnection = addColumnsIfNotExists(metaConnection, + PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0 - 2, + PhoenixDatabaseMetaData.IS_NAMESPACE_MAPPED + " " + + PBoolean.INSTANCE.getSqlTypeName()); + metaConnection = addColumnsIfNotExists(metaConnection, + PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0 - 1, + PhoenixDatabaseMetaData.AUTO_PARTITION_SEQ + " " + + PVarchar.INSTANCE.getSqlTypeName()); + metaConnection = addColumnsIfNotExists(metaConnection, + PhoenixDatabaseMetaData.SYSTEM_CATALOG, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0, + PhoenixDatabaseMetaData.APPEND_ONLY_SCHEMA + " " + + PBoolean.INSTANCE.getSqlTypeName()); + metaConnection = UpgradeUtil.disableViewIndexes(metaConnection); + if(getProps().getBoolean(QueryServices.LOCAL_INDEX_CLIENT_UPGRADE_ATTRIB, + QueryServicesOptions.DEFAULT_LOCAL_INDEX_CLIENT_UPGRADE)) { + metaConnection = UpgradeUtil.upgradeLocalIndexes(metaConnection); + } + ConnectionQueryServicesImpl.this.removeTable(null, + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME, null, + MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0); + clearCache(); } - ConnectionQueryServicesImpl.this.removeTable(null, - PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME, null, - MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0); - clearCache(); - } } } @@ -2527,7 +2539,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement if (currentServerSideTableTimeStamp < MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0) { metaConnection = addColumnsIfNotExists( metaConnection, - PhoenixDatabaseMetaData.SYSTEM_STATS_NAME, + SYSTEM_STATS_NAME, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP, PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT + " " + PLong.INSTANCE.getSqlTypeName()); @@ -2547,6 +2559,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement + PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA); } catch (NewerSchemaAlreadyExistsException e) {} } + success = true; scheduleRenewLeaseTasks(); } catch (Exception e) { if (e instanceof SQLException) { @@ -2566,6 +2579,15 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } } finally { try { + restoreFromSnapshot(sysCatalogTableName, snapshotName, success); + } catch (SQLException e) { + if (initializationException != null) { + initializationException.setNextException(e); + } else { + initializationException = e; + } + } + try { if (initializationException != null) { throw initializationException; } @@ -2578,6 +2600,101 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement return null; } + private void createSnapshot(String snapshotName, String tableName) + throws SQLException { + HBaseAdmin admin = null; + SQLException sqlE = null; + try { + admin = getAdmin(); + admin.snapshot(snapshotName, tableName); + logger.info("Successfully created snapshot " + snapshotName + " for " + + tableName); + } catch (Exception e) { + sqlE = new SQLException(e); + } finally { + try { + if (admin != null) { + admin.close(); + } + } catch (Exception e) { + SQLException adminCloseEx = new SQLException(e); + if (sqlE == null) { + sqlE = adminCloseEx; + } else { + sqlE.setNextException(adminCloseEx); + } + } finally { + if (sqlE != null) { + throw sqlE; + } + } + } + } + + private void restoreFromSnapshot(String tableName, String snapshotName, + boolean success) throws SQLException { + boolean snapshotRestored = false; + boolean tableDisabled = false; + if (!success && snapshotName != null) { + SQLException sqlE = null; + HBaseAdmin admin = null; + try { + logger.warn("Starting restore of " + tableName + " using snapshot " + + snapshotName + " because upgrade failed"); + admin = getAdmin(); + admin.disableTable(tableName); + tableDisabled = true; + admin.restoreSnapshot(snapshotName); + snapshotRestored = true; + logger.warn("Successfully restored " + tableName + " using snapshot " + + snapshotName); + } catch (Exception e) { + sqlE = new SQLException(e); + } finally { + if (admin != null && tableDisabled) { + try { + admin.enableTable(tableName); + if (snapshotRestored) { + logger.warn("Successfully restored and enabled " + tableName + " using snapshot " + + snapshotName); + } else { + logger.warn("Successfully enabled " + tableName + " after restoring using snapshot " + + snapshotName + " failed. "); + } + } catch (Exception e1) { + SQLException enableTableEx = new SQLException(e1); + if (sqlE == null) { + sqlE = enableTableEx; + } else { + sqlE.setNextException(enableTableEx); + } + logger.error("Failure in enabling " + + tableName + + (snapshotRestored ? " after successfully restoring using snapshot" + + snapshotName + : " after restoring using snapshot " + + snapshotName + " failed. ")); + } finally { + try { + admin.close(); + } catch (Exception e2) { + SQLException adminCloseEx = new SQLException(e2); + if (sqlE == null) { + sqlE = adminCloseEx; + } else { + sqlE.setNextException(adminCloseEx); + } + } finally { + if (sqlE != null) { + throw sqlE; + } + } + } + } + } + } + } + private void ensureSystemTablesUpgraded(ReadOnlyProps props) throws SQLException, IOException, IllegalArgumentException, InterruptedException { if (!SchemaUtil.isNamespaceMappingEnabled(PTableType.SYSTEM, props)) { return; } http://git-wip-us.apache.org/repos/asf/phoenix/blob/875c701c/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java index c9bb738..b2e8bbc 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java @@ -18,6 +18,8 @@ package org.apache.phoenix.util; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.phoenix.coprocessor.MetaDataProtocol.CURRENT_CLIENT_VERSION; +import static org.apache.phoenix.coprocessor.MetaDataProtocol.TIMESTAMP_VERSION_MAP; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ARRAY_SIZE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.CACHE_SIZE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_FAMILY; @@ -51,10 +53,13 @@ import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_ import java.io.IOException; import java.sql.Connection; +import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.text.Format; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -1890,4 +1895,10 @@ public class UpgradeUtil { } } + public static final String getUpgradeSnapshotName(String tableString, long currentSystemTableTimestamp) { + Format formatter = new SimpleDateFormat("yyyyMMddHHmmssZ"); + String date = formatter.format(new Date(System.currentTimeMillis())); + String upgradingFrom = TIMESTAMP_VERSION_MAP.get(currentSystemTableTimestamp); + return "SNAPSHOT_" + tableString + "_" + upgradingFrom + "_TO_" + CURRENT_CLIENT_VERSION + "_" + date; + } } \ No newline at end of file