JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net

The open source
grid computing

 Home   About   Features   Download   Documentation   On Github   Forums 

Execution Policies

From JPPF 4.2 Documentation

Jump to: navigation, search


Main Page > Development guide > Execution Policies

An execution policy is an object that determines whether a particular set of JPPF tasks can be executed on a JPPF node (for the server-side SLA) or if it can be sent via a communication channel (for the client-side). It does so by applying the set of rules (or tests) it is made of, against a set of properties associated with the node or channel.

These properties include:

  • JPPF configuration properties
  • System properties (including -D*=* properties specified on the JVM command line)
  • Environment variables (e.g. PATH, JAVA_HOME, etc.)
  • Networking: list of ipv4 and ipv6 addresses with corresponding host name when it can be resolved
  • Runtime information such as maximum heap memory, number of available processors, etc...
  • Disk space and storage information
  • A special boolean property named “” which indicates whether a node (server-side) or communication channel (client-side) is local to the JPPF server or client, respectively.

The kind of tests that can be performed apply to the value of a property, and include:

  • Binary comparison operators: ==, <, <=, >, >= ; for instance: property_value <= 15
  • Range operators (intervals): property_value in [a,b] , [a,b[ , ]a,b] , ]a,b[
  • "One of" operator (discrete sets): property_value in { a1, ... , aN }
  • "Contains string" operator: property_value contains "substring"
  • Regular expressions: property_value matches 'regexp'
  • Custom, user-defined tests

The tests can also be combined into complex expressions using the boolean operators NOT, AND, OR and XOR.

Using this mechanism, it is possible to write execution policies such as:

  • "Execute on a node only if the node has at least 256 MB of memory and at least 2 CPUs available"
  • “Execute the job only in the client's local executor”

In the context of a server-side SLA, an execution policy is sent along with the tasks to the JPPF driver, and evaluated by the driver. They do not need to be sent to the nodes.

For a detailed and complete description of all policy elements, operators and available properties, please refer to the chapter Appendix B: Execution policy reference.

1 Creating and using an execution policy

An execution policy is an object whose type is a subclass of ExecutionPolicy. It can be built in 2 ways:

By API, using the classes in the org.jppf.node.policy package.


// define a policy allowing only nodes with 2 processing threads or more
ExecutionPolicy atLeast2ThreadsPolicy = new AtLeast("jppf.processing.threads", 2);
// define a policy allowing only nodes that are part of the ""
// internet domain (case ignored)
ExecutionPolicy myDomainPolicy =
  new Contains("ipv4.addresses", true, "");
// define a policy that requires both of the above to be satisfied
ExecutionPolicy myPolicy = atLeast2ThreadsPolicy.and(myDomainPolicy);

Alternatively, this could be written in a single statement:

// define the same policy in one statement
ExecutionPolicy myPolicy = new AtLeast("jppf.processing.threads", 2).and(
  new Contains("ipv4.addresses", true, ""));

Using an XML policy document:

Example XML policy:

  <!-- define a policy that requires both rules to be satisfied -->
    <!-- define a policy allowing only nodes with 2 processing threads or more -->
    <!-- allow only nodes in the "" internet domain (case ignored) -->
    <Contains ignoreCase="true">

As you can see, this is the exact equivalent of the policy we constructed programmatically before.

To transform this XML policy into an ExecutionPolicy object, we will have to parse it using the PolicyParser API, by the means of one of the following methods:

static ExecutionPolicy parsePolicy(String)      // parse from a string
static ExecutionPolicy parsePolicyFile(String)  // parse from a file
static ExecutionPolicy parsePolicy(File)        // parse from a file
static ExecutionPolicy parsePolicy(Reader)      // parse from a Reader
static ExecutionPolicy parsePolicy(InputStream) // parse from an InputStream

Example use:

// parse the specified XML file into an ExecutionPolicy object
ExecutionPolicy myPolicy = PolicyParser.parsePolicyFile("../policies/MyPolicy.xml");

It is also possible to validate an XML execution policy against the JPPF Execution Policy schema using one of the validatePolicy() methods of PolicyParser:

static ExecutionPolicy validatePolicy(String)      // validate from a string
static ExecutionPolicy validatePolicyFile(String)  // validate from a file
static ExecutionPolicy validatePolicy(File)        // validate from a file
static ExecutionPolicy validatePolicy(Reader)      // validate from a Reader
static ExecutionPolicy validatePolicy(InputStream) // validate from an InputStream

To enable validation, the document's namespace must be specified in the root element:

<jppf:ExecutionPolicy xmlns:jppf="">

Example use:

public ExecutionPolicy createPolicy(String policyPath) {
  try {
    // validate the specified XML file
  } catch(Exception e) {
    // the validation and parsing errors are in the exception message
    System.err.println("The execution policy " + policyPath +
      " is not valid: " + e.getMessage());
   return null;
  // the policy is valid, we can parse it safely
  return PolicyParser.parsePolicyFile(policyPath);

2 Scripted policies

As we have seen earlier, execution policies are objects whose class extends ExecutionPolicy. The evaluation of an execution policy is performed by calling its accepts() method, which returns either true or false. A scripted policy is a special type of policy which can execute a script written in a script language. The result of the evaluation of this script, which must be a boolean, will be the value returned by its accept() method.

By default, JPPF provides engines for Groovy and JavaScript with the Rhino engine, however additional script languages can be added via the service provider interface (SPI).

2.1 Creating scripted policies

At runtime, a scripted policy is an instance of ScriptedPolicy, which defines the following constructors:

public class ScriptedPolicy extends ExecutionPolicy {
  // create with a script read from a string
  public ScriptedPolicy(String language, String script)

  // create with a script read from a reader
  public ScriptedPolicy(String language, Reader scriptReader) throws IOException

  // create with a script read from a file
  public ScriptedPolicy(String language, File scriptFile) throws IOException

The equivalent XML is as follows:

<Script language="_language_">simple script</Script>

<Script language="_language_"><![CDATA[
  a more complex
  script here

As for any other execution policy predicate, scripted policies can be combined with other predicates, using the logical operators AND, OR, XOR and NOT, for instance:

// Java
ExecutionPolicy policy = new AtLeast("processing.threads", 2).and(
  new ScriptedPolicy("groovy", "return true"));

<!-- XML equivalent -->
  <Equal valueType="numeric">
  <Script language="groovy">return true</Script>

The script must either be an expression which resolves to a boolean value, or return a boolean value. For instance, the Groovy statement “return true” and the Groovy expression “true” will work seamlessly.

2.2 Predefined variable bindings

6 pre-defined variables are made available to the scripts:

  • jppfSystemInfo: the parameter passed to the policy's accepts() method, its type is JPPFSystemInformation
  • jppfSla: the server-side SLA of the job being matched, if available, of type JobSLA
  • jppfClientSla: the client-side SLA of the job being matched, if available, of type JobClientSLA
  • jppfMetadata: the metadata of the job being matched, if available, of type JobMetadata
  • jppfDispatches: the number of nodes the job is already disatched to, of type int
  • jppfStats: the server statistics, of type JPPFStatistics

For example, let's look at the following JavaScript script, which determines the node participation based on a jobs priority: if the priority is 1 or less, the job can use no more than 10% of the total number of nodes, if the job priority is 2 then if can use no more than 20%, … up to 90% if the priority is 9 or more:

function accepts() {
  // total nodes in the grid from the server statistics
  var totalNodes = jppfStats.getSnapshot("nodes").getLatest();
  // the job priority
  var prio = jppfSla.getPriority();
  // determine max allowed nodes for the job, as % of total nodes
  var maxPct = (prio <= 1) ? 0.1 : (prio >= 9 ? 0.9 : prio / 10.0);
  // return true if current nodes for the job is less than max %
  return jppfDispatches < totalNodes * maxPct;

// returns a boolean value

Let's say this script is stored in a file located at ./policies/NodesFromPriority.js, we could then create an execution policy out of it, with the following code:

ScriptedPolicy policy =
  new ScriptedPolicy("javascript", new File("policies/NodesFromPriority.js"));

2.3 Adding available languages

The JPPF scripting APIs rely entirely on the JSR 223 specification, which is implemented in the JDK's javax.script package. This means that JPPF will be able to use any script language made available to the JVM, including the default JavaScript engine (i.e. Rhino in JDK 7 and Nashorn in JDK 8).

Thus to add a new language, all that is needed is to add the proper jar files, which declare a JSR-223 compliant script engine via the documented SPI discovery mechanism. For example, you can add the Groovy language by simply adding groovy-all-x.y.z.jar to the classpath, because it implements the JSR 223 specification (the jar file is located in the JPPF source distribution at JPPF/lib/Groovy/groovy-all-1.6.5.jar).

3 Creating custom policies

It is possible to apply user-defined policies. When you do so, a number of constraints must be respected:

  • the custom policy class must extend CustomPolicy
  • the custom policy class must be deployed in the JPPF server classpath as well as the client's

Here is a sample custom policy code:

package mypackage;
import org.jppf.utils.PropertiesCollection;
import org.jppf.node.policy.CustomPolicy;

// define a policy allowing only nodes with 2 processing threads or more
public class MyCustomPolicy extends CustomPolicy {
  public boolean accepts(PropertiesCollection info) {
    // get the value of the "processing.threads" property
    String s = this.getProperty(info, "processing.threads");
    int n = -1;
    try { n = Integer.valueOf(s); }
    catch(NumberFormatException e) { // process the exception }
  // node is accepted only if number of threads >= 2
  return n >= 2;

Now, let's imagine that we want our policy to be more generic, and to accept nodes with at least a parametrized number of threads given as argument to the policy.

Our policy becomes then:

public class MyCustomPolicy extends CustomPolicy {
  public MyCustomPolicy(String...args) { super(args); }

  public boolean accepts(PropertiesCollection info) {
    // get the value to compare with, passed as the first argument to this policy
    String s1 = getArgs()[0];
    int param = -1;
    try { param = Integer.valueOf(s1); }
    catch(NumberFormatException e) { }
    String s2 = getProperty(info, "processing.thread");
    int n = -1;
    try { n = Integer.valueOf(s2); }
    catch(NumberFormatException e) { }
    // node is accepted only if number of threads >= param
    return n >= param;

Here we use the getArgs() method which returns an array of strings, corresponding to the arguments passed in the XML representation of the policy.

To illustrate how to use a custom policy in an XML policy document, here is an example XML representation of the custom policy we created above:

<CustomRule class="mypackage.MyCustomPolicy">

The "class" attribute is the fully qualified name of the custom policy class. There can be any number of <Arg> elements, these are the parameters that will then be accessible through CustomPolicy.getArgs().

When the XML descriptor is parsed, an execution policy object will be created exactly as in this code snippet:

MyCustomPolicy policy = new MyCustomPolicy();
policy.setArgs( "3" );

Finally, to enable the use of this custom policy, you will need to add the corresponding class(es) to both the server's and the client's classpath, within either a jar file or a class folder.

Main Page > Development guide > Execution Policies

JPPF Copyright © 2005-2020 Powered by MediaWiki