HBASE-21751 WAL creation fails during region open may cause region assign forever fail
Signed-off-by: Allan Yang <allan163@apache.org> Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
parent
668f543cdc
commit
a2a929f488
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw when failed cleanup unsuccessful initialized wal
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Public
|
||||||
|
public class FailedCloseWALAfterInitializedErrorException
|
||||||
|
extends IOException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5463156587431677322L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor with error msg and throwable
|
||||||
|
* @param msg message
|
||||||
|
* @param t throwable
|
||||||
|
*/
|
||||||
|
public FailedCloseWALAfterInitializedErrorException(String msg, Throwable t) {
|
||||||
|
super(msg, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor with error msg
|
||||||
|
* @param msg message
|
||||||
|
*/
|
||||||
|
public FailedCloseWALAfterInitializedErrorException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor
|
||||||
|
*/
|
||||||
|
public FailedCloseWALAfterInitializedErrorException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,7 @@ import org.apache.hadoop.hbase.ChoreService;
|
|||||||
import org.apache.hadoop.hbase.ClockOutOfSyncException;
|
import org.apache.hadoop.hbase.ClockOutOfSyncException;
|
||||||
import org.apache.hadoop.hbase.CoordinatedStateManager;
|
import org.apache.hadoop.hbase.CoordinatedStateManager;
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
||||||
|
import org.apache.hadoop.hbase.FailedCloseWALAfterInitializedErrorException;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
@ -2130,11 +2131,17 @@ public class HRegionServer extends HasThread implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WAL getWAL(RegionInfo regionInfo) throws IOException {
|
public WAL getWAL(RegionInfo regionInfo) throws IOException {
|
||||||
|
try {
|
||||||
WAL wal = walFactory.getWAL(regionInfo);
|
WAL wal = walFactory.getWAL(regionInfo);
|
||||||
if (this.walRoller != null) {
|
if (this.walRoller != null) {
|
||||||
this.walRoller.addWAL(wal);
|
this.walRoller.addWAL(wal);
|
||||||
}
|
}
|
||||||
return wal;
|
return wal;
|
||||||
|
}catch (FailedCloseWALAfterInitializedErrorException ex) {
|
||||||
|
// see HBASE-21751 for details
|
||||||
|
abort("wal can not clean up after init failed", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LogRoller getWalRoller() {
|
public LogRoller getWalRoller() {
|
||||||
|
@ -427,6 +427,13 @@ public abstract class AbstractFSWAL<W extends WriterBase> implements WAL {
|
|||||||
this.implClassName = getClass().getSimpleName();
|
this.implClassName = getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to initialize the WAL. Usually just call rollWriter to create the first log writer.
|
||||||
|
*/
|
||||||
|
public void init() throws IOException {
|
||||||
|
rollWriter();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerWALActionsListener(WALActionsListener listener) {
|
public void registerWALActionsListener(WALActionsListener listener) {
|
||||||
this.listeners.add(listener);
|
this.listeners.add(listener);
|
||||||
|
@ -250,7 +250,6 @@ public class AsyncFSWAL extends AbstractFSWAL<AsyncWriter> {
|
|||||||
batchSize = conf.getLong(WAL_BATCH_SIZE, DEFAULT_WAL_BATCH_SIZE);
|
batchSize = conf.getLong(WAL_BATCH_SIZE, DEFAULT_WAL_BATCH_SIZE);
|
||||||
waitOnShutdownInSeconds = conf.getInt(ASYNC_WAL_WAIT_ON_SHUTDOWN_IN_SECONDS,
|
waitOnShutdownInSeconds = conf.getInt(ASYNC_WAL_WAIT_ON_SHUTDOWN_IN_SECONDS,
|
||||||
DEFAULT_ASYNC_WAL_WAIT_ON_SHUTDOWN_IN_SECONDS);
|
DEFAULT_ASYNC_WAL_WAIT_ON_SHUTDOWN_IN_SECONDS);
|
||||||
rollWriter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean waitingRoll(int epochAndState) {
|
private static boolean waitingRoll(int epochAndState) {
|
||||||
|
@ -217,9 +217,6 @@ public class FSHLog extends AbstractFSWAL<Writer> {
|
|||||||
|
|
||||||
this.useHsync = conf.getBoolean(HRegion.WAL_HSYNC_CONF_KEY, HRegion.DEFAULT_WAL_HSYNC);
|
this.useHsync = conf.getBoolean(HRegion.WAL_HSYNC_CONF_KEY, HRegion.DEFAULT_WAL_HSYNC);
|
||||||
|
|
||||||
// rollWriter sets this.hdfs_out if it can.
|
|
||||||
rollWriter();
|
|
||||||
|
|
||||||
// This is the 'writer' -- a single threaded executor. This single thread 'consumes' what is
|
// This is the 'writer' -- a single threaded executor. This single thread 'consumes' what is
|
||||||
// put on the ring buffer.
|
// put on the ring buffer.
|
||||||
String hostingThreadName = Thread.currentThread().getName();
|
String hostingThreadName = Thread.currentThread().getName();
|
||||||
|
@ -31,6 +31,7 @@ import org.apache.hadoop.conf.Configuration;
|
|||||||
import org.apache.hadoop.fs.FSDataInputStream;
|
import org.apache.hadoop.fs.FSDataInputStream;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.hbase.FailedCloseWALAfterInitializedErrorException;
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.ServerName;
|
import org.apache.hadoop.hbase.ServerName;
|
||||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||||
@ -150,6 +151,20 @@ public abstract class AbstractFSWALProvider<T extends AbstractFSWAL<?>> implemen
|
|||||||
return walCopy;
|
return walCopy;
|
||||||
}
|
}
|
||||||
walCopy = createWAL();
|
walCopy = createWAL();
|
||||||
|
boolean succ = false;
|
||||||
|
try {
|
||||||
|
walCopy.init();
|
||||||
|
succ = true;
|
||||||
|
} finally {
|
||||||
|
if (!succ) {
|
||||||
|
try {
|
||||||
|
walCopy.close();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new FailedCloseWALAfterInitializedErrorException(
|
||||||
|
"Failed close after init wal failed.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
wal = walCopy;
|
wal = walCopy;
|
||||||
return walCopy;
|
return walCopy;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -471,6 +471,11 @@ public class WALFactory {
|
|||||||
return FSHLogProvider.createWriter(configuration, fs, path, false);
|
return FSHLogProvider.createWriter(configuration, fs, path, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public String getFactoryId() {
|
||||||
|
return factoryId;
|
||||||
|
}
|
||||||
|
|
||||||
public final WALProvider getWALProvider() {
|
public final WALProvider getWALProvider() {
|
||||||
return this.provider;
|
return this.provider;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,7 @@ public class TestFailedAppendAndSync {
|
|||||||
FileSystem fs = FileSystem.get(CONF);
|
FileSystem fs = FileSystem.get(CONF);
|
||||||
Path rootDir = new Path(dir + getName());
|
Path rootDir = new Path(dir + getName());
|
||||||
DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
||||||
|
dodgyWAL.init();
|
||||||
LogRoller logRoller = new LogRoller(server, services);
|
LogRoller logRoller = new LogRoller(server, services);
|
||||||
logRoller.addWAL(dodgyWAL);
|
logRoller.addWAL(dodgyWAL);
|
||||||
logRoller.start();
|
logRoller.start();
|
||||||
|
@ -402,6 +402,7 @@ public class TestHRegion {
|
|||||||
FileSystem fs = FileSystem.get(CONF);
|
FileSystem fs = FileSystem.get(CONF);
|
||||||
Path rootDir = new Path(dir + testName);
|
Path rootDir = new Path(dir + testName);
|
||||||
FSHLog hLog = new FSHLog(fs, rootDir, testName, CONF);
|
FSHLog hLog = new FSHLog(fs, rootDir, testName, CONF);
|
||||||
|
hLog.init();
|
||||||
HRegion region = initHRegion(tableName, null, null, false, Durability.SYNC_WAL, hLog,
|
HRegion region = initHRegion(tableName, null, null, false, Durability.SYNC_WAL, hLog,
|
||||||
COLUMN_FAMILY_BYTES);
|
COLUMN_FAMILY_BYTES);
|
||||||
HStore store = region.getStore(COLUMN_FAMILY_BYTES);
|
HStore store = region.getStore(COLUMN_FAMILY_BYTES);
|
||||||
@ -1207,6 +1208,7 @@ public class TestHRegion {
|
|||||||
FailAppendFlushMarkerWAL wal =
|
FailAppendFlushMarkerWAL wal =
|
||||||
new FailAppendFlushMarkerWAL(FileSystem.get(walConf), FSUtils.getRootDir(walConf),
|
new FailAppendFlushMarkerWAL(FileSystem.get(walConf), FSUtils.getRootDir(walConf),
|
||||||
method, walConf);
|
method, walConf);
|
||||||
|
wal.init();
|
||||||
this.region = initHRegion(tableName, HConstants.EMPTY_START_ROW,
|
this.region = initHRegion(tableName, HConstants.EMPTY_START_ROW,
|
||||||
HConstants.EMPTY_END_ROW, false, Durability.USE_DEFAULT, wal, family);
|
HConstants.EMPTY_END_ROW, false, Durability.USE_DEFAULT, wal, family);
|
||||||
try {
|
try {
|
||||||
@ -1238,7 +1240,7 @@ public class TestHRegion {
|
|||||||
wal.flushActions = new FlushAction [] {FlushAction.COMMIT_FLUSH};
|
wal.flushActions = new FlushAction [] {FlushAction.COMMIT_FLUSH};
|
||||||
wal = new FailAppendFlushMarkerWAL(FileSystem.get(walConf), FSUtils.getRootDir(walConf),
|
wal = new FailAppendFlushMarkerWAL(FileSystem.get(walConf), FSUtils.getRootDir(walConf),
|
||||||
method, walConf);
|
method, walConf);
|
||||||
|
wal.init();
|
||||||
this.region = initHRegion(tableName, HConstants.EMPTY_START_ROW,
|
this.region = initHRegion(tableName, HConstants.EMPTY_START_ROW,
|
||||||
HConstants.EMPTY_END_ROW, false, Durability.USE_DEFAULT, wal, family);
|
HConstants.EMPTY_END_ROW, false, Durability.USE_DEFAULT, wal, family);
|
||||||
region.put(put);
|
region.put(put);
|
||||||
@ -2490,6 +2492,7 @@ public class TestHRegion {
|
|||||||
FileSystem fs = FileSystem.get(CONF);
|
FileSystem fs = FileSystem.get(CONF);
|
||||||
Path rootDir = new Path(dir + "testDataInMemoryWithoutWAL");
|
Path rootDir = new Path(dir + "testDataInMemoryWithoutWAL");
|
||||||
FSHLog hLog = new FSHLog(fs, rootDir, "testDataInMemoryWithoutWAL", CONF);
|
FSHLog hLog = new FSHLog(fs, rootDir, "testDataInMemoryWithoutWAL", CONF);
|
||||||
|
hLog.init();
|
||||||
// This chunk creation is done throughout the code base. Do we want to move it into core?
|
// This chunk creation is done throughout the code base. Do we want to move it into core?
|
||||||
// It is missing from this test. W/o it we NPE.
|
// It is missing from this test. W/o it we NPE.
|
||||||
ChunkCreator.initialize(MemStoreLABImpl.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null);
|
ChunkCreator.initialize(MemStoreLABImpl.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null);
|
||||||
|
@ -36,7 +36,6 @@ import org.apache.hadoop.hbase.client.TestIncrementsFromClientSide;
|
|||||||
import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
|
import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
|
||||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.wal.WAL;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
@ -81,8 +80,9 @@ public class TestRegionIncrement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private HRegion getRegion(final Configuration conf, final String tableName) throws IOException {
|
private HRegion getRegion(final Configuration conf, final String tableName) throws IOException {
|
||||||
WAL wal = new FSHLog(FileSystem.get(conf), TEST_UTIL.getDataTestDir(),
|
FSHLog wal = new FSHLog(FileSystem.get(conf), TEST_UTIL.getDataTestDir(),
|
||||||
TEST_UTIL.getDataTestDir().toString(), conf);
|
TEST_UTIL.getDataTestDir().toString(), conf);
|
||||||
|
wal.init();
|
||||||
ChunkCreator.initialize(MemStoreLABImpl.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null);
|
ChunkCreator.initialize(MemStoreLABImpl.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null);
|
||||||
return (HRegion)TEST_UTIL.createLocalHRegion(Bytes.toBytes(tableName),
|
return (HRegion)TEST_UTIL.createLocalHRegion(Bytes.toBytes(tableName),
|
||||||
HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, tableName, conf,
|
HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, tableName, conf,
|
||||||
|
@ -215,6 +215,7 @@ public class TestWALLockup {
|
|||||||
FileSystem fs = FileSystem.get(CONF);
|
FileSystem fs = FileSystem.get(CONF);
|
||||||
Path rootDir = new Path(dir + getName());
|
Path rootDir = new Path(dir + getName());
|
||||||
DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
||||||
|
dodgyWAL.init();
|
||||||
Path originalWAL = dodgyWAL.getCurrentFileName();
|
Path originalWAL = dodgyWAL.getCurrentFileName();
|
||||||
// I need a log roller running.
|
// I need a log roller running.
|
||||||
LogRoller logRoller = new LogRoller(server, services);
|
LogRoller logRoller = new LogRoller(server, services);
|
||||||
@ -390,6 +391,7 @@ public class TestWALLockup {
|
|||||||
FileSystem fs = FileSystem.get(CONF);
|
FileSystem fs = FileSystem.get(CONF);
|
||||||
Path rootDir = new Path(dir + getName());
|
Path rootDir = new Path(dir + getName());
|
||||||
final DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
final DodgyFSLog dodgyWAL = new DodgyFSLog(fs, rootDir, getName(), CONF);
|
||||||
|
dodgyWAL.init();
|
||||||
// I need a log roller running.
|
// I need a log roller running.
|
||||||
LogRoller logRoller = new LogRoller(server, services);
|
LogRoller logRoller = new LogRoller(server, services);
|
||||||
logRoller.addWAL(dodgyWAL);
|
logRoller.addWAL(dodgyWAL);
|
||||||
|
@ -436,6 +436,7 @@ public abstract class AbstractTestFSWAL {
|
|||||||
String testName = currentTest.getMethodName();
|
String testName = currentTest.getMethodName();
|
||||||
AbstractFSWAL<?> wal = newWAL(FS, CommonFSUtils.getWALRootDir(CONF), DIR.toString(), testName,
|
AbstractFSWAL<?> wal = newWAL(FS, CommonFSUtils.getWALRootDir(CONF), DIR.toString(), testName,
|
||||||
CONF, null, true, null, null);
|
CONF, null, true, null, null);
|
||||||
|
wal.init();
|
||||||
try {
|
try {
|
||||||
wal.sync();
|
wal.sync();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1098,6 +1098,7 @@ public abstract class AbstractTestWALReplay {
|
|||||||
|
|
||||||
private MockWAL createMockWAL() throws IOException {
|
private MockWAL createMockWAL() throws IOException {
|
||||||
MockWAL wal = new MockWAL(fs, hbaseRootDir, logName, conf);
|
MockWAL wal = new MockWAL(fs, hbaseRootDir, logName, conf);
|
||||||
|
wal.init();
|
||||||
// Set down maximum recovery so we dfsclient doesn't linger retrying something
|
// Set down maximum recovery so we dfsclient doesn't linger retrying something
|
||||||
// long gone.
|
// long gone.
|
||||||
HBaseTestingUtility.setMaxRecoveryErrorCount(wal.getOutputStream(), 1);
|
HBaseTestingUtility.setMaxRecoveryErrorCount(wal.getOutputStream(), 1);
|
||||||
|
@ -67,8 +67,10 @@ public class TestAsyncFSWAL extends AbstractTestFSWAL {
|
|||||||
protected AbstractFSWAL<?> newWAL(FileSystem fs, Path rootDir, String logDir, String archiveDir,
|
protected AbstractFSWAL<?> newWAL(FileSystem fs, Path rootDir, String logDir, String archiveDir,
|
||||||
Configuration conf, List<WALActionsListener> listeners, boolean failIfWALExists,
|
Configuration conf, List<WALActionsListener> listeners, boolean failIfWALExists,
|
||||||
String prefix, String suffix) throws IOException {
|
String prefix, String suffix) throws IOException {
|
||||||
return new AsyncFSWAL(fs, rootDir, logDir, archiveDir, conf, listeners, failIfWALExists, prefix,
|
AsyncFSWAL asyncFSWAL = new AsyncFSWAL(fs, rootDir, logDir, archiveDir, conf,
|
||||||
suffix, GROUP, CHANNEL_CLASS);
|
listeners, failIfWALExists, prefix, suffix, GROUP, CHANNEL_CLASS);
|
||||||
|
asyncFSWAL.init();
|
||||||
|
return asyncFSWAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,9 +78,8 @@ public class TestAsyncFSWAL extends AbstractTestFSWAL {
|
|||||||
String archiveDir, Configuration conf, List<WALActionsListener> listeners,
|
String archiveDir, Configuration conf, List<WALActionsListener> listeners,
|
||||||
boolean failIfWALExists, String prefix, String suffix, final Runnable action)
|
boolean failIfWALExists, String prefix, String suffix, final Runnable action)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return new AsyncFSWAL(fs, rootDir, logDir, archiveDir, conf, listeners, failIfWALExists, prefix,
|
AsyncFSWAL asyncFSWAL = new AsyncFSWAL(fs, rootDir, logDir, archiveDir, conf, listeners,
|
||||||
suffix, GROUP, CHANNEL_CLASS) {
|
failIfWALExists, prefix, suffix, GROUP, CHANNEL_CLASS) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void atHeadOfRingBufferEventHandlerAppend() {
|
void atHeadOfRingBufferEventHandlerAppend() {
|
||||||
action.run();
|
action.run();
|
||||||
@ -86,5 +87,7 @@ public class TestAsyncFSWAL extends AbstractTestFSWAL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
asyncFSWAL.init();
|
||||||
|
return asyncFSWAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,9 @@ public class TestAsyncWALReplay extends AbstractTestWALReplay {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WAL createWAL(Configuration c, Path hbaseRootDir, String logName) throws IOException {
|
protected WAL createWAL(Configuration c, Path hbaseRootDir, String logName) throws IOException {
|
||||||
return new AsyncFSWAL(FileSystem.get(c), hbaseRootDir, logName,
|
AsyncFSWAL asyncFSWAL = new AsyncFSWAL(FileSystem.get(c), hbaseRootDir, logName,
|
||||||
HConstants.HREGION_OLDLOGDIR_NAME, c, null, true, null, null, GROUP, CHANNEL_CLASS);
|
HConstants.HREGION_OLDLOGDIR_NAME, c, null, true, null, null, GROUP, CHANNEL_CLASS);
|
||||||
|
asyncFSWAL.init();
|
||||||
|
return asyncFSWAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,10 @@ public class TestFSHLog extends AbstractTestFSWAL {
|
|||||||
protected AbstractFSWAL<?> newWAL(FileSystem fs, Path rootDir, String walDir, String archiveDir,
|
protected AbstractFSWAL<?> newWAL(FileSystem fs, Path rootDir, String walDir, String archiveDir,
|
||||||
Configuration conf, List<WALActionsListener> listeners, boolean failIfWALExists,
|
Configuration conf, List<WALActionsListener> listeners, boolean failIfWALExists,
|
||||||
String prefix, String suffix) throws IOException {
|
String prefix, String suffix) throws IOException {
|
||||||
return new FSHLog(fs, rootDir, walDir, archiveDir, conf, listeners, failIfWALExists, prefix,
|
FSHLog fshLog = new FSHLog(fs, rootDir, walDir, archiveDir,
|
||||||
suffix);
|
conf, listeners, failIfWALExists, prefix, suffix);
|
||||||
|
fshLog.init();
|
||||||
|
return fshLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -83,8 +85,8 @@ public class TestFSHLog extends AbstractTestFSWAL {
|
|||||||
String archiveDir, Configuration conf, List<WALActionsListener> listeners,
|
String archiveDir, Configuration conf, List<WALActionsListener> listeners,
|
||||||
boolean failIfWALExists, String prefix, String suffix, final Runnable action)
|
boolean failIfWALExists, String prefix, String suffix, final Runnable action)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return new FSHLog(fs, rootDir, walDir, archiveDir, conf, listeners, failIfWALExists, prefix,
|
FSHLog fshLog = new FSHLog(fs, rootDir, walDir, archiveDir,
|
||||||
suffix) {
|
conf, listeners, failIfWALExists, prefix, suffix) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void atHeadOfRingBufferEventHandlerAppend() {
|
void atHeadOfRingBufferEventHandlerAppend() {
|
||||||
@ -92,6 +94,8 @@ public class TestFSHLog extends AbstractTestFSWAL {
|
|||||||
super.atHeadOfRingBufferEventHandlerAppend();
|
super.atHeadOfRingBufferEventHandlerAppend();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
fshLog.init();
|
||||||
|
return fshLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -100,6 +104,7 @@ public class TestFSHLog extends AbstractTestFSWAL {
|
|||||||
final String name = this.name.getMethodName();
|
final String name = this.name.getMethodName();
|
||||||
FSHLog log = new FSHLog(FS, FSUtils.getRootDir(CONF), name, HConstants.HREGION_OLDLOGDIR_NAME,
|
FSHLog log = new FSHLog(FS, FSUtils.getRootDir(CONF), name, HConstants.HREGION_OLDLOGDIR_NAME,
|
||||||
CONF, null, true, null, null);
|
CONF, null, true, null, null);
|
||||||
|
log.init();
|
||||||
try {
|
try {
|
||||||
Field ringBufferEventHandlerField = FSHLog.class.getDeclaredField("ringBufferEventHandler");
|
Field ringBufferEventHandlerField = FSHLog.class.getDeclaredField("ringBufferEventHandler");
|
||||||
ringBufferEventHandlerField.setAccessible(true);
|
ringBufferEventHandlerField.setAccessible(true);
|
||||||
@ -142,7 +147,7 @@ public class TestFSHLog extends AbstractTestFSWAL {
|
|||||||
try (FSHLog log =
|
try (FSHLog log =
|
||||||
new FSHLog(FS, FSUtils.getRootDir(CONF), name, HConstants.HREGION_OLDLOGDIR_NAME, CONF,
|
new FSHLog(FS, FSUtils.getRootDir(CONF), name, HConstants.HREGION_OLDLOGDIR_NAME, CONF,
|
||||||
null, true, null, null)) {
|
null, true, null, null)) {
|
||||||
|
log.init();
|
||||||
log.registerWALActionsListener(new WALActionsListener() {
|
log.registerWALActionsListener(new WALActionsListener() {
|
||||||
@Override
|
@Override
|
||||||
public void visitLogEntryBeforeWrite(WALKey logKey, WALEdit logEdit)
|
public void visitLogEntryBeforeWrite(WALKey logKey, WALEdit logEdit)
|
||||||
|
@ -104,6 +104,7 @@ public class TestWALDurability {
|
|||||||
FileSystem fs = FileSystem.get(conf);
|
FileSystem fs = FileSystem.get(conf);
|
||||||
Path rootDir = new Path(dir + getName());
|
Path rootDir = new Path(dir + getName());
|
||||||
CustomFSLog customFSLog = new CustomFSLog(fs, rootDir, getName(), conf);
|
CustomFSLog customFSLog = new CustomFSLog(fs, rootDir, getName(), conf);
|
||||||
|
customFSLog.init();
|
||||||
HRegion region = initHRegion(tableName, null, null, customFSLog);
|
HRegion region = initHRegion(tableName, null, null, customFSLog);
|
||||||
byte[] bytes = Bytes.toBytes(getName());
|
byte[] bytes = Bytes.toBytes(getName());
|
||||||
Put put = new Put(bytes);
|
Put put = new Put(bytes);
|
||||||
@ -118,6 +119,7 @@ public class TestWALDurability {
|
|||||||
conf.set(HRegion.WAL_HSYNC_CONF_KEY, "true");
|
conf.set(HRegion.WAL_HSYNC_CONF_KEY, "true");
|
||||||
fs = FileSystem.get(conf);
|
fs = FileSystem.get(conf);
|
||||||
customFSLog = new CustomFSLog(fs, rootDir, getName(), conf);
|
customFSLog = new CustomFSLog(fs, rootDir, getName(), conf);
|
||||||
|
customFSLog.init();
|
||||||
region = initHRegion(tableName, null, null, customFSLog);
|
region = initHRegion(tableName, null, null, customFSLog);
|
||||||
|
|
||||||
customFSLog.resetSyncFlag();
|
customFSLog.resetSyncFlag();
|
||||||
|
@ -0,0 +1,190 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase.regionserver.wal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileStatus;
|
||||||
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.hbase.FailedCloseWALAfterInitializedErrorException;
|
||||||
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
import org.apache.hadoop.hbase.HRegionInfo;
|
||||||
|
import org.apache.hadoop.hbase.ServerName;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
||||||
|
import org.apache.hadoop.hbase.util.CommonFSUtils;
|
||||||
|
import org.apache.hadoop.hbase.wal.FSHLogProvider;
|
||||||
|
import org.apache.hadoop.hbase.wal.WALFactory;
|
||||||
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.rules.TestName;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test WAL Init ERROR
|
||||||
|
*/
|
||||||
|
@Category({RegionServerTests.class, MediumTests.class})
|
||||||
|
public class TestWALOpenError {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
|
HBaseClassTestRule.forClass(TestWALOpenError.class);
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(TestWALOpenError.class);
|
||||||
|
|
||||||
|
protected static Configuration conf;
|
||||||
|
private static MiniDFSCluster cluster;
|
||||||
|
protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
|
||||||
|
protected static Path hbaseDir;
|
||||||
|
protected static Path hbaseWALDir;
|
||||||
|
|
||||||
|
protected FileSystem fs;
|
||||||
|
protected Path dir;
|
||||||
|
protected WALFactory wals;
|
||||||
|
private ServerName currentServername;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final TestName currentTest = new TestName();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
fs = cluster.getFileSystem();
|
||||||
|
dir = new Path(hbaseDir, currentTest.getMethodName());
|
||||||
|
this.currentServername = ServerName.valueOf(currentTest.getMethodName(), 16010, 1);
|
||||||
|
wals = new WALFactory(conf, this.currentServername.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
// testAppendClose closes the FileSystem, which will prevent us from closing cleanly here.
|
||||||
|
try {
|
||||||
|
wals.close();
|
||||||
|
} catch (IOException exception) {
|
||||||
|
LOG.warn("Encountered exception while closing wal factory. If you have other errors, this" +
|
||||||
|
" may be the cause. Message: " + exception);
|
||||||
|
LOG.debug("Exception details for failure to close wal factory.", exception);
|
||||||
|
}
|
||||||
|
FileStatus[] entries = fs.listStatus(new Path("/"));
|
||||||
|
for (FileStatus dir : entries) {
|
||||||
|
fs.delete(dir.getPath(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpBeforeClass() throws Exception {
|
||||||
|
TEST_UTIL.startMiniDFSCluster(3);
|
||||||
|
conf = TEST_UTIL.getConfiguration();
|
||||||
|
conf.set(WALFactory.WAL_PROVIDER, MyFSWalProvider.class.getName());
|
||||||
|
conf.set(WALFactory.META_WAL_PROVIDER, MyFSWalProvider.class.getName());
|
||||||
|
cluster = TEST_UTIL.getDFSCluster();
|
||||||
|
|
||||||
|
hbaseDir = TEST_UTIL.createRootDir();
|
||||||
|
hbaseWALDir = TEST_UTIL.createWALRootDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownAfterClass() throws Exception {
|
||||||
|
TEST_UTIL.shutdownMiniCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static MyFSLog myFSLogCreated;
|
||||||
|
private static boolean throwExceptionWhenCloseFSLogClose = false;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWALClosedIfOpenError() throws IOException {
|
||||||
|
|
||||||
|
throwExceptionWhenCloseFSLogClose = false;
|
||||||
|
|
||||||
|
boolean hasFakeInitException = false;
|
||||||
|
try {
|
||||||
|
wals.getWAL(HRegionInfo.FIRST_META_REGIONINFO);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
hasFakeInitException = ex.getMessage().contains("Fake init exception");
|
||||||
|
}
|
||||||
|
Assert.assertTrue(hasFakeInitException);
|
||||||
|
Assert.assertTrue(myFSLogCreated.closed);
|
||||||
|
|
||||||
|
FileStatus[] fileStatuses = CommonFSUtils.listStatus(fs, myFSLogCreated.walDir);
|
||||||
|
Assert.assertTrue(fileStatuses == null || fileStatuses.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThrowFailedCloseWalException() throws IOException {
|
||||||
|
throwExceptionWhenCloseFSLogClose = true;
|
||||||
|
boolean failedCloseWalException = false;
|
||||||
|
try {
|
||||||
|
wals.getWAL(HRegionInfo.FIRST_META_REGIONINFO);
|
||||||
|
} catch (FailedCloseWALAfterInitializedErrorException ex) {
|
||||||
|
failedCloseWalException = true;
|
||||||
|
}
|
||||||
|
Assert.assertTrue(failedCloseWalException);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MyFSWalProvider extends FSHLogProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MyFSLog createWAL() throws IOException {
|
||||||
|
MyFSLog myFSLog = new MyFSLog(CommonFSUtils.getWALFileSystem(conf),
|
||||||
|
CommonFSUtils.getWALRootDir(conf), getWALDirectoryName(factory.getFactoryId()),
|
||||||
|
getWALArchiveDirectoryName(conf, factory.getFactoryId()), conf, listeners, true, logPrefix,
|
||||||
|
META_WAL_PROVIDER_ID.equals(providerId) ? META_WAL_PROVIDER_ID : null);
|
||||||
|
|
||||||
|
myFSLogCreated = myFSLog;
|
||||||
|
|
||||||
|
return myFSLog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MyFSLog extends FSHLog {
|
||||||
|
public MyFSLog(final FileSystem fs, final Path rootDir, final String logDir,
|
||||||
|
final String archiveDir, final Configuration conf, final List<WALActionsListener> listeners,
|
||||||
|
final boolean failIfWALExists, final String prefix, final String suffix) throws IOException {
|
||||||
|
super(fs, rootDir, logDir, archiveDir, conf, listeners, failIfWALExists, prefix, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws IOException {
|
||||||
|
super.init();
|
||||||
|
throw new IOException("Fake init exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (throwExceptionWhenCloseFSLogClose) {
|
||||||
|
throw new IOException("Fake close exception");
|
||||||
|
}
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@ public class TestWALReplay extends AbstractTestWALReplay {
|
|||||||
@Override
|
@Override
|
||||||
protected WAL createWAL(Configuration c, Path hbaseRootDir, String logName) throws IOException {
|
protected WAL createWAL(Configuration c, Path hbaseRootDir, String logName) throws IOException {
|
||||||
FSHLog wal = new FSHLog(FileSystem.get(c), hbaseRootDir, logName, c);
|
FSHLog wal = new FSHLog(FileSystem.get(c), hbaseRootDir, logName, c);
|
||||||
|
wal.init();
|
||||||
// Set down maximum recovery so we dfsclient doesn't linger retrying something
|
// Set down maximum recovery so we dfsclient doesn't linger retrying something
|
||||||
// long gone.
|
// long gone.
|
||||||
HBaseTestingUtility.setMaxRecoveryErrorCount(wal.getOutputStream(), 1);
|
HBaseTestingUtility.setMaxRecoveryErrorCount(wal.getOutputStream(), 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user