use of org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner in project hbase by apache.
the class TestLogsCleaner method testZnodeCversionChange.
@Test(timeout = 5000)
public void testZnodeCversionChange() throws Exception {
Configuration conf = TEST_UTIL.getConfiguration();
ReplicationLogCleaner cleaner = new ReplicationLogCleaner();
cleaner.setConf(conf);
ReplicationQueuesClientZKImpl rqcMock = Mockito.mock(ReplicationQueuesClientZKImpl.class);
Mockito.when(rqcMock.getQueuesZNodeCversion()).thenReturn(1, 2, 3, 4);
Field rqc = ReplicationLogCleaner.class.getDeclaredField("replicationQueues");
rqc.setAccessible(true);
rqc.set(cleaner, rqcMock);
// This should return eventually when cversion stabilizes
cleaner.getDeletableFiles(new LinkedList<>());
}
use of org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner in project hbase by apache.
the class TestLogsCleaner method testLogCleaning.
/**
* This tests verifies LogCleaner works correctly with WALs and Procedure WALs located
* in the same oldWALs directory.
* Created files:
* - 2 invalid files
* - 5 old Procedure WALs
* - 30 old WALs from which 3 are in replication
* - 5 recent Procedure WALs
* - 1 recent WAL
* - 1 very new WAL (timestamp in future)
* - masterProcedureWALs subdirectory
* Files which should stay:
* - 3 replication WALs
* - 2 new WALs
* - 5 latest Procedure WALs
* - masterProcedureWALs subdirectory
*/
@Test
public void testLogCleaning() throws Exception {
// set TTLs
long ttlWAL = 2000;
long ttlProcedureWAL = 4000;
conf.setLong("hbase.master.logcleaner.ttl", ttlWAL);
conf.setLong("hbase.master.procedurewalcleaner.ttl", ttlProcedureWAL);
HMaster.decorateMasterConfiguration(conf);
Server server = new DummyServer();
ReplicationQueueStorage queueStorage = ReplicationStorageFactory.getReplicationQueueStorage(server.getZooKeeper(), conf);
String fakeMachineName = URLEncoder.encode(server.getServerName().toString(), StandardCharsets.UTF_8.name());
final FileSystem fs = FileSystem.get(conf);
fs.mkdirs(OLD_PROCEDURE_WALS_DIR);
final long now = EnvironmentEdgeManager.currentTime();
// Case 1: 2 invalid files, which would be deleted directly
fs.createNewFile(new Path(OLD_WALS_DIR, "a"));
fs.createNewFile(new Path(OLD_WALS_DIR, fakeMachineName + "." + "a"));
// Case 2: 5 Procedure WALs that are old which would be deleted
for (int i = 1; i <= 5; i++) {
final Path fileName = new Path(OLD_PROCEDURE_WALS_DIR, String.format("pv2-%020d.log", i));
fs.createNewFile(fileName);
}
// Sleep for sometime to get old procedure WALs
Thread.sleep(ttlProcedureWAL - ttlWAL);
// Case 3: old WALs which would be deletable
for (int i = 1; i <= 30; i++) {
Path fileName = new Path(OLD_WALS_DIR, fakeMachineName + "." + (now - i));
fs.createNewFile(fileName);
// files would pass TimeToLiveLogCleaner but would be rejected by ReplicationLogCleaner
if (i % (30 / 3) == 0) {
queueStorage.addWAL(server.getServerName(), fakeMachineName, fileName.getName());
LOG.info("Replication log file: " + fileName);
}
}
// Case 5: 5 Procedure WALs that are new, will stay
for (int i = 6; i <= 10; i++) {
Path fileName = new Path(OLD_PROCEDURE_WALS_DIR, String.format("pv2-%020d.log", i));
fs.createNewFile(fileName);
}
// Sleep for sometime to get newer modification time
Thread.sleep(ttlWAL);
fs.createNewFile(new Path(OLD_WALS_DIR, fakeMachineName + "." + now));
// Case 6: 1 newer WAL, not even deletable for TimeToLiveLogCleaner,
// so we are not going down the chain
fs.createNewFile(new Path(OLD_WALS_DIR, fakeMachineName + "." + (now + ttlWAL)));
FileStatus[] status = fs.listStatus(OLD_WALS_DIR);
LOG.info("File status: {}", Arrays.toString(status));
// There should be 34 files and 1 masterProcedureWALs directory
assertEquals(35, fs.listStatus(OLD_WALS_DIR).length);
// 10 procedure WALs
assertEquals(10, fs.listStatus(OLD_PROCEDURE_WALS_DIR).length);
LogCleaner cleaner = new LogCleaner(1000, server, conf, fs, OLD_WALS_DIR, POOL, null);
cleaner.chore();
// In oldWALs we end up with the current WAL, a newer WAL, the 3 old WALs which
// are scheduled for replication and masterProcedureWALs directory
TEST_UTIL.waitFor(1000, (Waiter.Predicate<Exception>) () -> 6 == fs.listStatus(OLD_WALS_DIR).length);
// In masterProcedureWALs we end up with 5 newer Procedure WALs
TEST_UTIL.waitFor(1000, (Waiter.Predicate<Exception>) () -> 5 == fs.listStatus(OLD_PROCEDURE_WALS_DIR).length);
if (LOG.isDebugEnabled()) {
FileStatus[] statusOldWALs = fs.listStatus(OLD_WALS_DIR);
FileStatus[] statusProcedureWALs = fs.listStatus(OLD_PROCEDURE_WALS_DIR);
LOG.debug("Kept log file for oldWALs: {}", Arrays.toString(statusOldWALs));
LOG.debug("Kept log file for masterProcedureWALs: {}", Arrays.toString(statusProcedureWALs));
}
}
use of org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner in project hbase by apache.
the class TestLogsCleaner method testZooKeeperNormal.
/**
* When zk is working both files should be returned
* @throws Exception from ZK watcher
*/
@Test
public void testZooKeeperNormal() throws Exception {
ReplicationLogCleaner cleaner = new ReplicationLogCleaner();
// Subtract 1000 from current time so modtime is for sure older
// than 'now'.
long modTime = EnvironmentEdgeManager.currentTime() - 1000;
List<FileStatus> dummyFiles = Arrays.asList(new FileStatus(100, false, 3, 100, modTime, new Path("log1")), new FileStatus(100, false, 3, 100, modTime, new Path("log2")));
ZKWatcher zkw = new ZKWatcher(conf, "testZooKeeperAbort-normal", null);
try {
cleaner.setConf(conf, zkw);
cleaner.preClean();
Iterable<FileStatus> filesToDelete = cleaner.getDeletableFiles(dummyFiles);
Iterator<FileStatus> iter = filesToDelete.iterator();
assertTrue(iter.hasNext());
assertEquals(new Path("log1"), iter.next().getPath());
assertTrue(iter.hasNext());
assertEquals(new Path("log2"), iter.next().getPath());
assertFalse(iter.hasNext());
} finally {
zkw.close();
}
}
use of org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner in project hbase by apache.
the class TestLogsCleaner method testZooKeeperAbort.
/**
* ReplicationLogCleaner should be able to ride over ZooKeeper errors without
* aborting.
*/
@Test
public void testZooKeeperAbort() throws Exception {
Configuration conf = TEST_UTIL.getConfiguration();
ReplicationLogCleaner cleaner = new ReplicationLogCleaner();
List<FileStatus> dummyFiles = Lists.newArrayList(new FileStatus(100, false, 3, 100, System.currentTimeMillis(), new Path("log1")), new FileStatus(100, false, 3, 100, System.currentTimeMillis(), new Path("log2")));
FaultyZooKeeperWatcher faultyZK = new FaultyZooKeeperWatcher(conf, "testZooKeeperAbort-faulty", null);
try {
faultyZK.init();
cleaner.setConf(conf, faultyZK);
// should keep all files due to a ConnectionLossException getting the queues znodes
Iterable<FileStatus> toDelete = cleaner.getDeletableFiles(dummyFiles);
assertFalse(toDelete.iterator().hasNext());
assertFalse(cleaner.isStopped());
} finally {
faultyZK.close();
}
// when zk is working both files should be returned
cleaner = new ReplicationLogCleaner();
ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "testZooKeeperAbort-normal", null);
try {
cleaner.setConf(conf, zkw);
Iterable<FileStatus> filesToDelete = cleaner.getDeletableFiles(dummyFiles);
Iterator<FileStatus> iter = filesToDelete.iterator();
assertTrue(iter.hasNext());
assertEquals(new Path("log1"), iter.next().getPath());
assertTrue(iter.hasNext());
assertEquals(new Path("log2"), iter.next().getPath());
assertFalse(iter.hasNext());
} finally {
zkw.close();
}
}
use of org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner in project hbase by apache.
the class TestLogsCleaner method testZooKeeperRecoveryDuringGetListOfReplicators.
@Test
public void testZooKeeperRecoveryDuringGetListOfReplicators() throws Exception {
ReplicationLogCleaner cleaner = new ReplicationLogCleaner();
List<FileStatus> dummyFiles = Arrays.asList(new FileStatus(100, false, 3, 100, EnvironmentEdgeManager.currentTime(), new Path("log1")), new FileStatus(100, false, 3, 100, EnvironmentEdgeManager.currentTime(), new Path("log2")));
FaultyZooKeeperWatcher faultyZK = new FaultyZooKeeperWatcher(conf, "testZooKeeperAbort-faulty", null);
final AtomicBoolean getListOfReplicatorsFailed = new AtomicBoolean(false);
try {
faultyZK.init(false);
ReplicationQueueStorage queueStorage = spy(ReplicationStorageFactory.getReplicationQueueStorage(faultyZK, conf));
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
try {
return invocation.callRealMethod();
} catch (ReplicationException e) {
LOG.debug("Caught Exception", e);
getListOfReplicatorsFailed.set(true);
throw e;
}
}
}).when(queueStorage).getAllWALs();
cleaner.setConf(conf, faultyZK, queueStorage);
// should keep all files due to a ConnectionLossException getting the queues znodes
cleaner.preClean();
Iterable<FileStatus> toDelete = cleaner.getDeletableFiles(dummyFiles);
assertTrue(getListOfReplicatorsFailed.get());
assertFalse(toDelete.iterator().hasNext());
assertFalse(cleaner.isStopped());
// zk recovery.
faultyZK.init(true);
cleaner.preClean();
Iterable<FileStatus> filesToDelete = cleaner.getDeletableFiles(dummyFiles);
Iterator<FileStatus> iter = filesToDelete.iterator();
assertTrue(iter.hasNext());
assertEquals(new Path("log1"), iter.next().getPath());
assertTrue(iter.hasNext());
assertEquals(new Path("log2"), iter.next().getPath());
assertFalse(iter.hasNext());
} finally {
faultyZK.close();
}
}
Aggregations