001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertNotEquals; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.Map; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.fs.FileSystem; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.HBaseTestingUtil; 032import org.apache.hadoop.hbase.HConstants; 033import org.apache.hadoop.hbase.regionserver.wal.FSHLog; 034import org.apache.hadoop.hbase.testclassification.MediumTests; 035import org.apache.hadoop.hbase.testclassification.RegionServerTests; 036import org.apache.hadoop.hbase.wal.WAL; 037import org.junit.jupiter.api.AfterEach; 038import org.junit.jupiter.api.BeforeEach; 039import org.junit.jupiter.api.Tag; 040import org.junit.jupiter.api.Test; 041import org.mockito.Mockito; 042 043@Tag(RegionServerTests.TAG) 044@Tag(MediumTests.TAG) 045public class TestLogRoller { 046 047 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 048 049 private static final int LOG_ROLL_PERIOD = 20 * 1000; 050 private static final String LOG_DIR = "WALs"; 051 private static final String ARCHIVE_DIR = "archiveWALs"; 052 private static final String WAL_PREFIX = "test-log-roller"; 053 private static Configuration CONF; 054 private static LogRoller ROLLER; 055 private static Path ROOT_DIR; 056 private static FileSystem FS; 057 058 @BeforeEach 059 public void setUp() throws Exception { 060 CONF = TEST_UTIL.getConfiguration(); 061 CONF.setInt("hbase.regionserver.logroll.period", LOG_ROLL_PERIOD); 062 CONF.setInt(HConstants.THREAD_WAKE_FREQUENCY, 300); 063 ROOT_DIR = TEST_UTIL.getRandomDir(); 064 FS = FileSystem.get(CONF); 065 FS.mkdirs(new Path(ROOT_DIR, LOG_DIR)); 066 RegionServerServices services = Mockito.mock(RegionServerServices.class); 067 Mockito.when(services.getConfiguration()).thenReturn(CONF); 068 ROLLER = new LogRoller(services); 069 ROLLER.start(); 070 } 071 072 @AfterEach 073 public void tearDown() throws Exception { 074 ROLLER.close(); 075 FS.close(); 076 TEST_UTIL.cleanupTestDir(); 077 } 078 079 @Test 080 public void testRemoveClosedWAL() throws Exception { 081 assertEquals(0, ROLLER.getWalNeedsRoll().size()); 082 for (int i = 1; i <= 3; i++) { 083 FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX, 084 getWALSuffix(i)); 085 ROLLER.addWAL(wal); 086 } 087 088 assertEquals(3, ROLLER.getWalNeedsRoll().size()); 089 Iterator<WAL> it = ROLLER.getWalNeedsRoll().keySet().iterator(); 090 WAL wal = it.next(); 091 assertTrue(ROLLER.getWalNeedsRoll().containsKey(wal)); 092 093 wal.close(); 094 Thread.sleep(LOG_ROLL_PERIOD + 5000); 095 096 assertEquals(2, ROLLER.getWalNeedsRoll().size()); 097 assertFalse(ROLLER.getWalNeedsRoll().containsKey(wal)); 098 099 wal = it.next(); 100 wal.close(); 101 wal = it.next(); 102 wal.close(); 103 Thread.sleep(LOG_ROLL_PERIOD + 5000); 104 105 assertEquals(0, ROLLER.getWalNeedsRoll().size()); 106 } 107 108 /** 109 * verify that each wal roll separately 110 */ 111 @Test 112 public void testRequestRollWithMultiWal() throws Exception { 113 // add multiple wal 114 Map<FSHLog, Path> wals = new HashMap<>(); 115 for (int i = 1; i <= 3; i++) { 116 FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX, 117 getWALSuffix(i)); 118 wal.init(); 119 wals.put(wal, wal.getCurrentFileName()); 120 ROLLER.addWAL(wal); 121 Thread.sleep(1000); 122 } 123 124 // request roll 125 Iterator<Map.Entry<FSHLog, Path>> it = wals.entrySet().iterator(); 126 Map.Entry<FSHLog, Path> walEntry = it.next(); 127 walEntry.getKey().requestLogRoll(); 128 Thread.sleep(5000); 129 130 assertNotEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName()); 131 walEntry.setValue(walEntry.getKey().getCurrentFileName()); 132 while (it.hasNext()) { 133 walEntry = it.next(); 134 assertEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName()); 135 } 136 137 // period roll 138 Thread.sleep(LOG_ROLL_PERIOD + 5000); 139 for (Map.Entry<FSHLog, Path> entry : wals.entrySet()) { 140 assertNotEquals(entry.getValue(), entry.getKey().getCurrentFileName()); 141 entry.getKey().close(); 142 } 143 } 144 145 private static String getWALSuffix(int id) { 146 return "." + id; 147 } 148}