Author: ekoifman
Date: Thu Apr 16 17:59:33 2015
New Revision: 1674120

URL: http://svn.apache.org/r1674120
Log:
HIVE-10242 ACID: insert overwrite prevents create table command (Eugene 
Koifman, reviewed by Alan Gates)

Added:
    
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-log4j.properties
    
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-site.mysql.xml
    
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java

Added: 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-log4j.properties
URL: 
http://svn.apache.org/viewvc/hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-log4j.properties?rev=1674120&view=auto
==============================================================================
--- 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-log4j.properties
 (added)
+++ 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-log4j.properties
 Thu Apr 16 17:59:33 2015
@@ -0,0 +1,88 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Define some default values that can be overridden by system properties
+hive.log.threshold=ALL
+hive.root.logger=DEBUG,DRFA
+hive.log.dir=/tmp/ekoifman
+hive.log.file=hive.log
+
+# Define the root logger to the system property "hadoop.root.logger".
+log4j.rootLogger=${hive.root.logger}, EventCounter
+
+# Logging Threshold
+log4j.threshold=${hive.log.threshold}
+
+#
+# Daily Rolling File Appender
+#
+# Use the PidDailyerRollingFileAppend class instead if you want to use 
separate log files
+# for different CLI session.
+#
+# log4j.appender.DRFA=org.apache.hadoop.hive.ql.log.PidDailyRollingFileAppender
+
+log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
+
+log4j.appender.DRFA.File=${hive.log.dir}/${hive.log.file}
+
+# Rollver at midnight
+log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
+
+# 30-day backup
+#log4j.appender.DRFA.MaxBackupIndex=30
+log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
+
+# Pattern format: Date LogLevel LoggerName LogMessage
+#log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+# Debugging Pattern format
+log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p [%t]: %c{2} 
(%F:%M(%L)) - %m%n
+
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} [%t]: %p 
%c{2}: %m%n
+log4j.appender.console.encoding=UTF-8
+
+#custom logging levels
+#log4j.logger.xxx=DEBUG
+
+#
+# Event Counter Appender
+# Sends counts of logging messages at different severity levels to Hadoop 
Metrics.
+#
+log4j.appender.EventCounter=org.apache.hadoop.hive.shims.HiveEventCounter
+
+
+log4j.category.DataNucleus=ERROR,DRFA
+log4j.category.Datastore=ERROR,DRFA
+log4j.category.Datastore.Schema=ERROR,DRFA
+log4j.category.JPOX.Datastore=ERROR,DRFA
+log4j.category.JPOX.Plugin=ERROR,DRFA
+log4j.category.JPOX.MetaData=ERROR,DRFA
+log4j.category.JPOX.Query=ERROR,DRFA
+log4j.category.JPOX.General=ERROR,DRFA
+log4j.category.JPOX.Enhancer=ERROR,DRFA
+
+
+# Silence useless ZK logs
+log4j.logger.org.apache.zookeeper.server.NIOServerCnxn=WARN,DRFA
+log4j.logger.org.apache.zookeeper.ClientCnxnSocketNIO=WARN,DRFA

Added: 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-site.mysql.xml
URL: 
http://svn.apache.org/viewvc/hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-site.mysql.xml?rev=1674120&view=auto
==============================================================================
--- 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-site.mysql.xml
 (added)
