com.symbian.driver.remoting.master.MasterRemoteImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.symbian.driver.remoting.master.MasterRemoteImpl.java

Source

/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

package com.symbian.driver.remoting.master;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.cli.ParseException;

import com.symbian.driver.core.environment.TDConfig;
import com.symbian.driver.remoting.client.ClientRemote;
import com.symbian.driver.remoting.client.TestJob;
import com.symbian.utils.Utils;

/**
 * RMI Remote Master class implementation.
 * 
 * @author EngineeringTools
 */
public final class MasterRemoteImpl extends UnicastRemoteObject implements MasterRemote {

    /** Serialised UID. */
    private static final long serialVersionUID = -3537075333900856492L;

    /**   the chunk size is 16k to retrieve remote file */
    private static final int TRANSFER_LENGTH = 1024 * 16;
    /** queued executor */
    private final QueuedExecutor executorQueue;

    /** a Job Counter */
    private final JobCounter jobCounter;

    /** a Job Folder */
    private final String jobsFolder;

    /** Logger for this class. */
    protected final static Logger LOGGER = Logger.getLogger(MasterRemoteImpl.class.getName());

    /**
     * Standard Constructor. It starts the execution queue.
     * 
     * @param aJobsFolder
     *            String : a folder wehere to store the jobs.
     * @param aJobCounter
     *            JobCounter : a job counter object.
     * @param aExecutorQueue
     *            QueuedExecutor : an execution queue.
     * @throws RemoteException
     */
    public MasterRemoteImpl(String aJobsFolder, JobCounter aJobCounter, QueuedExecutor aExecutorQueue)
            throws RemoteException {
        super();
        jobsFolder = aJobsFolder;
        jobCounter = aJobCounter;
        executorQueue = aExecutorQueue;
        executorQueue.start();
    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#queryMasterStatus()
     * @return String : a message conating the status of master 'busy' or 'free'
     *         and the number of jobs in the queue.
     */
    public String queryMasterStatus() {
        int noOfQueuedJobs = executorQueue.count();
        boolean jobRunning = JobTracker.isState(TestJob.EXECUTING);

        return ("Master: TestDriver is currently " + ((jobRunning) ? "busy" : "free") + " and there are "
                + ((noOfQueuedJobs < 1) ? "no" : String.valueOf(noOfQueuedJobs)) + " jobs waiting in the queue.");
    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#register(java.lang.String,
     *      com.symbian.driver.remoting.client.ClientRemote)
     */
    public void register(String aClientName, ClientRemote aClientRemote) {
        ClientRegister.register(aClientName, aClientRemote);
        ClientRegister.getInstance().takeSnapshot();
    }

    public boolean isRegistered(String aClientName) {
        return ClientRegister.isRegistered(aClientName);
    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#submitJob(com.symbian.driver.remoting.client.TestJob)
     */
    public int submitJob(TestJob aTestJob) throws RemoteException {
        // Assign a job id.
        jobCounter.increment();
        jobCounter.takeSnapshot(); // Need to take a snapshot at this point.
        int lTestJobId = jobCounter.get();
        aTestJob.setId(lTestJobId);

        // Add state of this job to the tracker.
        JobTracker.add(aTestJob.getId(), aTestJob.getState());

        // Create the folder for caching the files based on the testJobId.
        File lTargetFolder = new File(jobsFolder + File.separator + lTestJobId + File.separator + "Input");

        try {
            lTargetFolder.mkdirs();
        } catch (SecurityException lSE) {
            LOGGER.log(Level.SEVERE,
                    "Master: Unable to create input folder " + lTargetFolder + " for job " + lTestJobId + ".", lSE);
            throw new RemoteException("Master having problems creating the job input folder.");
        }

        // Cache the test package and image into the appropriate location.
        aTestJob.setTargetFolder(lTargetFolder.getAbsolutePath());
        boolean ret = getRemoteFile(aTestJob);
        if (!ret) {
            throw new RemoteException("Master having problems caching the files sent with the job.");
        }

        // Create the folder for the results based on the testJobId.
        File lResultsFolder = new File(jobsFolder + File.separator + lTestJobId + File.separator + "Output");
        try {
            lResultsFolder.mkdirs();
        } catch (SecurityException lSE) {
            LOGGER.log(Level.SEVERE, "Master: Unable to create output folder for job " + lTestJobId + ".", lSE);
            throw new RemoteException("Master having problems creating the job results folder.");
        }

        // Set the results folder. Needed by testwrapper.
        aTestJob.setResultsFolder(lResultsFolder.getAbsolutePath());

        // Add job to the executor queue.
        executorQueue.queueJob(aTestJob);

        return lTestJobId; // if successfully submitted return job id else if
        // failed exception would have been thrown.
    }

    /**
     * get package file from client remotely in multiple calls
     * @return
     */
    private boolean getRemoteFile(TestJob job) {
        //lookup client remote inteface
        String clientName = job.getRegistrationId();
        ClientRemote clientRemote = ClientRegister.getClient(clientName);

        String remoteFileName = job.getSourceFolder() + File.separator + job.getTestPackageName();
        String targetFile = job.getTagetFolder() + File.separator + job.getTestPackageName();

        //read file from remote in multiple calls to avoid OutOfMem if pass large file in memory at once. 
        BufferedOutputStream out = null;
        try {
            File testpackage = new File(targetFile);
            out = new BufferedOutputStream(new FileOutputStream(testpackage));
            byte[] data = null;
            long pos = 0;
            while ((data = clientRemote.readFile(remoteFileName, pos, TRANSFER_LENGTH)) != null) {

                out.write(data, 0, data.length);
                out.flush();
                pos += data.length;
            }
            LOGGER.log(Level.INFO, "received remote file:" + remoteFileName);
            LOGGER.log(Level.INFO, "  saved to :" + targetFile + " file size:" + testpackage.length());
            return true;
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "Master: Unable to retrive remote package file " + job.getId() + ".", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ioe) {
                }
                out = null;
            }
        }

        return false;
    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#queryJobStatus(int)
     */
    public String queryJobStatus(int aTestJobId) {
        boolean lTrackable = false;
        String lStatus = null;

        if ((JobTracker.isTrackable(aTestJobId))) {
            lStatus = JobTracker.queryStatus(aTestJobId);
            if (lStatus != null) {
                lTrackable = true;
            }
        }

        return (lTrackable) ? "Master: The current state of job " + aTestJobId + " is " + lStatus + "."
                : "Master: Job " + aTestJobId + " does not exist.";

    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#terminateJob(int)
     */
    public String terminateJob(int aTestJobId) {
        boolean lTerminated = false;
        String lStatus = null;
        String lNotTerminateMessage = " ";

        if ((JobTracker.isTrackable(aTestJobId))) {
            lStatus = JobTracker.queryStatus(aTestJobId);
            if (lStatus.equals(TestJob.WAITING)) {
                //de-queue
                TestJob testJob = executorQueue.removeJob(aTestJobId);
                if (testJob != null) {
                    if (ClientRegister.isRegistered(testJob.getRegistrationId())) {
                        ClientRegister.deregister(testJob.getRegistrationId());
                    }
                    lTerminated = true;
                }
            } /*else if(lStatus.equals(TestJob.EXECUTING)){
               // stop it.
               TestJob testJob = executorQueue.killJob(aTestJobId);
               if (testJob != null) {
                  if (ClientRegister.isRegistered(testJob.getRegistrationId())) {
                ClientRegister.deregister(testJob.getRegistrationId());
                  }
                  lTerminated = true;
               }
              }*/ else {
                lNotTerminateMessage = "Current state of job " + aTestJobId + " is " + lStatus
                        + ", so it cannot be terminated.";
            }
        } else {
            lNotTerminateMessage = "Job " + aTestJobId + " does not exist.";
        }

        return (lTerminated) ? "Master: Job " + aTestJobId + " has been removed sucessfully."
                : "Master: " + lNotTerminateMessage;
    }

    /**
     * 
     * @see com.symbian.driver.remoting.master.MasterRemote#getResults(int)
     */
    public TestResultSet getResults(int aTestJobId) throws RemoteException {
        String lStatus = null;
        TestResultSet lTestResultSet = null;

        if ((JobTracker.isTrackable(aTestJobId))) {
            lStatus = JobTracker.queryStatus(aTestJobId);
            if ((lStatus.equals(TestJob.COMPLETED)) || (lStatus.equals(TestJob.FAILED))) {
                try {
                    lTestResultSet = new TestResultSet(new Integer(aTestJobId));
                    lTestResultSet.Embed();
                } catch (IOException lE) {
                    LOGGER.log(Level.SEVERE,
                            "Master: Failed to send results for job " + aTestJobId + " on a client request.", lE);
                    throw new RemoteException(lE.getMessage());
                } catch (ParseException lE) {
                    LOGGER.log(Level.SEVERE, "Master: Error reading Preferences.", lE);
                    throw new RemoteException(lE.getMessage());
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
        return lTestResultSet;
    }

    /**
     * @see com.symbian.driver.remoting.master.MasterRemote#cleanupJob(int)
     */
    public String cleanupJob(int aTestJobId) throws RemoteException {
        String lStatus = null;
        String lMessage = "";

        try {
            File lResultsFolder = new File(jobsFolder); // jobs folders

            if (aTestJobId > 0) {
                //cleanup one jobs
                if ((JobTracker.isTrackable(aTestJobId))) {
                    lStatus = JobTracker.queryStatus(aTestJobId);
                    if ((lStatus.equals(TestJob.COMPLETED)) || (lStatus.equals(TestJob.FAILED))) {
                        lResultsFolder = new File(jobsFolder + File.separator + aTestJobId);
                    } else {
                        lMessage = "Job " + aTestJobId + " status is " + lStatus + ". Therefore no cleanup.";
                    }
                } else {
                    lMessage = lMessage + "Job " + aTestJobId + " is not valid. ";
                }
            } else if (!JobTracker.isState(TestJob.EXECUTING)) {
                //delete repository
                TDConfig CONFIG = TDConfig.getInstance();
                File lRepos = CONFIG.getPreferenceFile(TDConfig.REPOSITORY_ROOT);
                if (!Utils.recusiveDelete(lRepos)) {
                    lMessage = lMessage + "Failed to clean repository " + lRepos + ". ";
                }

                //empty the working drive
                File lEpoc = CONFIG.getPreferenceFile(TDConfig.EPOC_ROOT);
                if (!Utils.recusiveDelete(lEpoc)) {
                    lMessage = lMessage + "Failed to clean epocroot " + lEpoc + ". ";
                }

                //reset runnumber
                CONFIG.setPreferenceInteger(TDConfig.RUN_NUMBER, 0);

                /*                  //reset JOB ID 
                                  // should we reset this????
                                  jobCounter.reset();
                                  jobCounter.takeSnapshot();
                                  */

                //clean stat logs
                if (!Utils.recusiveDelete(new File("c:/apps/stat/work"))) {
                    lMessage = lMessage + "Failed to clean stat logs. ";
                }
            } else {
                lMessage = lMessage + "Request refused as there is a job running.";
            }

            if (!Utils.recusiveDelete(lResultsFolder)) {
                //It's OK just continue
                lMessage = lMessage + "Failed to clean jobs folder " + lResultsFolder + ". ";
            }
        } catch (ParseException lE) {
            lMessage = lMessage + "Master: Error reading Preferences." + lE.getMessage();
        } finally {
            // clean jobtracker
            if (aTestJobId > 0) {
                JobTracker.remove(aTestJobId);
            } else {
                JobTracker.removeAll();
            }
            JobTracker.getInstance().takeSnapshot();
        }
        if (lMessage.equals("")) {
            if (aTestJobId > 0) {
                return "Job " + aTestJobId + " cleanedup successfully.";
            } else {
                return "Master files cleaned up successfully.";
            }
        } else {
            return lMessage;
        }
    }
}