Search in sources :

Example 11 with BMUnitConfig

use of org.jboss.byteman.contrib.bmunit.BMUnitConfig in project partyline by Commonjava.

the class TwoConcurrentReadsOnTheSameFileTest method run.

/**
 * Test that verifies concurrent reading tasks on the same file are allowable, this setup an script of events for
 * one single file, where:
 * <ol>
 *     <li>Multiple reads happen simultaneously, read the content</li>
 *     <li>Simulate reading time as 1s before stream close</li>
 *     <li>Reading processes on the same file have no interaction between each other</li>
 * </ol>
 * @throws Exception
 */
@BMRules(rules = { // setup the rendezvous for all reading threads, which will mean suspending everything until all threads are started.
@BMRule(name = "init rendezvous", targetClass = "Partyline", targetMethod = "<init>", targetLocation = "ENTRY", action = "createRendezvous(\"begin\", 2);" + "debug(\"<<<init rendezvous for begin.\")"), // setup the rendezvous to wait for all threads to be ready before proceeding.
@BMRule(name = "openInputStream start", targetClass = "Partyline", targetMethod = "openInputStream", targetLocation = "ENTRY", action = "debug(\">>>Waiting for ALL to start.\");" + "rendezvous(\"begin\");" + "debug(\"<<<\"+Thread.currentThread().getName() + \": openInputStream() thread proceeding.\" )"), // hold inputStream waiting for 1s before its close
@BMRule(name = "hold closed", targetClass = "RandomAccessJF$JoinInputStream", targetMethod = "close", targetLocation = "ENTRY", action = "debug(\">>>waiting for closed.\");" + "java.lang.Thread.sleep(1000);") })
@Test
@BMUnitConfig(debug = true)
public void run() throws Exception {
    final ExecutorService execs = Executors.newFixedThreadPool(2);
    final CountDownLatch latch = new CountDownLatch(2);
    final Partyline manager = getPartylineInstance();
    final String content = "This is a bmunit test";
    final File file = temp.newFile("file_both_read.txt");
    FileUtils.write(file, content);
    List<String> returning = new ArrayList<String>();
    for (int i = 0; i < 2; i++) {
        final int k = i;
        execs.execute(() -> {
            Thread.currentThread().setName("openInputStream-" + k);
            try (InputStream s = manager.openInputStream(file)) {
                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int read = -1;
                final byte[] buf = new byte[512];
                System.out.println(String.format("<<<concurrent reading>>> will start to read from the resource with inputStream %s", s.getClass().getName()));
                while ((read = s.read(buf)) > -1) {
                    baos.write(buf, 0, read);
                }
                baos.close();
                s.close();
                System.out.println(String.format("<<<concurrent reading>>> reading from the resource done with inputStream %s", s.getClass().getName()));
                returning.add(new String(baos.toByteArray(), "UTF-8"));
            } catch (Exception e) {
                e.printStackTrace();
                fail("Failed to open inputStream: " + e.getMessage());
            } finally {
                latch.countDown();
            }
        });
    }
    latch.await();
    assertThat(returning.get(0), equalTo(content));
    assertThat(returning.get(1), equalTo(content));
}
Also used : InputStream(java.io.InputStream) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CountDownLatch(java.util.concurrent.CountDownLatch) File(java.io.File) BMUnitConfig(org.jboss.byteman.contrib.bmunit.BMUnitConfig) Test(org.junit.Test) BMRules(org.jboss.byteman.contrib.bmunit.BMRules)

Example 12 with BMUnitConfig

use of org.jboss.byteman.contrib.bmunit.BMUnitConfig in project partyline by Commonjava.

the class ReadLockOnDerivativeDontPreventMainFileReadTest method run.

/**
 * Test that verifies concurrent reading locks on different files will not effect each other's reading process,
 * this setup an script of events for multiple files, where:
 * <ol>
 *     <li>Multiple reads happen simultaneously, read locks on distinct files/li>
 *     <li>Reading processes for different files are isolated</li>
 * </ol>
 * @throws Exception
 */
