diff --git llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java index 60d6edfdcb..6bb1fd8533 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java @@ -279,6 +279,48 @@ public void allocateMultiple(MemoryBuffer[] dest, int size, BufferObjectFactory freeListIx, allocationSize, (int)(threadId % arenaCount), arenaCount); if (destAllocIx == dest.length) return; + // Before getting into brute force discard (eg random evictions section) + // let's try eviction more using cache eviction policy up tp a max allocation size. + int fastAttempt = 0; + long totalFastEvictedBytes = 0; + int startArenaIx; + + while (totalFastEvictedBytes < maxAllocation && fastAttempt < MAX_DISCARD_ATTEMPTS) { + // Try to evict more starting from how much memory we are missing allocLog2 << dest.length - destAllocIx + // Exponentially increase the eviction request based on fastAttempt counter. + // Why Exponentially increase, usually query fragments triggers a burst of allocation at the same time + // Thus to avoid lock contentions it is worth it to over evict thus next allocation will get free lunch. + totalFastEvictedBytes += memoryManager.evictMemory(allocLog2 << dest.length - destAllocIx + fastAttempt); + startArenaIx = (int) ((threadId + fastAttempt) % arenaCount); + if (fastAttempt == 0) { + // Try to allocate memory if we haven't allocated all the way to maxSize yet; very rare. + destAllocIx = allocateWithExpand(dest, destAllocIx, freeListIx, allocationSize, arenaCount); + if (destAllocIx == dest.length) { + return; + } + } + destAllocIx = + allocateFast(dest, null, destAllocIx, dest.length, freeListIx, allocationSize, startArenaIx, arenaCount); + if (destAllocIx == dest.length) { + return; + } + + destAllocIx = + allocateWithSplit(dest, + null, + destAllocIx, + dest.length, + freeListIx, + allocationSize, + startArenaIx, + arenaCount, + -1); + if (destAllocIx == dest.length) { + return; + } + fastAttempt++; + } + // We called reserveMemory so we know that there's memory waiting for us somewhere. // However, we have a class of rare race conditions related to the order of locking/checking of // different allocation areas. Simple case - say we have 2 arenas, 256Kb available in arena 2. @@ -301,18 +343,11 @@ public void allocateMultiple(MemoryBuffer[] dest, int size, BufferObjectFactory int discardFailed = 0; while (true) { // Try to split bigger blocks. - int startArenaIx = (int)((threadId + attempt) % arenaCount); + startArenaIx = (int)((threadId + attempt) % arenaCount); destAllocIx = allocateWithSplit(dest, null, destAllocIx, dest.length, freeListIx, allocationSize, startArenaIx, arenaCount, -1); if (destAllocIx == dest.length) return; - if (attempt == 0) { - // Try to allocate memory if we haven't allocated all the way to maxSize yet; very rare. - destAllocIx = allocateWithExpand( - dest, destAllocIx, freeListIx, allocationSize, arenaCount); - if (destAllocIx == dest.length) return; - } - // Try to force-evict the fragments of the requisite size. boolean hasDiscardedAny = false; DiscardContext ctx = threadCtx.get(); @@ -360,7 +395,8 @@ public void allocateMultiple(MemoryBuffer[] dest, int size, BufferObjectFactory ++attempt; } } finally { - memoryManager.releaseMemory(memoryForceReleased); + // if we fail to allocate need to release the reserved amount plus the force evicted amount. + memoryManager.releaseMemory(memoryForceReleased + dest.length << allocLog2); if (!isFailed && attempt >= LOG_DISCARD_ATTEMPTS) { LlapIoImpl.LOG.info("Allocation of " + dest.length + " buffers of size " + size + " took " + attempt + " attempts to free enough memory; force-released " + memoryForceReleased); diff --git llap-server/src/java/org/apache/hadoop/hive/llap/cache/LowLevelCacheMemoryManager.java llap-server/src/java/org/apache/hadoop/hive/llap/cache/LowLevelCacheMemoryManager.java index c5b5bf2977..a7e277090a 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/cache/LowLevelCacheMemoryManager.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/cache/LowLevelCacheMemoryManager.java @@ -66,6 +66,21 @@ public void reserveMemory(final long memoryToReserve, AtomicBoolean isStopped) { throw new ReserveFailedException(isStopped); } + /** + * Ask the memory manager to evict more memory + * + * @param memoryToReserve amount of bytes to evict + * @return actual amount of evicted bytes. + */ + @Override public long evictMemory(long memoryToReserve) { + if (evictor == null) { + return 0; + } + long evicted = evictor.evictSomeBlocks(memoryToReserve); + releaseMemory(evicted); + return evicted; + } + @VisibleForTesting public boolean reserveMemory(final long memoryToReserve, boolean waitForEviction, AtomicBoolean isStopped) { @@ -154,4 +169,9 @@ public long purge() { metrics.incrCacheCapacityUsed(-evicted); return evicted; } + + @VisibleForTesting + public long getCurrentUsedSize() { + return usedMemory.get(); + } } diff --git llap-server/src/java/org/apache/hadoop/hive/llap/cache/MemoryManager.java llap-server/src/java/org/apache/hadoop/hive/llap/cache/MemoryManager.java index 0d16703011..b2a42ad6ae 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/cache/MemoryManager.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/cache/MemoryManager.java @@ -57,4 +57,13 @@ * allocate the space. */ void reserveMemory(long memoryToReserve, AtomicBoolean isStopped); + + /** + * Ask the memory manager to evict more memory + * + * @param memoryToReserve amount of bytes to evict + * @return actual amount of evicted bytes. + */ + long evictMemory(long memoryToReserve); + } diff --git llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestBuddyAllocator.java llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestBuddyAllocator.java index bdaa12a724..d72707d594 100644 --- llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestBuddyAllocator.java +++ llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestBuddyAllocator.java @@ -62,6 +62,10 @@ public TestBuddyAllocator(boolean direct, boolean mmap) { public void reserveMemory(long memoryToReserve, AtomicBoolean isStopped) { } + @Override public long evictMemory(long memoryToReserve) { + return 0; + } + @Override public void releaseMemory(long memUsage) { } diff --git llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestCacheAllocationsEvictionsCycles.java llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestCacheAllocationsEvictionsCycles.java new file mode 100644 index 0000000000..004585baf2 --- /dev/null +++ llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestCacheAllocationsEvictionsCycles.java @@ -0,0 +1,320 @@ +/* + * 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.llap.cache; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hive.common.io.Allocator; +import org.apache.hadoop.hive.common.io.encoded.MemoryBuffer; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.llap.io.metadata.MetadataCache; +import org.apache.hadoop.hive.llap.metrics.LlapDaemonCacheMetrics; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * The main goal of this class is to test the allocation/eviction interactions when the cache is full + */ +public class TestCacheAllocationsEvictionsCycles { + + private final long maxSize = 1024; + private BuddyAllocator allocator; + private MemoryManager memoryManager; + private LowLevelCachePolicy cachePolicy; + private LlapDaemonCacheMetrics cacheMetrics = LlapDaemonCacheMetrics.create("testCache", "testSession"); + private Logger LOG = LoggerFactory.getLogger(TestCacheAllocationsEvictionsCycles.class); + private EvictionTracker evictionTracker; + private LowLevelCache dataCache = Mockito.mock(LowLevelCache.class); + private SerDeLowLevelCacheImpl serdCache = Mockito.mock(SerDeLowLevelCacheImpl.class); + private MetadataCache metaDataCache = Mockito.mock(MetadataCache.class); + + @Before public void setUp() throws Exception { + Configuration conf = new Configuration(); + // Set lambda to 1 so the heap size becomes 1 (LRU). + conf.setDouble(HiveConf.ConfVars.LLAP_LRFU_LAMBDA.varname, 1.0f); + int minBufferSize = 1; + cachePolicy = new LowLevelLrfuCachePolicy(minBufferSize, maxSize, conf); + memoryManager = new LowLevelCacheMemoryManager(maxSize, cachePolicy, cacheMetrics); + int maxAllocationSize = 1024; + int minAllocationSize = 8; + allocator = + new BuddyAllocator(true, + false, + minAllocationSize, + maxAllocationSize, + 1, + maxSize, + 0, + null, + memoryManager, + cacheMetrics, + "no-force-eviction", + true); + EvictionDispatcher evictionDispatcher = new EvictionDispatcher(dataCache, serdCache, metaDataCache, allocator); + evictionTracker = new EvictionTracker(evictionDispatcher); + cachePolicy.setEvictionListener(evictionTracker); + } + + @After public void tearDown() throws Exception { + LOG.info("Purge the cache on tear down"); + cachePolicy.purge(); + allocator = null; + memoryManager = null; + cachePolicy = null; + } + + /** + * Test case to ensure that deallocate it does merge small blocks into bigger ones. + */ + @Test(timeout = 6000L) public void TestMergeOfBlocksAfterDeallocate() { + // allocate blocks of cacheSize/16, Then deallocate then Allocate of size cacheSize/2 + MemoryBuffer[] dest = new MemoryBuffer[16]; + for (MemoryBuffer memoryBuffer : dest) { + Assert.assertNull(memoryBuffer); + } + allocator.allocateMultiple(dest, 64, null); + //Check that everything is allocated + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + for (MemoryBuffer value : dest) { + cachePolicy.notifyUnlock((LlapCacheableBuffer) value); + } + for (MemoryBuffer value : dest) { + Assert.assertTrue(value instanceof LlapDataBuffer); + LlapDataBuffer buffer = (LlapDataBuffer) value; + Assert.assertEquals(buffer.getMemoryUsage(), cachePolicy.evictSomeBlocks(buffer.getMemoryUsage())); + memoryManager.releaseMemory(buffer.getMemoryUsage()); + } + + // All is deAllocated thus used has to be zero + Assert.assertEquals(0, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + MemoryBuffer[] dest2 = new MemoryBuffer[2]; + for (MemoryBuffer memoryBuffer : dest2) { + Assert.assertNull(memoryBuffer); + } + allocator.allocateMultiple(dest2, 512, null); + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + for (int i = 0; i < dest2.length; i++) { + Assert.assertNotNull(dest[i]); + //we are not calling deallocate evict to avoid extra memory manager free calls + allocator.deallocate(dest2[i]); + } + Assert.assertEquals(0, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + } + + @Test(timeout = 6000L) public void TestSimpleAllocateThenEvictThenAllocate() { + // Allocate all the cache 16 * 64 + MemoryBuffer[] dest = new MemoryBuffer[16]; + for (MemoryBuffer memoryBuffer : dest) { + Assert.assertNull(memoryBuffer); + } + allocator.allocateMultiple(dest, 64, null); + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + for (MemoryBuffer buffer : dest) { + cachePolicy.notifyUnlock((LlapCacheableBuffer) buffer); + } + // allocate bigger blocks + dest = new MemoryBuffer[8]; + allocator.allocateMultiple(dest, 128, null); + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + for (MemoryBuffer memoryBuffer : dest) { + Assert.assertNotNull(memoryBuffer); + allocator.deallocate(memoryBuffer); + } + } + + @Test(timeout = 60000L) public void TestRandomFragmentation() { + + MemoryBuffer[] dest = new MemoryBuffer[64]; + MemoryBuffer[] dest_2 = new MemoryBuffer[16]; + MemoryBuffer[] dest_3 = new MemoryBuffer[8]; + for (MemoryBuffer memoryBuffer : dest) { + Assert.assertNull(memoryBuffer); + } + + allocator.allocateMultiple(dest, 8, null); + allocator.allocateMultiple(dest_2, 16, null); + allocator.allocateMultiple(dest_3, 32, null); + //all the cache is allocated with 8 X 128 + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + + for (int i = 0; i < dest.length; i++) { + LlapDataBuffer buffer = (LlapDataBuffer) dest[i]; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + cachePolicy.notifyUnlock(buffer); + // lock some buffers + if (i % 2 == 0) { + // lock the even buffers + buffer.incRef(); + } + } + + for (int i = 0; i < dest_2.length; i++) { + LlapDataBuffer buffer = (LlapDataBuffer) dest_2[i]; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + cachePolicy.notifyUnlock(buffer); + // lock some buffers + if (i % 2 == 0) { + // lock the even buffers + buffer.incRef(); + } + } + + for (int i = 0; i < dest_3.length; i++) { + LlapDataBuffer buffer = (LlapDataBuffer) dest_3[i]; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + cachePolicy.notifyUnlock(buffer); + // lock some buffers + if (i % 2 == 0) { + // lock the even buffers + buffer.incRef(); + } + } + Assert.assertEquals(512, ((LowLevelCacheMemoryManager) memoryManager).purge()); + + for (MemoryBuffer memoryBuffer : dest_3) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + if (buffer.isLocked()) { + buffer.decRef(); + } + cachePolicy.notifyUnlock(buffer); + } + + for (MemoryBuffer memoryBuffer : dest_2) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + if (buffer.isLocked()) { + buffer.decRef(); + } + cachePolicy.notifyUnlock(buffer); + } + + for (MemoryBuffer memoryBuffer : dest) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + if (buffer.isLocked()) { + buffer.decRef(); + } + cachePolicy.notifyUnlock(buffer); + } + Assert.assertEquals(maxSize / 2, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + + dest = new MemoryBuffer[64]; + dest_2 = new MemoryBuffer[16]; + dest_3 = new MemoryBuffer[8]; + evictionTracker.getEvicted().clear(); + allocator.allocateMultiple(dest_2, 16, null); + allocator.allocateMultiple(dest, 8, null); + allocator.allocateMultiple(dest_3, 32, null); + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + Assert.assertEquals(dest_3.length / 2 + dest_2.length / 2 + dest.length / 2, evictionTracker.getEvicted().size()); + for (MemoryBuffer memoryBuffer : dest) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + allocator.deallocate(buffer); + } + for (MemoryBuffer memoryBuffer : dest_2) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + allocator.deallocate(buffer); + } + + for (MemoryBuffer memoryBuffer : dest_3) { + LlapDataBuffer buffer = (LlapDataBuffer) memoryBuffer; + allocator.deallocate(buffer); + } + } + + @Test(timeout = 60000L) public void TestFragmentation() { + MemoryBuffer[] dest = new MemoryBuffer[128]; + for (MemoryBuffer memoryBuffer : dest) { + Assert.assertNull(memoryBuffer); + } + allocator.allocateMultiple(dest, 8, null); + //all the cache is allocated with 8 X 128 + Assert.assertEquals(maxSize, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + + for (int i = 0; i < dest.length; i++) { + LlapDataBuffer buffer = (LlapDataBuffer) dest[i]; + // this is needed to make sure that the policy adds the buffers to the linked list as buffers ready to be evicted + cachePolicy.notifyUnlock(buffer); + // lock some buffers + if (i % 2 == 0) { + // lock the even buffers + buffer.incRef(); + } + } + + // purge the cache should lead to only evicting the unlocked buffers + Assert.assertEquals(512, ((LowLevelCacheMemoryManager) memoryManager).purge()); + // After purge the used memory should be aligned to the amount of evicted items + Assert.assertEquals(512, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + + MemoryBuffer[] dest2 = new MemoryBuffer[1]; + Exception exception = null; + try { + allocator.allocateMultiple(dest2, 16, null); + } catch (Allocator.AllocatorOutOfMemoryException e) { + // we should fail since we have the extreme case where half of the leaf nodes are locked thus + // maximum fragmentation case + exception = e; + } + Assert.assertNotNull(exception); + Assert.assertEquals(512, ((LowLevelCacheMemoryManager) memoryManager).getCurrentUsedSize()); + // unlock one buffer + Assert.assertTrue(((LlapDataBuffer) dest[0]).isLocked()); + ((LlapDataBuffer) dest[0]).decRef(); + evictionTracker.clear(); + // this is needed since purge has removed the locked ones form the list, the assumption is that when we unlock + // a buffer we notify the cache policy. + cachePolicy.notifyUnlock((LlapDataBuffer) dest[0]); + // we should be able to allocate after some extra eviction + allocator.allocateMultiple(dest2, 16, null); + //we have to see that we have force evicted something to make room for the new allocation + Assert.assertTrue(evictionTracker.getEvicted().size() >= 1); + } + + private class EvictionTracker implements EvictionListener { + private final EvictionListener evictionListener; + + private List evicted = new ArrayList<>(); + + private EvictionTracker(EvictionListener evictionListener) { + this.evictionListener = evictionListener; + } + + @Override public void notifyEvicted(LlapCacheableBuffer buffer) { + evicted.add(buffer); + evictionListener.notifyEvicted(buffer); + } + + public List getEvicted() { + return evicted; + } + + public void clear() { + evicted.clear(); + } + } +} diff --git llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestOrcMetadataCache.java llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestOrcMetadataCache.java index ad6b90e358..f4d6156180 100644 --- llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestOrcMetadataCache.java +++ llap-server/src/test/org/apache/hadoop/hive/llap/cache/TestOrcMetadataCache.java @@ -86,6 +86,10 @@ public void reserveMemory(long memoryToReserve, AtomicBoolean isStopped) { ++allocs; } + @Override public long evictMemory(long memoryToReserve) { + return 0; + } + @Override public void releaseMemory(long memUsage) { } diff --git ql/src/java/org/apache/hadoop/hive/ql/ddl/table/CreateViewOperation.java ql/src/java/org/apache/hadoop/hive/ql/ddl/table/CreateViewOperation.java index f8d95aa747..bb9b18977b 100644 --- ql/src/java/org/apache/hadoop/hive/ql/ddl/table/CreateViewOperation.java +++ ql/src/java/org/apache/hadoop/hive/ql/ddl/table/CreateViewOperation.java @@ -60,11 +60,7 @@ public int execute() throws HiveException { } } - if (!desc.isReplace()) { - if (desc.getIfNotExists()) { - return 0; - } - + if (!desc.isReplace() && !desc.getIfNotExists()) { // View already exists, thus we should be replacing throw new HiveException(ErrorMsg.TABLE_ALREADY_EXISTS.getMsg(desc.getViewName())); } diff --git ql/src/test/queries/clientpositive/create_view.q ql/src/test/queries/clientpositive/create_view.q index 392ebf4591..3fe14f4ecd 100644 --- ql/src/test/queries/clientpositive/create_view.q +++ ql/src/test/queries/clientpositive/create_view.q @@ -238,12 +238,7 @@ create view view18 as select v+1 from (select 1 as v) t; select * from view18; -- create view if not exists -create view if not exists view18 as select "should be ignored"; -show create table view18; - --- 'create or replace' -create or replace view view18 as select "should replace"; -show create table view18; +create view if not exists view18 as select v+1 from (select 1 as v) t; DROP VIEW view1; DROP VIEW view2; diff --git ql/src/test/results/clientpositive/create_view.q.out ql/src/test/results/clientpositive/create_view.q.out index 7414d4749d..f3d7520e1c 100644 --- ql/src/test/results/clientpositive/create_view.q.out +++ ql/src/test/results/clientpositive/create_view.q.out @@ -1618,40 +1618,16 @@ POSTHOOK: Input: _dummy_database@_dummy_table POSTHOOK: Input: default@view18 #### A masked pattern was here #### 2 -PREHOOK: query: create view if not exists view18 as select "should be ignored" +PREHOOK: query: create view if not exists view18 as select v+1 from (select 1 as v) t PREHOOK: type: CREATEVIEW PREHOOK: Input: _dummy_database@_dummy_table PREHOOK: Output: database:default PREHOOK: Output: default@view18 -POSTHOOK: query: create view if not exists view18 as select "should be ignored" +POSTHOOK: query: create view if not exists view18 as select v+1 from (select 1 as v) t POSTHOOK: type: CREATEVIEW POSTHOOK: Input: _dummy_database@_dummy_table POSTHOOK: Output: database:default POSTHOOK: Output: default@view18 -PREHOOK: query: show create table view18 -PREHOOK: type: SHOW_CREATETABLE -PREHOOK: Input: default@view18 -POSTHOOK: query: show create table view18 -POSTHOOK: type: SHOW_CREATETABLE -POSTHOOK: Input: default@view18 -CREATE VIEW `view18` AS select `t`.`v`+1 from (select 1 as `v`) `t` -PREHOOK: query: create or replace view view18 as select "should replace" -PREHOOK: type: CREATEVIEW -PREHOOK: Input: _dummy_database@_dummy_table -PREHOOK: Output: database:default -PREHOOK: Output: default@view18 -POSTHOOK: query: create or replace view view18 as select "should replace" -POSTHOOK: type: CREATEVIEW -POSTHOOK: Input: _dummy_database@_dummy_table -POSTHOOK: Output: database:default -POSTHOOK: Output: default@view18 -PREHOOK: query: show create table view18 -PREHOOK: type: SHOW_CREATETABLE -PREHOOK: Input: default@view18 -POSTHOOK: query: show create table view18 -POSTHOOK: type: SHOW_CREATETABLE -POSTHOOK: Input: default@view18 -CREATE VIEW `view18` AS select "should replace" PREHOOK: query: DROP VIEW view1 PREHOOK: type: DROPVIEW PREHOOK: Input: default@view1