All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.massisframework.massis.util.io.SimulationSaver Maven / Gradle / Ivy

package com.massisframework.massis.util.io;

import com.eteks.sweethome3d.model.RecorderException;
import com.eteks.sweethome3d.tools.OperatingSystem;
import com.google.gson.Gson;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.massisframework.massis.util.gson.CompressorProcessor;
import com.massisframework.massis.util.io.storage.DefaultMassisStorage;
import com.massisframework.massis.util.io.storage.MassisStorage;
import sim.engine.SimState;
import sim.engine.Steppable;
import sim.engine.Stoppable;

public class SimulationSaver implements Steppable, Stoppable, RestorableObserver {

    private static final long serialVersionUID = 1L;
    public static final int DEFAULT_MAX_QUEUE_SIZE = 50;
    long currentStep;
    private final ArrayBlockingQueue queue;
    private boolean closed = false;
    private final HashSet changedObjects = new HashSet<>();
    private List states = new ArrayList<>();
    private final CompressorProcessor processor;
    private final Gson gson;
    private final BufferedWriter logBufferedWriter;
    private boolean started;
    private final Thread writerThread;
    private final Object lock = new Object();
    private final File inputFile;
    private final File outputFile;
    private final File tmpLog;

    public SimulationSaver(File inputFile, File outputFile) throws IOException, RecorderException, ClassNotFoundException
    {
        this(inputFile, outputFile, DEFAULT_MAX_QUEUE_SIZE);
    }

    public SimulationSaver(File inputFile, File outputFile,
            int max_queue_size) throws IOException, RecorderException, ClassNotFoundException
    {
        this.inputFile = inputFile;
        this.outputFile = outputFile;
        this.queue = new ArrayBlockingQueue<>(max_queue_size);
        /*
         * Copy metadata & home info before start 
         */
        try (MassisStorage origin = new DefaultMassisStorage(inputFile))
        {
            try (MassisStorage destination = new DefaultMassisStorage(outputFile))
            {
                destination.saveHome(origin.loadHome());
                destination.saveMetadata(origin.loadMetadata());
            }
        }
        this.processor = new CompressorProcessor();
        this.gson = this.processor.createBuilder().createGson();

        this.tmpLog = OperatingSystem.createTemporaryFile("_MASSIS_log_",
                ".json");

        final OutputStream logOS = new FileOutputStream(tmpLog);
        final OutputStreamWriter osw = new OutputStreamWriter(logOS);
        this.logBufferedWriter = new BufferedWriter(osw);
        this.started = false;
        this.writerThread = new Thread(new LogWriterRunnable());
        this.writerThread.start();
    }

    @Override
    public void stop()
    {
        if (this.closed)
        {
            return;
        }
        try
        {
            synchronized (lock)
            {
                this.closed = true;
                while (!queue.isEmpty())
                {
                    this.gson.toJson(queue.poll(), this.logBufferedWriter);
                    this.logBufferedWriter.write("\n");
                }
                /*
                 * Flush & close. There's no need to write anything else.
                 */
                logBufferedWriter.flush();
                logBufferedWriter.close();
                /*
                 * Save the compression map
                 */
                try (MassisStorage destination = new DefaultMassisStorage(
                        this.outputFile))
                {
                    String[][] compressionMap = this.processor.getCompressionKeyValueArray();
                    destination.saveCompressionMap(compressionMap);
                }
                /*
                 * Save log file
                 */
                try (MassisStorage destination = new DefaultMassisStorage(
                        this.outputFile))
                {

                    destination.saveSimulationLogFile(this.tmpLog);
                    this.tmpLog.deleteOnExit();
                }

            }
//            synchronized (writerThread)
//            {
//                writerThread.interrupt();
//            }
        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    protected void finalize() throws Throwable
    {
        super.finalize();
        this.stop();
    }

    @Override
    public void step(SimState simState)
    {
        checkStarted();
        try
        {

            this.queue.put(
                    this.states.toArray(new JsonState[this.states.size()]));
            System.err.println("SIZE STATES " + this.states.size());

        } catch (InterruptedException ex)
        {
            Logger.getLogger(SimulationSaver.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
        this.changedObjects.clear();
        this.states.clear();
    }

    @Override
    public void notifyChange(Restorable restorable, JsonState state)
    {
        this.states.add(state);
    }

    private void checkStarted()
    {
        if (!started)
        {
            this.started = true;

        }
    }

    private class LogWriterRunnable implements Runnable {

        @Override
        public void run()
        {
            try
            {
                while (!SimulationSaver.this.closed)
                {
                    JsonState[] states = queue.take();
                    synchronized (lock)
                    {
                        gson.toJson(states, logBufferedWriter);
                        logBufferedWriter.write("\n");
                        logBufferedWriter.flush();
                    }
                }
            } catch (InterruptedException ex)
            {
                Logger.getLogger(SimulationSaver.class.getName()).log(
                        Level.INFO,
                        "Writer Thread interrupted");
            } catch (IOException ex)
            {
                Logger.getLogger(SimulationSaver.class.getName()).log(
                        Level.SEVERE,
                        null, ex);
            }



        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy