Skip to content

Commit

Permalink
JFR module
Browse files Browse the repository at this point in the history
  • Loading branch information
danthe1st committed Sep 3, 2024
1 parent 9e29bdc commit a4d1957
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
arebac-neo4j/testdb
*.jfr

# Created by https://www.toptal.com/developers/gitignore/api/eclipse,java,maven
# Edit at https://www.toptal.com/developers/gitignore?templates=eclipse,java,maven
Expand Down
19 changes: 19 additions & 0 deletions arebac-jfr/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.danthe1st</groupId>
<artifactId>AReBAC</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>io.github.danthe1st</groupId>
<artifactId>arebac-jfr</artifactId>
<dependencies>
<dependency>
<groupId>io.github.danthe1st</groupId>
<artifactId>arebac-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.github.danthe1st.arebac.jfr;

import java.util.Objects;

import io.github.danthe1st.arebac.data.commongraph.attributed.AttributeValue;
import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedGraphEdge;
import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedNode;
import io.github.danthe1st.arebac.jfr.events.GetAttributeEvent;
import io.github.danthe1st.arebac.jfr.events.GetAttributeEvent.ElementType;

public class JFRRecordedGraphEdge<N extends AttributedNode, E extends AttributedGraphEdge<N>> implements AttributedGraphEdge<JFRRecordedGraphNode<N>> {

private final E edge;

public JFRRecordedGraphEdge(E edge) {
this.edge = edge;
}

@Override
public JFRRecordedGraphNode<N> source() {
return new JFRRecordedGraphNode<>(edge.source());
}

@Override
public JFRRecordedGraphNode<N> target() {
return new JFRRecordedGraphNode<>(edge.target());
}

@Override
public String id() {
return edge.id();
}

@Override
public boolean hasEdgeType(String edgeType) {
return edge.hasEdgeType(edgeType);
}

@Override
public AttributeValue<?> getAttribute(String key) {
GetAttributeEvent event = new GetAttributeEvent(edge.id(), key, ElementType.EDGE);
event.begin();
AttributeValue<?> attribute = edge.getAttribute(key);
event.commit();
return attribute;
}

@Override
public String toString() {
return "JFRRecordedGraphEdge [edge=" + edge + "]";
}

@Override
public int hashCode() {
return Objects.hash(edge);
}

@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if((obj == null) || (getClass() != obj.getClass())){
return false;
}
JFRRecordedGraphEdge<?, ?> other = (JFRRecordedGraphEdge<?, ?>) obj;
return Objects.equals(edge, other.edge);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.danthe1st.arebac.jfr;

import java.util.Objects;

import io.github.danthe1st.arebac.data.commongraph.attributed.AttributeValue;
import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedNode;
import io.github.danthe1st.arebac.jfr.events.GetAttributeEvent;
import io.github.danthe1st.arebac.jfr.events.GetAttributeEvent.ElementType;

public class JFRRecordedGraphNode<N extends AttributedNode> implements AttributedNode {

private final N node;

public JFRRecordedGraphNode(N node) {
this.node = node;
}

@Override
public String id() {
return node.id();
}

@Override
public boolean hasNodeType(String nodeType) {
return node.hasNodeType(nodeType);
}

@Override
public AttributeValue<?> getAttribute(String key) {
GetAttributeEvent event = new GetAttributeEvent(node.id(), key, ElementType.NODE);
event.begin();
AttributeValue<?> attribute = node.getAttribute(key);
event.commit();
return attribute;
}

N getInternalNode() {
return node;
}

@Override
public String toString() {
return "JFRRecordedGraphNode [node=" + node + "]";
}

@Override
public int hashCode() {
return Objects.hash(node);
}

@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if((obj == null) || (getClass() != obj.getClass())){
return false;
}
JFRRecordedGraphNode<?> other = (JFRRecordedGraphNode<?>) obj;
return Objects.equals(node, other.node);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.github.danthe1st.arebac.jfr;

import java.util.Collection;
import java.util.Objects;

import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedGraph;
import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedGraphEdge;
import io.github.danthe1st.arebac.data.commongraph.attributed.AttributedNode;
import io.github.danthe1st.arebac.jfr.events.FindEdgesEvent;
import io.github.danthe1st.arebac.jfr.events.FindEdgesEvent.Direction;
import io.github.danthe1st.arebac.jfr.events.FindNodeEvent;

public class JFRRecordedGraphWrapper<N extends AttributedNode, E extends AttributedGraphEdge<N>> implements AttributedGraph<JFRRecordedGraphNode<N>, JFRRecordedGraphEdge<N, E>> {

private final AttributedGraph<N, E> graph;

public JFRRecordedGraphWrapper(AttributedGraph<N, E> graph) {
this.graph = graph;
}

@Override
public JFRRecordedGraphNode<N> findNodeById(String id) {
FindNodeEvent event = new FindNodeEvent(id);
event.begin();
N node = graph.findNodeById(id);
event.commit();
return new JFRRecordedGraphNode<>(node);
}

@Override
public Collection<JFRRecordedGraphEdge<N, E>> findOutgoingEdges(JFRRecordedGraphNode<N> node) {
FindEdgesEvent event = new FindEdgesEvent(node.id(), Direction.OUTGOING);
event.begin();
Collection<E> outgoingEdges = graph.findOutgoingEdges(node.getInternalNode());
event.setFoundEdgesCount(outgoingEdges.size());
event.commit();
return outgoingEdges.stream().map(JFRRecordedGraphEdge::new).toList();
}

@Override
public Collection<JFRRecordedGraphEdge<N, E>> findIncomingEdges(JFRRecordedGraphNode<N> node) {
FindEdgesEvent event = new FindEdgesEvent(node.id(), Direction.INCOMING);
event.begin();
Collection<E> incomingEdges = graph.findIncomingEdges(node.getInternalNode());
event.setFoundEdgesCount(incomingEdges.size());
event.commit();
return incomingEdges.stream().map(JFRRecordedGraphEdge::new).toList();
}

@Override
public String toString() {
return "JFRRecordedGraphWrapper [graph=" + graph + "]";
}

@Override
public int hashCode() {
return Objects.hash(graph);
}

@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if((obj == null) || (getClass() != obj.getClass())){
return false;
}
JFRRecordedGraphWrapper<?, ?> other = (JFRRecordedGraphWrapper<?, ?>) obj;
return Objects.equals(graph, other.graph);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.github.danthe1st.arebac.jfr.events;

import java.util.Objects;

import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;

@Name(FindEdgesEvent.NAME)
@Category(JFREventConstants.CATEGORY)
@Description("find edges of a specified node")
public class FindEdgesEvent extends Event {
static final String NAME = "io.github.danthe1st.arebac.jfr.events.FindEdgesEvent";

@Label("node ID")
String nodeId;

@Label("outgoing")
boolean outgoing;

@Label("incoming")
boolean incoming;

@Label("foundEdgesCount")
int foundEdgesCount;

public FindEdgesEvent(String nodeId, Direction direction) {
this.nodeId = nodeId;
Objects.requireNonNull(direction);
this.outgoing = direction == Direction.OUTGOING;
this.incoming = direction == Direction.INCOMING;
}

public void setFoundEdgesCount(int foundEdgesCount) {
this.foundEdgesCount = foundEdgesCount;
}

public enum Direction {
INCOMING, OUTGOING
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.danthe1st.arebac.jfr.events;

import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;

@Name(FindNodeEvent.NAME)
@Category(JFREventConstants.CATEGORY)
@Description("find a node by its ID")
public class FindNodeEvent extends Event {
static final String NAME = "io.github.danthe1st.arebac.jfr.events.FindNodeEvent";

@Label("node ID")
String nodeId;

public FindNodeEvent(String nodeId) {
this.nodeId = nodeId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.github.danthe1st.arebac.jfr.events;

import java.util.Objects;

import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;

@Name(GetAttributeEvent.NAME)
@Category(JFREventConstants.CATEGORY)
@Description("get an attribute of a node or edge")
public class GetAttributeEvent extends Event {
static final String NAME = "io.github.danthe1st.arebac.jfr.events.GetAttributeEvent";

@Label("element ID")
@Description("ID of the node or edge")
String elementId;

@Label("attribute name")
String attributeName;

@Label("element is node")
@Description("true iff this event represents getting the attribute of a node")
boolean isNode;
@Label("element is edge")
@Description("true iff this event represents getting the attribute of a edge")
boolean isEdge;

public GetAttributeEvent(String elementId, String attributeName, ElementType type) {
this.elementId = elementId;
this.attributeName = attributeName;
Objects.requireNonNull(type);
isNode = type == ElementType.NODE;
isEdge = type == ElementType.EDGE;
}

public enum ElementType {
NODE, EDGE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.danthe1st.arebac.jfr.events;

public class JFREventConstants {
static final String CATEGORY = "AReBAC-jfr";
private JFREventConstants() {
// prevent instantiation
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.danthe1st.arebac.jfr;

import static io.github.danthe1st.arebac.data.commongraph.attributed.AttributeValue.attribute;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import io.github.danthe1st.arebac.data.memory.InMemoryGraph;
import io.github.danthe1st.arebac.data.memory.InMemoryGraphEdge;
import io.github.danthe1st.arebac.data.memory.InMemoryGraphNode;

public class JFRTest {
// run with -XX:StartFlightRecording:filename=test.jfr
public static void main(String[] args) {
InMemoryGraphNode internalNode = new InMemoryGraphNode("someId", "type", Map.of("attr", attribute("some attribute value")));
InMemoryGraphNode otherInternalNode = new InMemoryGraphNode("otherId", "type", Map.of("attr", attribute("some attribute value")));
InMemoryGraphEdge internalEdge = new InMemoryGraphEdge(internalNode, otherInternalNode, "someEdge", "eType", Map.of());
InMemoryGraph internalGraph = new InMemoryGraph(List.of(internalNode), List.of(internalEdge));
JFRRecordedGraphWrapper<InMemoryGraphNode, InMemoryGraphEdge> jfrGraph = new JFRRecordedGraphWrapper<>(internalGraph);
JFRRecordedGraphNode<InMemoryGraphNode> foundNode = jfrGraph.findNodeById("someId");
System.out.println(foundNode);
System.out.println(jfrGraph.findIncomingEdges(foundNode));
Collection<JFRRecordedGraphEdge<InMemoryGraphNode, InMemoryGraphEdge>> outgoingEdges = jfrGraph.findOutgoingEdges(foundNode);
System.out.println(outgoingEdges);
for(JFRRecordedGraphEdge<InMemoryGraphNode, InMemoryGraphEdge> jfrRecordedGraphEdge : outgoingEdges){
System.err.println(jfrRecordedGraphEdge.getAttribute("attr"));
}
System.out.println(foundNode.getAttribute("attr"));
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<modules>
<module>arebac-core</module>
<module>arebac-neo4j</module>
<module>arebac-jfr</module>
</modules>
<build>
<plugins>
Expand Down

0 comments on commit a4d1957

Please sign in to comment.