use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.BehaviourInjection in project hive by apache.
the class TestReplicationScenariosExternalTables method retryBootstrapExternalTablesFromDifferentDump.
@Test
public void retryBootstrapExternalTablesFromDifferentDump() throws Throwable {
List<String> loadWithClause = ReplicationTestUtils.includeExternalTableClause(true);
List<String> dumpWithClause = ReplicationTestUtils.includeExternalTableClause(false);
WarehouseInstance.Tuple tupleBootstrapWithoutExternal = primary.run("use " + primaryDbName).run("create external table t1 (id int)").run("insert into table t1 values (1)").run("create external table t2 (place string) partitioned by (country string)").run("insert into table t2 partition(country='india') values ('bangalore')").run("insert into table t2 partition(country='us') values ('austin')").run("create table t3 as select * from t1").dump(primaryDbName, dumpWithClause);
replica.load(replicatedDbName, primaryDbName, loadWithClause).status(replicatedDbName).verifyResult(tupleBootstrapWithoutExternal.lastReplicationId).run("use " + replicatedDbName).run("show tables").verifyResult("t3").run("select id from t3").verifyResult("1").verifyReplTargetProperty(replicatedDbName);
dumpWithClause = ReplicationTestUtils.externalTableWithClause(new ArrayList<>(), true, true);
primary.run("use " + primaryDbName).run("drop table t1").run("create external table t4 (id int)").run("insert into table t4 values (10)").run("create table t5 as select * from t4").dump(primaryDbName, dumpWithClause);
// Fail setting ckpt property for table t4 but success for t2.
BehaviourInjection<CallerArguments, Boolean> callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Nullable
@Override
public Boolean apply(@Nullable CallerArguments args) {
if (args.tblName.equalsIgnoreCase("t4") && 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 {
replica.loadFailure(replicatedDbName, primaryDbName, loadWithClause);
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);
}
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("show tables like 't1'").verifyFailure(new String[] { "t1" }).run("show tables like 't2'").verifyResult("t2").run("select country from t2 order by country").verifyResults(new String[] { "india", "us" }).run("select id from t4").verifyResults(Arrays.asList("10")).run("select id from t5").verifyResult("10").verifyReplTargetProperty(replicatedDbName);
// Insert into existing external table and then Drop it, add another managed table with same name
// and dump another bootstrap dump for external tables.
dumpWithClause = ReplicationTestUtils.includeExternalTableClause(true);
primary.run("use " + primaryDbName).run("insert into table t2 partition(country='india') values ('chennai')").run("drop table t2").run("create table t2 as select * from t4").run("insert into table t4 values (20)").dump(primaryDbName, dumpWithClause);
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("show tables like 't1'").verifyFailure(new String[] { "t1" }).run("select id from t2").verifyResult("10").run("select id from t4").verifyResults(Arrays.asList("10", "20")).run("select id from t5").verifyResult("10").verifyReplTargetProperty(replicatedDbName);
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.BehaviourInjection in project hive by apache.
the class TestReplicationScenariosAcrossInstances method testMoveOptimization.
private void testMoveOptimization(String primaryDb, String replicaDb, String replicatedDbName_CM, String tbl, String eventType, WarehouseInstance.Tuple tuple) throws Throwable {
// fail add notification for given event type.
BehaviourInjection<NotificationEvent, Boolean> callerVerifier = new BehaviourInjection<NotificationEvent, Boolean>() {
@Override
public Boolean apply(NotificationEvent entry) {
if (entry.getEventType().equalsIgnoreCase(eventType) && entry.getTableName().equalsIgnoreCase(tbl)) {
injectionPathCalled = true;
LOG.warn("Verifier - DB: " + String.valueOf(entry.getDbName()) + " Table: " + String.valueOf(entry.getTableName()) + " Event: " + String.valueOf(entry.getEventType()));
return false;
}
return true;
}
};
InjectableBehaviourObjectStore.setAddNotificationModifier(callerVerifier);
try {
replica.loadFailure(replicaDb, primaryDbName);
} finally {
InjectableBehaviourObjectStore.resetAddNotificationModifier();
}
callerVerifier.assertInjectionsPerformed(true, false);
replica.load(replicaDb, primaryDbName);
replica.run("use " + replicaDb).run("select country from " + tbl + " where country == 'india'").verifyResults(Arrays.asList("india"));
primary.run("use " + primaryDb).run("drop table " + tbl);
// delete load ack to reuse the dump
new Path(tuple.dumpLocation).getFileSystem(conf).delete(new Path(tuple.dumpLocation + Path.SEPARATOR + ReplUtils.REPL_HIVE_BASE_DIR + Path.SEPARATOR + LOAD_ACKNOWLEDGEMENT.toString()), true);
InjectableBehaviourObjectStore.setAddNotificationModifier(callerVerifier);
try {
replica.loadFailure(replicatedDbName_CM, primaryDbName);
} finally {
InjectableBehaviourObjectStore.resetAddNotificationModifier();
}
callerVerifier.assertInjectionsPerformed(true, false);
replica.load(replicatedDbName_CM, primaryDbName);
replica.run("use " + replicatedDbName_CM).run("select country from " + tbl + " where country == 'india'").verifyResults(Arrays.asList("india")).run(" drop database if exists " + replicatedDbName_CM + " cascade");
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.BehaviourInjection in project hive by apache.
the class TestReplicationScenariosAcrossInstances method testBootstrapReplLoadRetryAfterFailureForPartitions.
@Test
public void testBootstrapReplLoadRetryAfterFailureForPartitions() throws Throwable {
WarehouseInstance.Tuple tuple = primary.run("use " + primaryDbName).run("create table t2 (place string) partitioned by (country string)").run("insert into table t2 partition(country='india') values ('bangalore')").run("insert into table t2 partition(country='uk') values ('london')").run("insert into table t2 partition(country='us') values ('sfo')").run("CREATE FUNCTION " + primaryDbName + ".testFunctionOne as 'hivemall.tools.string.StopwordUDF' " + "using jar 'ivy://io.github.myui:hivemall:0.4.0-2'").dump(primaryDbName);
// Inject a behavior where REPL LOAD failed when try to load table "t2" and partition "uk".
// So, table "t2" will exist and partition "india" will exist, rest failed as operation failed.
BehaviourInjection<List<Partition>, Boolean> addPartitionStub = new BehaviourInjection<List<Partition>, Boolean>() {
@Override
public Boolean apply(List<Partition> ptns) {
for (Partition ptn : ptns) {
if (ptn.getValues().get(0).equals("uk")) {
injectionPathCalled = true;
LOG.warn("####getPartition Stub called");
return false;
}
}
return true;
}
};
InjectableBehaviourObjectStore.setAddPartitionsBehaviour(addPartitionStub);
// Make sure that there's some order in which the objects are loaded.
List<String> withConfigs = Arrays.asList("'hive.repl.approx.max.load.tasks'='1'", "'hive.in.repl.test.files.sorted'='true'", "'" + HiveConf.ConfVars.REPL_LOAD_PARTITIONS_WITH_DATA_COPY_BATCH_SIZE + "' = '1'");
replica.loadFailure(replicatedDbName, primaryDbName, withConfigs);
// reset the behaviour
InjectableBehaviourObjectStore.resetAddPartitionModifier();
addPartitionStub.assertInjectionsPerformed(true, false);
replica.run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult("null").run("show tables").verifyResults(new String[] { "t2" }).run("select country from t2 order by country").verifyResults(Collections.singletonList("india"));
// Verify if no create table calls. Add partitions and create function calls expected.
BehaviourInjection<CallerArguments, Boolean> callerVerifier = new BehaviourInjection<CallerArguments, Boolean>() {
@Nullable
@Override
public Boolean apply(@Nullable CallerArguments args) {
if (!args.dbName.equalsIgnoreCase(replicatedDbName) || (args.tblName != null)) {
injectionPathCalled = true;
LOG.warn("Verifier - DB: " + String.valueOf(args.dbName) + " Table: " + String.valueOf(args.tblName));
return false;
}
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 remaining partitions and function.
replica.load(replicatedDbName, primaryDbName);
callerVerifier.assertInjectionsPerformed(false, false);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetCallerVerifier();
}
replica.run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(tuple.lastReplicationId).run("show tables").verifyResults(new String[] { "t2" }).run("select country from t2 order by country").verifyResults(Arrays.asList("india", "uk", "us")).run("show functions like '" + replicatedDbName + "%'").verifyResult(replicatedDbName + ".testFunctionOne");
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.BehaviourInjection in project hive by apache.
the class TestReplicationScenarios method testEventTypesForDynamicAddPartitionByInsert.
@Test
public void testEventTypesForDynamicAddPartitionByInsert() throws IOException {
String name = testName.getMethodName();
final String dbName = createDB(name, driver);
String replDbName = dbName + "_dupe";
run("CREATE TABLE " + dbName + ".ptned(a string) partitioned by (b int) STORED AS TEXTFILE", driver);
Tuple bootstrap = bootstrapLoadAndVerify(dbName, replDbName);
String[] ptn_data = new String[] { "ten" };
run("INSERT INTO TABLE " + dbName + ".ptned partition(b=1) values('" + ptn_data[0] + "')", driver);
// Inject a behaviour where it throws exception if an INSERT event is found
// As we dynamically add a partition through INSERT INTO cmd, it should just add ADD_PARTITION
// event not an INSERT event
BehaviourInjection<NotificationEventResponse, NotificationEventResponse> eventTypeValidator = new BehaviourInjection<NotificationEventResponse, NotificationEventResponse>() {
@Nullable
@Override
public NotificationEventResponse apply(@Nullable NotificationEventResponse eventsList) {
if (null != eventsList) {
List<NotificationEvent> events = eventsList.getEvents();
for (int i = 0; i < events.size(); i++) {
NotificationEvent event = events.get(i);
// Skip all the events belong to other DBs/tables.
if (event.getDbName().equalsIgnoreCase(dbName)) {
if (event.getEventType().equalsIgnoreCase("INSERT")) {
// If an insert event is found, then return null hence no event is dumped.
LOG.error("Encountered INSERT event when it was not expected to");
return null;
}
}
}
injectionPathCalled = true;
}
return eventsList;
}
};
InjectableBehaviourObjectStore.setGetNextNotificationBehaviour(eventTypeValidator);
try {
incrementalLoadAndVerify(dbName, replDbName);
eventTypeValidator.assertInjectionsPerformed(true, false);
} finally {
// reset the behaviour
InjectableBehaviourObjectStore.resetGetNextNotificationBehaviour();
}
verifyRun("SELECT a from " + replDbName + ".ptned where (b=1)", ptn_data, driverMirror);
}
use of org.apache.hadoop.hive.metastore.InjectableBehaviourObjectStore.BehaviourInjection in project hive by apache.
the class TestReplicationScenariosAcidTables method testAcidTablesBootstrapWithConcurrentWrites.
@Test
public void testAcidTablesBootstrapWithConcurrentWrites() 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 on the acid table t1 when bootstrap dump in progress. Bootstrap
// won't see the written data but the subsequent incremental repl should see it.
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 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)");
} 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 snapshot before concurrent tread performed write. So, it won't see data "2".
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(bootstrapDump.lastReplicationId).run("select id from t1 order by id").verifyResults(new String[] { "1" });
// Incremental should include the concurrent write of data "2" from another txn.
WarehouseInstance.Tuple incrementalDump = primary.dump(primaryDbName);
replica.load(replicatedDbName, primaryDbName).run("use " + replicatedDbName).run("repl status " + replicatedDbName).verifyResult(incrementalDump.lastReplicationId).run("select id from t1 order by id").verifyResults(new String[] { "1", "2" });
}
Aggregations