[ 
https://issues.apache.org/jira/browse/DRILL-4112?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15011792#comment-15011792
 ] 

Deneche A. Hakim commented on DRILL-4112:
-----------------------------------------

a quick note here, the unit test is incomplete because we don't clear the 
allocated vector, but this doesn't change the original issue

> BaseDataValueVector.getBuffers(false) doesn't return it's inner buffer which 
> affects transfer of ownership between allocators in ExternalSort
> ---------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: DRILL-4112
>                 URL: https://issues.apache.org/jira/browse/DRILL-4112
>             Project: Apache Drill
>          Issue Type: Bug
>    Affects Versions: 1.2.0
>            Reporter: Deneche A. Hakim
>
> As part of fixing DRILL-2274, to avoid running out of memory in sort when it 
> spilled to disk we close the _copierAllocator_ after we receive the last 
> batch from upstream, this way it releases all it's allocated memory back to 
> it's parent allocator. The assumption is that the _copierAllocator_ doesn't 
> own any buffers once a _mergeAndSpill_ is done and we no longer need it if we 
> are no longer
> spilling to disk.
> This causes it's accountor to complain that some buffers weren't closed (when 
> assertions are enabled), which goes against the previous assumption.
> The _copierAllocator_ is used to allocate many batches while spilling but 
> only one is kept in memory and the following method transfers it's ownership 
> to the operator's allocator:
> {code}
>   private void takeOwnership(VectorAccessible batch) {
>     for (VectorWrapper<?> w : batch) {
>       DrillBuf[] bufs = w.getValueVector().getBuffers(false);
>       for (DrillBuf buf : bufs) {
>         if (buf.isRootBuffer()) {
>           oContext.getAllocator().takeOwnership(buf);
>         }
>       }
>     }
>   }
> {code}
> The problem comes from how _BaseDataValueVector.getBuffers(boolean clear)_ is 
> implemented:
> {code}
>   @Override
>   public DrillBuf[] getBuffers(boolean clear) {
>     DrillBuf[] out;
>     if (getBufferSize() == 0) {
>       out = new DrillBuf[0];
>     } else {
>       out = new DrillBuf[]{data};
>       if (clear) {
>         data.readerIndex(0);
>         data.retain(1);
>       }
>     }
>     if (clear) {
>       clear();
>     }
>     return out;
>   }
> {code}
> If we don't write any value into the vector, and call _getBuffers(false)_, it 
> won't return it's allocated buffer but an empty array instead. Thus, the 
> buffer won't be transferred to the operator's allocator.
> The following unit test will exposes the problem:
> {code}
>   @Test
>   public void testTakeOwnership() throws Exception {
>     final MaterializedField field = 
> MaterializedField.create(SchemaPath.getSimplePath(""), 
> NullableVarCharHolder.TYPE);
>     final DrillConfig drillConfig = DrillConfig.create();
>     final BufferAllocator allocator = 
> RootAllocatorFactory.newRoot(drillConfig);
>     final BufferAllocator childAllocator = allocator.getChildAllocator(null, 
> 10000, 20000, false);
>     final NullableVarCharVector vector = new NullableVarCharVector(field, 
> childAllocator);
>     vector.allocateNew(1024 * 10, 1024);
>     DrillBuf[] buffers = vector.getBuffers(false);
>     for (final DrillBuf buffer : buffers) {
>       allocator.takeOwnership(buffer);
>     }
>     childAllocator.close();
>     allocator.close();
>   }
> {code}
> When closing _childAllocator_ we get the following exception (when assertions 
> are enabled):
> {noformat}
> java.lang.IllegalStateException: Attempted to close accountor with 3 
> buffer(s) still allocated.
>       Total 1 allocation(s) of byte size(s): 4100, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.UInt4Vector.allocateBytes(UInt4Vector.java:209)
>               
> org.apache.drill.exec.vector.UInt4Vector.allocateNew(UInt4Vector.java:191)
>               
> org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:386)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
>       Total 1 allocation(s) of byte size(s): 1024, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.UInt1Vector.allocateBytes(UInt1Vector.java:209)
>               
> org.apache.drill.exec.vector.UInt1Vector.allocateNew(UInt1Vector.java:191)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:225)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
>       Total 1 allocation(s) of byte size(s): 10240, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:385)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               java.lang.reflect.Method.invoke(Method.java:606)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> java.lang.IllegalStateException: Attempted to close accountor with 3 
> buffer(s) still allocated.
>       Total 1 allocation(s) of byte size(s): 4100, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.UInt4Vector.allocateBytes(UInt4Vector.java:209)
>               
> org.apache.drill.exec.vector.UInt4Vector.allocateNew(UInt4Vector.java:191)
>               
> org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:386)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
>       Total 1 allocation(s) of byte size(s): 1024, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.UInt1Vector.allocateBytes(UInt1Vector.java:209)
>               
> org.apache.drill.exec.vector.UInt1Vector.allocateNew(UInt1Vector.java:191)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:225)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
>       Total 1 allocation(s) of byte size(s): 10240, at stack location:
>               
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
>               
> org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:385)
>               
> org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
>               
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>               
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
>               
> mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
>               
> mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
>               sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>               
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>               
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>               
> mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
>               
> mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
>               
> mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
>               
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
>               
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
>               
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
>               
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>               
> org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
>       at org.apache.drill.exec.memory.Accountor.close(Accountor.java:381)
>       at 
> org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.close(TopLevelAllocator.java:327)
>       at 
> org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:130)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to