From 403f543801383e25cf3fe2d7a92b7f70f3ff5434 Mon Sep 17 00:00:00 2001 From: "Jan S. Rellermeyer" Date: Thu, 18 May 2017 05:43:09 +0000 Subject: [PATCH] applied a couple of improvements to the PR as discussed with Rei. re-compiled the CapiOSInfo.class to be target=1.5 replaced the CompletableFuture with a custom implementation since it requires Java 1.8 simplified the handling in the timeout test for the emulation case (which never times out) --- .../research/capiblock/CapiBlockDevice.java | 59 +++++---- .../ibm/research/capiblock/EmulatedChunk.java | 49 ++++++-- .../capiblock/CapiBlockDeviceTest.java | 119 ++++++++---------- .../com/ibm/research/osinfo/CapiOSInfo.class | Bin 865 -> 826 bytes 4 files changed, 124 insertions(+), 103 deletions(-) diff --git a/src/java/capiblock/com/ibm/research/capiblock/CapiBlockDevice.java b/src/java/capiblock/com/ibm/research/capiblock/CapiBlockDevice.java index cbbc65ae..94a9f544 100644 --- a/src/java/capiblock/com/ibm/research/capiblock/CapiBlockDevice.java +++ b/src/java/capiblock/com/ibm/research/capiblock/CapiBlockDevice.java @@ -49,8 +49,12 @@ public class CapiBlockDevice { * the block size in Bytes */ public static final int BLOCK_SIZE = 4096; + public static final String CAPI_BLOCK_VERBOSE_PROPERTY_NAME = "com.ibm.research.capiblock.verbose"; //$NON-NLS-1$ + public static final String CAPI_BLOCK_EMULATION_PROPERTY_NAME = "com.ibm.research.capiblock.emulation"; //$NON-NLS-1$ + public static final String CAPI_BLOCK_CAPACITY_PROPERTY_NAME = "com.ibm.research.capiblock.capacity"; //$NON-NLS-1$ + private static boolean useEmulation = false; - private static boolean verbose = Boolean.parseBoolean(System.getProperty("capi.block.verbose", "false")); + private static boolean verbose = Boolean.parseBoolean(System.getProperty(CAPI_BLOCK_VERBOSE_PROPERTY_NAME, "false")); static { initialize(); @@ -58,28 +62,28 @@ public class CapiBlockDevice { // Have this private static method because a static initializer cannot have return in it. private static void initialize() { - String emulationProperty = System.getProperty("capi.block.emulation"); + final String emulationProperty = System.getProperty(CAPI_BLOCK_EMULATION_PROPERTY_NAME); if (emulationProperty != null) { - useEmulation = Boolean.parseBoolean(emulationProperty); + useEmulation = Boolean.getBoolean(CAPI_BLOCK_EMULATION_PROPERTY_NAME); if (useEmulation) { if (verbose) { - System.err.println("WARNING: CAPI block library will use emulation"); + System.err.println("WARNING: CAPI block library will use emulation"); //$NON-NLS-1$ } return; } } - String resourceName = "/linux/" + System.getProperty("os.arch") + "/libcapiblock.so"; - InputStream is = CapiBlockDevice.class.getResourceAsStream(resourceName); + final String resourceName = "/linux/" + System.getProperty("os.arch") + "/libcapiblock.so"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + final InputStream is = CapiBlockDevice.class.getResourceAsStream(resourceName); if (is == null) { if (emulationProperty != null && !useEmulation) { // The user explicitly disabled the emulation, // but cannot find the JNI library, so throw an exception. - throw new UnsupportedOperationException("Unsupported OS/arch. Cannot find " + resourceName); + throw new UnsupportedOperationException("Unsupported OS/arch. Cannot find " + resourceName); //$NON-NLS-1$ } else { useEmulation = true; if (verbose) { - System.err.println("WARNING: CAPI block library will use emulation"); + System.err.println("WARNING: CAPI block library will use emulation"); //$NON-NLS-1$ } return; } @@ -88,10 +92,10 @@ private static void initialize() { boolean loaded = false; FileOutputStream out = null; try { - tempLib = File.createTempFile("libcapiblock", ".so"); + tempLib = File.createTempFile("libcapiblock", ".so"); //$NON-NLS-1$ //$NON-NLS-2$ out = new FileOutputStream(tempLib); - byte[] buf = new byte[4096]; + final byte[] buf = new byte[4096]; while (true) { int read = is.read(buf); if (read == -1) { @@ -103,15 +107,15 @@ private static void initialize() { out = null; System.load(tempLib.getAbsolutePath()); loaded = true; - } catch (IOException ex) { + } catch (final IOException ex) { if (emulationProperty != null && !useEmulation) { // The user explicitly disabled the emulation, // but cannot load the JNI library, so throw an exception. - throw new ExceptionInInitializerError("Cannot load libcapiblock"); + throw new ExceptionInInitializerError("Cannot load libcapiblock"); //$NON-NLS-1$ } else { useEmulation = true; if (verbose) { - System.err.println("WARNING: CAPI block library will use emulation"); + System.err.println("WARNING: CAPI block library will use emulation"); //$NON-NLS-1$ } return; } @@ -120,7 +124,8 @@ private static void initialize() { if (out != null) { out.close(); } - } catch (IOException ex) { + } catch (final IOException ex) { + // ignore exception during close } if (tempLib != null && tempLib.exists()) { if (!loaded) { @@ -146,9 +151,9 @@ public static synchronized CapiBlockDevice getInstance() { if (instance == null) { instance = new CapiBlockDevice(); if (useEmulation) { - String capacityProperty = System.getProperty("capi.block.capacity"); + final String capacityProperty = System.getProperty(CAPI_BLOCK_CAPACITY_PROPERTY_NAME); if (capacityProperty == null) { - throw new IllegalStateException("Necessary property capi.block.capacity is not set"); + throw new IllegalStateException("Necessary property com.ibm.research.capiblock.capacity is not set"); //$NON-NLS-1$ } capacity = Integer.parseInt(capacityProperty); } @@ -161,7 +166,7 @@ public static synchronized CapiBlockDevice getInstance() { * * @return true, if the CAPI Flash emulation is being used. false, otherwise. */ - public boolean useEmulation() { + public boolean isEmulated() { return useEmulation; } @@ -191,20 +196,20 @@ public Chunk openChunk(final String path) throws IOException { * @throws IOException * when the operation failed. */ - public Chunk openChunk(final String path, int maxRequests) + public Chunk openChunk(final String path, final int maxRequests) throws IOException { if (useEmulation) { if (maxRequests < 0) { - throw new IOException("maxRequests must not be negative"); + throw new IOException("maxRequests must not be negative"); //$NON-NLS-1$ } synchronized (this) { RandomAccessFile f = null; if (files.containsKey(path)) { - FileAndCounterPair pair = files.get(path); + final FileAndCounterPair pair = files.get(path); pair.referenceCounter++; f = pair.file; } else { - f = new RandomAccessFile(path, "rws"); + f = new RandomAccessFile(path, "rws"); //$NON-NLS-1$ f.setLength((long) BLOCK_SIZE * capacity); files.put(path, new FileAndCounterPair(f)); } @@ -215,13 +220,13 @@ public Chunk openChunk(final String path, int maxRequests) } } - synchronized void closeEmulation(String path) throws IOException { + synchronized void closeEmulation(final String path) throws IOException { if (!useEmulation) { - throw new IllegalStateException("closeEmulation() is called when CAPI Flash emulation is not used"); + throw new IllegalStateException("closeEmulation() is called when CAPI Flash emulation is not used"); //$NON-NLS-1$ } - FileAndCounterPair pair = files.get(path); + final FileAndCounterPair pair = files.get(path); if (pair == null) { - throw new IllegalStateException("Trying to close a non-existing CAPI Flash emulation file: " + path); + throw new IllegalStateException("Trying to close a non-existing CAPI Flash emulation file: " + path); //$NON-NLS-1$ } pair.referenceCounter--; if (pair.referenceCounter == 0) { @@ -231,10 +236,10 @@ synchronized void closeEmulation(String path) throws IOException { } private class FileAndCounterPair { - RandomAccessFile file; + final RandomAccessFile file; int referenceCounter; - FileAndCounterPair(RandomAccessFile file) { + FileAndCounterPair(final RandomAccessFile file) { this.file = file; referenceCounter = 1; } diff --git a/src/java/capiblock/com/ibm/research/capiblock/EmulatedChunk.java b/src/java/capiblock/com/ibm/research/capiblock/EmulatedChunk.java index 763e5ddc..7a4bd2a6 100644 --- a/src/java/capiblock/com/ibm/research/capiblock/EmulatedChunk.java +++ b/src/java/capiblock/com/ibm/research/capiblock/EmulatedChunk.java @@ -1,7 +1,7 @@ /* IBM_PROLOG_BEGIN_TAG * This is an automatically generated prolog. * - * $Source: src/java/capiblock/com/ibm/research/capiblock/Chunk.java $ + * $Source: src/java/capiblock/com/ibm/research/capiblock/EmulatedChunk.java $ * * IBM Data Engine for NoSQL - Power Systems Edition User Library Project * @@ -28,8 +28,8 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; /** * Emulated chunk of CAPI Flash, using RandomAccessFile @@ -73,9 +73,9 @@ public long writeBlock(final long lba, final long nBlocks, final ByteBuffer buf) buf.rewind(); buf.limit((int) nBlocks * CapiBlockDevice.BLOCK_SIZE); synchronized (inChannel) { - inChannel.write(buf, (long) lba * CapiBlockDevice.BLOCK_SIZE); + inChannel.write(buf, lba * CapiBlockDevice.BLOCK_SIZE); } - } catch (Exception ex) { + } catch (final Exception ex) { throw new IOException(ex); } synchronized (this) { @@ -106,11 +106,11 @@ public long readBlock(final long lba, final long nBlocks, final ByteBuffer buf) int oldLimit = buf.limit(); buf.limit((int) (nBlocks * CapiBlockDevice.BLOCK_SIZE)); synchronized (inChannel) { - inChannel.read(buf, (long) lba * CapiBlockDevice.BLOCK_SIZE); + inChannel.read(buf, lba * CapiBlockDevice.BLOCK_SIZE); } buf.limit(oldLimit); buf.rewind(); - } catch (Exception ex) { + } catch (final Exception ex) { throw new IOException(ex); } synchronized (this) { @@ -143,9 +143,7 @@ public Future readBlockAsync(final long lba, final long nBlocks, final Byt numAReads++; numReads--; } - CompletableFuture future = new CompletableFuture(); - future.complete(retVal); - return (Future) future; + return new EmulatedFuture(retVal); } /** @@ -171,9 +169,7 @@ public Future writeBlockAsync(final long lba, final long nBlocks, final By numAWrites++; numWrites--; } - CompletableFuture future = new CompletableFuture(); - future.complete(retVal); - return (Future) future; + return new EmulatedFuture(retVal); } /** @@ -234,4 +230,33 @@ public Stats getStats() { 0, 0, 0, 0); } + + private static class EmulatedFuture implements Future { + + private final long retVal; + + protected EmulatedFuture(final long retVal) { + this.retVal = retVal; + } + + public boolean cancel(final boolean ignored) { + return false; + } + + public Long get() { + return retVal; + } + + public Long get(final long timeout, final TimeUnit unit) { + return retVal; + } + + public boolean isCancelled() { + return false; + } + + public boolean isDone() { + return true; + } + } } diff --git a/src/java/capiblock/test/com/ibm/research/capiblock/CapiBlockDeviceTest.java b/src/java/capiblock/test/com/ibm/research/capiblock/CapiBlockDeviceTest.java index 3fe080b4..bab09364 100644 --- a/src/java/capiblock/test/com/ibm/research/capiblock/CapiBlockDeviceTest.java +++ b/src/java/capiblock/test/com/ibm/research/capiblock/CapiBlockDeviceTest.java @@ -48,10 +48,10 @@ * */ public class CapiBlockDeviceTest { - - static final String CAPI_DEVICE_PATH_PROP = "CAPI_DEVICE_PATH"; //$NON-NLS-1$ - static final String DEVICE = System.getProperty(CAPI_DEVICE_PATH_PROP, "/dev/sdc"); //$NON-NLS-1$ + static final String CAPI_DEVICE_PATH_PROP = "CAPI_DEVICE_PATH"; //$NON-NLS-1$ + + static final String DEVICE = System.getProperty(CAPI_DEVICE_PATH_PROP, "/dev/sdc"); //$NON-NLS-1$ private CapiBlockDevice cblk; @@ -73,37 +73,37 @@ private String generateString(final int len) { @Test public void testOpen() { - try (final Chunk chunk = cblk.openChunk("/dev/foo")) { //$NON-NLS-1$ + try (final Chunk chunk = cblk.openChunk("/dev/foo")) { //$NON-NLS-1$ fail(); } catch (final IOException ioe) { // expected } - - try (final Chunk chunk = cblk.openChunk("/dev/null")) { //$NON-NLS-1$ + + try (final Chunk chunk = cblk.openChunk("/dev/null")) { //$NON-NLS-1$ fail(); } catch (final IOException ioe) { // expected } - try (final Chunk chunk = cblk.openChunk(DEVICE)) { + try (final Chunk chunk = cblk.openChunk(DEVICE)) { // success } catch (final IOException ioe) { fail(ioe.getMessage()); } - - try (final Chunk chunk = cblk.openChunk(DEVICE, 0)) { + + try (final Chunk chunk = cblk.openChunk(DEVICE, 0)) { // success } catch (final IOException ioe) { fail(ioe.getMessage()); } - - try (final Chunk chunk = cblk.openChunk(DEVICE, -1)) { + + try (final Chunk chunk = cblk.openChunk(DEVICE, -1)) { fail(); } catch (final IOException ioe) { // expected } } - + public void testClose() throws IOException { final Chunk chunk = cblk.openChunk(DEVICE); @@ -112,7 +112,7 @@ public void testClose() throws IOException { } catch (final IOException ioe) { fail(ioe.getMessage()); } - + try { chunk.close(); fail(); @@ -120,11 +120,11 @@ public void testClose() throws IOException { // expected } } - + @Test public void testExceptions() throws Exception { final ByteBuffer buf = ByteBuffer.allocateDirect(4096); - try (final Chunk chunk = cblk.openChunk(DEVICE, 0)) { + try (final Chunk chunk = cblk.openChunk(DEVICE, 0)) { try { chunk.readBlock(-1, 1, buf); fail(); @@ -149,15 +149,15 @@ public void testExceptions() throws Exception { } catch (final IOException ioe) { // expected } - } + } } - + @Test public void testSynchronous() throws Exception { final Chunk chunk = cblk.openChunk(DEVICE); final String str = "THIS IS A TEST"; //$NON-NLS-1$ - + final ByteBuffer buf = ByteBuffer.allocateDirect(4096); final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(str); @@ -183,7 +183,7 @@ public void testMultipleSynchronous() throws Exception { final Chunk chunk = cblk.openChunk(DEVICE); final String str = generateString(10 * 4096); - + final ByteBuffer buf = ByteBuffer.allocateDirect(10 * 4096); final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(10, str); @@ -217,7 +217,7 @@ public void testAsynchronousRead() throws Exception { chunk.close(); assertTrue(w == 1); - + final Chunk chunk2 = cblk.openChunk(DEVICE); final ByteBuffer buf = ByteBuffer.allocateDirect(4096); @@ -231,7 +231,7 @@ public void testAsynchronousRead() throws Exception { assertTrue(f.get().longValue() == 1L); assertEquals(buffer2.unwrap(), str); } - + @Test public void testAsynchronousWrite() throws Exception { final Chunk chunk = cblk.openChunk(DEVICE); @@ -239,17 +239,17 @@ public void testAsynchronousWrite() throws Exception { final String str = "THIS IS A TEST"; //$NON-NLS-1$ final ByteBuffer buf = ByteBuffer.allocateDirect(4096); - + final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(str); final Future f = chunk.writeBlockAsync(0, 1, buffer.buf); final long w = f.get().longValue(); - + chunk.close(); - + assertTrue(w == 1); - + final Chunk chunk2 = cblk.openChunk(DEVICE); final long r = chunk2.readBlock(0, 1, buf); @@ -261,13 +261,13 @@ public void testAsynchronousWrite() throws Exception { assertTrue(r == 1); assertEquals(buffer2.unwrap(), str); } - + @Test public void testMultipleAsynchronous() throws Exception { final Chunk chunk = cblk.openChunk(DEVICE); final String str = generateString(10 * 4096); - + final ByteBuffer buf = ByteBuffer.allocateDirect(10 * 4096); final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(10, str); @@ -275,17 +275,17 @@ public void testMultipleAsynchronous() throws Exception { Future f = chunk.writeBlockAsync(5, 10, buffer.buf); final long w = f.get().longValue(); - + chunk.close(); assertTrue(w == 10); - + final Chunk chunk2 = cblk.openChunk(DEVICE); final Future f2 = chunk2.readBlockAsync(5, 10, buf); final long r = f2.get().longValue(); - + final ObjectStreamBuffer buffer2 = new ObjectStreamBuffer(buf); chunk2.close(); @@ -293,75 +293,66 @@ public void testMultipleAsynchronous() throws Exception { assertTrue(r == 10); assertEquals(buffer2.unwrap(), str); } - + @Test public void testTimeout() throws Exception { - if (!cblk.useEmulation()) { - try (final Chunk chunk = cblk.openChunk(DEVICE)) { //$NON-NLS-1$ - final String str = generateString(100 * 4096); - - final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(100, str); - - Future f = chunk.writeBlockAsync(0, 100, buffer.buf); - - f.get(1, TimeUnit.NANOSECONDS); - - fail(); - } catch (final TimeoutException te) { - // expected - } - } - - try (final Chunk chunk = cblk.openChunk(DEVICE)) { //$NON-NLS-1$ + try (final Chunk chunk = cblk.openChunk(DEVICE)) { // $NON-NLS-1$ final String str = generateString(100 * 4096); final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(100, str); Future f = chunk.writeBlockAsync(0, 100, buffer.buf); - f.get(1, TimeUnit.SECONDS); + f.get(1, TimeUnit.NANOSECONDS); + + if (!cblk.isEmulated()) { + fail(); + } } catch (final TimeoutException te) { - fail("timeout unexpected"); //$NON-NLS-1$ + // expected + if (cblk.isEmulated()) { + fail("timeout unexpected"); //$NON-NLS-1$ + } } } - + @Test public void testStatus() throws Exception { - try (final Chunk chunk = cblk.openChunk(DEVICE)) { //$NON-NLS-1$ + try (final Chunk chunk = cblk.openChunk(DEVICE)) { // $NON-NLS-1$ final Stats stats = chunk.getStats(); assertTrue(stats.blockSize == 4096); - - final String str = "test content"; //$NON-NLS-1$ + + final String str = "test content"; //$NON-NLS-1$ final ObjectStreamBuffer buffer = ObjectStreamBuffer.wrap(2, str); - + chunk.writeBlock(0, 2, buffer.buf); - + final Stats stats2 = chunk.getStats(); assertTrue(stats2.numWrites == stats.numWrites + 1); assertTrue(stats2.numBlocksWritten == stats.numBlocksWritten + 2); - + final ByteBuffer buf = ByteBuffer.allocateDirect(6 * 4096); chunk.readBlock(0, 6, buf); - + final Stats stats3 = chunk.getStats(); - + assertTrue(stats3.numReads == stats.numReads + 1); assertTrue(stats3.numBlocksRead == stats.numBlocksRead + 6); - + final Future w = chunk.writeBlockAsync(0, 2, buffer.buf); - + w.get(); - + final Stats stats4 = chunk.getStats(); assertTrue(stats4.numAWrites == stats.numAWrites + 1); assertTrue(stats4.numBlocksWritten == stats3.numBlocksWritten + 2); } } - + @Test public void testBlock() throws Exception { - try (final Chunk chunk = cblk.openChunk(DEVICE)) { //$NON-NLS-1$ + try (final Chunk chunk = cblk.openChunk(DEVICE)) { // $NON-NLS-1$ final ByteBuffer buf = ByteBuffer.allocateDirect(1); try { chunk.readBlock(0, 100, buf); diff --git a/src/java/osinfo/com/ibm/research/osinfo/CapiOSInfo.class b/src/java/osinfo/com/ibm/research/osinfo/CapiOSInfo.class index 93cc82a7090dafe5e0fd408ec037477af9fe42b5..72e034132ea4d76d1dadfd781673ae38cef072a7 100644 GIT binary patch delta 209 zcmWm9J5B;o7(n6kL!5h=+yY{ZJbj|bV;BeVy@83bv$dHRLohHTD#RU7QIP5AS%C=! zg$r;OZp1KCp07K9*4pxa|JOf&$GuIKf=!WvmcgMdSdJ40!&ilCIL8yz=%by8p~Ho+_1F)`UxqH1hAXaP86={( xG2C(&<>V!r%1$o(7EA(n5QIJV>GQoG_P!TV5}8G-)U!ymo%S-qZhVj;zX9<3B~<_b delta 233 zcmWm9%`O8`9ES1dKQeQUlS5btMSZpEb4q=G?kB>kmNugiY19xZaSL`vuRvUaT^BCE zUAPUA#yQL9w|Vn+qn{}G?sdO_EshOCOc*99YNia+%xGqP&uL1&%l$6qH5J1Gi<%|P zvSvlGs)+OCWO$(7P8&C8>HT?n*}76x^VdqUW?82uL~)#@w_Yt9Yzpe`vFgRT@ogbI zZDvo;mK}C2d+a-Dc~Kl#4mrwujj;XD%&t3iDSf_3LFB#j5nM>{)>kWzx(|bd=8v*s O>=zY`AQYSijQ<0x$SM&4