@BMRules(rules = { // wait for first openInputStream call to exit
@BMRule(name = "second openInputStream", targetClass = "Partyline", targetMethod = "openInputStream", targetLocation = "ENTRY", binding = "name:String = $1.getName()", condition = "name.equals(\"bar-1.pom\")", action = "debug(\">>>wait for service enter first openInputStream.\");" + "waitFor(\"first openInputStream\");" + "debug(\"<<<proceed with second openInputStream.\")"), // setup the trigger to signal second openInputStream when the first openInputStream exits
@BMRule(name = "first openInputStream", targetClass = "Partyline", targetMethod = "openInputStream", targetLocation = "ENTRY", binding = "name:String = $1.getName()", condition = "name.equals(\"bar-1.pom.sha1\")", action = "debug(\"<<<signalling second openInputStream.\"); " + "signalWake(\"first openInputStream\", true);" + "debug(\"<<<signalled second openInputStream.\")") })
@Test
@BMUnitConfig(debug = true)
public void run() throws Exception {
    final ExecutorService execs = Executors.newFixedThreadPool(2);
    final CountDownLatch latch = new CountDownLatch(2);
    final Partyline manager = getPartylineInstance();
    final String main = "main";
    final String derivative = "derivative";
    final File d = temp.newFolder();
    final File mFile = new File(d, "org/foo/bar/1/bar-1.pom");
    final File dFile = new File(d, "org/foo/bar/1/bar-1.pom.sha1");
    FileUtils.write(mFile, main);
    FileUtils.write(dFile, derivative);
    Map<String, String> returning = new ConcurrentHashMap<>();
    for (int i = 0; i < 2; i++) {
        final int k = i;
        execs.execute(() -> {
            File file = null;
            String name = "";
            switch(k) {
                case 0:
                    file = mFile;
                    name = main;
                    break;
                case 1:
                    file = dFile;
                    name = derivative;
                    break;
            }
            Thread.currentThread().setName(name);
            try (InputStream s = manager.openInputStream(file)) {
                returning.put(name, IOUtils.toString(s));
                s.close();
            } catch (final Exception e) {
                e.printStackTrace();
                fail("Failed to open inputStream: " + e.getMessage());
            } finally {
                latch.countDown();
            }
        });
        // make the fragile BMRule to always work
        Thread.sleep(1000);
    }
    latch.await();
    // note reporting main null error
    final String mainStream = returning.get(main);
    assertThat(mainStream, equalTo(main));
}
Also used : InputStream(java.io.InputStream) ExecutorService(java.util.concurrent.ExecutorService) CountDownLatch(java.util.concurrent.CountDownLatch) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) File(java.io.File) BMUnitConfig(org.jboss.byteman.contrib.bmunit.BMUnitConfig) Test(org.junit.Test) BMRules(org.jboss.byteman.contrib.bmunit.BMRules)

Example 13 with BMUnitConfig

use of org.jboss.byteman.contrib.bmunit.BMUnitConfig in project partyline by Commonjava.

the class JoinFileWriteTest method run.

/**
 * Test verifies JoinableFile read could be done before its write stream close
 * without any delay, this setup an script of events for one single file, where:
 * <ol>
 *     <li>Simulate JoinableFile write process </li>
 *     <li>Read should be proceeded before write stream close</li>
 * </ol>
 * @throws Exception
 */
