use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.CallerArguments in project hive by apache.
the class TestReplicationScenariosAcrossInstances method testBootstrapReplLoadRetryAfterFailureForTablesAndConstraints.
@Test
public void testBootstrapReplLoadRetryAfterFailureForTablesAndConstraints() throws Throwable {
WarehouseInstance.Tuple tuple = primary.run("use " + primaryDbName).run("create table t1(a string, b string, primary key (a, b) disable novalidate rely)").run("create table t2(a string, b string, foreign key (a, b) references t1(a, b) disable novalidate)").run("create table t3(a string, b string not null disable, unique (a) disable)").dump(primaryDbName);
// Need to drop the primary DB as metastore is shared by both primary/replica. So, constraints
// conflict when loaded. Some issue with framework which needs to be relook into later.
primary.run("drop database if exists " + primaryDbName + " cascade");
// Allow create table only on t1. Create should fail for rest of the tables and hence constraints
// also not loaded.
BehaviourInjection<CallerArguments, Boolean> callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Override
public Boolean apply(CallerArguments args) {
injectionPathCalled = true;
if (!args.dbName.equalsIgnoreCase(replicatedDbName) || (args.constraintTblName != null)) {
LOG.warn("Verifier - DB: " + String.valueOf(args.dbName) + " Constraint Table: " + String.valueOf(args.constraintTblName));
return false;
}
if (args.tblName != null) {
LOG.warn("Verifier - Table: " + String.valueOf(args.tblName));
return args.tblName.equals("t1");
}
return true;
}
};
InjectableBehaviourObjectStore.setCallerVerifier(callerVerifier);
// Trigger bootstrap dump which just creates table t1 and other tables (t2, t3) and constraints not loaded.
List<String> withConfigs = Arrays.asList("'hive.repl.approx.max.load.tasks'='1'");
try {
replica.loadFailure(replicatedDbName, primaryDbName, withConfigs);
callerVerifier.assertInjectionsPerformed(true, false);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetCallerVerifier();
}
replica.run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult("null");
assertEquals(0, replica.getPrimaryKeyList(replicatedDbName, "t1").size());
assertEquals(0, replica.getUniqueConstraintList(replicatedDbName, "t3").size());
assertEquals(0, replica.getNotNullConstraintList(replicatedDbName, "t3").size());
assertEquals(0, replica.getForeignKeyList(replicatedDbName, "t2").size());
// Verify if create table is not called on table t1 but called for t2 and t3.
// Also, allow constraint creation only on t1 and t3. Foreign key creation on t2 fails.
callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Override
public Boolean apply(CallerArguments args) {
injectionPathCalled = true;
if (!args.dbName.equalsIgnoreCase(replicatedDbName) || (args.funcName != null)) {
LOG.warn("Verifier - DB: " + String.valueOf(args.dbName) + " Func: " + String.valueOf(args.funcName));
return false;
}
if (args.constraintTblName != null) {
LOG.warn("Verifier - Constraint Table: " + String.valueOf(args.constraintTblName));
return (args.constraintTblName.equals("t1") || args.constraintTblName.equals("t3"));
}
return true;
}
};
InjectableBehaviourObjectStore.setCallerVerifier(callerVerifier);
try {
// Retry with same dump with which it was already loaded should resume the bootstrap load.
// This time, it fails when try to load the foreign key constraints. All other constraints are loaded.
replica.loadFailure(replicatedDbName, primaryDbName, withConfigs);
callerVerifier.assertInjectionsPerformed(true, false);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetCallerVerifier();
}
replica.run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult("null").run("show tables").verifyResults(new String[] { "t1", "t2", "t3" });
assertEquals(2, replica.getPrimaryKeyList(replicatedDbName, "t1").size());
assertEquals(1, replica.getUniqueConstraintList(replicatedDbName, "t3").size());
assertEquals(1, replica.getNotNullConstraintList(replicatedDbName, "t3").size());
assertEquals(0, replica.getForeignKeyList(replicatedDbName, "t2").size());
// Verify if no create table/function calls. Only add foreign key constraints on table t2.
callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Override
public Boolean apply(CallerArguments args) {
injectionPathCalled = true;
if (!args.dbName.equalsIgnoreCase(replicatedDbName) || (args.tblName != null)) {
LOG.warn("Verifier - DB: " + String.valueOf(args.dbName) + " Table: " + String.valueOf(args.tblName));
return false;
}
if (args.constraintTblName != null) {
LOG.warn("Verifier - Constraint Table: " + String.valueOf(args.constraintTblName));
return args.constraintTblName.equals("t2");
}
return true;
}
};
InjectableBehaviourObjectStore.setCallerVerifier(callerVerifier);
try {
// Retry with same dump with which it was already loaded should resume the bootstrap load.
// This time, it completes by adding just foreign key constraints for table t2.
replica.load(replicatedDbName, primaryDbName);
callerVerifier.assertInjectionsPerformed(true, false);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetCallerVerifier();
}
replica.run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(tuple.lastReplicationId).run("show tables").verifyResults(new String[] { "t1", "t2", "t3" });
assertEquals(2, replica.getPrimaryKeyList(replicatedDbName, "t1").size());
assertEquals(1, replica.getUniqueConstraintList(replicatedDbName, "t3").size());
assertEquals(1, replica.getNotNullConstraintList(replicatedDbName, "t3").size());
assertEquals(2, replica.getForeignKeyList(replicatedDbName, "t2").size());
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.CallerArguments in project hive by apache.
the class TestReplicationScenariosAcidTables method testAcidTablesBootstrapWithConcurrentDropTable.
@Test
public void testAcidTablesBootstrapWithConcurrentDropTable() throws Throwable {
HiveConf primaryConf = primary.getConf();
primary.run("use " + primaryDbName).run("create table t1 (id int) clustered by(id) into 3 buckets stored as orc " + "tblproperties (\"transactional\"=\"true\")").run("insert into t1 values(1)");
// Perform concurrent write + drop on the acid table t1 when bootstrap dump in progress. Bootstrap
// won't dump the table but the subsequent incremental repl with new table with same name should be seen.
BehaviourInjection<CallerArguments, Boolean> callerInjectedBehavior = new BehaviourInjection<CallerArguments, Boolean>() {
@Nullable
@Override
public Boolean apply(@Nullable CallerArguments args) {
if (injectionPathCalled) {
nonInjectedPathCalled = true;
} else {
// Insert another row to t1 and drop the table from another txn when bootstrap dump in progress.
injectionPathCalled = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
LOG.info("Entered new thread");
IDriver driver = DriverFactory.newDriver(primaryConf);
SessionState.start(new CliSessionState(primaryConf));
try {
driver.run("insert into " + primaryDbName + ".t1 values(2)");
driver.run("drop table " + primaryDbName + ".t1");
} catch (CommandProcessorException e) {
throw new RuntimeException(e);
}
LOG.info("Exit new thread success");
}
});
t.start();
LOG.info("Created new thread {}", t.getName());
try {
t.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return true;
}
};
InjectableBehaviourObjectStore.setCallerVerifier(callerInjectedBehavior);
WarehouseInstance.Tuple bootstrapDump = null;
try {
bootstrapDump = primary.dump(primaryDbName);
callerInjectedBehavior.assertInjectionsPerformed(true, true);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetCallerVerifier();
}
// Bootstrap dump has taken latest list of tables and hence won't see table t1 as it is dropped.
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(bootstrapDump.lastReplicationId).run("show tables").verifyResult(null);
// Create another ACID table with same name and insert a row. It should be properly replicated.
WarehouseInstance.Tuple incrementalDump = primary.run("use " + primaryDbName).run("create table t1 (id int) clustered by(id) into 3 buckets stored as orc " + "tblproperties (\"transactional\"=\"true\")").run("insert into t1 values(100)").dump(primaryDbName);
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(incrementalDump.lastReplicationId).run("select id from t1 order by id").verifyResult("100");
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.CallerArguments in project hive by apache.
the class TestReplicationScenariosAcidTablesBootstrap method testRetryAcidTablesBootstrapFromDifferentDump.
@Test
public void testRetryAcidTablesBootstrapFromDifferentDump() throws Throwable {
WarehouseInstance.Tuple bootstrapDump = prepareDataAndDump(primaryDbName, dumpWithoutAcidClause);
LOG.info(testName.getMethodName() + ": loading dump without acid tables.");
replica.load(replicatedDbName, primaryDbName);
verifyLoadExecution(replicatedDbName, bootstrapDump.lastReplicationId, false);
prepareIncAcidData(primaryDbName);
prepareIncNonAcidData(primaryDbName);
LOG.info(testName.getMethodName() + ": first incremental dump with acid table bootstrap.");
WarehouseInstance.Tuple incDump = primary.run("use " + primaryDbName).dump(primaryDbName, dumpWithAcidBootstrapClause);
// Fail setting ckpt property for table t5 but success for earlier tables
BehaviourInjection<CallerArguments, Boolean> callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Nullable
@Override
public Boolean apply(@Nullable CallerArguments args) {
if (args.tblName.equalsIgnoreCase("t5") && args.dbName.equalsIgnoreCase(replicatedDbName)) {
injectionPathCalled = true;
LOG.warn("Verifier - DB : " + args.dbName + " TABLE : " + args.tblName);
return false;
}
return true;
}
};
// Fail repl load before the ckpt property is set for t4 and after it is set for t2.
// In the retry, these half baked tables should be dropped and bootstrap should be successful.
InjectableBehaviourObjectStore.setAlterTableModifier(callerVerifier);
try {
LOG.info(testName.getMethodName() + ": loading first incremental dump with acid table bootstrap (will fail)");
replica.loadFailure(replicatedDbName, primaryDbName);
callerVerifier.assertInjectionsPerformed(true, false);
} finally {
InjectableBehaviourObjectStore.resetAlterTableModifier();
}
Path baseDumpDir = new Path(primary.hiveConf.getVar(HiveConf.ConfVars.REPLDIR));
Path nonRecoverablePath = TestReplicationScenarios.getNonRecoverablePath(baseDumpDir, primaryDbName, primary.hiveConf);
if (nonRecoverablePath != null) {
baseDumpDir.getFileSystem(primary.hiveConf).delete(nonRecoverablePath, true);
}
// Load again should succeed as checkpointing is in place
replica.load(replicatedDbName, primaryDbName);
verifyIncLoad(replicatedDbName, incDump.lastReplicationId);
prepareInc2AcidData(primaryDbName, primary.hiveConf);
prepareInc2NonAcidData(primaryDbName, primary.hiveConf);
LOG.info(testName.getMethodName() + ": second incremental dump with acid table bootstrap");
WarehouseInstance.Tuple inc2Dump = primary.run("use " + primaryDbName).dump(primaryDbName, dumpWithAcidClause);
LOG.info(testName.getMethodName() + ": trying to load second incremental dump (with acid bootstrap) again." + " Should succeed.");
replica.load(replicatedDbName, primaryDbName);
verifyInc2Load(replicatedDbName, inc2Dump.lastReplicationId);
}
Aggregations