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    FS.mkdirs(new Path(ROOT_DIR, LOG_DIR));
071    RegionServerServices services = Mockito.mock(RegionServerServices.class);
072    Mockito.when(services.getConfiguration()).thenReturn(CONF);
073    ROLLER = new LogRoller(services);
074    ROLLER.start();
075  }
076
077  @After
078  public void tearDown() throws Exception {
079    ROLLER.close();
080    FS.close();
081    TEST_UTIL.cleanupTestDir();
082  }
083
084  @Test
085  public void testRemoveClosedWAL() throws Exception {
086    assertEquals(0, ROLLER.getWalNeedsRoll().size());
087    for (int i = 1; i <= 3; i++) {
088      FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX,
089        getWALSuffix(i));
090      ROLLER.addWAL(wal);
091    }
092
093    assertEquals(3, ROLLER.getWalNeedsRoll().size());
094    Iterator<WAL> it = ROLLER.getWalNeedsRoll().keySet().iterator();
095    WAL wal = it.next();
096    assertTrue(ROLLER.getWalNeedsRoll().containsKey(wal));
097
098    wal.close();
099    Thread.sleep(LOG_ROLL_PERIOD + 5000);
100
101    assertEquals(2, ROLLER.getWalNeedsRoll().size());
102    assertFalse(ROLLER.getWalNeedsRoll().containsKey(wal));
103
104    wal = it.next();
105    wal.close();
106    wal = it.next();
107    wal.close();
108    Thread.sleep(LOG_ROLL_PERIOD + 5000);
109
110    assertEquals(0, ROLLER.getWalNeedsRoll().size());
111  }
112
113  /**
114   * verify that each wal roll separately
115   */
116  @Test
117  public void testRequestRollWithMultiWal() throws Exception {
118    // add multiple wal
119    Map<FSHLog, Path> wals = new HashMap<>();
120    for (int i = 1; i <= 3; i++) {
121      FSHLog wal = new FSHLog(FS, ROOT_DIR, LOG_DIR, ARCHIVE_DIR, CONF, null, true, WAL_PREFIX,
122        getWALSuffix(i));
123      wal.init();
124      wals.put(wal, wal.getCurrentFileName());
125      ROLLER.addWAL(wal);
126      Thread.sleep(1000);
127    }
128
129    // request roll
130    Iterator<Map.Entry<FSHLog, Path>> it = wals.entrySet().iterator();
131    Map.Entry<FSHLog, Path> walEntry = it.next();
132    walEntry.getKey().requestLogRoll();
133    Thread.sleep(5000);
134
135    assertNotEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName());
136    walEntry.setValue(walEntry.getKey().getCurrentFileName());
137    while (it.hasNext()) {
138      walEntry = it.next();
139      assertEquals(walEntry.getValue(), walEntry.getKey().getCurrentFileName());
140    }
141
142    // period roll
143    Thread.sleep(LOG_ROLL_PERIOD + 5000);
144    for (Map.Entry<FSHLog, Path> entry : wals.entrySet()) {
145      assertNotEquals(entry.getValue(), entry.getKey().getCurrentFileName());
146      entry.getKey().close();
147    }
148  }
149
150  private static String getWALSuffix(int id) {
151    return "." + id;
152  }
153}