net.sf.mpaxs.spi.computeHost.Host.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.mpaxs.spi.computeHost.Host.java

Source

/*
 * Mpaxs, modular parallel execution system.
 * Copyright (C) 2010-2013, The authors of Mpaxs. All rights reserved.
 *
 * Project website: http://mpaxs.sf.net
 *
 * Mpaxs may be used under the terms of either the
 *
 * GNU Lesser General Public License (LGPL)
 * http://www.gnu.org/licenses/lgpl.html
 *
 * or the
 *
 * Eclipse Public License (EPL)
 * http://www.eclipse.org/org/documents/epl-v10.php
 *
 * As a user/recipient of Mpaxs, you may choose which license to receive the code
 * under. Certain files or entire directories may not be covered by this
 * dual license, but are subject to licenses compatible to both LGPL and EPL.
 * License exceptions are explicitly declared in all relevant files or in a
 * LICENSE file in the relevant directories.
 *
 * Mpaxs is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. Please consult the relevant license documentation
 * for details.
 */
package net.sf.mpaxs.spi.computeHost;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.mpaxs.api.ConfigurationKeys;
import net.sf.mpaxs.api.computeHost.IComputeHost;
import net.sf.mpaxs.api.computeHost.IRemoteHost;
import net.sf.mpaxs.api.job.IJob;
import net.sf.mpaxs.api.server.IRemoteServer;
import net.sf.mpaxs.spi.computeHost.consoleInput.Input;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author hoffmann
 */
public class Host implements IRemoteHost {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private Settings settings = null;
    private UUID authToken = null;

