use of org.apache.hadoop.hbase.regionserver.LogRoller in project hbase by apache.
the class PeerProcedureHandlerImpl method transitSyncReplicationPeerState.
@Override
public void transitSyncReplicationPeerState(String peerId, int stage, HRegionServer rs) throws ReplicationException, IOException {
ReplicationPeers replicationPeers = replicationSourceManager.getReplicationPeers();
Lock peerLock = peersLock.acquireLock(peerId);
try {
ReplicationPeerImpl peer = replicationPeers.getPeer(peerId);
if (peer == null) {
throw new ReplicationException("Peer with id=" + peerId + " is not cached.");
}
if (!peer.getPeerConfig().isSyncReplication()) {
throw new ReplicationException("Peer with id=" + peerId + " is not synchronous.");
}
SyncReplicationState newSyncReplicationState = peer.getNewSyncReplicationState();
if (stage == 0) {
if (newSyncReplicationState != SyncReplicationState.NONE) {
LOG.warn("The new sync replication state for peer {} has already been set to {}, " + "this should be a retry, give up", peerId, newSyncReplicationState);
return;
}
// refresh the peer state first, as when we transit to STANDBY, we may need to disable the
// peer before processing the sync replication state.
PeerState oldState = peer.getPeerState();
boolean success = false;
try {
PeerState newState = replicationPeers.refreshPeerState(peerId);
if (oldState.equals(PeerState.ENABLED) && newState.equals(PeerState.DISABLED)) {
replicationSourceManager.refreshSources(peerId);
}
success = true;
} finally {
if (!success) {
peer.setPeerState(oldState.equals(PeerState.ENABLED));
}
}
newSyncReplicationState = replicationPeers.refreshPeerNewSyncReplicationState(peerId);
SyncReplicationState oldSyncReplicationState = peer.getSyncReplicationState();
peerActionListener.peerSyncReplicationStateChange(peerId, oldSyncReplicationState, newSyncReplicationState, stage);
} else {
if (newSyncReplicationState == SyncReplicationState.NONE) {
LOG.warn("The new sync replication state for peer {} has already been clear, and the " + "current state is {}, this should be a retry, give up", peerId, newSyncReplicationState);
return;
}
if (newSyncReplicationState == SyncReplicationState.STANDBY) {
replicationSourceManager.drainSources(peerId);
// Need to roll the wals and make the ReplicationSource for this peer track the new file.
// If we do not do this, there will be two problems that can not be addressed at the same
// time. First, if we just throw away the current wal file, and later when we transit the
// peer to DA, and the wal has not been rolled yet, then the new data written to the wal
// file will not be replicated and cause data inconsistency. But if we just track the
// current wal file without rolling, it may contains some data before we transit the peer
// to S, later if we transit the peer to DA, the data will also be replicated and cause
// data inconsistency. So here we need to roll the wal, and let the ReplicationSource
// track the new wal file, and throw the old wal files away.
LogRoller roller = rs.getWalRoller();
roller.requestRollAll();
try {
roller.waitUntilWalRollFinished();
} catch (InterruptedException e) {
// reset the interrupted flag
Thread.currentThread().interrupt();
throw (IOException) new InterruptedIOException("Interrupted while waiting for wal roll finish").initCause(e);
}
}
SyncReplicationState oldState = peer.getSyncReplicationState();
peerActionListener.peerSyncReplicationStateChange(peerId, oldState, newSyncReplicationState, stage);
peer.transitSyncReplicationState();
}
} finally {
peerLock.unlock();
}
}
use of org.apache.hadoop.hbase.regionserver.LogRoller in project hbase by apache.
the class WALPerformanceEvaluation method run.
@Override
public int run(String[] args) throws Exception {
Path rootRegionDir = null;
int numThreads = 1;
long numIterations = 1000000;
int numFamilies = 1;
int syncInterval = 0;
boolean noSync = false;
boolean verify = false;
boolean verbose = false;
boolean cleanup = true;
boolean noclosefs = false;
long roll = Long.MAX_VALUE;
boolean compress = false;
String cipher = null;
int numRegions = 1;
// Process command line args
for (int i = 0; i < args.length; i++) {
String cmd = args[i];
try {
if (cmd.equals("-threads")) {
numThreads = Integer.parseInt(args[++i]);
} else if (cmd.equals("-iterations")) {
numIterations = Long.parseLong(args[++i]);
} else if (cmd.equals("-path")) {
rootRegionDir = new Path(args[++i]);
} else if (cmd.equals("-families")) {
numFamilies = Integer.parseInt(args[++i]);
} else if (cmd.equals("-qualifiers")) {
numQualifiers = Integer.parseInt(args[++i]);
} else if (cmd.equals("-keySize")) {
keySize = Integer.parseInt(args[++i]);
} else if (cmd.equals("-valueSize")) {
valueSize = Integer.parseInt(args[++i]);
} else if (cmd.equals("-syncInterval")) {
syncInterval = Integer.parseInt(args[++i]);
} else if (cmd.equals("-nosync")) {
noSync = true;
} else if (cmd.equals("-verify")) {
verify = true;
} else if (cmd.equals("-verbose")) {
verbose = true;
} else if (cmd.equals("-nocleanup")) {
cleanup = false;
} else if (cmd.equals("-noclosefs")) {
noclosefs = true;
} else if (cmd.equals("-roll")) {
roll = Long.parseLong(args[++i]);
} else if (cmd.equals("-compress")) {
compress = true;
} else if (cmd.equals("-encryption")) {
cipher = args[++i];
} else if (cmd.equals("-regions")) {
numRegions = Integer.parseInt(args[++i]);
} else if (cmd.equals("-traceFreq")) {
// keep it here for compatible
System.err.println("-traceFreq is not supported any more");
} else if (cmd.equals("-h")) {
printUsageAndExit();
} else if (cmd.equals("--help")) {
printUsageAndExit();
} else {
System.err.println("UNEXPECTED: " + cmd);
printUsageAndExit();
}
} catch (Exception e) {
printUsageAndExit();
}
}
if (compress) {
Configuration conf = getConf();
conf.setBoolean(HConstants.ENABLE_WAL_COMPRESSION, true);
}
if (cipher != null) {
// Set up WAL for encryption
Configuration conf = getConf();
conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName());
conf.set(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, "hbase");
conf.setClass("hbase.regionserver.hlog.reader.impl", SecureProtobufLogReader.class, WAL.Reader.class);
conf.setClass("hbase.regionserver.hlog.writer.impl", SecureProtobufLogWriter.class, Writer.class);
conf.setBoolean(HConstants.ENABLE_WAL_ENCRYPTION, true);
conf.set(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, cipher);
}
if (numThreads < numRegions) {
LOG.warn("Number of threads is less than the number of regions; some regions will sit idle.");
}
// Internal config. goes off number of threads; if more threads than handlers, stuff breaks.
// In regionserver, number of handlers == number of threads.
getConf().setInt(HConstants.REGION_SERVER_HANDLER_COUNT, numThreads);
if (rootRegionDir == null) {
TEST_UTIL = new HBaseTestingUtil(getConf());
rootRegionDir = TEST_UTIL.getDataTestDirOnTestFS("WALPerformanceEvaluation");
}
// Run WAL Performance Evaluation
// First set the fs from configs. In case we are on hadoop1
CommonFSUtils.setFsDefault(getConf(), CommonFSUtils.getRootDir(getConf()));
FileSystem fs = FileSystem.get(getConf());
LOG.info("FileSystem={}, rootDir={}", fs, rootRegionDir);
Span span = TraceUtil.getGlobalTracer().spanBuilder("WALPerfEval").startSpan();
try (Scope scope = span.makeCurrent()) {
rootRegionDir = rootRegionDir.makeQualified(fs.getUri(), fs.getWorkingDirectory());
cleanRegionRootDir(fs, rootRegionDir);
CommonFSUtils.setRootDir(getConf(), rootRegionDir);
final WALFactory wals = new WALFactory(getConf(), "wals");
final HRegion[] regions = new HRegion[numRegions];
final Runnable[] benchmarks = new Runnable[numRegions];
final MockRegionServerServices mockServices = new MockRegionServerServices(getConf());
final LogRoller roller = new LogRoller(mockServices);
Threads.setDaemonThreadRunning(roller, "WALPerfEval.logRoller");
try {
for (int i = 0; i < numRegions; i++) {
// Initialize Table Descriptor
// a table per desired region means we can avoid carving up the key space
final TableDescriptor htd = createHTableDescriptor(i, numFamilies);
regions[i] = openRegion(fs, rootRegionDir, htd, wals, roll, roller);
benchmarks[i] = new WALPutBenchmark(regions[i], htd, numIterations, noSync, syncInterval);
}
ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).outputTo(System.out).convertRatesTo(TimeUnit.SECONDS).filter(MetricFilter.ALL).build();
reporter.start(30, TimeUnit.SECONDS);
long putTime = runBenchmark(benchmarks, numThreads);
logBenchmarkResult("Summary: threads=" + numThreads + ", iterations=" + numIterations + ", syncInterval=" + syncInterval, numIterations * numThreads, putTime);
for (int i = 0; i < numRegions; i++) {
if (regions[i] != null) {
closeRegion(regions[i]);
regions[i] = null;
}
}
if (verify) {
LOG.info("verifying written log entries.");
Path dir = new Path(CommonFSUtils.getRootDir(getConf()), AbstractFSWALProvider.getWALDirectoryName("wals"));
long editCount = 0;
FileStatus[] fsss = fs.listStatus(dir);
if (fsss.length == 0)
throw new IllegalStateException("No WAL found");
for (FileStatus fss : fsss) {
Path p = fss.getPath();
if (!fs.exists(p))
throw new IllegalStateException(p.toString());
editCount += verify(wals, p, verbose);
}
long expected = numIterations * numThreads;
if (editCount != expected) {
throw new IllegalStateException("Counted=" + editCount + ", expected=" + expected);
}
}
} finally {
mockServices.stop("test clean up.");
for (int i = 0; i < numRegions; i++) {
if (regions[i] != null) {
closeRegion(regions[i]);
}
}
if (null != roller) {
LOG.info("shutting down log roller.");
roller.close();
}
wals.shutdown();
// Remove the root dir for this test region
if (cleanup)
cleanRegionRootDir(fs, rootRegionDir);
}
} finally {
span.end();
// We may be called inside a test that wants to keep on using the fs.
if (!noclosefs) {
fs.close();
}
}
return 0;
}
use of org.apache.hadoop.hbase.regionserver.LogRoller in project hbase by apache.
the class TestSerialSyncReplication method test.
@Test
public void test() throws Exception {
// change to serial
UTIL1.getAdmin().updateReplicationPeerConfig(PEER_ID, ReplicationPeerConfig.newBuilder(UTIL1.getAdmin().getReplicationPeerConfig(PEER_ID)).setSerial(true).build());
UTIL2.getAdmin().updateReplicationPeerConfig(PEER_ID, ReplicationPeerConfig.newBuilder(UTIL2.getAdmin().getReplicationPeerConfig(PEER_ID)).setSerial(true).build());
UTIL2.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.STANDBY);
UTIL1.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.ACTIVE);
UTIL2.getAdmin().disableReplicationPeer(PEER_ID);
writeAndVerifyReplication(UTIL1, UTIL2, 0, 100);
MasterFileSystem mfs = UTIL2.getMiniHBaseCluster().getMaster().getMasterFileSystem();
Path remoteWALDir = ReplicationUtils.getPeerRemoteWALDir(new Path(mfs.getWALRootDir(), ReplicationUtils.REMOTE_WAL_DIR_NAME), PEER_ID);
FileStatus[] remoteWALStatus = mfs.getWALFileSystem().listStatus(remoteWALDir);
assertEquals(1, remoteWALStatus.length);
Path remoteWAL = remoteWALStatus[0].getPath();
assertThat(remoteWAL.getName(), endsWith(ReplicationUtils.SYNC_WAL_SUFFIX));
// will not replay this wal when transiting to DA.
for (RegionServerThread t : UTIL1.getMiniHBaseCluster().getRegionServerThreads()) {
LogRoller roller = t.getRegionServer().getWalRoller();
roller.requestRollAll();
roller.waitUntilWalRollFinished();
}
waitUntilDeleted(UTIL2, remoteWAL);
UTIL2.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.DOWNGRADE_ACTIVE);
UTIL1.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.STANDBY);
// let's reopen the region
RegionInfo region = Iterables.getOnlyElement(UTIL2.getAdmin().getRegions(TABLE_NAME));
HRegionServer target = UTIL2.getOtherRegionServer(UTIL2.getRSForFirstRegionInTable(TABLE_NAME));
UTIL2.getAdmin().move(region.getEncodedNameAsBytes(), target.getServerName());
// here we will remove all the pending wals. This is not a normal operation sequence but anyway,
// user could do this.
UTIL2.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.STANDBY);
// transit back to DA
UTIL2.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID, SyncReplicationState.DOWNGRADE_ACTIVE);
UTIL2.getAdmin().enableReplicationPeer(PEER_ID);
// make sure that the async replication still works
writeAndVerifyReplication(UTIL2, UTIL1, 100, 200);
}
use of org.apache.hadoop.hbase.regionserver.LogRoller in project hbase by apache.
the class TestAsyncFSWAL method testBrokenWriter.
@Test
public void testBrokenWriter() throws Exception {
RegionServerServices services = mock(RegionServerServices.class);
when(services.getConfiguration()).thenReturn(CONF);
TableDescriptor td = TableDescriptorBuilder.newBuilder(TableName.valueOf("table")).setColumnFamily(ColumnFamilyDescriptorBuilder.of("row")).build();
RegionInfo ri = RegionInfoBuilder.newBuilder(td.getTableName()).build();
MultiVersionConcurrencyControl mvcc = new MultiVersionConcurrencyControl();
NavigableMap<byte[], Integer> scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
for (byte[] fam : td.getColumnFamilyNames()) {
scopes.put(fam, 0);
}
long timestamp = EnvironmentEdgeManager.currentTime();
String testName = currentTest.getMethodName();
AtomicInteger failedCount = new AtomicInteger(0);
try (LogRoller roller = new LogRoller(services);
AsyncFSWAL wal = new AsyncFSWAL(FS, CommonFSUtils.getWALRootDir(CONF), DIR.toString(), testName, CONF, null, true, null, null, GROUP, CHANNEL_CLASS) {
@Override
protected AsyncWriter createWriterInstance(Path path) throws IOException {
AsyncWriter writer = super.createWriterInstance(path);
return new AsyncWriter() {
@Override
public void close() throws IOException {
writer.close();
}
@Override
public long getLength() {
return writer.getLength();
}
@Override
public long getSyncedLength() {
return writer.getSyncedLength();
}
@Override
public CompletableFuture<Long> sync(boolean forceSync) {
CompletableFuture<Long> result = writer.sync(forceSync);
if (failedCount.incrementAndGet() < 1000) {
CompletableFuture<Long> future = new CompletableFuture<>();
FutureUtils.addListener(result, (r, e) -> future.completeExceptionally(new IOException("Inject Error")));
return future;
} else {
return result;
}
}
@Override
public void append(Entry entry) {
writer.append(entry);
}
};
}
}) {
wal.init();
roller.addWAL(wal);
roller.start();
int numThreads = 10;
AtomicReference<Exception> error = new AtomicReference<>();
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < 10; i++) {
final int index = i;
threads[index] = new Thread("Write-Thread-" + index) {
@Override
public void run() {
byte[] row = Bytes.toBytes("row" + index);
WALEdit cols = new WALEdit();
cols.add(new KeyValue(row, row, row, timestamp + index, row));
WALKeyImpl key = new WALKeyImpl(ri.getEncodedNameAsBytes(), td.getTableName(), SequenceId.NO_SEQUENCE_ID, timestamp, WALKey.EMPTY_UUIDS, HConstants.NO_NONCE, HConstants.NO_NONCE, mvcc, scopes);
try {
wal.append(ri, key, cols, true);
} catch (IOException e) {
// should not happen
throw new UncheckedIOException(e);
}
try {
wal.sync();
} catch (IOException e) {
error.set(e);
}
}
};
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
assertNull(error.get());
}
}
Aggregations