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}