/**
*
*/
package water;
import water.api.DocGen;
import water.fvec.Frame;
import water.fvec.Vec;
import java.util.HashSet;
/**
* Short-time computation which is not a job.
*/
public abstract class Func extends Request2 {
static final int API_WEAVER = 1; // This file has auto-gen'd doc & json fields
static public DocGen.FieldDoc[] DOC_FIELDS; // Initialized from Auto-Gen code.
/** A set containing a temporary vectors which are <strong>automatically</strong> deleted when job is done.
* Deletion is by {@link #cleanup()} call. */
private transient HashSet<Key> _gVecTrash = new HashSet<Key>();
/** Local trash which can be deleted by user call.
* @see #emptyLTrash() */
private transient HashSet<Key> _lVecTrash = new HashSet<Key>();
/** Invoke this function in blocking way. */
public void invoke() {
init();
exec();
}
/** The function implementation.
* <p>It introduces blocking call which after finish of
* the function performs cleanup.
* </p><p>
* The method should not handle exceptions which it cannot handle and should let
* them to propagate to upper levels.
* </p>
*/
protected final void exec() {
try {
execImpl();
} finally {
cleanup(); // Perform job cleanup
}
}
/** The real implementation which should be provided by ancestors. */
protected void execImpl() { throw new RuntimeException("Job does not support exec call! Please implement execImpl method!"); };
/**
* Invoked before run. This is the place to checks arguments are valid or throw
* IllegalArgumentException. It will get invoked both from the Web and Java APIs.
*
* @throws IllegalArgumentException throws the exception if initialization fails to ensure
* correct job runtime environment.
*/
protected void init() throws IllegalArgumentException { }
@Override protected Response serve() {
invoke();
return Response.done(this);
}
/** Clean-up code which is executed after each {@link Job#exec()} call in any case (normal/exceptional). */
protected void cleanup() {
// Clean-up global list of temporary vectors
Futures fs = new Futures();
cleanupTrash(_gVecTrash, fs);
cleanupTrash(_lVecTrash, fs);
fs.blockForPending();
}
/** User call which empty local trash of vectors. */
protected final void emptyLTrash() {
if (_lVecTrash.isEmpty()) return;
Futures fs = new Futures();
cleanupTrash(_lVecTrash, fs);
fs.blockForPending();
}
/** Append all vectors from given frame to a global clean up list.
* If the Frame itself is in the K-V store, then trash that too.
* @see #cleanup()
* @see #_gVecTrash */
protected final void gtrash(Frame fr) { gtrash(fr.vecs()); if (fr._key != null && UKV.get(fr._key) != null) _gVecTrash.add(fr._key); }
/** Append given vector to clean up list.
* @see #cleanup()*/
protected final void gtrash(Vec ...vec) { appendToTrash(_gVecTrash, vec); }
/** Put given frame vectors into local trash which can be emptied by a user calling the {@link #emptyLTrash()} method.
* @see #emptyLTrash() */
protected final void ltrash(Frame fr) { ltrash(fr.vecs()); if (fr._key != null && UKV.get(fr._key) != null) _lVecTrash.add(fr._key); }
/** Put given vectors into local trash.
* * @see #emptyLTrash() */
protected final void ltrash(Vec ...vec) { appendToTrash(_lVecTrash, vec); }
/** Put given vectors into a given trash. */
private void appendToTrash(HashSet<Key> t, Vec[] vec) {
for (Vec v : vec) t.add(v._key);
}
/** Delete all vectors in given trash. */
private void cleanupTrash(HashSet<Key> trash, Futures fs) {
for (Key k : trash) UKV.remove(k, fs);
}
}