@BMRules(rules = { // wait for read call to exit
@BMRule(name = "write close", targetClass = "RandomAccessJF", targetMethod = "close", targetLocation = "ENTRY", condition = "incrementCounter($0)==1", action = "debug(\">>>wait for service enter read.\");" + "waitFor(\"read\");" + "debug(\"<<<proceed with write close.\")"), // setup the trigger to signal write close when the read exits
@BMRule(name = "read", targetClass = "RandomAccessJF", targetMethod = "joinStream", targetLocation = "EXIT", action = "debug(\"<<<signalling write close.\"); " + "signalWake(\"read\", true);" + "debug(\"<<<signalled write close.\")") })
@Test
@BMUnitConfig(debug = true)
public void run() throws Exception {
    final ExecutorService execs = Executors.newFixedThreadPool(2);
    final CountDownLatch latch = new CountDownLatch(2);
    final File file = temp.newFile();
    String threadName = "writer" + writers++;
    final JoinableFile stream = new RandomAccessJFS().getFile(file, new LocalLockOwner(file.getAbsolutePath(), name.getMethodName(), LockLevel.write), null, true, new SignallingLock());
    execs.execute(() -> {
        Thread.currentThread().setName(threadName);
        new TimedFileWriter(stream, 0, latch).run();
    });
    execs.execute(() -> {
        Thread.currentThread().setName("reader" + readers++);
        new AsyncFileReader(0, -1, -1, stream, latch).run();
    });
    System.out.println("Waiting for " + name.getMethodName() + " threads to complete.");
    latch.await();
}
Also used : SignallingLock(org.commonjava.cdi.util.weft.SignallingLock) RandomAccessJFS(org.commonjava.util.partyline.impl.local.RandomAccessJFS) TimedFileWriter(org.commonjava.util.partyline.fixture.TimedFileWriter) ExecutorService(java.util.concurrent.ExecutorService) JoinableFile(org.commonjava.util.partyline.spi.JoinableFile) CountDownLatch(java.util.concurrent.CountDownLatch) LocalLockOwner(org.commonjava.util.partyline.lock.local.LocalLockOwner) File(java.io.File) JoinableFile(org.commonjava.util.partyline.spi.JoinableFile) BMUnitConfig(org.jboss.byteman.contrib.bmunit.BMUnitConfig) Test(org.junit.Test) BMRules(org.jboss.byteman.contrib.bmunit.BMRules)

Example 14 with BMUnitConfig

use of org.jboss.byteman.contrib.bmunit.BMUnitConfig in project partyline by Commonjava.

the class ConcurrentFirstReaderTest method run.

/**
 * GIVEN:
 * <ol>
 *     <li>File exists on disk</li>
 *     <li>File is not opened for reading or writing</li>
 *     <li>The underlying filesystem is slow to respond to lock requests on FileChannel</li>
 * </ol>
 * <br/>
 * WHEN:
 * <ol>
 *     <li>Two reader threads attempt to open the file at the same time</li>
 * </ol>
 * <br/>
 * THEN:
 * <ol>
 *     <li>One reader thread should "win" and be the first to open the file</li>
 *     <li>The other reader thread should "join" that first thread's open file</li>
 *     <li>No OverlappingFileLockException should be thrown</li>
 * </ol>
 * @throws Exception
 */
/*@formatter:off*/
@BMRules(rules = { // setup a rendezvous to control thread execution
@BMRule(name = "init rendezvous", targetClass = "FileTree", targetMethod = "<init>", targetLocation = "ENTRY", action = "createRendezvous(\"begin\", 2);" + "debug(\"<<<init rendezvous for begin.\")"), // sync up to reduce chances of missing the race condition for the opLock.lock() control.
@BMRule(name = "sync FileTree.setOrJoin", targetClass = "FileTree", targetMethod = "setOrJoinFile", targetLocation = "ENTRY", action = "debug(\"Rendezvous read operations.\"); " + "rendezvous(\"begin\"); " + "debug(\"Continue read operations.\");"), // When we try to init a new JoinableFile for INPUT, simulate an IOException from somewhere deeper in the stack.
@BMRule(name = "new JoinableFile lock delay", targetClass = "RandomAccessJF", targetMethod = "<init>", targetLocation = "ENTRY", action = "debug(\"Delaying JoinableFile.init. Lock is: \" + $5); " + "Thread.sleep(500);" + "debug( \"Resuming lock operation.\" );") })
/*@formatter:on*/
@BMUnitConfig(debug = true)
@Test
public void run() throws Exception {
    // let's get some serious data going.
    byte[] bytes = new byte[1024 * 1024 * 2];
    Random rand = new Random();
    rand.nextBytes(bytes);
    final ExecutorService execs = Executors.newFixedThreadPool(2);
    final File f = temp.newFile("child.bin");
    FileUtils.writeByteArrayToFile(f, bytes);
    final CountDownLatch latch = new CountDownLatch(2);
    final Partyline manager = getPartylineInstance();
    manager.startReporting(5000, 5000);
    for (int i = 0; i < 2; i++) {
        final int k = i;
        execs.execute(reader(k, manager, f, latch, true));
    }
    latch.await();
}
Also used : Random(java.util.Random) ExecutorService(java.util.concurrent.ExecutorService) CountDownLatch(java.util.concurrent.CountDownLatch) File(java.io.File) BMUnitConfig(org.jboss.byteman.contrib.bmunit.BMUnitConfig) Test(org.junit.Test) BMRules(org.jboss.byteman.contrib.bmunit.BMRules)

