org.apache.hadoop.hbase.master.assignment.TestRegionStates.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.hbase.master.assignment.TestRegionStates.java

Source

/**
 * 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.hadoop.hbase.master.assignment;

import static org.junit.Assert.assertEquals;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.procedure2.util.StringUtils;
import org.apache.hadoop.hbase.testclassification.MasterTests;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Threads;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

@Category({ MasterTests.class, MediumTests.class })
public class TestRegionStates {
    private static final Log LOG = LogFactory.getLog(TestRegionStates.class);

    protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();

    private static ThreadPoolExecutor threadPool;
    private static ExecutorCompletionService executorService;

    @BeforeClass
    public static void setUp() throws Exception {
        threadPool = Threads.getBoundedCachedThreadPool(32, 60L, TimeUnit.SECONDS,
                Threads.newDaemonThreadFactory("ProcedureDispatcher", new UncaughtExceptionHandler() {
                    @Override
                    public void uncaughtException(Thread t, Throwable e) {
                        LOG.warn("Failed thread " + t.getName(), e);
                    }
                }));
        executorService = new ExecutorCompletionService(threadPool);
    }

    @AfterClass
    public static void tearDown() throws Exception {
        threadPool.shutdown();
    }

    @Before
    public void testSetup() {
    }

    @After
    public void testTearDown() throws Exception {
        while (true) {
            Future<Object> f = executorService.poll();
            if (f == null)
                break;
            f.get();
        }
    }

    private static void waitExecutorService(final int count) throws Exception {
        for (int i = 0; i < count; ++i) {
            executorService.take().get();
        }
    }

    // ==========================================================================
    //  Regions related
    // ==========================================================================

    @Test
    public void testRegionDoubleCreation() throws Exception {
        // NOTE: HRegionInfo sort by table first, so we are relying on that
        final TableName TABLE_NAME_A = TableName.valueOf("testOrderedByTableA");
        final TableName TABLE_NAME_B = TableName.valueOf("testOrderedByTableB");
        final TableName TABLE_NAME_C = TableName.valueOf("testOrderedByTableC");
        final RegionStates stateMap = new RegionStates();
        final int NRUNS = 1000;
        final int NSMALL_RUNS = 3;

        // add some regions for table B
        for (int i = 0; i < NRUNS; ++i) {
            addRegionNode(stateMap, TABLE_NAME_B, i);
        }
        // re-add the regions for table B
        for (int i = 0; i < NRUNS; ++i) {
            addRegionNode(stateMap, TABLE_NAME_B, i);
        }
        waitExecutorService(NRUNS * 2);

        // add two other tables A and C that will be placed before and after table B (sort order)
        for (int i = 0; i < NSMALL_RUNS; ++i) {
            addRegionNode(stateMap, TABLE_NAME_A, i);
            addRegionNode(stateMap, TABLE_NAME_C, i);
        }
        waitExecutorService(NSMALL_RUNS * 2);
        // check for the list of regions of the 3 tables
        checkTableRegions(stateMap, TABLE_NAME_A, NSMALL_RUNS);
        checkTableRegions(stateMap, TABLE_NAME_B, NRUNS);
        checkTableRegions(stateMap, TABLE_NAME_C, NSMALL_RUNS);
    }

    private void checkTableRegions(final RegionStates stateMap, final TableName tableName, final int nregions) {
        List<HRegionInfo> hris = stateMap.getRegionsOfTable(tableName, true);
        assertEquals(nregions, hris.size());
        for (int i = 1; i < hris.size(); ++i) {
            long a = Bytes.toLong(hris.get(i - 1).getStartKey());
            long b = Bytes.toLong(hris.get(i + 0).getStartKey());
            assertEquals(b, a + 1);
        }
    }

    private void addRegionNode(final RegionStates stateMap, final TableName tableName, final long regionId) {
        executorService.submit(new Callable<Object>() {
            @Override
            public Object call() {
                HRegionInfo hri = new HRegionInfo(tableName, Bytes.toBytes(regionId), Bytes.toBytes(regionId + 1),
                        false, 0);
                return stateMap.getOrCreateRegionNode(hri);
            }
        });
    }

    private Object createRegionNode(final RegionStates stateMap, final TableName tableName, final long regionId) {
        return stateMap.getOrCreateRegionNode(createRegionInfo(tableName, regionId));
    }

    private HRegionInfo createRegionInfo(final TableName tableName, final long regionId) {
        return new HRegionInfo(tableName, Bytes.toBytes(regionId), Bytes.toBytes(regionId + 1), false, 0);
    }

    @Test
    public void testPerf() throws Exception {
        final TableName TABLE_NAME = TableName.valueOf("testPerf");
        final int NRUNS = 1000000; // 1M
        final RegionStates stateMap = new RegionStates();

        long st = System.currentTimeMillis();
        for (int i = 0; i < NRUNS; ++i) {
            final int regionId = i;
            executorService.submit(new Callable<Object>() {
                @Override
                public Object call() {
                    HRegionInfo hri = createRegionInfo(TABLE_NAME, regionId);
                    return stateMap.getOrCreateRegionNode(hri);
                }
            });
        }
        waitExecutorService(NRUNS);
        long et = System.currentTimeMillis();
        LOG.info(String.format("PERF STATEMAP INSERT: %s %s/sec", StringUtils.humanTimeDiff(et - st),
                StringUtils.humanSize(NRUNS / ((et - st) / 1000.0f))));

        st = System.currentTimeMillis();
        for (int i = 0; i < NRUNS; ++i) {
            final int regionId = i;
            executorService.submit(new Callable<Object>() {
                @Override
                public Object call() {
                    HRegionInfo hri = createRegionInfo(TABLE_NAME, regionId);
                    return stateMap.getRegionState(hri);
                }
            });
        }

        waitExecutorService(NRUNS);
        et = System.currentTimeMillis();
        LOG.info(String.format("PERF STATEMAP GET: %s %s/sec", StringUtils.humanTimeDiff(et - st),
                StringUtils.humanSize(NRUNS / ((et - st) / 1000.0f))));
    }

    @Test
    public void testPerfSingleThread() {
        final TableName TABLE_NAME = TableName.valueOf("testPerf");
        final int NRUNS = 1 * 1000000; // 1M

        final RegionStates stateMap = new RegionStates();
        long st = System.currentTimeMillis();
        for (int i = 0; i < NRUNS; ++i) {
            stateMap.createRegionNode(createRegionInfo(TABLE_NAME, i));
        }
        long et = System.currentTimeMillis();
        LOG.info(String.format("PERF SingleThread: %s %s/sec", StringUtils.humanTimeDiff(et - st),
                StringUtils.humanSize(NRUNS / ((et - st) / 1000.0f))));
    }

    // ==========================================================================
    //  Server related
    // ==========================================================================
}