
water.Atomic Maven / Gradle / Ivy
package water;
/**
* Atomic update of a Key
*
* @author
* @version 1.0
*/
abstract public class Atomic extends DTask {
protected Key _key; // Transaction key
public Atomic(){}
public Atomic(H2O.H2OCountedCompleter completer){super(completer);}
// User's function to be run atomically. The Key's Value is fetched from the
// home STORE and passed in. The returned Value is atomically installed as
// the new Value (and the function is retried until it runs atomically). The
// original Value is supposed to be read-only. If the original Key misses
// (no Value), one is created with 0 length and wrong Value._type to allow
// the Key to passed in (as part of the Value)
abstract protected Value atomic( Value val );
/** Executed on the transaction key's home node after any successful
* atomic update. Override this if you need to perform some action after
* the update succeeds (eg cleanup).
*/
protected void onSuccess( Value old ){}
/** Block until it completes, even if run remotely */
public final T invoke( Key key ) {
RPC> rpc = fork(key);
return (T)(rpc == null ? this : rpc.get()); // Block for it
}
// Fork off
public final RPC> fork(Key key) {
_key = key;
if( key.home() ) { // Key is home?
compute2(); // Also, run it blocking/now
return null;
} else { // Else run it remotely
return RPC.call(key.home_node(),this);
}
}
// The (remote) workhorse:
@Override protected final void compute2( ) {
assert _key.home() : "Atomic on wrong node; SELF="+H2O.SELF+
", key_home="+_key.home_node()+", key_is_home="+_key.home()+", class="+getClass();
Futures fs = new Futures(); // Must block on all invalidates eventually
Value val1 = DKV.get(_key);
while( true ) {
// Run users' function. This is supposed to read-only from val1 and
// return new val2 to atomically install.
Value val2 = atomic(val1);
if( val2 == null ) break; // ABORT: they gave up
assert val1 != val2; // No returning the same Value
// Attempt atomic update
Value res = DKV.DputIfMatch(_key,val2,val1,fs);
if( res == val1 ) { // Success?
onSuccess(val1); // Call user's post-XTN function
fs.blockForPending(); // Block for any pending invalidates on the atomic update
break;
}
val1 = res; // Otherwise try again with the current value
} // and retry
_key = null; // No need for key no more, don't send it back
tryComplete();
}
@Override protected byte priority() { return H2O.ATOMIC_PRIORITY; }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy