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

ru.taskurotta.service.dependency.links.MemoryGraphDao Maven / Gradle / Ivy

package ru.taskurotta.service.dependency.links;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * User: romario
 * Date: 4/5/13
 * Time: 11:23 AM
 */
public class MemoryGraphDao implements GraphDao {

    private final static Logger logger = LoggerFactory.getLogger(MemoryGraphDao.class);

    // TODO: garbage collection policy for real database
    private Map graphs = new ConcurrentHashMap();
    private Map decisions = new ConcurrentHashMap();

    private Object newGraphLock = new Object();

    //TODO: find and delete usage
    //TODO: configuration support
    private int retryTimes = 100;

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
    }


    /**
     * Table of row contains current graph (process) state
     */
    public static class GraphRow {
        private int version;
        private String jsonGraph;

        protected GraphRow(Graph graph) {
            version = graph.getVersion();
            dump(graph);
        }


        /**
         * @param modifiedGraph
         * @return true if modification was successful
         */
        protected synchronized boolean updateGraph(Graph modifiedGraph) {

            int newVersion = modifiedGraph.getVersion();

            if (version != newVersion - 1) {
                return false;
            }
            version = newVersion;
            dump(modifiedGraph);

            return true;
        }


        protected void dump(Graph graph) {
            try {
                jsonGraph = mapper.writeValueAsString(graph);
            } catch (JsonProcessingException e) {
                // TODO: create new RuntimeException type
                throw new RuntimeException("Can not create json String from Object: " + graph, e);
            }
        }


        protected Graph parse() {

            try {
                return mapper.readValue(jsonGraph, Graph.class);
            } catch (IOException e) {
                // TODO: create new RuntimeException type
                throw new RuntimeException("Can not instantiate Object from json. JSON value: " + jsonGraph, e);
            }
        }


    }

    /**
     * Table of row contains decision stuff
     */
    private static class DecisionRow {
        private UUID itemId;
        private Modification modification;
        private UUID[] readyItems;
    }


    @Override
    public void createGraph(UUID graphId, UUID taskId) {

        if (graphs.get(graphId) != null) {
            return;
        }

        // too ugly
        synchronized (newGraphLock) {

            if (graphs.get(graphId) != null) {
                return;
            }

            Graph graph = new Graph(graphId, taskId);
            GraphRow graphRow = new GraphRow(graph);

            graphs.put(graphId, graphRow);
        }
    }

    @Override
    public void deleteGraph(UUID graphId) {
        graphs.remove(graphId);
    }

    @Override
    public Graph getGraph(UUID graphId) {

        GraphRow graphRow = graphs.get(graphId);

        if (graphRow == null) {
            return null;
        }

        return graphRow.parse();
    }

    private boolean updateGraph(Graph modifiedGraph) {

        logger.debug("updateGraph() modifiedGraph = [{}]", modifiedGraph);

        Modification modification = modifiedGraph.getModification();

        if (modification != null) {
            DecisionRow decisionRow = new DecisionRow();

            decisionRow.itemId = modification.getCompletedItem();
            decisionRow.modification = modification;
            decisionRow.readyItems = modifiedGraph.getReadyItems();

            decisions.put(decisionRow.itemId, decisionRow);
        }

        GraphRow graphRow = graphs.get(modifiedGraph.getGraphId());

        return graphRow.updateGraph(modifiedGraph);
    }


    @Override
    public UUID[] getReadyTasks(UUID finishedTaskId, UUID processId) {

        DecisionRow decisionRow = decisions.get(finishedTaskId);
        if (decisionRow != null) {
            return decisionRow.readyItems;
        }

        return Graph.EMPTY_ARRAY;
    }

    @Override
    public boolean changeGraph(Updater updater) {

        UUID processId = updater.getProcessId();

        for (int i = 0; i < retryTimes; i++) {

            Graph graph = getGraph(processId);

            if (!updater.apply(graph)) {
                break;
            }

            if (updateGraph(graph)) {
                return true;
            }
        }

        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy