public void read( final long position, final long size, final ByteBuffer directByteBuffer, final AIOCallback aioPackage) throws HornetQException { checkOpened(); if (poller == null) { startPoller(); } pendingWrites.countUp(); maxIOSemaphore.acquireUninterruptibly(); try { read(handler, position, size, directByteBuffer, aioPackage); } catch (HornetQException e) { // Release only if an exception happened maxIOSemaphore.release(); pendingWrites.countDown(); throw e; } catch (RuntimeException e) { // Release only if an exception happened maxIOSemaphore.release(); pendingWrites.countDown(); throw e; } }
/** * This test will call file.close() when there are still callbacks being processed. This could * cause a crash or callbacks missing and this test is validating both situations. The file is * also read after being written to validate its correctness */ @Test public void testConcurrentClose() throws Exception { controller = new AsynchronousFileImpl(executor, pollerExecutor); final int NUMBER_LINES = 1000; CountDownLatch readLatch = new CountDownLatch(NUMBER_LINES); final int SIZE = 1024; controller.open(fileName, 10000); controller.fill(0, 1, NUMBER_LINES * SIZE, (byte) 'j'); controller.setBufferCallback(bufferCallbackDestroy); for (int i = 0; i < NUMBER_LINES; i++) { ByteBuffer buffer = AsynchronousFileImpl.newBuffer(SIZE); buffer.clear(); addString("Str value " + i + "\n", buffer); for (int j = buffer.position(); j < buffer.capacity() - 1; j++) { buffer.put((byte) ' '); } buffer.put((byte) '\n'); CountDownCallback aio = new CountDownCallback(readLatch, null, null, 0); controller.write(i * SIZE, SIZE, buffer, aio); } // If you call close you're supposed to wait events to finish before // closing it controller.close(); controller.setBufferCallback(null); Assert.assertEquals(0, readLatch.getCount()); waitForLatch(readLatch); controller.open(fileName, 10); ByteBuffer newBuffer = AsynchronousFileImpl.newBuffer(SIZE); ByteBuffer buffer = AsynchronousFileImpl.newBuffer(SIZE); for (int i = 0; i < NUMBER_LINES; i++) { newBuffer.clear(); addString("Str value " + i + "\n", newBuffer); for (int j = newBuffer.position(); j < newBuffer.capacity() - 1; j++) { newBuffer.put((byte) ' '); } newBuffer.put((byte) '\n'); CountDownLatch latch = new CountDownLatch(1); CountDownCallback aio = new CountDownCallback(latch, null, null, 0); controller.read(i * SIZE, SIZE, buffer, aio); waitForLatch(latch); Assert.assertEquals(0, aio.errorCalled); Assert.assertTrue(aio.doneCalled); byte bytesRead[] = new byte[SIZE]; byte bytesCompare[] = new byte[SIZE]; newBuffer.rewind(); newBuffer.get(bytesCompare); buffer.rewind(); buffer.get(bytesRead); for (int count = 0; count < SIZE; count++) { Assert.assertEquals( "byte position " + count + " differs on line " + i, bytesCompare[count], bytesRead[count]); } Assert.assertTrue(buffer.equals(newBuffer)); } destroy(newBuffer); }
@Test public void testRead() throws Exception { controller = new AsynchronousFileImpl(executor, pollerExecutor); controller.setBufferCallback(bufferCallbackDestroy); final int NUMBER_LINES = 1000; final int SIZE = 1024; controller.open(fileName, 1000); controller.fill(0, 1, NUMBER_LINES * SIZE, (byte) 'j'); { CountDownLatch latch = new CountDownLatch(NUMBER_LINES); ArrayList<Integer> result = new ArrayList<Integer>(); AtomicInteger errors = new AtomicInteger(0); for (int i = 0; i < NUMBER_LINES; i++) { if (i % 100 == 0) { System.out.println("Wrote " + i + " lines"); } final ByteBuffer buffer0 = AsynchronousFileImpl.newBuffer(SIZE); for (int j = 0; j < SIZE; j++) { buffer0.put(UnitTestCase.getSamplebyte(j)); } CountDownCallback aio = new CountDownCallback(latch, errors, result, i); controller.write(i * SIZE, SIZE, buffer0, aio); } waitForLatch(latch); Assert.assertEquals(0, errors.get()); CountDownCallback.checkResults(NUMBER_LINES, result); } // If you call close you're supposed to wait events to finish before // closing it controller.close(); controller.setBufferCallback(null); controller.open(fileName, 10); buffer = AsynchronousFileImpl.newBuffer(SIZE); for (int i = 0; i < NUMBER_LINES; i++) { if (i % 100 == 0) { System.out.println("Read " + i + " lines"); } AsynchronousFileImpl.clearBuffer(buffer); CountDownLatch latch = new CountDownLatch(1); AtomicInteger errors = new AtomicInteger(0); CountDownCallback aio = new CountDownCallback(latch, errors, null, 0); controller.read(i * SIZE, SIZE, buffer, aio); waitForLatch(latch); Assert.assertEquals(0, errors.get()); Assert.assertTrue(aio.doneCalled); byte bytesRead[] = new byte[SIZE]; buffer.get(bytesRead); for (int count = 0; count < SIZE; count++) { Assert.assertEquals( "byte position " + count + " differs on line " + i + " position = " + count, UnitTestCase.getSamplebyte(count), bytesRead[count]); } } }
@Test public void testInvalidReads() throws Exception { controller = new AsynchronousFileImpl(executor, pollerExecutor); final int SIZE = 512; controller.open(fileName, 10); controller.close(); controller = new AsynchronousFileImpl(executor, pollerExecutor); controller.open(fileName, 10); controller.fill(0, 1, 512, (byte) 'j'); buffer = AsynchronousFileImpl.newBuffer(SIZE); buffer.clear(); for (int i = 0; i < SIZE; i++) { buffer.put((byte) (i % 100)); } LocalCallback callbackLocal = new LocalCallback(); controller.write(0, 512, buffer, callbackLocal); waitForLatch(callbackLocal.latch); { ByteBuffer newBuffer = AsynchronousFileImpl.newBuffer(512); try { callbackLocal = new LocalCallback(); controller.read(0, 50, newBuffer, callbackLocal); waitForLatch(callbackLocal.latch); Assert.assertTrue(callbackLocal.error); } finally { // We have to destroy the native buffer manually as it was created with a malloc like C // function destroy(newBuffer); newBuffer = null; } } callbackLocal = new LocalCallback(); byte bytes[] = new byte[512]; { try { ByteBuffer newBuffer = ByteBuffer.wrap(bytes); controller.read(0, 512, newBuffer, callbackLocal); Assert.fail("An exception was supposed to be thrown"); } catch (HornetQException ignored) { System.out.println(ignored); } } { final ByteBuffer newBuffer = AsynchronousFileImpl.newBuffer(512); try { callbackLocal = new LocalCallback(); controller.read(0, 512, newBuffer, callbackLocal); waitForLatch(callbackLocal.latch); Assert.assertFalse(callbackLocal.error); newBuffer.rewind(); byte[] bytesRead = new byte[SIZE]; newBuffer.get(bytesRead); for (int i = 0; i < SIZE; i++) { Assert.assertEquals((byte) (i % 100), bytesRead[i]); } } finally { destroy(newBuffer); } } }