Search in sources :

Example 1 with TestTableProcedure

use of org.apache.hadoop.hbase.master.procedure.TestMasterProcedureScheduler.TestTableProcedure in project hbase by apache.

the class TestMasterProcedureSchedulerConcurrency method testConcurrentWriteOps.

/**
   * Verify that "write" operations for a single table are serialized,
   * but different tables can be executed in parallel.
   */
@Test(timeout = 60000)
public void testConcurrentWriteOps() throws Exception {
    final TestTableProcSet procSet = new TestTableProcSet(queue);
    final int NUM_ITEMS = 10;
    final int NUM_TABLES = 4;
    final AtomicInteger opsCount = new AtomicInteger(0);
    for (int i = 0; i < NUM_TABLES; ++i) {
        TableName tableName = TableName.valueOf(String.format("testtb-%04d", i));
        for (int j = 1; j < NUM_ITEMS; ++j) {
            procSet.addBack(new TestTableProcedure(i * 100 + j, tableName, TableProcedureInterface.TableOperationType.EDIT));
            opsCount.incrementAndGet();
        }
    }
    assertEquals(opsCount.get(), queue.size());
    final Thread[] threads = new Thread[NUM_TABLES * 2];
    final HashSet<TableName> concurrentTables = new HashSet<>();
    final ArrayList<String> failures = new ArrayList<>();
    final AtomicInteger concurrentCount = new AtomicInteger(0);
    for (int i = 0; i < threads.length; ++i) {
        threads[i] = new Thread() {

            @Override
            public void run() {
                while (opsCount.get() > 0) {
                    try {
                        Procedure proc = procSet.acquire();
                        if (proc == null) {
                            queue.signalAll();
                            if (opsCount.get() > 0) {
                                continue;
                            }
                            break;
                        }
                        TableName tableId = procSet.getTableName(proc);
                        synchronized (concurrentTables) {
                            assertTrue("unexpected concurrency on " + tableId, concurrentTables.add(tableId));
                        }
                        assertTrue(opsCount.decrementAndGet() >= 0);
                        try {
                            long procId = proc.getProcId();
                            int concurrent = concurrentCount.incrementAndGet();
                            assertTrue("inc-concurrent=" + concurrent + " 1 <= concurrent <= " + NUM_TABLES, concurrent >= 1 && concurrent <= NUM_TABLES);
                            LOG.debug("[S] tableId=" + tableId + " procId=" + procId + " concurrent=" + concurrent);
                            Thread.sleep(2000);
                            concurrent = concurrentCount.decrementAndGet();
                            LOG.debug("[E] tableId=" + tableId + " procId=" + procId + " concurrent=" + concurrent);
                            assertTrue("dec-concurrent=" + concurrent, concurrent < NUM_TABLES);
                        } finally {
                            synchronized (concurrentTables) {
                                assertTrue(concurrentTables.remove(tableId));
                            }
                            procSet.release(proc);
                        }
                    } catch (Throwable e) {
                        LOG.error("Failed " + e.getMessage(), e);
                        synchronized (failures) {
                            failures.add(e.getMessage());
                        }
                    } finally {
                        queue.signalAll();
                    }
                }
            }
        };
        threads[i].start();
    }
    for (int i = 0; i < threads.length; ++i) {
        threads[i].join();
    }
    assertTrue(failures.toString(), failures.isEmpty());
    assertEquals(0, opsCount.get());
    assertEquals(0, queue.size());
    for (int i = 1; i <= NUM_TABLES; ++i) {
        final TableName table = TableName.valueOf(String.format("testtb-%04d", i));
        final TestTableProcedure dummyProc = new TestTableProcedure(100, table, TableProcedureInterface.TableOperationType.DELETE);
        assertTrue("queue should be deleted, table=" + table, queue.markTableAsDeleted(table, dummyProc));
    }
}
Also used : ArrayList(java.util.ArrayList) TableName(org.apache.hadoop.hbase.TableName) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestTableProcedure(org.apache.hadoop.hbase.master.procedure.TestMasterProcedureScheduler.TestTableProcedure) Procedure(org.apache.hadoop.hbase.procedure2.Procedure) TestTableProcedure(org.apache.hadoop.hbase.master.procedure.TestMasterProcedureScheduler.TestTableProcedure) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 TableName (org.apache.hadoop.hbase.TableName)1 TestTableProcedure (org.apache.hadoop.hbase.master.procedure.TestMasterProcedureScheduler.TestTableProcedure)1 Procedure (org.apache.hadoop.hbase.procedure2.Procedure)1 Test (org.junit.Test)1