Example 15 with BMUnitConfig

use of org.jboss.byteman.contrib.bmunit.BMUnitConfig in project partyline by Commonjava.

the class JoinFileWriteJustBeforeFinishedTest method run.

/**
 * Test verifies JoinableFile read could be done before its write stream close
 * with read init delay, this setup an script of events for one single file, where:
 * <ol>
 *     <li>Simulate JoinableFile write process </li>
 *     <li>Read should be proceeded before write stream close</li>
 * </ol>
 * @throws Exception
 */
@BMRules(rules = { // wait for read call to exit
@BMRule(name = "write close", targetClass = "RandomAccessJF", targetMethod = "close", targetLocation = "ENTRY", condition = "incrementCounter($0)==1", action = "debug(\">>>wait for service enter read.\");" + "waitFor(\"read\");" + "debug(\"<<<proceed with write close.\")"), // setup the trigger to signal write close when the read exits
@BMRule(name = "read", targetClass = "RandomAccessJF", targetMethod = "joinStream", targetLocation = "EXIT", action = "debug(\"<<<signalling write close.\"); " + "signalWake(\"read\", true);" + "debug(\"<<<signalled write close.\")") })
@Test
@BMUnitConfig(debug = true)
public void run() throws Exception {
    final ExecutorService execs = Executors.newFixedThreadPool(2);
    final CountDownLatch latch = new CountDownLatch(2);
    final File file = temp.newFile();
    String threadName = "writer" + writers++;
    final JoinableFile stream = new RandomAccessJFS().getFile(file, new LocalLockOwner(file.getAbsolutePath(), name.getMethodName(), LockLevel.write), null, true, new SignallingLock());
    execs.execute(() -> {
        Thread.currentThread().setName(threadName);
        new TimedFileWriter(stream, 1, latch).run();
    });
    execs.execute(() -> {
        Thread.currentThread().setName("reader" + readers++);
        new AsyncFileReader(1000, -1, -1, stream, latch).run();
    });
    System.out.println("Waiting for " + name.getMethodName() + " threads to complete.");
    latch.await();
}
Also used : SignallingLock(org.commonjava.cdi.util.weft.SignallingLock) RandomAccessJFS(org.commonjava.util.partyline.impl.local.RandomAccessJFS) TimedFileWriter(org.commonjava.util.partyline.fixture.TimedFileWriter) ExecutorService(java.util.concurrent.ExecutorService) JoinableFile(org.commonjava.util.partyline.spi.JoinableFile) CountDownLatch(java.util.concurrent.CountDownLatch) LocalLockOwner(org.commonjava.util.partyline.lock.local.LocalLockOwner) File(java.io.File) JoinableFile(org.commonjava.util.partyline.spi.JoinableFile) BMUnitConfig(org.jboss.byteman.contrib.bmunit.BMUnitConfig) Test(org.junit.Test) BMRules(org.jboss.byteman.contrib.bmunit.BMRules)

Aggregations

File (java.io.File)15 BMUnitConfig (org.jboss.byteman.contrib.bmunit.BMUnitConfig)15 Test (org.junit.Test)15 BMRules (org.jboss.byteman.contrib.bmunit.BMRules)13 CountDownLatch (java.util.concurrent.CountDownLatch)12 ExecutorService (java.util.concurrent.ExecutorService)12 JoinableFile (org.commonjava.util.partyline.spi.JoinableFile)5 SignallingLock (org.commonjava.cdi.util.weft.SignallingLock)4 TimedFileWriter (org.commonjava.util.partyline.fixture.TimedFileWriter)4 RandomAccessJFS (org.commonjava.util.partyline.impl.local.RandomAccessJFS)4 LocalLockOwner (org.commonjava.util.partyline.lock.local.LocalLockOwner)4 InputStream (java.io.InputStream)3 ArrayList (java.util.ArrayList)3 IOException (java.io.IOException)2 OutputStream (java.io.OutputStream)2 LinkedHashMap (java.util.LinkedHashMap)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 Closeable (java.io.Closeable)1 WeakReference (java.lang.ref.WeakReference)1 Map (java.util.Map)1