+++ 
hive/trunk/hcatalog/src/test/e2e/templeton/deployers/config/hive/hive-site.mysql.xml
 Thu Apr 16 17:59:33 2015
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+<configuration>
+<!--hive-site.xml template for MySQL backed metastore-->
+    <property>
+        <name>javax.jdo.option.ConnectionURL</name>
+        <value>jdbc:mysql://localhost/metastore</value>
+    </property>
+    <property>
+        <name>javax.jdo.option.ConnectionUserName</name>
+        <value>hive</value>
+    </property>
+    <property>
+        <name>javax.jdo.option.ConnectionPassword</name>
+        <value>hive</value>
+    </property>
+    <property>
+        <name>javax.jdo.option.ConnectionDriverName</name>
+        <value>com.mysql.jdbc.Driver</value>
+    </property>
+    <property>
+        <name>datanucleus.autoCreateSchema</name>
+        <value>false</value>
+    </property>
+    <property>
+      <name>datanucleus.fixedDatastore</name>
+        <value>true</value>
+    </property>
+    <!--start ACID related properties-->
+    <property>
+        <name>hive.support.concurrency</name>
+        <value>true</value>
+    </property>
+    <property>
+        <name>hive.txn.manager</name>
+        <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
+    </property>
+    <property>
+        <name>hive.enforce.bucketing</name>
+        <value>true</value>
+    </property>
+    <property>
+        <name>hive.exec.dynamic.partition.mode</name>
+        <value>nonstrict</value>
+    </property>
+    <!--end ACID related properties-->
+<!--
+    <property>
+        <name>hive.exec.rowoffset</name>
+        <value>true</value>
+    </property>
+    -->
+    <!--
+    can be used by DataNucleus (have not tried)
+    javax.jdo.mapping.Catalog={the_catalog_name}
+    javax.jdo.mapping.Schema={the_schema_name}
+    -->
+</configuration>

