com.skynetcomputing.skynetclient.persistence.PersistenceManager.java Source code

Java tutorial

Introduction

Here is the source code for com.skynetcomputing.skynetclient.persistence.PersistenceManager.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.skynetcomputing.skynetclient.persistence;

import com.google.gson.Gson;
import com.skynetcomputing.api.jobs.TaskInfo;
import com.skynetcomputing.api.jobs.data.TaskData;
import com.skynetcomputing.serializable.SrzData;
import com.skynetcomputing.serializable.SrzJar;
import com.skynetcomputing.serializable.SrzTask;
import com.skynetcomputing.utils.MiscUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Kargathia
 */
public class PersistenceManager {

    private final String rootDir;

    /**
     * Directory structure:
     *
     */
    private final static String TASK_DIR = "CurrentTask" + File.separator;
    private final static String JAR_DIR = "Jars" + File.separator;
    private final static String DATA_DIR = "Data" + File.separator;

    /**
     * Starts a new PersistenceManager, using provided directory path as root.
     * <br>
     * Files are saved in the following file system order:
     * <blockquote><pre>
     * root\
     *      Jars\
     *          (jar_name)_(jar_version).jar
     *      CurrentTask\
     *          (task_id).task
     *          Data\
     *             (data_id).data
     *
     * </pre></blockquote>
     *
     * @param rootDir
     */
    public PersistenceManager(String rootDir) throws IOException {
        rootDir = rootDir.replace("\\", File.separator).replace("/", File.separator);
        if (!rootDir.endsWith(File.separator)) {
            rootDir = rootDir + File.separator;
        }
        this.rootDir = rootDir;
        String propertyKey = MiscUtils.getProperty("resetDatabase");
        if (propertyKey != null) {
            String strReset = MiscUtils.getPropertyOrDefault("resetDatabase", "false");
            boolean reset = strReset.equalsIgnoreCase("true");
            if (reset) {
                FileUtils.deleteDirectory(new File(rootDir, JAR_DIR));
            }
        }

        // Recursively creates all directories if they don't exist.
        FileUtils.forceMkdir(new File(rootDir, JAR_DIR));
        FileUtils.forceMkdir(new File(rootDir, TASK_DIR));
        FileUtils.forceMkdir(new File(rootDir, TASK_DIR + DATA_DIR));
    }

    /**
     * Removes current task / data files, and re-makes their directories
     *
     * @throws IOException
     */
    public void clearTask() throws IOException {
        File taskDir = new File(rootDir + TASK_DIR);
        FileUtils.deleteDirectory(taskDir);
        taskDir.mkdirs();
        File dataDir = new File(taskDir, DATA_DIR);
        FileUtils.deleteDirectory(dataDir);
        dataDir.mkdirs();
    }

