示例#1
0
  @Test
  public void testSimpleGraphWithOneScope() {
    Dependencies deps = new Dependencies();
    deps.addDependencies(A1, createMap(A2, A3));
    deps.addDependencies(A2, createMap(A3));

    DependencyGraph graph = deps.getDependencyGraph(TestScope.scope1);

    assertEquals(createSet(A1, A2, A3), graph.getAllItems());
    assertEquals(createSet(A2, A3), graph.getDependencies(A1));
    assertEquals(createSet(A3), graph.getDependencies(A2));
    assertEquals(Collections.EMPTY_SET, graph.getDependencies(A3));
  }
示例#2
0
  @Test
  public void testTwoScopesGraphWithDirectAndDerivedDependencies() {
    Dependencies deps = new Dependencies();
    deps.addDependencies(A1, createMap(A2));
    deps.addDependencies(B1, createMap(B3));
    deps.addChild(B1, A1);
    deps.addChild(B2, A2);

    DependencyGraph graph = deps.getDependencyGraph(TestScope.scope2);

    assertEquals(createSet(B1, B2, B3), graph.getAllItems());
    assertEquals(createSet(B2, B3), graph.getDependencies(B1));
    assertEquals(Collections.EMPTY_SET, graph.getDependencies(B2));
    assertEquals(Collections.EMPTY_SET, graph.getDependencies(B3));
  }
  private CompositeModuleInterpreterActor(Factory factory) {
    super(
        factory.interpreterProperties,
        factory.stagingArea.getAnnotatedExecutionTrace(),
        factory.moduleId);

    module = factory.module;
    stagingArea = factory.stagingArea;
    interpreterPropsProvider = factory.interpreterPropsProvider;
    recomputedInPorts = factory.recomputedInPorts;
    requestedOutPorts = factory.requestedOutPorts;

    int numSubmodules = module.getModules().size();
    childExecutors = new ActorRef[numSubmodules];
    outPortsRequiringValue = (BitSet) requestedOutPorts.clone();
    childActorMap = new HashMap<>(numSubmodules);

    dependencyGraph = new DependencyGraph(module, requestedOutPorts);
    for (InPortNode inPortNode : dependencyGraph.inPortNodes()) {
      HasValue hasValue = factory.inPortsHasValueList.get(inPortNode.getElement().getInIndex());
      assert hasValue != HasValue.PENDING_VALUE_CHECK;
      inPortNode.setHasValue(hasValue);
    }

    inPortReceivedMessage = new BitSet(module.getInPorts().size());
    submoduleOutPortsReceivedMessage = new BitSet[numSubmodules];
    for (RuntimeModule submodule : module.getModules()) {
      submoduleOutPortsReceivedMessage[submodule.getIndex()] =
          new BitSet(submodule.getOutPorts().size());
    }

    computeResumeState =
        new ComputeResumeState(dependencyGraph, recomputedInPorts, this::asynchronousHasValueCheck);
  }
  /**
   * Starts the interpretation of the current parent module if algorithm ComputeResumeState has
   * finished.
   *
   * <p>This method sets the state of this actor to {@link State#RUNNING} and thus also finished the
   * asynchronous action that was started in {@link #preStart()}.
   */
  private void startRunningIfQueueEmpty() {
    assert state == State.STARTING;

    if (!computeResumeState.isFinished()) {
      return;
    }

    // Trigger in-ports
    initialInPortsTrigger();
    state = State.RUNNING;

    // Start child interpreters for all submodules that have at least one in-port whose state is
    // READY
    submodules:
    for (List<SubmoduleInPortNode> submoduleInPortNodes : dependencyGraph.submodulesInPortNodes()) {
      for (SubmoduleInPortNode submoduleInPortNode : submoduleInPortNodes) {
        if (submoduleInPortNode.getPortState() == PortState.READY) {
          getChildExecutor(submoduleInPortNode.getElement().getModule());
          continue submodules;
        }
      }
    }

    // Start child interpreters for all submodules that have no in-ports and whose state is READY
    for (SubmoduleNode submoduleNode : dependencyGraph.submoduleNodes()) {
      if (submoduleNode.getElement().getInPorts().isEmpty()
          && submoduleNode.getPortState() == PortState.READY) {
        getChildExecutor(submoduleNode.getElement());
      }
    }

    // Trigger all out-ports whose state is READY
    dependencyGraph
        .outPortNodes()
        .stream()
        .filter(node -> node.getPortState() == PortState.READY)
        .forEach(node -> outportCarriesSignal(node.getElement().getOutIndex()));

    if (outPortsRequiringValue.isEmpty()) {
      state = State.ALL_OUTPUTS;
    }

    // Finish the asynchronous action started in #preStart().
    checkIfNoAsynchronousActions();
  }
 /**
  * Returns whether the given connection ends in a port that is a node in the dependency graph with
  * state {@link PortState#RECOMPUTE}.
  *
  * <p>This method always returns false if the connection is not within the current parent module.
  */
 private boolean isConnectionToRecomputedNode(RuntimeConnection runtimeConnection) {
   if (runtimeConnection.getParentModule() == module) {
     DependencyGraphNode portNode = dependencyGraph.targetNode(runtimeConnection.getToPort());
     if (portNode.getPortState() == PortState.RECOMPUTE) {
       return true;
     }
   }
   return false;
 }
  /**
   * Returns, and if necessary creates, the submodule interpreter actor for the given submodule.
   *
   * <p>A submodule interpreter actor is created at most once during the lifetime of the current
   * actor. If the submodule actor is created, it will be supervised by the current actor.
   *
   * <p>This method starts one asynchronous action for each out-port of the submodule that satisfies
   * {@link #isOutPortNeeded(RuntimeOutPort)}; these will be finished in {@link
   * #submoduleOutPortNoLongerNeeded}. This prevents this actor from terminating even though a child
   * interpreter may still send values for out-ports.
   *
   * <p>One additional asynchronous action is started for the child actor, which will be finished in
   * {@link #childActorTerminated(ActorRef)}.
   *
   * @param submodule submodule
   * @return reference to the submodule actor
   */
  private ActorRef getChildExecutor(RuntimeModule submodule) {
    assert state == State.REPLAY || state == State.RUNNING || state == State.ALL_OUTPUTS;

    int submoduleId = submodule.getIndex();
    if (childExecutors[submoduleId] == null) {
      List<SubmoduleInPortNode> submoduleInPortNodes =
          dependencyGraph.submodulesInPortNodes().get(submoduleId);

      ImmutableList<HasValue> submoduleInPortHasValueList =
          submoduleInPortNodes
              .stream()
              .map(SubmoduleInPortNode::getHasValue)
              .collect(ImmutableList.collector());

      BitSet submoduleRecomputedInPorts = new BitSet(submodule.getInPorts().size());
      submoduleInPortNodes
          .stream()
          .filter(node -> node.getPortState() == PortState.RECOMPUTE)
          .forEach(node -> submoduleRecomputedInPorts.set(node.getElement().getInIndex()));

      BitSet submoduleRequestedOutPorts =
          computeResumeState.getSubmodulesNeededOutPorts()[submoduleId];
      submoduleRequestedOutPorts
          .stream()
          .mapToObj(id -> submodule.getOutPorts().get(id))
          .forEach(
              outPort ->
                  startAsynchronousAction(
                      outPort,
                      "waiting for value to pass through submodule out-port %s#%s",
                      submodule.getSimpleName(),
                      outPort.getSimpleName()));

      childExecutors[submoduleId] =
          getContext()
              .actorOf(
                  interpreterPropsProvider.provideInterpreterProps(
                      getInterpreterProperties(),
                      stagingArea.resolveDescendant(
                          ExecutionTrace.empty()
                              .resolveContent()
                              .resolveModule(submodule.getSimpleName())),
                      submoduleId,
                      submoduleInPortHasValueList,
                      submoduleRecomputedInPorts,
                      submoduleRequestedOutPorts),
                  submodule.getSimpleName().toString());
      getContext().watch(childExecutors[submoduleId]);
      childActorMap.put(childExecutors[submoduleId], submodule);
      startAsynchronousAction(
          childExecutors[submoduleId],
          "supervising interpreter for submodule %s",
          submodule.getSimpleName());
    }
    return childExecutors[submoduleId];
  }
  private static DependencyGraph loadGraphs(int startingAt, String... mainArgs) throws Exception {
    String filename;
    if (mainArgs.length < startingAt + 1) {
      return loadGraph("thread_dependency_graph.ser");
    }

    DependencyGraph result = new DependencyGraph();

    for (int i = startingAt; i < mainArgs.length; i++) {
      filename = mainArgs[i];
      DependencyGraph gr = loadGraph(filename);
      if (gr == null) {
        return null;
      }
      result.addEdges(gr.getEdges());
    }

    return result;
  }
  public static void main(String... args) throws Exception {
    if (args.length == 0) {
      printHelp();
      return;
    }

    DependencyGraph graph;

    switch (args[0]) {
      case "print":
        graph = loadGraphs(1, args);
        System.out.println(prettyFormat(graph));
        break;
      case "findCycle":
        graph = loadGraphs(1, args);
        List<Dependency> cycle = graph.findCycle();
        if (cycle == null) {
          System.out.println("no deadlock found");
        } else {
          System.out.println("deadlocked threads: \n" + cycle);
        }
        break;
      case "findImpasse":
        graph = loadGraphs(1, args);
        graph = graph.findLongestCallChain();
        if (graph == null) {
          System.out.println("no long call chain could be found!");
        } else {
          System.out.println("longest call chain: \n" + prettyFormat(graph));
        }
        break;
      case "findObject":
        graph = loadGraphs(2, args);
        List<DependencyGraph> graphs = graph.findDependenciesWith(args[1]);
        if (graphs.isEmpty()) {
          System.out.println(
              "thread not found! Try using the print command to see all threads and locate the name of the one you're interested in?");
        } else {
          int numGraphs = graphs.size();
          int i = 0;
          System.out.println("findObject \"" + args[1] + "\"\n\n");
          for (DependencyGraph g : graphs) {
            i += 1;
            System.out.println("graph " + i + " of " + numGraphs + ":");
            System.out.println(prettyFormat(sortDependencies(g.getEdges())));
            if (i < numGraphs) {
              System.out.println("\n\n\n");
            }
          }
        }
        break;
      default:
        printHelp();
        break;
    }
  }
  /**
   * Triggers all in-ports that either are in state {@link PortState#READY} or that received a value
   * while the state of this actor was {@link State#STARTING}.
   */
  private void initialInPortsTrigger() {
    assert state == State.STARTING;

    state = State.REPLAY;

    // Trigger all in-ports whose state is READY
    dependencyGraph
        .inPortNodes()
        .stream()
        .filter(node -> node.getPortState() == PortState.READY)
        .forEach(node -> transmitValueFromInPort(node.getElement()));

    // Trigger all in-ports who received a value while state was STARTING
    inPortReceivedMessage.stream().forEach(this::inPortHasSignal);
  }
