Repository: phoenix Updated Branches: refs/heads/3.0 9c85887af -> 507476b9b
New test to repro skip scan after manual splits Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/507476b9 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/507476b9 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/507476b9 Branch: refs/heads/3.0 Commit: 507476b9bcf4c2f2edb2d84690508c0e45788818 Parents: 9c85887 Author: James Taylor <jtay...@salesforce.com> Authored: Mon Jul 28 13:00:23 2014 -0700 Committer: James Taylor <jtay...@salesforce.com> Committed: Mon Jul 28 13:00:23 2014 -0700 ---------------------------------------------------------------------- .../end2end/SkipScanAfterManualSplit.java | 242 +++++++++++++++++++ 1 file changed, 242 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/507476b9/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanAfterManualSplit.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanAfterManualSplit.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanAfterManualSplit.java new file mode 100644 index 0000000..99405f2 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SkipScanAfterManualSplit.java @@ -0,0 +1,242 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.HTableInterface; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.query.ConnectionQueryServices; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.util.ReadOnlyProps; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +@Category(HBaseManagedTimeTest.class) +public class SkipScanAfterManualSplit extends BaseHBaseManagedTimeIT { + + private static final int BATCH_SIZE = 25; + private static final int MAX_FILESIZE = 1024 * 10; + private static final int PAYLOAD_SIZE = 1024; + private static final String PAYLOAD; + static { + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < PAYLOAD_SIZE; i++) { + buf.append('a'); + } + PAYLOAD = buf.toString(); + } + //private static final String SPLIT_POINT = "j"; + private static final String TABLE_NAME = "S"; + private static final byte[] TABLE_NAME_BYTES = Bytes.toBytes(TABLE_NAME); + private static final int MIN_CHAR = 'a'; + private static final int MAX_CHAR = 'z'; + //private static final int PERC_TO_SELECT = 4; + private static final Random RAND = new Random(); + + @BeforeClass + @Shadower(classBeingShadowed = BaseHBaseManagedTimeIT.class) + public static void doSetup() throws Exception { + Map<String,String> props = Maps.newHashMapWithExpectedSize(2); + props.put(QueryServices.THREAD_POOL_SIZE_ATTRIB, Integer.toString(32)); + props.put(QueryServices.QUEUE_SIZE_ATTRIB, Integer.toString(1000)); + setUpTestDriver(getUrl(), new ReadOnlyProps(props.entrySet().iterator())); + } + + private static void initTable() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + conn.createStatement().execute("CREATE TABLE " + TABLE_NAME + "(" + + "a VARCHAR PRIMARY KEY, b VARCHAR) " + + HTableDescriptor.MAX_FILESIZE + "=" + MAX_FILESIZE + "," + + " SALT_BUCKETS = 4"); + PreparedStatement stmt = conn.prepareStatement("UPSERT INTO s VALUES(?,?)"); + int rowCount = 0; + for (int c1 = MIN_CHAR; c1 <= MAX_CHAR; c1++) { + for (int c2 = MIN_CHAR; c2 <= MAX_CHAR; c2++) { + String pk = Character.toString((char)c1) + Character.toString((char)c2); + stmt.setString(1, pk); + stmt.setString(2, PAYLOAD); + stmt.execute(); + rowCount++; + if (rowCount % BATCH_SIZE == 0) { + conn.commit(); + } + } + } + conn.commit(); + ConnectionQueryServices services = conn.unwrap(PhoenixConnection.class).getQueryServices(); + HBaseAdmin admin = services.getAdmin(); + try { + admin.flush(TABLE_NAME); + } finally { + admin.close(); + } + conn.close(); + } + + public static int doFullScan(ConnectionQueryServices services) throws Exception{ + HTableInterface ht = services.getTable(TABLE_NAME_BYTES); + ResultScanner scanner = ht.getScanner(new Scan()); + int count = 0; + while (scanner.next() != null) { + count++; + } + return count; + } + + private static void traceRegionBoundaries(ConnectionQueryServices services) throws Exception { + List<String> boundaries = Lists.newArrayList(); + List<HRegionLocation> regions = services.getAllTableRegions(TABLE_NAME_BYTES); + for (HRegionLocation region : regions.subList(1, regions.size())) { + boundaries.add(Bytes.toStringBinary(region.getRegionInfo().getStartKey())); + } + System.out.println("Region boundaries:\n" + boundaries); + } + + protected int getTotalRows() { + return (MAX_CHAR - MIN_CHAR) * (MAX_CHAR - MIN_CHAR); + } + protected Set<String> getRandomRows(int nRows) { + Set<String> pks = Sets.newHashSetWithExpectedSize(nRows); + while (pks.size() < nRows) { + int c1 = MIN_CHAR + (Math.abs(RAND.nextInt()) % (MAX_CHAR - MIN_CHAR)); + int c2 = MIN_CHAR + (Math.abs(RAND.nextInt()) % (MAX_CHAR - MIN_CHAR)); + String pk = Character.toString((char)c1) + Character.toString((char)c2); + pks.add(pk); + } + return pks; + } + + @Ignore + @Test + public void testManualSplit() throws Exception { + initTable(); + Connection conn = DriverManager.getConnection(getUrl()); + ConnectionQueryServices services = conn.unwrap(PhoenixConnection.class).getQueryServices(); + traceRegionBoundaries(services); + int nRegions = services.getAllTableRegions(TABLE_NAME_BYTES).size(); + int nInitialRegions = nRegions; + HBaseAdmin admin = services.getAdmin(); + try { + admin.split(TABLE_NAME); + int nTries = 0; + while (nRegions == nInitialRegions && nTries < 10) { + Thread.sleep(1000); + nRegions = services.getAllTableRegions(TABLE_NAME_BYTES).size(); + nTries++; + } + assertEquals(nRegions, nInitialRegions); + + /* works + nTries = 0; + while (nRegions == nInitialRegions && nTries < 10) { + Thread.sleep(1000); + int count = doFullScan(services); + assertEquals(26, count); + nRegions = services.getAllTableRegions(TABLE_NAME_BYTES).size(); + nTries++; + } + assertNotEquals(nRegions, nInitialRegions); + */ + /* + nTries = 0; + while (nRegions == nInitialRegions && nTries < 10) { + Thread.sleep(1000); + ResultSet rs = conn.createStatement().executeQuery("SELECT count(*) FROM " + TABLE_NAME); + assertTrue(rs.next()); + assertEquals(26, rs.getInt(1)); + nRegions = services.getAllTableRegions(TABLE_NAME_BYTES).size(); + nTries++; + } + assertNotEquals(nRegions, nInitialRegions); + */ + /* + String select1 = "SELECT "; + StringBuilder buf = new StringBuilder("count(*) FROM " + TABLE_NAME + " WHERE a IN ("); + int nRows = getTotalRows() * PERC_TO_SELECT / 100; + for (int i = 0; i < nRows; i++) { + buf.append("?,"); + } + buf.setCharAt(buf.length()-1, ')'); + String query = buf.toString(); + */ + int nRows = 25; + String query = "SELECT count(*) FROM S WHERE a IN ('tl','jt','ju','rj','hj','vt','hh','br','ga','vn','th','sv','dl','mj','is','op','ug','sq','mv','qe','kq','xy','ek','aa','ae')"; + /* + PreparedStatement stmt1 = conn.prepareStatement(select1 + query); + PreparedStatement stmt2 = conn.prepareStatement(select2 + query); + int param = 1; + List<String> pks = Lists.newArrayList(); + for (String pk : getRandomRows(nRows)) { + stmt1.setString(param, pk); + stmt2.setString(param, pk); + pks.add(pk); + param++; + } + ResultSet rs1 = stmt1.executeQuery(); + */ + ResultSet rs1 = conn.createStatement().executeQuery(query); + assertTrue(rs1.next()); + //ResultSet rs2 = stmt2.executeQuery(); + //assertTrue(rs2.next()); + traceRegionBoundaries(services); + nRegions = services.getAllTableRegions(TABLE_NAME_BYTES).size(); + assertNotEquals(nRegions, nInitialRegions); + //assertEquals(nRows, rs2.getInt(1)); + if (nRows != rs1.getInt(1)) { + ResultSet rs3 = conn.createStatement().executeQuery(query); + assertTrue(rs3.next()); + assertEquals(nRows, rs3.getInt(1)); + } + /* + StringBuilder failedStmt = new StringBuilder("SELECT count(*) FROM " + TABLE_NAME + " WHERE a IN ("); + for (String pk : pks) { + failedStmt.append("'" + pk + "',"); + } + failedStmt.setCharAt(failedStmt.length()-1, ')'); + */ + assertEquals(nRows, rs1.getInt(1)); + } finally { + admin.close(); + } + + } +}