    @Override
    public void configure(Configuration cfg) {
        settings = new Settings(cfg);
        Logger.getLogger(Host.class.getName()).log(Level.INFO, "Running ComputeHost at IP {0}",
                settings.getLocalIp());
        File baseDir = new File(settings.getOption(ConfigurationKeys.KEY_COMPUTE_HOST_WORKING_DIR));
        try {
            //remove leftovers from previous run
            FileUtils.deleteDirectory(baseDir);
        } catch (IOException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
        }
        baseDir.mkdirs();
        settings.setOption(ConfigurationKeys.KEY_COMPUTE_HOST_ERROR_FILE,
                new File(baseDir, "error.txt").getAbsolutePath());
        settings.setOption(ConfigurationKeys.KEY_COMPUTE_HOST_OUTPUT_FILE,
                new File(baseDir, "output.txt").getAbsolutePath());
        try {
            System.setErr(new PrintStream(
                    new FileOutputStream(settings.getOption(ConfigurationKeys.KEY_COMPUTE_HOST_ERROR_FILE))));
            System.setOut(new PrintStream(
                    new FileOutputStream(settings.getOption(ConfigurationKeys.KEY_COMPUTE_HOST_OUTPUT_FILE))));
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void sendDoneJob(IJob job) {
        IRemoteServer remRef = settings.getRemoteReference();
        try {
            remRef.addDoneJob(authToken, job);
        } catch (RemoteException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Meldet diesen Host beim Masterserver an. Nach erfolgreicher Anmeldung
     * kann der Masterserver Jobs an diesen Host vergeben.
     */
    private void connectToMasterServer() {
        final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
        final long startUpAt = System.currentTimeMillis();
        final long failAfter = 5000;
        ses.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                Logger.getLogger(Host.class.getName()).log(Level.FINE,
                        "Trying to connect to MasterServer from IP " + settings.getLocalIp());
                long currentTime = System.currentTimeMillis();
                if (currentTime - startUpAt >= failAfter) {
                    Logger.getLogger(Host.class.getName()).log(Level.WARNING,
                            "Waited {0} seconds for MasterServer, shutting down ComputeHost", (failAfter / 1000));
                    System.exit(1);
                }
                try {
                    Logger.getLogger(Host.class.getName()).log(Level.FINE,
                            "Trying to bind to MasterServer at " + settings.getMasterServerIP() + ":"
                                    + settings.getMasterServerPort() + " with name: "
                                    + settings.getMasterServerName());
                    IRemoteServer remRef = (IRemoteServer) Naming.lookup("//" + settings.getMasterServerIP() + ":"
                            + settings.getMasterServerPort() + "/" + settings.getMasterServerName());
                    settings.setRemoteReference(remRef);
                    UUID hostID = remRef.addHost(authToken, settings.getName(), settings.getLocalIp(),
                            settings.getCores());
                    settings.setHostID(hostID);
                    Logger.getLogger(Host.class.getName()).log(Level.FINE, "Connection to server established!");
                    ses.shutdown();
                    try {
                        ses.awaitTermination(5, TimeUnit.SECONDS);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } catch (NotBoundException ex) {
                    Logger.getLogger(Host.class.getName()).log(Level.INFO,
                            "Master server not found, waiting for connection!");
                    //Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
                } catch (MalformedURLException ex) {
                    Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
                    System.exit(1);
                } catch (RemoteException ex) {
                    Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
                    System.exit(1);
                }
            }
        }, 1, settings.getMasterServerTimeout(), TimeUnit.SECONDS);

    }

    private void MasterServerStillAlive() {
        scheduler.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                try {
                    settings.getRemoteReference().stillAlive(authToken);

                } catch (RemoteException ex) {
                    if (!settings.getSilentMode()) {
                        Input.printErr("MasterServer is not responding!");
                        Input.printErr("This ComputeHost will shutdown now!");
                    }
                    shutdown(settings.getRemoteReference());
                }
            }
        }, settings.getMasterServerTimeout(), settings.getMasterServerTimeout(), TimeUnit.SECONDS);
    }

    /**
     * Meldet diesen Host vom Server ab.
     *
     * @return true = erfolgreich abgemeldet, false = Abmeldung fehlgeschlagen
     */
    @Override
    public boolean disconnectFromMasterServer() {
        boolean ret = false;
        try {
            ret = settings.getRemoteReference().delHost(authToken, settings.getHostID());
        } catch (RemoteException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
        }
        return ret;
    }

    /**
     * Erstellt ein RemoteObject vom Typ IRemoteHost und trgt es in die lokale
     * RMI Registry ein. ber dieses RemoteObject knnen Jobs an diesen
     * ComputeHoste gesendet werden.
     */
    private void getReadyForClients() {
        Logger.getLogger(Host.class.getName()).log(Level.FINE, "Trying to create registry at {0}:{1}",
                new Object[] { settings.getLocalIp(), settings.getLocalPort() });
        try {
            LocateRegistry.createRegistry(settings.getLocalPort());
            Logger.getLogger(Host.class.getName()).log(Level.FINE, "Started own RMI-Registry on port {0}",
                    settings.getLocalPort());
        } catch (RemoteException ex) {
            if (!settings.getSilentMode()) {
                Logger.getLogger(Host.class.getName()).log(Level.FINE, "RMI-Registry already running on port {0}.",
                        settings.getLocalPort());
                Logger.getLogger(Host.class.getName()).log(Level.FINE,
                        "ComputeHost will use the already running Registry.");
            }
        }
        try {

            // RemoteObject erstellen
            IComputeHost remObj = new ComputeHostImpl(this, settings);
            String bindString = "//" + settings.getLocalIp() + ":" + settings.getLocalPort() + "/"
                    + settings.getName();
            Logger.getLogger(Host.class.getName()).log(Level.FINE, "Trying to bind {0}", bindString);
            Naming.bind(bindString, remObj);
        } catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Meldet das RemoteObject ab und schliet danach das Programm.
     *
     * @param obj RemoteObject
     */
    @Override
    public void shutdown(Remote obj) {
        try {
            Naming.unbind("//" + settings.getLocalIp() + "/" + settings.getName());
            UnicastRemoteObject.unexportObject(obj, true);
        } catch (RemoteException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.FINE, null, ex);
            //System.out.println("one");
        } catch (NotBoundException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.FINE, null, ex);
            //System.out.println("two");
        } catch (MalformedURLException ex) {
            Logger.getLogger(Host.class.getName()).log(Level.FINE, null, ex);
            //System.out.println("three");
        }
        new Thread() {

            @Override
            public void run() {
                try {
                    sleep(settings.getTimeoutBeforeShutdown());
                } catch (InterruptedException ex) {
                    Logger.getLogger(Host.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.exit(0);
            }
        }.start();
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Logger.getLogger(Host.class.getName()).log(Level.SEVERE, "Unknown error:", e);
        System.exit(1);
    }

    @Override
    public void setAuthenticationToken(UUID authToken) {
        this.authToken = authToken;
        Logger.getLogger(Host.class.getName()).log(Level.FINE, "AuthToken for Host is: " + authToken);
    }

    @Override
    public void startComputeHost() {
        getReadyForClients();
        connectToMasterServer();
        MasterServerStillAlive();
        if (!settings.getSilentMode()) {
            new Input(this);
        }
    }

    @Override
    public UUID getAuthenticationToken() {
        return this.authToken;
    }

    @Override
    public UUID getHostId() {
        return settings.getHostID();
    }
}