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.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertNotEquals;
023import static org.junit.Assert.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.HBaseClassTestRule;
032import org.apache.hadoop.hbase.HBaseTestingUtil;
033import org.apache.hadoop.hbase.HConstants;
034import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
035import org.apache.hadoop.hbase.testclassification.MediumTests;
036import org.apache.hadoop.hbase.testclassification.RegionServerTests;
037import org.apache.hadoop.hbase.wal.WAL;
038import org.junit.After;
039import org.junit.Before;
040import org.junit.ClassRule;
041import org.junit.Test;
042import org.junit.experimental.categories.Category;
043import org.mockito.Mockito;
044
045@Category({ RegionServerTests.class, MediumTests.class })
046public class TestLogRoller {
047
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050    HBaseClassTestRule.forClass(TestLogRoller.class);
051
052  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
053
054  private static final int LOG_ROLL_PERIOD = 20 * 1000;
055  private static final String LOG_DIR = "WALs";
056  private static final String ARCHIVE_DIR = "archiveWALs";
057  private static final String WAL_PREFIX = "test-log-roller";
058  private static Configuration CONF;
059  private static LogRoller ROLLER;
060  private static Path ROOT_DIR;
061  private static FileSystem FS;
062
063  @Before
064  public void setup() throws Exception {
065    CONF = TEST_UTIL.getConfiguration();
066    CONF.setInt("hbase.regionserver.logroll.period", LOG_ROLL_PERIOD);
067    CONF.setInt(HConstants.THREAD_WAKE_FREQUENCY, 300);
068    ROOT_DIR = TEST_UTIL.getRandomDir();
069    FS = FileSystem.get(CONF);
070    RegionServerServices services = Mockito.mock(RegionServerServices.class);
071    Mockito.when(services.getConfiguration()).thenReturn(CONF);
072    ROLLER = new LogRoller(services);
073    ROLLER.start();
074  }
075
076  @After
077  public void tearDown() throws Exception {
078    ROLLER.close();
079    FS.close();
080    TEST_UTIL.shutdownMiniCluster();
081  }
082
083  @Test
084  public void testRemoveClosedWAL() throws Exception {
085    assertEquals(0, ROLLER.getWalNeedsRoll().size());
086    for (int i = 1; i <= 3; i++) {
087      FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX,
088        getWALSuffix(i));
089      ROLLER.addWAL(wal);
090    }
091
092    assertEquals(3, ROLLER.getWalNeedsRoll().size());
093    Iterator<WAL> it = ROLLER.getWalNeedsRoll().keySet().iterator();
094    WAL wal = it.next();
095    assertTrue(ROLLER.getWalNeedsRoll().containsKey(wal));
096
097    wal.close();
098    Thread.sleep(LOG_ROLL_PERIOD + 5000);
099
100    assertEquals(2, ROLLER.getWalNeedsRoll().size());
101    assertFalse(ROLLER.getWalNeedsRoll().containsKey(wal));
102
103    wal = it.next();
104    wal.close();
105    wal = it.next();
106    wal.close();
107    Thread.sleep(LOG_ROLL_PERIOD + 5000);
108
109    assertEquals(0, ROLLER.getWalNeedsRoll().size());
110  }
111
112  /**
113   * verify that each wal roll separately
114   */
115  @Test
116  public void testRequestRollWithMultiWal() throws Exception {
117    // add multiple wal
118    Map<FSHLog, Path> wals = new HashMap<>();
119    for (int i = 1; i <= 3; i++) {
120      FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX,
121        getWALSuffix(i));
122      wal.init();
123      wals.put(wal, wal.getCurrentFileName());
124      ROLLER.addWAL(wal);
125      Thread.sleep(1000);
126    }
127
128    // request roll
129    Iterator<Map.Entry<FSHLog, Path>> it = wals.entrySet().iterator();
130    Map.Entry<FSHLog, Path> walEntry = it.next();
131    walEntry.getKey().requestLogRoll();
132    Thread.sleep(5000);
133
134    assertNotEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName());
135    walEntry.setValue(walEntry.getKey().getCurrentFileName());
136    while (it.hasNext()) {
137      walEntry = it.next();
138      assertEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName());
139    }
140
141    // period roll
142    Thread.sleep(LOG_ROLL_PERIOD + 5000);
143    for (Map.Entry<FSHLog, Path> entry : wals.entrySet()) {
144      assertNotEquals(entry.getValue(), entry.getKey().getCurrentFileName());
145      entry.getKey().close();
146    }
147  }
148
149  private static String getWALSuffix(int id) {
150    return "." + id;
151  }
152}