From a7a3d5ab98ee0ad33fdef50bf081afeb8295ebe4 Mon Sep 17 00:00:00 2001 From: Sven Gothel <sgothel@jausoft.com> Date: Fri, 3 Oct 2014 03:12:42 +0200 Subject: MappedByteBuffer*Stream: - Validate active and GC'ed mapped-buffer count in cleanAllSlices() via close() .. - Fix missing unmapping last buffer in notifyLengthChangeImpl(), branch criteria was off by one. - cleanSlice(..) now also issues cleanBuffer(..) on the GC'ed entry, hence if WeakReference is still alive, enforce it's release. - cleanBuffer(..) reverts FLUSH_PRE_HARD -> FLUSH_PRE_SOFT in case of an error. - flush() -> flush(boolean metaData) to expose FileChannel.force(metaData). - Add synchronous mode, flushing/syncing the mapped buffers when in READ_WRITE mapping mode and issue FileChannel.force() if not READ_ONLY. Above is implemented via flush()/flushImpl(..) for buffers and FileChannel, as well as in syncSlice(..) for buffers only. flush*()/syncSlice() is covered by: - setLength() - notifyLengthChange*(..) - nextSlice() Always issue flushImpl() in close(). - Windows: Clean all buffers in setLength(), otherwise Windows will report: - Windows: Catch MappedByteBuffer.force() IOException - Optimization of position(..) position(..) is now standalone to allow issuing flushSlice(..) before gathering the new mapped buffer. This shall avoid one extra cache miss. Hence rename positionImpl(..) -> position2(..). - All MappedByteBufferOutputStream.write(..) methods issue syncSlice(..) on the last written current slice to ensure new 'synchronous' mode is honored. +++ Unit tests: - Ensure test files are being deleted - TestByteBufferCopyStream: Reduced test file size to more sensible values. - --- .../common/nio/TestByteBufferCopyStream.java | 105 ++++++++++++++------- 1 file changed, 69 insertions(+), 36 deletions(-) (limited to 'src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java') diff --git a/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java b/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java index 3442159..fef26b6 100644 --- a/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java +++ b/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java @@ -100,74 +100,107 @@ public class TestByteBufferCopyStream extends JunitTracer { Assert.assertEquals(0, mos.position()); Assert.assertEquals(0, mos.remaining()); - mos.write(mis, mis.remaining()); + OutOfMemoryError oome = null; + IOException ioe = null; - Assert.assertEquals(size, input.length()); - Assert.assertEquals(size, output.length()); - Assert.assertEquals(size, mis.length()); - Assert.assertEquals(size, mos.length()); - Assert.assertEquals(size, mis.position()); - Assert.assertEquals(size, mos.position()); - Assert.assertEquals(0, mis.remaining()); - Assert.assertEquals(0, mos.remaining()); - - mos.close(); - mis.close(); - input.close(); - output.close(); - srcFile.delete(); - dstFile.delete(); - TestByteBufferInputStream.dumpMem(prefix+" after ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 ); - System.gc(); try { - Thread.sleep(500); - } catch (final InterruptedException e) { } - TestByteBufferInputStream.dumpMem(prefix+" gc'ed ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 ); + mos.write(mis, mis.remaining()); + + Assert.assertEquals(size, input.length()); + Assert.assertEquals(size, output.length()); + Assert.assertEquals(size, mis.length()); + Assert.assertEquals(size, mos.length()); + Assert.assertEquals(size, mis.position()); + Assert.assertEquals(size, mos.position()); + Assert.assertEquals(0, mis.remaining()); + Assert.assertEquals(0, mos.remaining()); + + } catch (final IOException e) { + if( e.getCause() instanceof OutOfMemoryError ) { + oome = (OutOfMemoryError) e.getCause(); // oops + } else { + ioe = e; + } + } catch (final OutOfMemoryError m) { + oome = m; // oops + } finally { + mos.close(); + mis.close(); + input.close(); + output.close(); + srcFile.delete(); + dstFile.delete(); + TestByteBufferInputStream.dumpMem(prefix+" after ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 ); + System.gc(); + try { + Thread.sleep(500); + } catch (final InterruptedException e) { } + TestByteBufferInputStream.dumpMem(prefix+" gc'ed ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 ); + } + if( null != ioe || null != oome ) { + if( null != oome ) { + System.err.printf("%s: OutOfMemoryError.2 %s%n", prefix, oome.getMessage()); + oome.printStackTrace(); + } else { + Assert.assertNull(ioe); + } + } } + /** {@value} */ + static final long halfMiB = 1L << 19; + /** {@value} */ + static final long oneGiB = 1L << 30; + /** {@value} */ + static final long onePlusGiB = oneGiB + halfMiB; + /** {@value} */ + static final long twoGiB = ( 2L << 30 ); + /** {@value} */ + static final long twoPlusGiB = twoGiB + halfMiB; + @Test public void test00() throws IOException { final int srcSliceShift = MappedByteBufferInputStream.DEFAULT_SLICE_SHIFT; final int dstSliceShift = MappedByteBufferInputStream.DEFAULT_SLICE_SHIFT; - final long size = 3L * ( 1L << 30 ); // 3 GiB - testImpl("./testIn.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_HARD, srcSliceShift, - "./testOut.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_HARD, dstSliceShift ); + final long size = twoPlusGiB; + testImpl(getSimpleTestName(".")+"_In.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_HARD, srcSliceShift, + getSimpleTestName(".")+"_Out.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_HARD, dstSliceShift ); } @Test public void test01() throws IOException { final int srcSliceShift = MappedByteBufferInputStream.DEFAULT_SLICE_SHIFT; final int dstSliceShift = MappedByteBufferInputStream.DEFAULT_SLICE_SHIFT; - final long size = 3L * ( 1L << 30 ); // 3 GiB - testImpl("./testIn.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, - "./testOut.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); + final long size = twoPlusGiB; + testImpl(getSimpleTestName(".")+"_In.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, + getSimpleTestName(".")+"_Out.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); } @Test public void test02() throws IOException { final int srcSliceShift = 28; // 256M bytes per slice final int dstSliceShift = 28; // 256M bytes per slice - final long size = 3L * ( 1L << 30 ); // 3 GiB - testImpl("./testIn.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, - "./testOut.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); + final long size = onePlusGiB; + testImpl(getSimpleTestName(".")+"_In.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, + getSimpleTestName(".")+"_Out.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); } @Test public void test11() throws IOException { final int srcSliceShift = 28; // 256M bytes per slice final int dstSliceShift = 27; // 128M bytes per slice - final long size = 3L * ( 1L << 30 ); // 3 GiB - testImpl("./testIn.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, - "./testOut.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); + final long size = onePlusGiB; + testImpl(getSimpleTestName(".")+"_In.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, + getSimpleTestName(".")+"_Out.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); } @Test public void test12() throws IOException { final int srcSliceShift = 27; // 128M bytes per slice final int dstSliceShift = 28; // 256M bytes per slice - final long size = 3L * ( 1L << 30 ); // 3 GiB - testImpl("./testIn.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, - "./testOut.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); + final long size = onePlusGiB; + testImpl(getSimpleTestName(".")+"_In.bin", size, MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, srcSliceShift, + getSimpleTestName(".")+"_Out.bin", MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT, dstSliceShift ); } public static void main(final String args[]) throws IOException { -- cgit v1.2.3