com.google.cloud.bigtable.hbase.TestCreateTable.java Source code

Java tutorial

Introduction

Here is the source code for com.google.cloud.bigtable.hbase.TestCreateTable.java

Source

/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed 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 com.google.cloud.bigtable.hbase;

import static com.google.cloud.bigtable.hbase.IntegrationTests.COLUMN_FAMILY;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Assert;
import org.junit.Test;

import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestCreateTable extends AbstractTest {

    private static final Logger LOG = new Logger(TestCreateTable.class);

    /**
     * Requirement 1.8 - Table names must match [_a-zA-Z0-9][-_.a-zA-Z0-9]*
     */
    @Test(timeout = 1000l * 60 * 4)
    public void testTableNames() throws IOException {
        String shouldTest = System.getProperty("bigtable.test.create.table", "true");
        if (!"true".equals(shouldTest)) {
            return;
        }
        String[] goodNames = { "a", "1", "_", // Really?  Yuck.
                "_x", "a-._5x", "_a-._5x",
                // TODO(sduskis): Join the last 2 strings once the Bigtable backend supports table names
                // longer than 50 characters.
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi", "jklmnopqrstuvwxyz1234567890_-." };
        String[] badNames = { "-x", ".x", "a!", "a@", "a#", "a$", "a%", "a^", "a&", "a*", "a(", "a+", "a=", "a~",
                "a`", "a{", "a[", "a|", "a\\", "a/", "a<", "a,", "a?",
                "a" + RandomStringUtils.random(10, false, false) };

        final Admin admin = getConnection().getAdmin();

        for (String badName : badNames) {
            boolean failed = false;
            try {
                admin.createTable(new HTableDescriptor(TableName.valueOf(badName))
                        .addFamily(new HColumnDescriptor(COLUMN_FAMILY)));
            } catch (IllegalArgumentException e) {
                failed = true;
            }
            Assert.assertTrue("Should fail as table name: '" + badName + "'", failed);
        }

        final TableName[] tableNames = admin.listTableNames();

        List<ListenableFuture<Void>> futures = new ArrayList<>();
        ListeningExecutorService es = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
        for (final String goodName : goodNames) {
            futures.add(es.submit(new Callable<Void>() {
                @Override
                public Void call() throws IOException {
                    createTable(admin, goodName, tableNames);
                    return null;
                }
            }));
        }
        try {
            try {
                Futures.allAsList(futures).get(3, TimeUnit.MINUTES);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } finally {
            es.shutdownNow();
        }
    }

    private void createTable(Admin admin, String goodName, TableName[] tableNames) throws IOException {
        LOG.info("Try create table for: %s", goodName);
        TableName tableName = TableName.valueOf(goodName);
        HTableDescriptor descriptor = new HTableDescriptor(tableName)
                .addFamily(new HColumnDescriptor(COLUMN_FAMILY));

        try {
            if (contains(tableNames, tableName)) {
                LOG.warn("Not creating the table since it exists: %s", tableName);
            } else {
                LOG.info("Do create table for: %s", goodName);
                admin.createTable(descriptor);
            }
        } finally {
            try {
                admin.disableTable(tableName);
                LOG.info("Do delete table for: %s", goodName);
                admin.deleteTable(tableName);
            } catch (Throwable t) {
                // Log the error and ignore it.
                LOG.warn("Error cleaning up the table", t);
            }
        }
    }

    private boolean contains(TableName[] tableNames, TableName tableNameTocheck) {
        for (TableName tableName : tableNames) {
            if (tableName.equals(tableNameTocheck)) {
                return true;
            }
        }
        return false;
    }

    @Test
    public void testSplitKeys() throws IOException {
        byte[][] splits = new byte[][] { Bytes.toBytes("AAA"), Bytes.toBytes("BBB"), Bytes.toBytes("CCC"), };

        Admin admin = getConnection().getAdmin();

        TableName tableName = TableName.valueOf("TestTable" + UUID.randomUUID().toString());
        HTableDescriptor descriptor = new HTableDescriptor(tableName);
        descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY));

        try {
            admin.createTable(descriptor, splits);
            List<HRegionLocation> regions = null;
            try (RegionLocator locator = getConnection().getRegionLocator(tableName)) {
                regions = locator.getAllRegionLocations();
            }
            // The number of regions should be the number of splits + 1.
            Assert.assertEquals(splits.length + 1, regions.size());
            for (int i = 0; i < regions.size(); i++) {
                HRegionLocation region = regions.get(i);
                String start_key = Bytes.toString(region.getRegionInfo().getStartKey());
                String end_key = Bytes.toString(region.getRegionInfo().getEndKey());
                // Check start & end keys vs what was requested.
                if (i == 0) {
                    // First split: the end key must be the first element of splits.
                    Assert.assertEquals(Bytes.toString(splits[0]), end_key);
                } else if (i == regions.size() - 1) {
                    // Last split: the start key must be the last element of splits.
                    Assert.assertEquals(Bytes.toString(splits[splits.length - 1]), start_key);
                } else {
                    // For all others: start_key = splits[i-i], end_key = splits[i].
                    Assert.assertEquals(Bytes.toString(splits[i - 1]), start_key);
                    Assert.assertEquals(Bytes.toString(splits[i]), end_key);
                }
            }
        } finally {
            try {
                admin.disableTable(tableName);
                admin.deleteTable(tableName);
            } catch (Throwable t) {
                // Log the error and ignore it.
                LOG.warn("Error cleaning up the table", t);
            }
        }
    }

    @Test
    public void testEvenSplitKeysFailures() throws IOException {
        Admin admin = getConnection().getAdmin();
        TableName tableName = TableName.valueOf("TestTable" + UUID.randomUUID().toString());
        HTableDescriptor descriptor = new HTableDescriptor(tableName);
        descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY));
        byte[] startKey = Bytes.toBytes("AAA");
        byte[] endKey = Bytes.toBytes("ZZZ");

        try {
            admin.createTable(descriptor, startKey, endKey, 2);
            Assert.fail();
        } catch (IllegalArgumentException e) {
        }
        try {
            admin.createTable(descriptor, endKey, startKey, 5);
            Assert.fail();
        } catch (IllegalArgumentException e) {
        }
    }

    @Test
    public void testThreeRegionSplit() throws IOException {

        Admin admin = getConnection().getAdmin();

        TableName tableName = TableName.valueOf("TestTable" + UUID.randomUUID().toString());
        HTableDescriptor descriptor = new HTableDescriptor(tableName);
        descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY));
        byte[] startKey = Bytes.toBytes("AAA");
        byte[] endKey = Bytes.toBytes("ZZZ");

        try {
            admin.createTable(descriptor, startKey, endKey, 3);
            List<HRegionLocation> regions = null;
            try (RegionLocator locator = getConnection().getRegionLocator(tableName)) {
                regions = locator.getAllRegionLocations();
            }
            Assert.assertEquals(3, regions.size());
            for (int i = 0; i < regions.size(); i++) {
                HRegionLocation region = regions.get(i);
                String start_key = Bytes.toString(region.getRegionInfo().getStartKey());
                String end_key = Bytes.toString(region.getRegionInfo().getEndKey());

                // Check start & end keys vs what was requested.
                if (i == 0) {
                    Assert.assertEquals(Bytes.toString(startKey), end_key);
                } else if (i == 1) {
                    Assert.assertEquals(Bytes.toString(startKey), start_key);
                    Assert.assertEquals(Bytes.toString(endKey), end_key);
                } else {
                    Assert.assertEquals(Bytes.toString(endKey), start_key);
                }
            }
        } finally {
            try {
                admin.disableTable(tableName);
                admin.deleteTable(tableName);
            } catch (Throwable t) {
                // Log the error and ignore it.
                LOG.warn("Error cleaning up the table", t);
            }
        }
    }

    @Test
    public void testFiveRegionSplit() throws IOException {

        Admin admin = getConnection().getAdmin();

        TableName tableName = TableName.valueOf("TestTable" + UUID.randomUUID().toString());
        HTableDescriptor descriptor = new HTableDescriptor(tableName);
        descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY));
        byte[] startKey = Bytes.toBytes("AAA");
        byte[] endKey = Bytes.toBytes("ZZZ");
        byte[][] splitKeys = Bytes.split(startKey, endKey, 2);

        try {
            admin.createTable(descriptor, startKey, endKey, 5);
            List<HRegionLocation> regions = null;
            try (RegionLocator locator = getConnection().getRegionLocator(tableName)) {
                regions = locator.getAllRegionLocations();
            }
            // The number of regions should be the number of splits + 1.
            Assert.assertEquals(5, regions.size());
            for (int i = 0; i < regions.size(); i++) {
                HRegionLocation region = regions.get(i);
                String start_key = Bytes.toString(region.getRegionInfo().getStartKey());
                String end_key = Bytes.toString(region.getRegionInfo().getEndKey());

                // Check start & end keys vs what was requested.
                if (i == 0) {
                    // First split: the end key must be the first element of splits.
                    Assert.assertEquals(Bytes.toString(startKey), end_key);
                } else if (i == regions.size() - 1) {
                    // Last split: the start key must be the last element of splits.
                    Assert.assertEquals(Bytes.toString(endKey), start_key);
                } else {
                    // For all others: start_key = splits[i-i], end_key = splits[i].
                    Assert.assertEquals(Bytes.toString(splitKeys[i - 1]), start_key);
                    Assert.assertEquals(Bytes.toString(splitKeys[i]), end_key);
                }
            }
        } finally {
            try {
                admin.disableTable(tableName);
                admin.deleteTable(tableName);
            } catch (Throwable t) {
                // Log the error and ignore it.
                LOG.warn("Error cleaning up the table", t);
            }
        }
    }
}