    /**
     * Reads task file and initiates new task. Wipes current task directory.
     * TaskInfo is saved to file, and from now on can be retrieved with
     * getCurrentTask()
     *
     * @param inputFile
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws ParseException
     */
    public SrzTask saveTaskFile(File inputFile) throws IOException, ClassNotFoundException, ParseException {
        clearTask();
        SrzTask task = readTaskFile(inputFile);
        File outputFile = new File(rootDir + TASK_DIR + task.getID() + SrzTask.EXT);
        Files.copy(inputFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        return task;
    }

    /**
     * Reads given file into a task. Does not save the task to the file system.
     *
     * @param taskFile
     * @return
     * @throws IOException
     */
    public SrzTask readTaskFile(File taskFile) throws IOException {
        if (taskFile == null || taskFile.length() <= 0) {
            return null;
        }
        Gson gson = new Gson();
        SrzTask output = null;
        try (BufferedReader br = new BufferedReader(new FileReader(taskFile))) {
            output = gson.fromJson(br, SrzTask.class);
        }
        return output;
    }

    /**
     * Saves given SrzData to file. Will overwrite any previous data file with
     * same ID.
     *
     * @param data
     * @return
     * @throws IOException
     */
    public File saveData(SrzData data) throws IOException {
        File dataDir = new File(rootDir + TASK_DIR + DATA_DIR);
        dataDir.mkdirs();
        File output = new File(dataDir, data.getID() + SrzData.EXT);
        Gson gson = new Gson();
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(output))) {
            gson.toJson(data, bw);
        } catch (IOException ex) {
            output.delete();
            output = null;
            throw ex;
        }
        return output;
    }

    /**
     * Saves given data file to file system, and returns the SrzData object.
     *
     * @param dataFile
     * @return
     * @throws IOException
     */
    public SrzData saveDataFile(File dataFile) throws IOException {
        File dataDir = new File(rootDir + TASK_DIR + DATA_DIR);
        dataDir.mkdirs();
        SrzData output = readDataFile(dataFile);
        File outputFile = new File(
                String.format("%s%s%s%d%s", rootDir, TASK_DIR, DATA_DIR, output.getID(), SrzData.EXT));
        Files.copy(dataFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        return output;
    }

    /**
     * Reads given task data file into a SrzData object. <br>
     * File is not saved to worker file system.
     *
     * @param dataFile
     * @return
     * @throws IOException
     */
    public SrzData readDataFile(File dataFile) throws IOException {
        if (dataFile == null || dataFile.length() <= 0) {
            return null;
        }
        Gson gson = new Gson();
        SrzData output = null;
        try (BufferedReader br = new BufferedReader(new FileReader(dataFile))) {
            output = gson.fromJson(br, SrzData.class);
        }
        return output;
    }

    /**
     * Reads data object for current task with given ID from file system.
     *
     * @param ID
     * @return
     * @throws IOException
     */
    public SrzData getData(int ID) throws IOException {
        SrzData output = null;
        File dataFile = new File(rootDir + TASK_DIR + DATA_DIR + ID + SrzData.EXT);
        if (dataFile.length() > 0) {
            output = readDataFile(dataFile);
        }
        return output;
    }

    /**
     * Saves jar file to file system. Name is its MD5 checksum
     *
     * @param jarFile
     * @return
     * @throws IOException
     */
    public File saveJar(File jarFile) throws IOException {
        File outputFile = null;
        try (FileInputStream fis = new FileInputStream(jarFile)) {
            String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(fis);
            outputFile = new File(String.format("%s%s%s%s", rootDir, JAR_DIR, md5, SrzJar.EXT));
            Files.copy(jarFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }
        return outputFile;
    }

    /**
     *
     * @param task
     * @return
     */
    public File getJarFile(SrzTask task) {
        File jarFile = new File(String.format("%s%s%s%s", rootDir, JAR_DIR, task.getJar().getHash(), SrzJar.EXT));
        if (jarFile.length() <= 0) {
            return null;
        }
        return jarFile;
    }

    /**
     *
     * @return @throws IOException
     */
    public SrzTask getCurrentTask() throws IOException {
        File taskDir = new File(rootDir + TASK_DIR);
        File taskFile = null;
        for (File f : taskDir.listFiles()) {
            if (f.isFile() && FilenameUtils.getExtension(f.getPath())
                    // includes double backslash to escape . special char for regex
                    .equals(SrzTask.EXT.replaceAll("\\.", ""))) {
                taskFile = f;
                break;
            }
        }
        return readTaskFile(taskFile);
    }

    /**
     *
     * @param input
     * @return
     */
    public boolean isAllDataPresent(SrzTask input) {
        Map<String, Boolean> presentData = new HashMap<>();
        File dataDir = new File(rootDir + TASK_DIR + DATA_DIR);
        for (File f : dataDir.listFiles()) {
            presentData.put(f.getName(), true);
        }
        for (Integer i : input.getDependencies()) {
            if (presentData.get(i + SrzData.EXT) == null) {
                return false;
            }
        }
        return true;
    }

}