Repository: phoenix Updated Branches: refs/heads/calcite 9ac854ae5 -> 36ee23ab7
PHOENIX-2706 Implement client-side mechanism to know if stats are enabled Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/a1e6ae44 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/a1e6ae44 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/a1e6ae44 Branch: refs/heads/calcite Commit: a1e6ae44be757b3fc5c4192ad55ecd8f3c03c01a Parents: e4acd0c Author: James Taylor <jtay...@salesforce.com> Authored: Mon Feb 22 18:49:04 2016 -0800 Committer: James Taylor <jtay...@salesforce.com> Committed: Mon Feb 22 18:49:04 2016 -0800 ---------------------------------------------------------------------- .../StatisticsCollectionRunTrackerIT.java | 10 ++-- .../org/apache/phoenix/end2end/IndexToolIT.java | 3 +- .../phoenix/end2end/MutableIndexToolIT.java | 1 + .../end2end/StatsCollectionDisabledIT.java | 19 +++++-- .../phoenix/end2end/StatsCollectorIT.java | 3 ++ .../coprocessor/MetaDataEndpointImpl.java | 12 +---- .../UngroupedAggregateRegionObserver.java | 27 +++++----- .../phoenix/iterate/BaseResultIterators.java | 25 ++++++++- .../phoenix/query/ConnectionQueryServices.java | 7 ++- .../query/ConnectionQueryServicesImpl.java | 25 +++++++-- .../query/ConnectionlessQueryServicesImpl.java | 18 ++++++- .../query/DelegateConnectionQueryServices.java | 10 ++++ .../org/apache/phoenix/query/QueryServices.java | 1 + .../phoenix/query/QueryServicesOptions.java | 7 +++ .../apache/phoenix/schema/MetaDataClient.java | 2 + .../schema/stats/NoOpStatisticsCollector.java | 3 -- .../stats/StatisticsCollectionRunTracker.java | 7 ++- .../phoenix/schema/stats/StatisticsUtil.java | 16 ++++++ .../org/apache/phoenix/util/MetaDataUtil.java | 55 +++++++++++++------- .../phoenix/query/QueryServicesTestImpl.java | 2 + .../apache/phoenix/util/MetaDataUtilTest.java | 33 ++++++++++++ 21 files changed, 215 insertions(+), 71 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/it/java/org/apache/phoenix/coprocessor/StatisticsCollectionRunTrackerIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/coprocessor/StatisticsCollectionRunTrackerIT.java b/phoenix-core/src/it/java/org/apache/phoenix/coprocessor/StatisticsCollectionRunTrackerIT.java index bf567f0..345400e 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/coprocessor/StatisticsCollectionRunTrackerIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/coprocessor/StatisticsCollectionRunTrackerIT.java @@ -17,8 +17,7 @@ */ package org.apache.phoenix.coprocessor; -import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.COMPACTION_UPDATE_STATS_ROW_COUNT; -import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.CONCURRENT_UPDATE_STATS_ROW_COUNT; +import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.UPDATE_STATS_SKIPPED; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -38,7 +37,6 @@ import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker; import org.apache.phoenix.util.ReadOnlyProps; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -105,7 +103,8 @@ public class StatisticsCollectionRunTrackerIT extends BaseOwnClusterHBaseManaged HRegionInfo regionInfo = createTableAndGetRegion(tableName); // simulate stats collection via major compaction by marking the region as compacting in the tracker markRegionAsCompacting(regionInfo); - Assert.assertEquals("Row count didn't match", COMPACTION_UPDATE_STATS_ROW_COUNT, runUpdateStats(tableName)); + long returnValue = runUpdateStats(tableName); + assertTrue("Update stats should have been skipped", returnValue >= UPDATE_STATS_SKIPPED); StatisticsCollectionRunTracker tracker = StatisticsCollectionRunTracker.getInstance(new Configuration()); // assert that the tracker state was cleared. @@ -117,8 +116,7 @@ public class StatisticsCollectionRunTrackerIT extends BaseOwnClusterHBaseManaged String tableName = "testUpdateStatsPreventsAnotherUpdateStatsFromRunning".toUpperCase(); HRegionInfo regionInfo = createTableAndGetRegion(tableName); markRunningUpdateStats(regionInfo); - Assert.assertEquals("Row count didn't match", CONCURRENT_UPDATE_STATS_ROW_COUNT, - runUpdateStats(tableName)); + assertTrue("Update stats should have been skipped", runUpdateStats(tableName) >= UPDATE_STATS_SKIPPED); // assert that running the concurrent and race-losing update stats didn't clear the region // from the tracker. If the method returned true it means the tracker was still tracking http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java ---------------------------------------------------------------------- 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 aba9c11..fe95470 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 @@ -108,7 +108,8 @@ public class IndexToolIT extends BaseOwnClusterHBaseManagedTimeIT { final String fullTableName = SchemaUtil.getTableName(schemaName, dataTable); final String indxTable = String.format("%s_%s", dataTable, "INDX"); Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); - props.setProperty(QueryServices.TRANSACTIONS_ENABLED, "true"); + props.setProperty(QueryServices.TRANSACTIONS_ENABLED, Boolean.TRUE.toString()); + props.setProperty(QueryServices.EXPLAIN_ROW_COUNT_ATTRIB, Boolean.FALSE.toString()); Connection conn = DriverManager.getConnection(getUrl(), props); Statement stmt = conn.createStatement(); try { http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/it/java/org/apache/phoenix/end2end/MutableIndexToolIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MutableIndexToolIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MutableIndexToolIT.java index 0791479..8125007 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MutableIndexToolIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MutableIndexToolIT.java @@ -61,6 +61,7 @@ public class MutableIndexToolIT extends BaseOwnClusterHBaseManagedTimeIT { final String dataTable = "DATA_TABLE5"; final String indxTable = String.format("%s_%s",dataTable,"INDX"); Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + props.setProperty(QueryServices.EXPLAIN_ROW_COUNT_ATTRIB, Boolean.FALSE.toString()); Connection conn = DriverManager.getConnection(getUrl(), props); Statement stmt = conn.createStatement(); try { http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectionDisabledIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectionDisabledIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectionDisabledIT.java index a92a665..c3cdbc0 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectionDisabledIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectionDisabledIT.java @@ -17,24 +17,27 @@ */ package org.apache.phoenix.end2end; +import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import java.sql.Connection; import java.sql.DriverManager; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Map; import java.util.Properties; -import com.google.common.collect.Maps; +import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.util.PropertiesUtil; import org.apache.phoenix.util.ReadOnlyProps; import org.junit.BeforeClass; import org.junit.Test; -import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; -import static org.junit.Assert.assertFalse; +import com.google.common.collect.Maps; /** * Verifies that statistics are not collected if they are disabled via a setting @@ -54,15 +57,21 @@ public class StatsCollectionDisabledIT extends StatsCollectorAbstractIT { public void testStatisticsAreNotWritten() throws SQLException { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); Connection conn = DriverManager.getConnection(getUrl(), props); + assertFalse(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE T1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR)"); + stmt.execute("CREATE TABLE T1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR) SALT_BUCKETS=3"); stmt.execute("UPSERT INTO T1 VALUES (1, 'NAME1')"); stmt.execute("UPSERT INTO T1 VALUES (2, 'NAME2')"); stmt.execute("UPSERT INTO T1 VALUES (3, 'NAME3')"); conn.commit(); stmt.execute("UPDATE STATISTICS T1"); + assertFalse(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); ResultSet rs = stmt.executeQuery("SELECT * FROM SYSTEM.STATS"); assertFalse(rs.next()); + rs = conn.createStatement().executeQuery("SELECT count(*) FROM T1"); + assertTrue(rs.next()); + assertEquals(3,rs.getInt(1)); + assertFalse(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); rs.close(); stmt.close(); conn.close(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java index e72f41f..6cd8e13 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java @@ -94,6 +94,7 @@ public class StatsCollectorIT extends StatsCollectorAbstractIT { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); // props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10)); conn = DriverManager.getConnection(getUrl(), props); + assertTrue(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); conn.createStatement().execute( "CREATE TABLE " + fullTableName +" ( k VARCHAR, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4] \n" + " CONSTRAINT pk PRIMARY KEY (k, b_string_array DESC))" @@ -104,6 +105,7 @@ public class StatsCollectorIT extends StatsCollectorAbstractIT { // CAll the update statistics query here. If already major compaction has run this will not get executed. stmt = conn.prepareStatement("UPDATE STATISTICS " + tableName); stmt.execute(); + assertTrue(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); stmt = upsertStmt(conn, tableName); stmt.setString(1, "z"); s = new String[] { "xyz", "def", "ghi", "jkll", null, null, "xxx" }; @@ -120,6 +122,7 @@ public class StatsCollectorIT extends StatsCollectorAbstractIT { stmt.execute(); rs = conn.createStatement().executeQuery("SELECT k FROM " + tableName); assertTrue(rs.next()); + assertTrue(conn.unwrap(PhoenixConnection.class).getQueryServices().areStatsEnabled()); conn.close(); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java index ba7eb39..411ce03 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java @@ -138,7 +138,6 @@ import org.apache.phoenix.expression.LiteralExpression; import org.apache.phoenix.hbase.index.covered.update.ColumnReference; import org.apache.phoenix.hbase.index.util.GenericKeyValueBuilder; import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; -import org.apache.phoenix.hbase.index.util.IndexManagementUtil; import org.apache.phoenix.index.IndexMaintainer; import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; @@ -2717,16 +2716,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso RpcCallback<GetVersionResponse> done) { GetVersionResponse.Builder builder = GetVersionResponse.newBuilder(); - // The first 3 bytes of the long is used to encoding the HBase version as major.minor.patch. - // The next 4 bytes of the value is used to encode the Phoenix version as major.minor.patch. - long version = MetaDataUtil.encodeHBaseAndPhoenixVersions(this.env.getHBaseVersion()); - - // The last byte is used to communicate whether or not mutable secondary indexing - // was configured properly. - version = - MetaDataUtil.encodeHasIndexWALCodec(version, - IndexManagementUtil.isWALEditCodecSet(this.env.getConfiguration())); - + long version = MetaDataUtil.encodeVersion(env.getHBaseVersion(), env.getConfiguration()); builder.setVersion(version); done.run(builder.build()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java index 6550653..7c98be0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java @@ -22,8 +22,9 @@ import static org.apache.phoenix.query.QueryConstants.SINGLE_COLUMN; import static org.apache.phoenix.query.QueryConstants.SINGLE_COLUMN_FAMILY; import static org.apache.phoenix.query.QueryConstants.UNGROUPED_AGG_ROW_KEY; import static org.apache.phoenix.query.QueryServices.MUTATE_BATCH_SIZE_ATTRIB; -import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.COMPACTION_UPDATE_STATS_ROW_COUNT; -import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.CONCURRENT_UPDATE_STATS_ROW_COUNT; +import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.UPDATE_STATS_DISABLED; +import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.UPDATE_STATS_RUN; +import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.UPDATE_STATS_SKIPPED; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -59,7 +60,6 @@ import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.regionserver.ScanType; import org.apache.hadoop.hbase.regionserver.Store; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.io.WritableUtils; import org.apache.phoenix.coprocessor.generated.PTableProtos; import org.apache.phoenix.exception.DataExceedsCapacityException; @@ -90,6 +90,7 @@ import org.apache.phoenix.schema.ValueSchema.Field; import org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker; import org.apache.phoenix.schema.stats.StatisticsCollector; import org.apache.phoenix.schema.stats.StatisticsCollectorFactory; +import org.apache.phoenix.schema.stats.StatisticsUtil; import org.apache.phoenix.schema.tuple.MultiKeyValueTuple; import org.apache.phoenix.schema.types.PBinary; import org.apache.phoenix.schema.types.PChar; @@ -608,7 +609,6 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver InternalScanner internalScanner = scanner; if (scanType.equals(ScanType.COMPACT_DROP_DELETES)) { try { - Pair<HRegionInfo, HRegionInfo> mergeRegions = null; long clientTimeStamp = TimeKeeper.SYSTEM.getCurrentTime(); StatisticsCollector stats = StatisticsCollectorFactory.createStatisticsCollector( c.getEnvironment(), table.getNameAsString(), clientTimeStamp, @@ -643,22 +643,23 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver if (asyncBytes != null) { async = Bytes.toBoolean(asyncBytes); } - long rowCount = 0; // in case of async, we report 0 as number of rows updated + long returnValue = UPDATE_STATS_RUN; // in case of async, we report 1 as number of rows updated + boolean statsEnabled = StatisticsUtil.isStatsEnabled(config); StatisticsCollectionRunTracker statsRunTracker = StatisticsCollectionRunTracker.getInstance(config); - boolean runUpdateStats = statsRunTracker.addUpdateStatsCommandRegion(region.getRegionInfo()); + boolean runUpdateStats = statsEnabled && statsRunTracker.addUpdateStatsCommandRegion(region.getRegionInfo()); if (runUpdateStats) { if (!async) { - rowCount = callable.call(); + returnValue = callable.call(); } else { statsRunTracker.runTask(callable); } } else { - rowCount = CONCURRENT_UPDATE_STATS_ROW_COUNT; - logger.info("UPDATE STATISTICS didn't run because another UPDATE STATISTICS command was already running on the region " + returnValue = statsEnabled ? UPDATE_STATS_SKIPPED : UPDATE_STATS_DISABLED; + logger.info("UPDATE STATISTICS didn't run because " + (statsEnabled ? " another UPDATE STATISTICS command was already running on the region " : " stats are disabled ") + region.getRegionInfo().getRegionNameAsString()); } - byte[] rowCountBytes = PLong.INSTANCE.toBytes(Long.valueOf(rowCount)); + byte[] rowCountBytes = PLong.INSTANCE.toBytes(Long.valueOf(returnValue)); final KeyValue aggKeyValue = KeyValueUtil.newKeyValue(UNGROUPED_AGG_ROW_KEY, SINGLE_COLUMN_FAMILY, SINGLE_COLUMN, AGG_TIMESTAMP, rowCountBytes, 0, rowCountBytes.length); @@ -728,22 +729,22 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver region.startRegionOperation(); boolean hasMore = false; boolean noErrors = false; - boolean compactionRunning = areStatsBeingCollectedViaCompaction(); long rowCount = 0; + boolean compactionRunning = areStatsBeingCollectedViaCompaction(); try { if (!compactionRunning) { synchronized (innerScanner) { do { List<Cell> results = new ArrayList<Cell>(); hasMore = innerScanner.nextRaw(results); - stats.collectStatistics(results); rowCount++; + stats.collectStatistics(results); compactionRunning = areStatsBeingCollectedViaCompaction(); } while (hasMore && !compactionRunning); noErrors = true; } } - return compactionRunning ? COMPACTION_UPDATE_STATS_ROW_COUNT : rowCount; + return compactionRunning ? UPDATE_STATS_SKIPPED : UPDATE_STATS_RUN; } catch (IOException e) { logger.error("IOException in update stats: " + Throwables.getStackTraceAsString(e)); throw e; http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java index fc3edbe..8d1a365 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java @@ -122,6 +122,7 @@ public abstract class BaseResultIterators extends ExplainTable implements Result private final List<List<List<Pair<Scan,Future<PeekingResultIterator>>>>> allFutures; private long estimatedRows; private long estimatedSize; + private boolean areStatsEnabled; static final Function<HRegionLocation, KeyRange> TO_KEY_RANGE = new Function<HRegionLocation, KeyRange>() { @Override @@ -369,6 +370,11 @@ public abstract class BaseResultIterators extends ExplainTable implements Result return scans; } + // TODO: add to ResultIterators and QueryPlan interfaces? + public boolean areStatsEnabled() { + return this.areStatsEnabled; + } + private static List<byte[]> toBoundaries(List<HRegionLocation> regionLocations) { int nBoundaries = regionLocations.size() - 1; List<byte[]> ranges = Lists.newArrayListWithExpectedSize(nBoundaries); @@ -524,6 +530,17 @@ public abstract class BaseResultIterators extends ExplainTable implements Result ImmutableBytesWritable currentGuidePost = ByteUtil.EMPTY_IMMUTABLE_BYTE_ARRAY; List<Scan> scans = Lists.newArrayListWithExpectedSize(estGuidepostsPerRegion); ImmutableBytesWritable guidePosts = gps.getGuidePosts(); + // If we have any guideposts, then we can definitely say that stats are enabled. + // If we have no guideposts, though, we cannot assume that stats are disabled, + // as the table may just be too small to have them. + if (guidePosts.getLength() > 0) { + areStatsEnabled = true; + // It's possible that the server was bounced and stats have changed + // to become enabled without a client bounce. + this.context.getConnection().getQueryServices().setStatsEnabled(true); + } else { + areStatsEnabled = this.context.getConnection().getQueryServices().areStatsEnabled(); + } ByteArrayInputStream stream = null; DataInput input = null; PrefixByteDecoder decoder = null; @@ -851,14 +868,18 @@ public abstract class BaseResultIterators extends ExplainTable implements Result @Override public void explain(List<String> planSteps) { - boolean displayChunkCount = context.getConnection().getQueryServices().getProps().getBoolean( + ConnectionQueryServices services = context.getConnection().getQueryServices(); + boolean displayChunkCount = services.getProps().getBoolean( QueryServices.EXPLAIN_CHUNK_COUNT_ATTRIB, QueryServicesOptions.DEFAULT_EXPLAIN_CHUNK_COUNT); + boolean displayRowCount = services.getProps().getBoolean( + QueryServices.EXPLAIN_ROW_COUNT_ATTRIB, + QueryServicesOptions.DEFAULT_EXPLAIN_ROW_COUNT); StringBuilder buf = new StringBuilder(); buf.append("CLIENT "); if (displayChunkCount) { buf.append(this.splits.size()).append("-CHUNK "); - if (estimatedRows > 0) { + if (displayRowCount && areStatsEnabled) { buf.append(estimatedRows).append(" ROWS "); buf.append(estimatedSize).append(" BYTES "); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java index b5f1f85..471562a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java @@ -23,8 +23,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import co.cask.tephra.TransactionSystemClient; - import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.client.HBaseAdmin; @@ -46,6 +44,8 @@ import org.apache.phoenix.schema.SequenceAllocation; import org.apache.phoenix.schema.SequenceKey; import org.apache.phoenix.schema.stats.PTableStats; +import co.cask.tephra.TransactionSystemClient; + public interface ConnectionQueryServices extends QueryServices, MetaDataMutated { public static final int INITIAL_META_DATA_TABLE_CAPACITY = 100; @@ -123,4 +123,7 @@ public interface ConnectionQueryServices extends QueryServices, MetaDataMutated TransactionSystemClient getTransactionSystemClient(); public long getRenewLeaseThresholdMilliSeconds(); public boolean isRenewingLeasesEnabled(); + + public boolean areStatsEnabled(); + public void setStatsEnabled(boolean statsEnabled); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/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 d55ab30..b428eb9 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 @@ -241,6 +241,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement private TransactionServiceClient txServiceClient; private volatile boolean initialized; private volatile int nSequenceSaltBuckets; + private volatile boolean areStatsEnabled; // writes guarded by "this" private volatile boolean closed; @@ -1108,6 +1109,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement private void checkClientServerCompatibility() throws SQLException { StringBuilder buf = new StringBuilder("The following servers require an updated " + QueryConstants.DEFAULT_COPROCESS_PATH + " to be put in the classpath of HBase: "); boolean isIncompatible = false; + boolean areStatsEnabled = false; int minHBaseVersion = Integer.MAX_VALUE; try { List<HRegionLocation> locations = this.getAllTableRegions(SYSTEM_CATALOG_NAME_BYTES); @@ -1141,18 +1143,23 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement }); for (Map.Entry<byte[],Long> result : results.entrySet()) { // This is the "phoenix.jar" is in-place, but server is out-of-sync with client case. - if (!isCompatible(result.getValue())) { + long version = result.getValue(); + // Set stats as being enabled if enabled on *any* region server (though it should + // really match across all regions servers). + areStatsEnabled |= MetaDataUtil.decodeStatsEnabled(version); + if (!isCompatible(version)) { isIncompatible = true; HRegionLocation name = regionMap.get(result.getKey()); buf.append(name); buf.append(';'); } - hasIndexWALCodec &= hasIndexWALCodec(result.getValue()); - if (minHBaseVersion > MetaDataUtil.decodeHBaseVersion(result.getValue())) { - minHBaseVersion = MetaDataUtil.decodeHBaseVersion(result.getValue()); + hasIndexWALCodec &= hasIndexWALCodec(version); + if (minHBaseVersion > MetaDataUtil.decodeHBaseVersion(version)) { + minHBaseVersion = MetaDataUtil.decodeHBaseVersion(version); } } lowestClusterHBaseVersion = minHBaseVersion; + this.areStatsEnabled = areStatsEnabled; } catch (SQLException e) { throw e; } catch (Throwable t) { @@ -3379,4 +3386,14 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } } + @Override + public boolean areStatsEnabled() { + return areStatsEnabled; + } + + @Override + public void setStatsEnabled(boolean statsEnabled) { + this.areStatsEnabled = statsEnabled; + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java index b4bbe1f..453d04f 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java @@ -76,6 +76,7 @@ import org.apache.phoenix.schema.SequenceNotFoundException; import org.apache.phoenix.schema.TableAlreadyExistsException; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.stats.PTableStats; +import org.apache.phoenix.schema.stats.StatisticsUtil; import org.apache.phoenix.util.JDBCUtil; import org.apache.phoenix.util.MetaDataUtil; import org.apache.phoenix.util.PhoenixRuntime; @@ -106,7 +107,8 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple private final Map<SequenceKey, SequenceInfo> sequenceMap = Maps.newHashMap(); private final String userName; private final TransactionSystemClient txSystemClient; - private KeyValueBuilder kvBuilder; + private final KeyValueBuilder kvBuilder; + private volatile boolean areStatsEnabled; private volatile boolean initialized; private volatile SQLException initializationException; private final Map<String, List<HRegionLocation>> tableSplits = Maps.newHashMap(); @@ -136,6 +138,8 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple config = HBaseFactoryProvider.getConfigurationFactory().getConfiguration(config); TransactionManager txnManager = new TransactionManager(config); this.txSystemClient = new InMemoryTxSystemClient(txnManager); + // Just check the properties on the client side (instead of normally the server side) + this.areStatsEnabled = StatisticsUtil.isStatsEnabled(config); } private PMetaData newEmptyMetaData() { @@ -527,6 +531,7 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple return txSystemClient; } + @Override public MetaDataMutationResult createFunction(List<Mutation> functionData, PFunction function, boolean temporary) throws SQLException { return new MetaDataMutationResult(MutationCode.FUNCTION_NOT_FOUND, 0l, null); @@ -578,6 +583,7 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple return false; } + @Override public HRegionLocation getTableRegionLocation(byte[] tableName, byte[] row) throws SQLException { List<HRegionLocation> regions = tableSplits.get(Bytes.toString(tableName)); if (regions != null) { @@ -592,4 +598,14 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple new HRegionInfo(TableName.valueOf(tableName), HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW), SERVER_NAME, -1); } + + @Override + public boolean areStatsEnabled() { + return areStatsEnabled; + } + + @Override + public void setStatsEnabled(boolean statsEnabled) { + this.areStatsEnabled = statsEnabled; + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java index 4c7446b..2d0f677 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java @@ -310,4 +310,14 @@ public class DelegateConnectionQueryServices extends DelegateQueryServices imple throws SQLException { return getDelegate().getTableRegionLocation(tableName, row); } + + @Override + public boolean areStatsEnabled() { + return getDelegate().areStatsEnabled(); + } + + @Override + public void setStatsEnabled(boolean statsEnabled) { + getDelegate().setStatsEnabled(statsEnabled); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java index 1efcd8c..32b4fc0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java @@ -162,6 +162,7 @@ public interface QueryServices extends SQLCloseable { public static final String SEQUENCE_SALT_BUCKETS_ATTRIB = "phoenix.sequence.saltBuckets"; public static final String COPROCESSOR_PRIORITY_ATTRIB = "phoenix.coprocessor.priority"; public static final String EXPLAIN_CHUNK_COUNT_ATTRIB = "phoenix.explain.displayChunkCount"; + public static final String EXPLAIN_ROW_COUNT_ATTRIB = "phoenix.explain.displayRowCount"; public static final String ALLOW_ONLINE_TABLE_SCHEMA_UPDATE = "hbase.online.schema.update.enable"; public static final String NUM_RETRIES_FOR_SCHEMA_UPDATE_CHECK = "phoenix.schema.change.retries"; public static final String DELAY_FOR_SCHEMA_UPDATE_CHECK = "phoenix.schema.change.delay"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java index 27c5693..3e0ffe1 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java @@ -29,6 +29,7 @@ import static org.apache.phoenix.query.QueryServices.DATE_FORMAT_TIMEZONE_ATTRIB import static org.apache.phoenix.query.QueryServices.DELAY_FOR_SCHEMA_UPDATE_CHECK; import static org.apache.phoenix.query.QueryServices.DROP_METADATA_ATTRIB; import static org.apache.phoenix.query.QueryServices.EXPLAIN_CHUNK_COUNT_ATTRIB; +import static org.apache.phoenix.query.QueryServices.EXPLAIN_ROW_COUNT_ATTRIB; import static org.apache.phoenix.query.QueryServices.EXTRA_JDBC_ARGUMENTS_ATTRIB; import static org.apache.phoenix.query.QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB; import static org.apache.phoenix.query.QueryServices.GLOBAL_METRICS_ENABLED; @@ -196,6 +197,7 @@ public class QueryServicesOptions { */ public static final int DEFAULT_COPROCESSOR_PRIORITY = Coprocessor.PRIORITY_SYSTEM/2 + Coprocessor.PRIORITY_USER/2; // Divide individually to prevent any overflow public static final boolean DEFAULT_EXPLAIN_CHUNK_COUNT = true; + public static final boolean DEFAULT_EXPLAIN_ROW_COUNT = true; public static final boolean DEFAULT_ALLOW_ONLINE_TABLE_SCHEMA_UPDATE = true; public static final int DEFAULT_RETRIES_FOR_SCHEMA_UPDATE_CHECK = 10; public static final long DEFAULT_DELAY_FOR_SCHEMA_UPDATE_CHECK = 5 * 1000; // 5 seconds. @@ -573,6 +575,11 @@ public class QueryServicesOptions { return this; } + public QueryServicesOptions setExplainRowCount(boolean showRowCount) { + config.setBoolean(EXPLAIN_ROW_COUNT_ATTRIB, showRowCount); + return this; + } + public QueryServicesOptions setAllowOnlineSchemaUpdate(boolean allow) { config.setBoolean(ALLOW_ONLINE_TABLE_SCHEMA_UPDATE, allow); return this; http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java index 7f3f850..eee42ea 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java @@ -182,6 +182,7 @@ import org.apache.phoenix.schema.PTable.IndexType; import org.apache.phoenix.schema.PTable.LinkType; import org.apache.phoenix.schema.PTable.ViewType; import org.apache.phoenix.schema.stats.PTableStats; +import org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PDate; import org.apache.phoenix.schema.types.PInteger; @@ -955,6 +956,7 @@ public class MetaDataClient { } MutationState mutationState = plan.execute(); rowCount = mutationState.getUpdateCount(); + this.getConnection().getQueryServices().setStatsEnabled(rowCount != StatisticsCollectionRunTracker.UPDATE_STATS_DISABLED); } /* http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/NoOpStatisticsCollector.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/NoOpStatisticsCollector.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/NoOpStatisticsCollector.java index 1063229..6c73f16 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/NoOpStatisticsCollector.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/NoOpStatisticsCollector.java @@ -21,13 +21,10 @@ import java.io.IOException; import java.util.List; import org.apache.hadoop.hbase.Cell; -import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; -import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.InternalScanner; import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.regionserver.Store; -import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; /** http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollectionRunTracker.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollectionRunTracker.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollectionRunTracker.java index 4ed3325..6413e37 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollectionRunTracker.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollectionRunTracker.java @@ -24,7 +24,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HRegionInfo; @@ -45,9 +44,9 @@ public class StatisticsCollectionRunTracker { .newSetFromMap(new ConcurrentHashMap<HRegionInfo, Boolean>()); private final ExecutorService executor; - // Constants added for testing purposes - public static final long CONCURRENT_UPDATE_STATS_ROW_COUNT = -100l; - public static final long COMPACTION_UPDATE_STATS_ROW_COUNT = -200l; + public static final long UPDATE_STATS_RUN = 1L; + public static final long UPDATE_STATS_SKIPPED = 100000L; + public static final long UPDATE_STATS_DISABLED = 0; public static StatisticsCollectionRunTracker getInstance(Configuration config) { StatisticsCollectionRunTracker result = INSTANCE; http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java index 5b47104..9dd72e8 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.SortedMap; import java.util.TreeMap; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.HConstants; @@ -40,6 +41,8 @@ import org.apache.phoenix.coprocessor.MetaDataProtocol; import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.query.QueryServicesOptions; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.types.PLong; import org.apache.phoenix.util.ByteUtil; @@ -220,4 +223,17 @@ public class StatisticsUtil { ptr.set(row, gpOffset, row.length - gpOffset); return ByteUtil.copyKeyBytesIfNecessary(ptr); } + + public static boolean isStatsEnabled(Configuration conf) { + if (conf.getBoolean(QueryServices.STATS_ENABLED_ATTRIB, true)) { + if (conf.getInt(QueryServices.STATS_GUIDEPOST_PER_REGION_ATTRIB, + QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_PER_REGION) != 1) { + if (conf.getLong(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, + QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_WIDTH_BYTES) < HConstants.DEFAULT_MAX_FILE_SIZE) { + return true; + } + } + } + return false; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java index 6d5903d..5ee3c0a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java @@ -44,6 +44,7 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.ipc.RemoteException; import org.apache.phoenix.coprocessor.MetaDataProtocol; import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; +import org.apache.phoenix.hbase.index.util.IndexManagementUtil; import org.apache.phoenix.hbase.index.util.KeyValueBuilder; import org.apache.phoenix.hbase.index.util.VersionUtil; import org.apache.phoenix.jdbc.PhoenixConnection; @@ -56,6 +57,7 @@ import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SequenceKey; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TableNotFoundException; +import org.apache.phoenix.schema.stats.StatisticsUtil; import org.apache.phoenix.schema.types.PBoolean; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PLong; @@ -103,26 +105,25 @@ public class MetaDataUtil { // The second byte in int would be the major version, 3rd byte minor version, and 4th byte // patch version. public static int decodePhoenixVersion(long version) { - return (int) ((version << Byte.SIZE * 3) >>> Byte.SIZE * 4); - } - - // TODO: generalize this to use two bytes to return a SQL error code instead - public static long encodeHasIndexWALCodec(long version, boolean isValid) { - if (!isValid) { - return version | 1; - } - return version; + return (int) ((version << Byte.SIZE * 4) >>> Byte.SIZE * 5); } public static boolean decodeHasIndexWALCodec(long version) { return (version & 0xF) == 0; } + // Given the encoded integer representing the phoenix version in the encoded version value. + // The second byte in int would be the major version, 3rd byte minor version, and 4th byte + // patch version. + public static boolean decodeStatsEnabled(long version) { + return ((int) ((version << Byte.SIZE * 3) >>> Byte.SIZE * 7) & 0x1) != 0; + } + // Given the encoded integer representing the client hbase version in the encoded version value. // The second byte in int would be the major version, 3rd byte minor version, and 4th byte // patch version. public static int decodeHBaseVersion(long version) { - return (int) (version >>> Byte.SIZE * 5); + return (int) (version >>> (Byte.SIZE * 5)); } public static String decodeHBaseVersionAsString(int version) { @@ -132,17 +133,33 @@ public class MetaDataUtil { return major + "." + minor + "." + patch; } - public static int encodePhoenixVersion() { - return VersionUtil.encodeVersion(MetaDataProtocol.PHOENIX_MAJOR_VERSION, MetaDataProtocol.PHOENIX_MINOR_VERSION, + // The first 3 bytes of the long is used to encoding the HBase version as major.minor.patch. + // The next 4 bytes of the value is used to encode the Phoenix version as major.minor.patch. + /** + * Encode HBase and Phoenix version along with some server-side config information such + * as whether WAL codec is installed (necessary for non transactional, mutable secondar + * indexing), and whether stats are enabled. + * @param env RegionCoprocessorEnvironment to access HBase version and Configuration. + * @return long value sent back during initialization of a cluster connection. + */ + public static long encodeVersion(String hbaseVersionStr, Configuration config) { + long hbaseVersion = VersionUtil.encodeVersion(hbaseVersionStr); + long statsEnabled = StatisticsUtil.isStatsEnabled(config) ? 1 : 0; + long phoenixVersion = VersionUtil.encodeVersion(MetaDataProtocol.PHOENIX_MAJOR_VERSION, MetaDataProtocol.PHOENIX_MINOR_VERSION, MetaDataProtocol.PHOENIX_PATCH_NUMBER); + long walCodec = IndexManagementUtil.isWALEditCodecSet(config) ? 0 : 1; + long version = + // Encode HBase major, minor, patch version + (hbaseVersion << (Byte.SIZE * 5)) + // Encode if stats are enabled on the server side + | (statsEnabled << (Byte.SIZE * 4)) + // Encode Phoenix major, minor, patch version + | (phoenixVersion << (Byte.SIZE * 1)) + // Encode whether or not non transactional, mutable secondary indexing was configured properly. + | walCodec; + return version; } - - public static long encodeHBaseAndPhoenixVersions(String hbaseVersion) { - return (((long) VersionUtil.encodeVersion(hbaseVersion)) << (Byte.SIZE * 5)) | - (((long) VersionUtil.encodeVersion(MetaDataProtocol.PHOENIX_MAJOR_VERSION, MetaDataProtocol.PHOENIX_MINOR_VERSION, - MetaDataProtocol.PHOENIX_PATCH_NUMBER)) << (Byte.SIZE * 1)); - } - + public static void getTenantIdAndSchemaAndTableName(List<Mutation> tableMetadata, byte[][] rowKeyMetaData) { Mutation m = getTableHeaderRow(tableMetadata); getVarChars(m.getRow(), 3, rowKeyMetaData); http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/test/java/org/apache/phoenix/query/QueryServicesTestImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/QueryServicesTestImpl.java b/phoenix-core/src/test/java/org/apache/phoenix/query/QueryServicesTestImpl.java index 29a7001..6ae655c 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/query/QueryServicesTestImpl.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/query/QueryServicesTestImpl.java @@ -54,6 +54,7 @@ public final class QueryServicesTestImpl extends BaseQueryServicesImpl { public static final long DEFAULT_MAX_CLIENT_METADATA_CACHE_SIZE = 1024L*1024L*2L; // 2 Mb public static final int DEFAULT_MIN_STATS_UPDATE_FREQ_MS = 0; public static final boolean DEFAULT_EXPLAIN_CHUNK_COUNT = false; // TODO: update explain plans in test and set to true + public static final boolean DEFAULT_EXPLAIN_ROW_COUNT = false; // TODO: update explain plans in test and set to true public static final String DEFAULT_EXTRA_JDBC_ARGUMENTS = PhoenixRuntime.PHOENIX_TEST_DRIVER_URL_PARAM; private static final boolean DEFAULT_RUN_UPDATE_STATS_ASYNC = false; private static final boolean DEFAULT_COMMIT_STATS_ASYNC = false; @@ -80,6 +81,7 @@ public final class QueryServicesTestImpl extends BaseQueryServicesImpl { private static QueryServicesOptions getDefaultServicesOptions() { return withDefaults() .setExplainChunkCount(DEFAULT_EXPLAIN_CHUNK_COUNT) + .setExplainRowCount(DEFAULT_EXPLAIN_ROW_COUNT) .setSequenceSaltBuckets(DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS) .setMinStatsUpdateFrequencyMs(DEFAULT_MIN_STATS_UPDATE_FREQ_MS) .setThreadPoolSize(DEFAULT_THREAD_POOL_SIZE) http://git-wip-us.apache.org/repos/asf/phoenix/blob/a1e6ae44/phoenix-core/src/test/java/org/apache/phoenix/util/MetaDataUtilTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/MetaDataUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/MetaDataUtilTest.java index 1e06379..7ffc054 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/util/MetaDataUtilTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/util/MetaDataUtilTest.java @@ -21,15 +21,19 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.VersionInfo; +import org.apache.phoenix.coprocessor.MetaDataProtocol; import org.apache.phoenix.hbase.index.util.GenericKeyValueBuilder; import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; import org.apache.phoenix.hbase.index.util.KeyValueBuilder; import org.apache.phoenix.hbase.index.util.VersionUtil; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; +import org.apache.phoenix.query.HBaseFactoryProvider; +import org.apache.phoenix.query.QueryServices; import org.junit.Test; @@ -58,6 +62,35 @@ public class MetaDataUtilTest { assertFalse(MetaDataUtil.areClientAndServerCompatible(VersionUtil.encodeVersion(3,1,10), 3, 5)); } + @Test + public void testEncodeDecode() { + String hbaseVersionStr = "0.98.14"; + Configuration config = HBaseFactoryProvider.getConfigurationFactory().getConfiguration(); + config.setBoolean(QueryServices.STATS_ENABLED_ATTRIB, false); + + long version = MetaDataUtil.encodeVersion(hbaseVersionStr, config); + int hbaseVersion = MetaDataUtil.decodeHBaseVersion(version); + int expectedHBaseVersion = VersionUtil.encodeVersion(0, 98, 14); + assertEquals(expectedHBaseVersion, hbaseVersion); + boolean areStatsEnabled = MetaDataUtil.decodeStatsEnabled(version); + assertFalse(areStatsEnabled); + int phoenixVersion = MetaDataUtil.decodePhoenixVersion(version); + int expectedPhoenixVersion = VersionUtil.encodeVersion(MetaDataProtocol.PHOENIX_MAJOR_VERSION, MetaDataProtocol.PHOENIX_MINOR_VERSION, + MetaDataProtocol.PHOENIX_PATCH_NUMBER); + assertEquals(expectedPhoenixVersion, phoenixVersion); + + config.setBoolean(QueryServices.STATS_ENABLED_ATTRIB, true); + version = MetaDataUtil.encodeVersion(hbaseVersionStr, config); + hbaseVersion = MetaDataUtil.decodeHBaseVersion(version); + expectedHBaseVersion = VersionUtil.encodeVersion(0, 98, 14); + assertEquals(expectedHBaseVersion, hbaseVersion); + areStatsEnabled = MetaDataUtil.decodeStatsEnabled(version); + assertTrue(areStatsEnabled); + phoenixVersion = MetaDataUtil.decodePhoenixVersion(version); + expectedPhoenixVersion = VersionUtil.encodeVersion(MetaDataProtocol.PHOENIX_MAJOR_VERSION, MetaDataProtocol.PHOENIX_MINOR_VERSION, + MetaDataProtocol.PHOENIX_PATCH_NUMBER); + assertEquals(expectedPhoenixVersion, phoenixVersion); + } /** * Ensure it supports {@link GenericKeyValueBuilder} * @throws Exception on failure