示例#10
0
  @Test
  public void testGetGraphByParentsTwoScopesUp() {
    Dependencies deps = new Dependencies();
    deps.addDependencies(A1, createMap(A2, A3, A4));
    deps.addDependencies(A2, createMap(A3, A4));

    deps.addChild(B1, A1);
    deps.addChild(B1, A2);
    deps.addChild(B2, A3);
    deps.addChild(B3, A4);
    deps.addChild(C1, B1);
    deps.addChild(C2, B2);
    deps.addChild(C3, B3);

    DependencyGraph graph =
        deps.getDependencyGraph(
            TestScope.scope1, new HashSet(Arrays.asList(C1, C2)), DependencyFilter.none);

    assertEquals(createSet(A1, A2, A3), graph.getAllItems());
    assertEquals(createSet(A2, A3), graph.getDependencies(A1));
    assertEquals(createSet(A3), graph.getDependencies(A2));
    assertEquals(Collections.EMPTY_SET, graph.getDependencies(A3));

    DependencyGraph graphFiltered =
        deps.getDependencyGraph(
            TestScope.scope1,
            new HashSet(Arrays.asList(C1)),
            DependencyFilter.itemsContributingToTheParentDependencyWeight);
    assertTrue(graphFiltered.getAllItems().size() == 0);

    graphFiltered =
        deps.getDependencyGraph(
            TestScope.scope1,
            new HashSet(Arrays.asList(C1, C2)),
            DependencyFilter.itemsContributingToTheParentDependencyWeight);
    assertEquals(createSet(A1, A2, A3), graphFiltered.getAllItems());
    assertEquals(createSet(A3), graphFiltered.getDependencies(A1));
    assertEquals(createSet(A3), graphFiltered.getDependencies(A2));
  }
 /** Find the all of the dependencies of a given thread. */
 public DependencyGraph findDependencyGraph(ThreadReference thread) {
   return graph.getSubGraph(thread);
 }
 /**
  * Finds the first deadlock in the list of dependencies, or null if there are no deadlocks in the
  * set of dependencies.
  *
  * @return a linked list of dependencies which shows the circular dependencies. The List will be
  *     of the form Dependency(A,B), Dependency(B,C), Dependency(C, A).
  */
 public LinkedList<Dependency> findDeadlock() {
   return graph.findCycle();
 }
 /** Add a set of dependencies to the dependency graph to be analyzed. */
 public void addDependencies(Set<Dependency> dependencies) {
   graph.addEdges(dependencies);
 }
 /** Format dependency graph for displaying to a user. */
 public static String prettyFormat(DependencyGraph graph) {
   return prettyFormat(graph.getEdges());
 }
示例#15
0
 @Test
 public void testGetEmptyGraph() {
   DependencyGraph graph = new Dependencies().getDependencyGraph(TestScope.scope1);
   assertTrue(graph.getAllItems().isEmpty());
 }