package hex.createframe;
import water.H2O;
import water.Iced;
import water.Job;
import water.Key;
import water.fvec.Frame;
import water.util.Log;
import java.util.Random;
/**
* Base class for all frame creation recipes.
*/
public abstract class CreateFrameRecipe<T extends CreateFrameRecipe<T>> extends Iced<T> {
public Key<Frame> dest;
public long seed = -1;
//--------------------------------------------------------------------------------------------------------------------
// Inheritance interface
//--------------------------------------------------------------------------------------------------------------------
/**
* Test whether the input parameters are valid, and throw error if they
* aren't. You may use the {@link #check(boolean, String)} helper function
* to make this somewhat easier.
*/
protected abstract void checkParametersValidity();
/**
* Set up the provided {@link CreateFrameExecutor} so that it knows how to
* construct the frame corresponding to the recipe being built.
*/
protected abstract void buildRecipe(CreateFrameExecutor cfe);
//--------------------------------------------------------------------------------------------------------------------
// Other
//--------------------------------------------------------------------------------------------------------------------
/**
* This function will be called by the REST API handler to initiate making
* of the recipe. It returns a {@link Job} which will hold the created frame
* once it is finished.
*/
public Job<Frame> exec() {
fillMissingParameters();
Job<Frame> job = new Job<>(dest, Frame.class.getName(), "CreateFrame:original");
CreateFrameExecutor cfe = new CreateFrameExecutor(job);
checkParametersValidity();
buildRecipe(cfe);
checkParametersValidity2(cfe);
return job.start(cfe, cfe.workAmount());
}
/**
* Resolve parameter values that cannot be initialized to static defaults.
* If you're overriding this method, please make sure to invoke the super
* implementation as well.
*/
protected void fillMissingParameters() {
if (dest == null) {
dest = Key.make();
}
if (seed == -1) {
seed = new Random().nextLong();
Log.info("Generated seed: " + seed);
}
}
/**
* Final step of parameter testing, after the {@link CreateFrameExecutor}
* has been set up, but just before the actual frame creation commences.
* This method shall only be used to perform checks that cannot be done
* without the {@link CreateFrameExecutor} instance.
*/
protected void checkParametersValidity2(CreateFrameExecutor cfe) {
long byteEstimate = cfe.estimatedByteSize();
long clusterFreeMem = H2O.CLOUD.free_mem();
double gb = (double) (1 << 30);
check(byteEstimate <= clusterFreeMem,
String.format("Frame is expected to require %.3fGb, which will not fit into H2O's free memory of %.3fGb",
byteEstimate/gb, clusterFreeMem/gb));
}
/** Simple helper function for parameter testing. */
protected void check(boolean test, String msg) {
if (!test) throw new IllegalArgumentException(msg);
}
}