Github user ChinmaySKulkarni commented on a diff in the pull request:
https://github.com/apache/phoenix/pull/313#discussion_r204968699
--- Diff: phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
---
@@ -1274,28 +1341,145 @@ public void testChildViewCreationFails() throws
Exception {
PhoenixRuntime.getTableNoCache(conn, fullViewName2);
}
- private static final String FAILED_VIEWNAME = "FAILED_VIEW";
- private static final byte[] ROWKEY_TO_FAIL_BYTES =
SchemaUtil.getTableKey(null, Bytes.toBytes(SCHEMA2),
- Bytes.toBytes(FAILED_VIEWNAME));
-
- public static class FailingRegionObserver extends SimpleRegionObserver
{
- @Override
- public void
preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
- MiniBatchOperationInProgress<Mutation> miniBatchOp) throws
IOException {
- if (shouldFail(c, miniBatchOp.getOperation(0))) {
- // throwing anything other than instances of IOException
result
- // in this coprocessor being unloaded
- // DoNotRetryIOException tells HBase not to retry this
mutation
- // multiple times
- throw new DoNotRetryIOException();
- }
- }
-
- private boolean
shouldFail(ObserverContext<RegionCoprocessorEnvironment> c, Mutation m) {
- TableName tableName =
c.getEnvironment().getRegion().getRegionInfo().getTable();
- return
tableName.equals(PhoenixDatabaseMetaData.SYSTEM_CATALOG_HBASE_TABLE_NAME)
- && (Bytes.equals(ROWKEY_TO_FAIL_BYTES, m.getRow()));
- }
-
- }
+ @Test
+ public void testConcurrentViewCreationAndTableDrop() throws Exception {
+ try (Connection conn = DriverManager.getConnection(getUrl())) {
+ String fullTableName = SchemaUtil.getTableName(SCHEMA1,
generateUniqueName());
+ String fullViewName1 = SchemaUtil.getTableName(SCHEMA2,
SLOW_VIEWNAME_PREFIX + "_" + generateUniqueName());
+ String fullViewName2 = SchemaUtil.getTableName(SCHEMA3,
generateUniqueName());
+ latch1 = new CountDownLatch(1);
+ latch2 = new CountDownLatch(1);
+ String tableDdl = "CREATE TABLE " + fullTableName + "
(k INTEGER NOT NULL PRIMARY KEY, v1 DATE)"
+ + tableDDLOptions;
+ conn.createStatement().execute(tableDdl);
+
+ ExecutorService executorService =
Executors.newFixedThreadPool(1, new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t =
Executors.defaultThreadFactory().newThread(r);
+ t.setDaemon(true);
+ t.setPriority(Thread.MIN_PRIORITY);
+ return t;
+ }
+ });
+
+ // create the view in a separate thread (which will
take some time
+ // to complete)
+ Future<Exception> future = executorService.submit(new
CreateViewRunnable(fullTableName, fullViewName1));
+ // wait till the thread makes the rpc to create the view
+ latch1.await();
+ tableDdl = "DROP TABLE " + fullTableName;
+ try {
+ // drop table should fail as we are
concurrently adding a view
+ conn.createStatement().execute(tableDdl);
+ fail("Creating a view while concurrently
dropping the base table should fail");
+ } catch (ConcurrentTableMutationException e) {
+ }
+ latch2.countDown();
+
+ Exception e = future.get();
+ assertTrue(e == null);
+
+ // create another view to ensure that the cell used to
prevent
+ // concurrent modifications was removed
+ String ddl = "CREATE VIEW " + fullViewName2 + " (v2
VARCHAR) AS SELECT * FROM " + fullTableName
+ + " WHERE k = 6";
+ conn.createStatement().execute(ddl);
+ }
+ }
+
+ @Test
+ public void testConcurrentAddColumn() throws Exception {
+ try (Connection conn = DriverManager.getConnection(getUrl())) {
+ String fullTableName = SchemaUtil.getTableName(SCHEMA1,
generateUniqueName());
+ String fullViewName = SchemaUtil.getTableName(SCHEMA2,
SLOW_VIEWNAME_PREFIX + "_" + generateUniqueName());
+ // create base table
+ String tableDdl = "CREATE TABLE " + fullTableName + "
(k INTEGER NOT NULL PRIMARY KEY, v1 DATE)"
+ + tableDDLOptions;
+ conn.createStatement().execute(tableDdl);
+ // create a view
+ String ddl = "CREATE VIEW " + fullViewName + " (v2
VARCHAR) AS SELECT * FROM " + fullTableName
+ + " WHERE k = 6";
+ conn.createStatement().execute(ddl);
+
+ latch1 = new CountDownLatch(1);
+ latch2 = new CountDownLatch(1);
+ ExecutorService executorService =
Executors.newFixedThreadPool(1, new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t =
Executors.defaultThreadFactory().newThread(r);
+ t.setDaemon(true);
+ t.setPriority(Thread.MIN_PRIORITY);
+ return t;
+ }
+ });
+
+ // add a column to the view in a separate thread (which
will take
+ // some time to complete)
+ Future<Exception> future = executorService.submit(new
AddColumnRunnable(fullViewName));
+ // wait till the thread makes the rpc to create the view
+ boolean result = latch1.await(2, TimeUnit.MINUTES);
+ if (!result) {
+ fail("The create view rpc look too long");
+ }
+ tableDdl = "ALTER TABLE " + fullTableName + " ADD v3
INTEGER";
+ try {
+ // add the same column to the base table with a
different type
+ conn.createStatement().execute(tableDdl);
+ fail("Creating a view while concurrently
dropping the base table should fail");
+ } catch (ConcurrentTableMutationException e) {
+ }
+ latch2.countDown();
+
+ Exception e = future.get();
+ assertTrue(e == null);
--- End diff --
nit: `assertNull`
---