@Test public void testRollback() throws IOException { final int rowcount = TEST_UTIL.loadRegion(this.parent, CF); assertTrue(rowcount > 0); int parentRowCount = TEST_UTIL.countRows(this.parent); assertEquals(rowcount, parentRowCount); // Start transaction. HRegion spiedRegion = spy(this.parent); SplitTransactionImpl st = prepareGOOD_SPLIT_ROW(spiedRegion); SplitTransactionImpl spiedUponSt = spy(st); doNothing() .when(spiedUponSt) .assertReferenceFileCount( anyInt(), eq(parent.getRegionFileSystem().getSplitsDir(st.getFirstDaughter()))); when(spiedRegion.createDaughterRegionFromSplits(spiedUponSt.getSecondDaughter())) .thenThrow(new MockedFailedDaughterCreation()); // Run the execute. Look at what it returns. boolean expectedException = false; Server mockServer = Mockito.mock(Server.class); when(mockServer.getConfiguration()).thenReturn(TEST_UTIL.getConfiguration()); try { spiedUponSt.execute(mockServer, null); } catch (MockedFailedDaughterCreation e) { expectedException = true; } assertTrue(expectedException); // Run rollback assertTrue(spiedUponSt.rollback(null, null)); // Assert I can scan parent. int parentRowCount2 = TEST_UTIL.countRows(this.parent); assertEquals(parentRowCount, parentRowCount2); // Assert rollback cleaned up stuff in fs assertTrue(!this.fs.exists(HRegion.getRegionDir(this.testdir, st.getFirstDaughter()))); assertTrue(!this.fs.exists(HRegion.getRegionDir(this.testdir, st.getSecondDaughter()))); assertTrue(!this.parent.lock.writeLock().isHeldByCurrentThread()); // Now retry the split but do not throw an exception this time. assertTrue(st.prepare()); PairOfSameType<Region> daughters = st.execute(mockServer, null); // Count rows. daughters are already open int daughtersRowCount = 0; for (Region openRegion : daughters) { try { int count = TEST_UTIL.countRows(openRegion); assertTrue(count > 0 && count != rowcount); daughtersRowCount += count; } finally { HBaseTestingUtility.closeRegionAndWAL(openRegion); } } assertEquals(rowcount, daughtersRowCount); // Assert the write lock is no longer held on parent assertTrue(!this.parent.lock.writeLock().isHeldByCurrentThread()); assertTrue("Rollback hooks should be called.", wasRollBackHookCalled()); }
@Test public void testCountReferencesFailsSplit() throws IOException { final int rowcount = TEST_UTIL.loadRegion(this.parent, CF); assertTrue(rowcount > 0); int parentRowCount = TEST_UTIL.countRows(this.parent); assertEquals(rowcount, parentRowCount); // Start transaction. HRegion spiedRegion = spy(this.parent); SplitTransactionImpl st = prepareGOOD_SPLIT_ROW(spiedRegion); SplitTransactionImpl spiedUponSt = spy(st); doThrow(new IOException("Failing split. Expected reference file count isn't equal.")) .when(spiedUponSt) .assertReferenceFileCount( anyInt(), eq( new Path( this.parent.getRegionFileSystem().getTableDir(), st.getSecondDaughter().getEncodedName()))); // Run the execute. Look at what it returns. boolean expectedException = false; Server mockServer = Mockito.mock(Server.class); when(mockServer.getConfiguration()).thenReturn(TEST_UTIL.getConfiguration()); try { spiedUponSt.execute(mockServer, null); } catch (IOException e) { expectedException = true; } assertTrue(expectedException); }
@Test public void testWholesomeSplit() throws IOException { final int rowcount = TEST_UTIL.loadRegion(this.parent, CF, true); assertTrue(rowcount > 0); int parentRowCount = TEST_UTIL.countRows(this.parent); assertEquals(rowcount, parentRowCount); // Pretend region's blocks are not in the cache, used for // testWholesomeSplitWithHFileV1 CacheConfig cacheConf = new CacheConfig(TEST_UTIL.getConfiguration()); ((LruBlockCache) cacheConf.getBlockCache()).clearCache(); // Start transaction. SplitTransactionImpl st = prepareGOOD_SPLIT_ROW(); // Run the execute. Look at what it returns. Server mockServer = Mockito.mock(Server.class); when(mockServer.getConfiguration()).thenReturn(TEST_UTIL.getConfiguration()); PairOfSameType<Region> daughters = st.execute(mockServer, null); // Do some assertions about execution. assertTrue(this.fs.exists(this.parent.getRegionFileSystem().getSplitsDir())); // Assert the parent region is closed. assertTrue(this.parent.isClosed()); // Assert splitdir is empty -- because its content will have been moved out // to be under the daughter region dirs. assertEquals(0, this.fs.listStatus(this.parent.getRegionFileSystem().getSplitsDir()).length); // Check daughters have correct key span. assertTrue( Bytes.equals( parent.getRegionInfo().getStartKey(), daughters.getFirst().getRegionInfo().getStartKey())); assertTrue(Bytes.equals(GOOD_SPLIT_ROW, daughters.getFirst().getRegionInfo().getEndKey())); assertTrue(Bytes.equals(daughters.getSecond().getRegionInfo().getStartKey(), GOOD_SPLIT_ROW)); assertTrue( Bytes.equals( parent.getRegionInfo().getEndKey(), daughters.getSecond().getRegionInfo().getEndKey())); // Count rows. daughters are already open int daughtersRowCount = 0; for (Region openRegion : daughters) { try { int count = TEST_UTIL.countRows(openRegion); assertTrue(count > 0 && count != rowcount); daughtersRowCount += count; } finally { HBaseTestingUtility.closeRegionAndWAL(openRegion); } } assertEquals(rowcount, daughtersRowCount); // Assert the write lock is no longer held on parent assertTrue(!this.parent.lock.writeLock().isHeldByCurrentThread()); }
/** Test SplitTransactionListener */ @Test public void testSplitTransactionListener() throws IOException { SplitTransactionImpl st = new SplitTransactionImpl(this.parent, GOOD_SPLIT_ROW); SplitTransaction.TransactionListener listener = Mockito.mock(SplitTransaction.TransactionListener.class); st.registerTransactionListener(listener); st.prepare(); Server mockServer = Mockito.mock(Server.class); when(mockServer.getConfiguration()).thenReturn(TEST_UTIL.getConfiguration()); PairOfSameType<Region> daughters = st.execute(mockServer, null); verify(listener) .transition( st, SplitTransaction.SplitTransactionPhase.STARTED, SplitTransaction.SplitTransactionPhase.PREPARED); verify(listener, times(15)) .transition( any(SplitTransaction.class), any(SplitTransaction.SplitTransactionPhase.class), any(SplitTransaction.SplitTransactionPhase.class)); verifyNoMoreInteractions(listener); }
@Test public void testFailAfterPONR() throws IOException, KeeperException { final int rowcount = TEST_UTIL.loadRegion(this.parent, CF); assertTrue(rowcount > 0); int parentRowCount = TEST_UTIL.countRows(this.parent); assertEquals(rowcount, parentRowCount); // Start transaction. SplitTransactionImpl st = prepareGOOD_SPLIT_ROW(); SplitTransactionImpl spiedUponSt = spy(st); Mockito.doThrow(new MockedFailedDaughterOpen()) .when(spiedUponSt) .openDaughterRegion((Server) Mockito.anyObject(), (HRegion) Mockito.anyObject()); // Run the execute. Look at what it returns. boolean expectedException = false; Server mockServer = Mockito.mock(Server.class); when(mockServer.getConfiguration()).thenReturn(TEST_UTIL.getConfiguration()); try { spiedUponSt.execute(mockServer, null); } catch (IOException e) { if (e.getCause() != null && e.getCause() instanceof MockedFailedDaughterOpen) { expectedException = true; } } assertTrue(expectedException); // Run rollback returns that we should restart. assertFalse(spiedUponSt.rollback(null, null)); // Make sure that region a and region b are still in the filesystem, that // they have not been removed; this is supposed to be the case if we go // past point of no return. Path tableDir = this.parent.getRegionFileSystem().getTableDir(); Path daughterADir = new Path(tableDir, spiedUponSt.getFirstDaughter().getEncodedName()); Path daughterBDir = new Path(tableDir, spiedUponSt.getSecondDaughter().getEncodedName()); assertTrue(TEST_UTIL.getTestFileSystem().exists(daughterADir)); assertTrue(TEST_UTIL.getTestFileSystem().exists(daughterBDir)); }