package org.corfudb.samples;
import org.corfudb.runtime.collections.SMRMap;
import java.util.Map;
/**
* Consider again the code from {@link org.corfudb.samples::HeloCorfu.java}:
*
Integer previous = map.get("a");
if (previous == null) {
System.out.println("This is the first time we were run!");
map.put("a", 1);
}
else {
map.put("a", ++previous);
System.out.println("This is the " + previous + " time we were run!");
}
* If three program instances arrive at this code piece one after another, then the outcome would be:
"This is the first time we were run!"<br>
"... 2 time ..." <br>
"... 3 time"
*
* What if we were to execute the above code concurrently? Try it.
*
* Note that there is no need to worry about the atomicity of interleaved calls to individual Corfu-object methods,
* e.g., `map.put` and `map.get`. All Corfu-object methods are guaranteed to be atomic
* against multi-threaded programs and concurrent program instaces.
*
* However, there is no guarantee about the interleaving of `map.get` followed by `map.put`,
* when invoked from concurrent program instances. Therefore, any of the following outputs are valid:
*
* Output 1:
"... first time ..."<br>
"... first time ..."<br>
"... first time ..."
* Output 2:
"... first time ..." <br>
"... first time ..."<br>
"... 2 time ..."
* Output 3:
"... first time ..."<br>
"... 2 time ..."<br>
"... 2 time ..."
* Output 4:
"... first time ..."<br>
"... 2 time ..."<br>
"... 3 time ..."
* In order to enforce a consistent behavior, Corfu provides support for ACID transactions.
* A transaction is a body of code wrapped with `TXBegin()` and `TXEnd()`.
* For example, in the code below, we will wrap the code above with a transaction block:
corfuRuntime.getObjectsView().TXBegin();
Integer previous = map.get("a");
if (previous == null) {
System.out.println("This is the first time we were run!");
map.put("a", 1);
}
else {
map.put("a", ++previous);
System.out.println("This is the " + previous + " time we were run!");
}
corfuRuntime.getObjectsView.TXEnd();
* If we were to run three instances of this program concurrently, we would guarantee
* a **serializable** execution order. The only valid output would be
"... first time ..." <br>
"... 2 time ..." <br>
"... 3 time ..."
* Created by dalia on 12/30/16.
*/
public class SimpleAtomicTransaction extends BaseCorfuAppUtils {
/**
* main() and standard setup methods are deferred to BaseCorfuAppUtils
* @return
*/
static BaseCorfuAppUtils selfFactory() { return new SimpleAtomicTransaction(); }
public static void main(String[] args) { selfFactory().start(args); }
/**
* this method initiates activity
*/
@Override
void action() {
/**
* A Corfu Stream is a log dedicated specifically to the history of updates of one object.
* We will instantiate a stream by giving it a name "A",
* and then instantiate an object by specifying its class
*/
Map<String, Integer> map = getCorfuRuntime().getObjectsView()
.build()
.setStreamName("A") // stream name
.setType(SMRMap.class) // object class backed by this stream
.open(); // instantiate the object!
/**
* Execute an atomic transaction over the shared map.
* Inside the transaction, an application first obtains the current value of an entry "a",
* then it increments the value and replaces the map entry with the incremented value.
*/
getCorfuRuntime().getObjectsView().TXBegin();
Integer previous = map.get("a");
if (previous == null) {
System.out.println("This is the first time we were run!");
map.put("a", 1);
}
else {
map.put("a", ++previous);
System.out.println("This is the " + previous + " time we were run!");
}
getCorfuRuntime().getObjectsView().TXEnd();
/**
* If we were to run three instances of this program concurrently, we would guarantee
* a **serializable** execution order. The only valid output would be
"... first time ..." <br>
"... 2 time ..." <br>
"... 3 time ..."
*
*/
}
}