Added: 
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java
URL: 
http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java?rev=1674120&view=auto
==============================================================================
--- 
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java 
(added)
+++ 
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java 
Thu Apr 16 17:59:33 2015
@@ -0,0 +1,233 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hive.ql.lockmgr;
+
+import junit.framework.Assert;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.metastore.api.LockState;
+import org.apache.hadoop.hive.metastore.api.LockType;
+import org.apache.hadoop.hive.metastore.api.ShowLocksResponse;
+import org.apache.hadoop.hive.metastore.api.ShowLocksResponseElement;
+import org.apache.hadoop.hive.metastore.txn.TxnDbUtil;
+import org.apache.hadoop.hive.ql.Context;
+import org.apache.hadoop.hive.ql.Driver;
+import org.apache.hadoop.hive.ql.metadata.Hive;
+import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse;
+import org.apache.hadoop.hive.ql.session.SessionState;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * See additional tests in {@link 
org.apache.hadoop.hive.ql.lockmgr.TestDbTxnManager}
+ * Tests here 
+ */
+public class TestDbTxnManager2 {
+  private static HiveConf conf = new HiveConf(Driver.class);
+  private HiveTxnManager txnMgr;
+  private Context ctx;
+  private Driver driver;
+
+  @BeforeClass
+  public static void setUpClass() throws Exception {
+    TxnDbUtil.setConfValues(conf);
+    conf.setVar(HiveConf.ConfVars.DYNAMICPARTITIONINGMODE, "nonstrict");
+    conf.setBoolVar(HiveConf.ConfVars.HIVEENFORCEBUCKETING, true);
+  }
+  @Before
+  public void setUp() throws Exception {
+    SessionState.start(conf);
+    ctx = new Context(conf);
+    driver = new Driver(conf);
+    driver.init();
+    TxnDbUtil.cleanDb();
+    TxnDbUtil.prepDb();
+    txnMgr = TxnManagerFactory.getTxnManagerFactory().getTxnManager(conf);
+    Assert.assertTrue(txnMgr instanceof DbTxnManager);
+  }
+  @After
+  public void tearDown() throws Exception {
+    driver.close();
+    if (txnMgr != null) txnMgr.closeTxnManager();
+    TxnDbUtil.cleanDb();
+    TxnDbUtil.prepDb();
+  }
+  @Test
+  public void createTable() throws Exception {
+    CommandProcessorResponse cpr = driver.compileAndRespond("create table if 
not exists T (a int, b int)");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 1, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", null, null, 
locks.get(0));
+    txnMgr.getLockManager().releaseLocks(ctx.getHiveLocks());
+    Assert.assertEquals("Lock remained", 0, getLocks().size());
+  }
+  @Test
+  public void insertOverwriteCreate() throws Exception {
+    CommandProcessorResponse cpr = driver.run("create table if not exists T2(a 
int)");
+    checkCmdOnDriver(cpr);
+    cpr = driver.run("create table if not exists T3(a int)");
+    checkCmdOnDriver(cpr);
+    cpr = driver.compileAndRespond("insert overwrite table T3 select a from 
T2");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "T2", null, 
locks.get(0));
+    checkLock(LockType.EXCLUSIVE, LockState.ACQUIRED, "default", "T3", null, 
locks.get(1));
+    txnMgr.getLockManager().releaseLocks(ctx.getHiveLocks());
+    Assert.assertEquals("Lock remained", 0, getLocks().size());
+    cpr = driver.run("drop table if exists T1");
+    checkCmdOnDriver(cpr);
+    cpr = driver.run("drop table if exists T2");
+    checkCmdOnDriver(cpr);
+  }
+  @Test
+  public void insertOverwritePartitionedCreate() throws Exception {
+    CommandProcessorResponse cpr = driver.run("create table if not exists T4 
(name string, gpa double) partitioned by (age int)");
+    checkCmdOnDriver(cpr);
+    cpr = driver.run("create table if not exists T5(name string, age int, gpa 
double)");
+    checkCmdOnDriver(cpr);
+    cpr = driver.compileAndRespond("INSERT OVERWRITE TABLE T4 PARTITION (age) 
SELECT name, age, gpa FROM T5");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "T5", null, 
locks.get(0));
+    checkLock(LockType.EXCLUSIVE, LockState.ACQUIRED, "default", "T4", null, 
locks.get(1));
+    txnMgr.getLockManager().releaseLocks(ctx.getHiveLocks());
+    Assert.assertEquals("Lock remained", 0, getLocks().size());
+    cpr = driver.run("drop table if exists T5");
+    checkCmdOnDriver(cpr);
+    cpr = driver.run("drop table if exists T4");
+    checkCmdOnDriver(cpr);
+  }
+  @Test
+  public void basicBlocking() throws Exception {
+    CommandProcessorResponse cpr = driver.run("create table if not exists T6(a 
int)");
+    checkCmdOnDriver(cpr);
+    cpr = driver.compileAndRespond("select a from T6");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");//gets S lock on T6
+    List<HiveLock> selectLocks = ctx.getHiveLocks();
+    cpr = driver.compileAndRespond("drop table if exists T6");
+    checkCmdOnDriver(cpr);
+    //tries to get X lock on T1 and gets Waiting state
+    LockState lockState = ((DbTxnManager) 
txnMgr).acquireLocks(driver.getPlan(), ctx, "Fiddler", false);
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "T6", null, 
locks.get(0));
+    checkLock(LockType.EXCLUSIVE, LockState.WAITING, "default", "T6", null, 
locks.get(1));
+    txnMgr.getLockManager().releaseLocks(selectLocks);//release S on T6
+    //attempt to X on T6 again - succeed
+    lockState = 
((DbLockManager)txnMgr.getLockManager()).checkLock(locks.get(1).getLockid());
+    locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 1, locks.size());
+    checkLock(LockType.EXCLUSIVE, LockState.ACQUIRED, "default", "T6", null, 
locks.get(0));
+    List<HiveLock> xLock = new ArrayList<HiveLock>(0);
+    xLock.add(new DbLockManager.DbHiveLock(locks.get(0).getLockid()));
+    txnMgr.getLockManager().releaseLocks(xLock);
+    cpr = driver.run("drop table if exists T6");
+    locks = getLocks();
+    Assert.assertEquals("Unexpected number of locks found", 0, locks.size());
+    checkCmdOnDriver(cpr);
+  }
+  @Test
+  public void lockConflictDbTable() throws Exception {
+    CommandProcessorResponse cpr = driver.run("create database if not exists 
temp");
+    checkCmdOnDriver(cpr);
+    cpr = driver.run("create table if not exists temp.T7(a int, b int) 
clustered by(b) into 2 buckets stored as orc TBLPROPERTIES 
('transactional'='true')");
+    checkCmdOnDriver(cpr);
+    cpr = driver.compileAndRespond("update temp.T7 set a = 5 where b = 6");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");
+    List<HiveLock> updateLocks = ctx.getHiveLocks();
+    cpr = driver.compileAndRespond("drop database if exists temp");
+    LockState lockState = ((DbTxnManager) 
txnMgr).acquireLocks(driver.getPlan(), ctx, "Fiddler", false);//gets SS lock on 
T7
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+    checkLock(LockType.SHARED_WRITE, LockState.ACQUIRED, "temp", "T7", null, 
locks.get(0));
+    checkLock(LockType.EXCLUSIVE, LockState.WAITING, "temp", null, null, 
locks.get(1));
+    txnMgr.getLockManager().releaseLocks(updateLocks);
+    lockState = 
((DbLockManager)txnMgr.getLockManager()).checkLock(locks.get(1).getLockid());
+    locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 1, locks.size());
+    checkLock(LockType.EXCLUSIVE, LockState.ACQUIRED, "temp", null, null, 
locks.get(0));
+    List<HiveLock> xLock = new ArrayList<HiveLock>(0);
+    xLock.add(new DbLockManager.DbHiveLock(locks.get(0).getLockid()));
+    txnMgr.getLockManager().releaseLocks(xLock);
+  }
+  @Test
+  public void updateSelectUpdate() throws Exception {
+    CommandProcessorResponse cpr = driver.run("create table T8(a int, b int) 
clustered by(b) into 2 buckets stored as orc TBLPROPERTIES 
('transactional'='true')");
+    checkCmdOnDriver(cpr);
+    cpr = driver.compileAndRespond("delete from T8 where b = 89");
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fifer");//gets SS lock on T8
+    List<HiveLock> deleteLocks = ctx.getHiveLocks();
+    cpr = driver.compileAndRespond("select a from T8");//gets S lock on T8
+    checkCmdOnDriver(cpr);
+    txnMgr.acquireLocks(driver.getPlan(), ctx, "Fiddler");
+    cpr = driver.compileAndRespond("update T8 set a = 1 where b = 1");
+    checkCmdOnDriver(cpr);
+    LockState lockState = ((DbTxnManager) 
txnMgr).acquireLocks(driver.getPlan(), ctx, "Practical", false);//waits for SS 
lock on T8 from fifer
+    List<ShowLocksResponseElement> locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 3, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "T8", null, 
locks.get(0));
+    checkLock(LockType.SHARED_WRITE, LockState.ACQUIRED, "default", "T8", 
null, locks.get(1));
+    checkLock(LockType.SHARED_WRITE, LockState.WAITING, "default", "T8", null, 
locks.get(2));
+    txnMgr.getLockManager().releaseLocks(deleteLocks);
+    lockState = 
((DbLockManager)txnMgr.getLockManager()).checkLock(locks.get(2).getLockid());
+    locks = getLocks();
+    Assert.assertEquals("Unexpected lock count", 2, locks.size());
+    checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "T8", null, 
locks.get(0));
+    checkLock(LockType.SHARED_WRITE, LockState.ACQUIRED, "default", "T8", 
null, locks.get(1));
+    List<HiveLock> relLocks = new ArrayList<HiveLock>(2);
+    relLocks.add(new DbLockManager.DbHiveLock(locks.get(0).getLockid()));
+    relLocks.add(new DbLockManager.DbHiveLock(locks.get(1).getLockid()));
+    txnMgr.getLockManager().releaseLocks(relLocks);
+    cpr = driver.run("drop table if exists T6");
+    locks = getLocks();
+    Assert.assertEquals("Unexpected number of locks found", 0, locks.size());
+    checkCmdOnDriver(cpr);
+  }
+  
+  
+  private void checkLock(LockType type, LockState state, String db, String 
table, String partition, ShowLocksResponseElement l) {
+    Assert.assertEquals(l.toString(),l.getType(), type);
+    Assert.assertEquals(l.toString(),l.getState(), state);
+    Assert.assertEquals(l.toString(), normalizeCase(l.getDbname()), 
normalizeCase(db));
+    Assert.assertEquals(l.toString(), normalizeCase(l.getTablename()), 
normalizeCase(table));
+    Assert.assertEquals(l.toString(), normalizeCase(l.getPartname()), 
normalizeCase(partition));
+  }
+  private void checkCmdOnDriver(CommandProcessorResponse cpr) {
+    Assert.assertTrue(cpr.toString(), cpr.getResponseCode() == 0);
+  }
+  private String normalizeCase(String s) {
+    return s == null ? null : s.toLowerCase();
+  }
+  private List<ShowLocksResponseElement> getLocks() throws Exception {
+    ShowLocksResponse rsp = 
((DbLockManager)txnMgr.getLockManager()).getLocks();
+    return rsp.getLocks();
+  }
+}


Reply via email to