Sunday, March 31, 2013

STM, vert.x and the Pi Part 1

Given other priorities (aka 'my day job'), I'm slowly working my way through another pet project I've had for a while: adding transactions, and specifically STM, to vert.x. Of course at the moment I also try to add an influence from my other pet project, the Raspberry Pi, so I'm doing it on the Pi as much as possible. OK, it may not be the fastest machine on the block, but it's a lot of fun!

We've had STM in Narayana for a while, so I won't cover the basic again. I'm also not going to cover any Pi-related set up: by this point you should know enough to do this yourself. So let's start with cloning the most recent version of Narayana:


Make sure your path and JAVA_HOME are set so we're using JDK 7:

 
Next let's build the components we need for STM:


Don't forget that this is going to take a while, so maybe time to go grab a coffee, read a book, play with your kids, or watch an episode of Lost.


With that build complete, we've already run a lot of STM examples in the form of unit tests. However, let's take a simple example:

import java.io.IOException;

import org.jboss.stm.annotations.Transactional;
import org.jboss.stm.annotations.ReadLock;
import org.jboss.stm.annotations.WriteLock;
import org.jboss.stm.internal.RecoverableContainer;

import com.arjuna.ats.arjuna.AtomicAction;

/**
 * @author Mark Little
 */


public class Example
{  
    @Transactional
    public interface Atomic
     {
     public void change (int value) throws Exception;
       
     public void set (int value) throws Exception;
       
     public int get () throws Exception;
    }
   
    @Transactional
    public class ExampleSTM implements Atomic
     {  
        @ReadLock
     public int get () throws Exception
     {
         return state;
     }

        @WriteLock
     public void set (int value) throws Exception
     {
         state = value;
     }
       
        @WriteLock
     public void change (int value) throws Exception
     {
         state += value;
     }

     private int state;
    }
   
    public void testExample () throws Exception
    {
        RecoverableContainer theContainer = new RecoverableContainer();
        ExampleSTM basic = new ExampleSTM();
        Atomic obj = null;
       
        try
        {
        obj = theContainer.enlist(basic);
        }
        catch (final Throwable ex)
        {
        ex.printStackTrace();
           
        return;
        }
       
        AtomicAction a = new AtomicAction();
       
        a.begin();
       
        obj.set(1234);
       
        a.commit();

    System.out.println("Should get() 1234 after commit: "+obj.get());
       
        a = new AtomicAction();

        a.begin();

        obj.change(1);
       
        a.abort();

    System.out.println("Should get() 1234 after abort: "+obj.get());
    }

    public static void main (String[] args)
    {
    Example ex = new Example();

    try
    {
        ex.testExample();
    }
    catch (final Exception e)
    {
        e.printStackTrace();
    }
    }
}


Stick this at the same level of Narayana if you want to use the same CLASSPATH as here:

narayana/ext/jboss-logging.jar:narayana/ArjunaCore/arjuna/target/test-classes:narayana/common/target/common-5.0.0.M3-SNAPSHOT.jar:narayana/STM/target/core-5.0.0.M3-SNAPSHOT.jar:narayana/ArjunaCore/txoj/target/txoj-5.0.0.M3-SNAPSHOT.jar:narayana/ArjunaCore/arjuna/target/arjuna-5.0.0.M3-SNAPSHOT.jar:.

After compiling, run the example and you should see the following:


Despite what I said at the start of this entry, there's a distinct lack of vert.x involved here at the moment. That's because there are a few changes we need to make to the STM implementation to make it easier to share transactional objects between address spaces. This is all stuff that's available "natively" in TXOJ, so developers could use that API immediately. However, the STM approach simplifies a lot so once those additional features from TXOJ are integrated there, we'll have a follow up article to discuss what, how and why.

No comments: