Cluster Migration

To demonstrate the use of process migration and restarting we need to create a Callable instance that will execute slow enough to observe.

package jatherexample;

import jather.JatherClient;
import jather.SerializableCallable;

public class MainSlowClient
{
        public static void main(String[] args) throws Exception
        {
                JatherClient client = new JatherClient();
                String result = client.execute(new MySlowCallable(1000));
                System.out.println(result);
                client.close();
        }
}

class MySlowCallable implements SerializableCallable<String>
{
        public int number;

        public MySlowCallable(int number)
        {
                this.number = number;
        }

        public String call() throws Exception
        {
                String result = "";

                for (int i = 1; i <= number; i++)
                {
                        if (number % i == 0)
                        {
                                Thread.sleep(1000);
                                System.out.println(number + ") adding factor..." + i);
                                result+=i+",";
                        }
                }

                return result;
        }

}

Running this client we can see the same output as produced by the MainClient example, but much slower.

To see a failed process restart, run a new MainExecutive default process, then Start the MainSlowClient . You should see the process output of the slow Callable running in the executive process. When the executive process is part way through, kill the executive java process and watch the client process output. After a pause you should see the Callable execution re-start in the client process and continue to completion.

This resumption of the Callable execution is due to the group membership monitoring of the underlying JGroups framework. Once the executive process has been disconnected from the cluster, the Callable executive is re-submitted to the cluster for execution and this time is found by the only remaining cluster member running in the client process and completed.

To see the resumption of the submitted Callable by another executive, start two default MainExecutive instances in separate processes and kill the one that first executes the Callable . The execution should then resume in the second executive process.

Client local process

When the JatherClient starts executing by default, it starts a local Executive instance with a maxGroupSize of zero. The maxGroupSize is the minimum number of other cluster members (not including the client member and itself) that must be running before the Executive will execute any Callable instances.

The maxGroupSize setting of zero means that the default Executive instances will only run Callable instances if there are no other cluster members. This default Executive can be accessed from the client, and the following example removes the default executive.

package jatherexample;

import jather.JatherClient;

public class MainNoExecClient
{
        public static void main(String[] args) throws Exception
        {
                JatherClient client = new JatherClient(JatherClient.DEFAULT_CLUSTER_NAME, false);
                String result = client.execute(new MySlowCallable(1000));
                System.out.println(result);
                client.close();
        }
}

Running the MainNoExecClient instance will now produce a client that will not complete unless there is another Executive instance running.

By running the MainNoExecClient instance with no default Executive instance processes running, we can see that the client blocks. Then by starting a new default Executive instance we can see how a new Executive member added to the cluster can pickup and start executing any waiting Callable instances.