Menu

Concepts

ENGITEX

Concepts

Everything can be also found in com.company.RunSample class. The first and the easy part is about running a piece of Java code on a separate process locally with a possibility to explicitly set its CPU affinity.
More complex approach is to start JMP node either on a local or remote machine. In this case the node will handle load balancing not only between its CPUs but between its "slave" nodes as well.

1. Single process without a node
A new process can be started in three different ways. The first one starts a single process on a local (or remote) machine with a possibility to assign CPUs that will be used by the process. For this an object of ProcessInvocatorclass has to be created:
ProcessInvocator pi = new ProcessInvocator(RunnableWrapper rw, String ip_string_or_null_if_local, char[] affinityCPU);

RunnableWrapper rw contains the piece of code in its run() method that should be run in a separate process.

Next a process is started asynchronously:
pi.start();

A process will terminate itself after run() has completed.
To start a process on a remote machine, that machine should be made part of a cluster, i.e. a node must be started on it. A node concept is described below.

2. Processes on a node
Another two ways start a process on a running node (local or remote) which is always a seprate process itself. Hence a node must be started before any process is assigned to it. A node will handle load balancing not only between its own CPUs but between its "slave" nodes as well.
Like RMI registry having one instance at a time on a given machine and always taking port 1099, only one node can be running on a machine. It always takes port 3740.

A node monitors:
a. Processes running locally on the machine that have been started through this node.
b. Processes running on remote (child) nodes on other machines.
The node knows nothing about other processes running on a machine outside of the node - this must be kept in mind when designing a distributed system.

A node implements some kind of load distribution policy between available resources on local machine and on remote (child) nodes.
Node X handles and assigns tasks on its own and node X caller, be it a user or a parent node, does not have to deal with load distribution within the scope of node X.
Obviously a node is always started locally, just like RMI registry.
First, Node constructor must be called. If it is a local node and it has not been started yet, it can be started right from the code with start() method.

// local node
Node nodeLoc = new Node();
try {
    nodeLoc.start(); // this is only needed when local node is not already running on the PC
}
catch (SystemProcessException spe) {
    System.out.println(spe.getMessage());
}

// remote node
Node nodeRem = new Node(ip); // no need to call start() on a remote node since it must have already been started

Starting a node from terminal in a separate window:
java org.engitex.JMP.StartNodeAdminPanel -v
This a more advanced way of working with a node which allows more user control over node settings.
Read more about running a node from terminal here:
[Node admin panel]

Then processes can be started on it:

// constructor: ProcessInvocator(RunnableWrapper rw, String taskName, Node node);
ProcessInvocator pi1 = new ProcessInvocator(rw1, taskName1, node);
pi1.start();
ProcessInvocator pi2 = new ProcessInvocator(rw2, taskName2, node);
pi2.start();

Another way to start a process on remote node is:

ProcessInvocator pi = new ProcessInvocator(rw, taskName, nodeRemIP);
pi.start();

A node will terminate itself either when the process that started the node has terminated (no matter if it has been a normal exit or a crash) or upon
node.stop();

Remember that a node should never be stopped while there are active processes running on it.

3. Get data from a process

Both a process started "directly" and a process running on a node allow deta retrieval as also shown in com.company.RunSample.
Current state of a process can be checked with methods:

boolean ProcessData.isError();
boolean ProcessData.isStarted();
boolean ProcessData.isFinished();

Usually it makes sense to set data members of ProcessData after the task is finished.
Hence any data of interest can be retrieved like this:

ProcessData pd = pi.getProcessData(null); // has to provide a null argument here
if (pd.isFinished()) {
               // do the casting only if the process is finished!
               System.out.println("my task result is " + ((MyCustomProcessData)pd).myCustomDataMemberName);
 }

The same data can be obtained via a Node object rather than via ProcessInvocator in case the process has been started on remote node:
ProcessData pd = n.getProcessData(taskName);


Related

Wiki: Examples of use cases
Wiki: Node admin panel
Wiki: Overview

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.