HBASE-18068 Fix flaky test TestAsyncSnapshotAdminApi
- internalRestoreSnapshot() returns future which completes by just getting proc_id from master. Changed it to wait for the procedure to complete. - Refactor TestAsyncSnapshotAdminApi: Add cleanup() which deletes all tables and snapshots after every test run. Simplifies individual tests. Change-Id: Idc30fb699db32d58fd0f60da220953a430f1d3cc
This commit is contained in:
parent
3aac047a4f
commit
23ea2c36f5
|
@ -90,7 +90,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRe
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionRequest;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionRequest;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionResponse;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionResponse;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest;
|
||||||
|
@ -1528,7 +1527,8 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> addReplicationPeer(String peerId, ReplicationPeerConfig peerConfig) {
|
public CompletableFuture<Void> addReplicationPeer(String peerId,
|
||||||
|
ReplicationPeerConfig peerConfig) {
|
||||||
return this
|
return this
|
||||||
.<Void> newMasterCaller()
|
.<Void> newMasterCaller()
|
||||||
.action(
|
.action(
|
||||||
|
@ -1798,11 +1798,11 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
future.completeExceptionally(err);
|
future.completeExceptionally(err);
|
||||||
} else {
|
} else {
|
||||||
// Step.2 Restore snapshot
|
// Step.2 Restore snapshot
|
||||||
internalRestoreSnapshot(snapshotName, tableName).whenComplete((ret2, err2) -> {
|
internalRestoreSnapshot(snapshotName, tableName).whenComplete((void2, err2) -> {
|
||||||
if (err2 != null) {
|
if (err2 != null) {
|
||||||
// Step.3.a Something went wrong during the restore and try to rollback.
|
// Step.3.a Something went wrong during the restore and try to rollback.
|
||||||
internalRestoreSnapshot(failSafeSnapshotSnapshotName, tableName)
|
internalRestoreSnapshot(failSafeSnapshotSnapshotName, tableName)
|
||||||
.whenComplete((ret3, err3) -> {
|
.whenComplete((void3, err3) -> {
|
||||||
if (err3 != null) {
|
if (err3 != null) {
|
||||||
future.completeExceptionally(err3);
|
future.completeExceptionally(err3);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1864,13 +1864,8 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
future.completeExceptionally(err2);
|
future.completeExceptionally(err2);
|
||||||
} else if (!exists) {
|
} else if (!exists) {
|
||||||
// if table does not exist, then just clone snapshot into new table.
|
// if table does not exist, then just clone snapshot into new table.
|
||||||
internalRestoreSnapshot(snapshotName, finalTableName).whenComplete((ret, err3) -> {
|
completeConditionalOnFuture(future,
|
||||||
if (err3 != null) {
|
internalRestoreSnapshot(snapshotName, finalTableName));
|
||||||
future.completeExceptionally(err3);
|
|
||||||
} else {
|
|
||||||
future.complete(ret);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
isTableDisabled(finalTableName).whenComplete((disabled, err4) -> {
|
isTableDisabled(finalTableName).whenComplete((disabled, err4) -> {
|
||||||
if (err4 != null) {
|
if (err4 != null) {
|
||||||
|
@ -1878,14 +1873,8 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
} else if (!disabled) {
|
} else if (!disabled) {
|
||||||
future.completeExceptionally(new TableNotDisabledException(finalTableName));
|
future.completeExceptionally(new TableNotDisabledException(finalTableName));
|
||||||
} else {
|
} else {
|
||||||
restoreSnapshotWithFailSafe(snapshotName, finalTableName, takeFailSafeSnapshot)
|
completeConditionalOnFuture(future,
|
||||||
.whenComplete((ret, err5) -> {
|
restoreSnapshotWithFailSafe(snapshotName, finalTableName, takeFailSafeSnapshot));
|
||||||
if (err5 != null) {
|
|
||||||
future.completeExceptionally(err5);
|
|
||||||
} else {
|
|
||||||
future.complete(ret);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1894,6 +1883,17 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> void completeConditionalOnFuture(CompletableFuture<T> dependentFuture,
|
||||||
|
CompletableFuture<T> parentFuture) {
|
||||||
|
parentFuture.whenComplete((res, err) -> {
|
||||||
|
if (err != null) {
|
||||||
|
dependentFuture.completeExceptionally(err);
|
||||||
|
} else {
|
||||||
|
dependentFuture.complete(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> cloneSnapshot(String snapshotName, TableName tableName) {
|
public CompletableFuture<Void> cloneSnapshot(String snapshotName, TableName tableName) {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
|
@ -1903,13 +1903,7 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
} else if (exists) {
|
} else if (exists) {
|
||||||
future.completeExceptionally(new TableExistsException(tableName));
|
future.completeExceptionally(new TableExistsException(tableName));
|
||||||
} else {
|
} else {
|
||||||
internalRestoreSnapshot(snapshotName, tableName).whenComplete((ret, err2) -> {
|
completeConditionalOnFuture(future, internalRestoreSnapshot(snapshotName, tableName));
|
||||||
if (err2 != null) {
|
|
||||||
future.completeExceptionally(err2);
|
|
||||||
} else {
|
|
||||||
future.complete(ret);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return future;
|
return future;
|
||||||
|
@ -1924,13 +1918,15 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return failedFuture(e);
|
return failedFuture(e);
|
||||||
}
|
}
|
||||||
return this.<Void> newMasterCaller()
|
return waitProcedureResult(
|
||||||
|
this.<Long> newMasterCaller()
|
||||||
.action((controller, stub) -> this
|
.action((controller, stub) -> this
|
||||||
.<RestoreSnapshotRequest, RestoreSnapshotResponse, Void> call(controller, stub,
|
.<RestoreSnapshotRequest, RestoreSnapshotResponse, Long> call(controller, stub,
|
||||||
RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
|
RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
|
||||||
.setNonceGroup(ng.getNonceGroup()).setNonce(ng.newNonce()).build(),
|
.setNonceGroup(ng.getNonceGroup()).setNonce(ng.newNonce()).build(),
|
||||||
(s, c, req, done) -> s.restoreSnapshot(c, req, done), resp -> null))
|
(s, c, req, done) -> s.restoreSnapshot(c, req, done),
|
||||||
.call();
|
(resp) -> resp.getProcId()))
|
||||||
|
.call());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,9 +22,13 @@ import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
||||||
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.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.rules.TestName;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -34,14 +38,30 @@ import java.util.regex.Pattern;
|
||||||
@Category({ MediumTests.class, ClientTests.class })
|
@Category({ MediumTests.class, ClientTests.class })
|
||||||
public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTakeSnapshot() throws Exception {
|
|
||||||
String snapshotName1 = "snapshotName1";
|
String snapshotName1 = "snapshotName1";
|
||||||
String snapshotName2 = "snapshotName2";
|
String snapshotName2 = "snapshotName2";
|
||||||
TableName tableName = TableName.valueOf("testTakeSnapshot");
|
String snapshotName3 = "snapshotName3";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TestName testName = new TestName();
|
||||||
|
TableName tableName;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
tableName = TableName.valueOf(testName.getMethodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanup() throws Exception {
|
||||||
|
admin.deleteSnapshots(".*").get();
|
||||||
|
admin.disableTables(".*").get();
|
||||||
|
admin.deleteTables(".*").get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTakeSnapshot() throws Exception {
|
||||||
Admin syncAdmin = TEST_UTIL.getAdmin();
|
Admin syncAdmin = TEST_UTIL.getAdmin();
|
||||||
|
|
||||||
try {
|
|
||||||
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
||||||
for (int i = 0; i < 3000; i++) {
|
for (int i = 0; i < 3000; i++) {
|
||||||
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
||||||
|
@ -65,21 +85,13 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
Assert.assertEquals(snapshotName2, snapshots.get(1).getName());
|
Assert.assertEquals(snapshotName2, snapshots.get(1).getName());
|
||||||
Assert.assertEquals(tableName, snapshots.get(1).getTableName());
|
Assert.assertEquals(tableName, snapshots.get(1).getTableName());
|
||||||
Assert.assertEquals(SnapshotType.FLUSH, snapshots.get(1).getType());
|
Assert.assertEquals(SnapshotType.FLUSH, snapshots.get(1).getType());
|
||||||
} finally {
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName1);
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName2);
|
|
||||||
TEST_UTIL.deleteTable(tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCloneSnapshot() throws Exception {
|
public void testCloneSnapshot() throws Exception {
|
||||||
String snapshotName1 = "snapshotName1";
|
|
||||||
TableName tableName = TableName.valueOf("testCloneSnapshot");
|
|
||||||
TableName tableName2 = TableName.valueOf("testCloneSnapshot2");
|
TableName tableName2 = TableName.valueOf("testCloneSnapshot2");
|
||||||
Admin syncAdmin = TEST_UTIL.getAdmin();
|
Admin syncAdmin = TEST_UTIL.getAdmin();
|
||||||
|
|
||||||
try {
|
|
||||||
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
||||||
for (int i = 0; i < 3000; i++) {
|
for (int i = 0; i < 3000; i++) {
|
||||||
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
||||||
|
@ -106,10 +118,6 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
Assert.assertTrue(!syncAdmin.tableExists(tableName2));
|
Assert.assertTrue(!syncAdmin.tableExists(tableName2));
|
||||||
admin.cloneSnapshot(snapshotName1, tableName2).get();
|
admin.cloneSnapshot(snapshotName1, tableName2).get();
|
||||||
syncAdmin.tableExists(tableName2);
|
syncAdmin.tableExists(tableName2);
|
||||||
} finally {
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName1);
|
|
||||||
TEST_UTIL.deleteTable(tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertResult(TableName tableName, int expectedRowCount) throws IOException {
|
private void assertResult(TableName tableName, int expectedRowCount) throws IOException {
|
||||||
|
@ -131,12 +139,6 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRestoreSnapshot() throws Exception {
|
public void testRestoreSnapshot() throws Exception {
|
||||||
String snapshotName1 = "snapshotName1";
|
|
||||||
String snapshotName2 = "snapshotName2";
|
|
||||||
TableName tableName = TableName.valueOf("testRestoreSnapshot");
|
|
||||||
Admin syncAdmin = TEST_UTIL.getAdmin();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
||||||
for (int i = 0; i < 3000; i++) {
|
for (int i = 0; i < 3000; i++) {
|
||||||
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
||||||
|
@ -157,22 +159,10 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
admin.restoreSnapshot(snapshotName2, false).get();
|
admin.restoreSnapshot(snapshotName2, false).get();
|
||||||
admin.enableTable(tableName).get();
|
admin.enableTable(tableName).get();
|
||||||
assertResult(tableName, 3000);
|
assertResult(tableName, 3000);
|
||||||
} finally {
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName1);
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName2);
|
|
||||||
TEST_UTIL.deleteTable(tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListSnapshots() throws Exception {
|
public void testListSnapshots() throws Exception {
|
||||||
String snapshotName1 = "snapshotName1";
|
|
||||||
String snapshotName2 = "snapshotName2";
|
|
||||||
String snapshotName3 = "snapshotName3";
|
|
||||||
TableName tableName = TableName.valueOf("testListSnapshots");
|
|
||||||
Admin syncAdmin = TEST_UTIL.getAdmin();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
||||||
for (int i = 0; i < 3000; i++) {
|
for (int i = 0; i < 3000; i++) {
|
||||||
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
||||||
|
@ -192,23 +182,10 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
Assert.assertEquals(admin.listTableSnapshots("testListSnapshots", "s(.*)").get().size(), 3);
|
Assert.assertEquals(admin.listTableSnapshots("testListSnapshots", "s(.*)").get().size(), 3);
|
||||||
Assert.assertEquals(admin.listTableSnapshots("fakeTableName", "snap(.*)").get().size(), 0);
|
Assert.assertEquals(admin.listTableSnapshots("fakeTableName", "snap(.*)").get().size(), 0);
|
||||||
Assert.assertEquals(admin.listTableSnapshots("test(.*)", "snap(.*)[1|3]").get().size(), 2);
|
Assert.assertEquals(admin.listTableSnapshots("test(.*)", "snap(.*)[1|3]").get().size(), 2);
|
||||||
|
|
||||||
} finally {
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName1);
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName2);
|
|
||||||
syncAdmin.deleteSnapshot(snapshotName3);
|
|
||||||
TEST_UTIL.deleteTable(tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteSnapshots() throws Exception {
|
public void testDeleteSnapshots() throws Exception {
|
||||||
String snapshotName1 = "snapshotName1";
|
|
||||||
String snapshotName2 = "snapshotName2";
|
|
||||||
String snapshotName3 = "snapshotName3";
|
|
||||||
TableName tableName = TableName.valueOf("testDeleteSnapshots");
|
|
||||||
|
|
||||||
try {
|
|
||||||
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
|
||||||
for (int i = 0; i < 3000; i++) {
|
for (int i = 0; i < 3000; i++) {
|
||||||
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
|
||||||
|
@ -238,8 +215,5 @@ public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
|
||||||
|
|
||||||
admin.deleteTableSnapshots("(.*)", "(.*)3").get();
|
admin.deleteTableSnapshots("(.*)", "(.*)3").get();
|
||||||
Assert.assertEquals(admin.listSnapshots().get().size(), 0);
|
Assert.assertEquals(admin.listSnapshots().get().size(), 0);
|
||||||
} finally {
|
|
||||||
TEST_UTIL.deleteTable(tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue