Changeset View
Changeset View
Standalone View
Standalone View
java/src/main/java/org/softwareheritage/graph/Entry.java
package org.softwareheritage.graph; | package org.softwareheritage.graph; | ||||
import java.io.DataOutputStream; | import java.io.*; | ||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import com.fasterxml.jackson.databind.ObjectMapper; | import com.fasterxml.jackson.databind.ObjectMapper; | ||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy; | import com.fasterxml.jackson.databind.PropertyNamingStrategy; | ||||
public class Entry { | public class Entry { | ||||
private final long PATH_SEPARATOR_ID = -1; | |||||
private Graph graph; | private Graph graph; | ||||
public void load_graph(String graphBasename) throws IOException { | public void load_graph(String graphBasename) throws IOException { | ||||
System.err.println("Loading graph " + graphBasename + " ..."); | System.err.println("Loading graph " + graphBasename + " ..."); | ||||
this.graph = Graph.loadMapped(graphBasename); | this.graph = Graph.loadMapped(graphBasename); | ||||
System.err.println("Graph loaded."); | System.err.println("Graph loaded."); | ||||
} | } | ||||
public Graph get_graph() { | public Graph get_graph() { | ||||
return graph.copy(); | return graph.copy(); | ||||
} | } | ||||
public String stats() { | public String stats() { | ||||
try { | try { | ||||
Stats stats = new Stats(graph.getPath()); | Stats stats = new Stats(graph.getPath()); | ||||
ObjectMapper objectMapper = new ObjectMapper(); | ObjectMapper objectMapper = new ObjectMapper(); | ||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); | objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); | ||||
return objectMapper.writeValueAsString(stats); | return objectMapper.writeValueAsString(stats); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Cannot read stats: " + e); | throw new RuntimeException("Cannot read stats: " + e); | ||||
} | } | ||||
} | } | ||||
public void check_swhid(String src) { | |||||
graph.getNodeId(new SWHID(src)); | |||||
} | |||||
private int count_visitor(NodeCountVisitor f, long srcNodeId) { | private int count_visitor(NodeCountVisitor f, long srcNodeId) { | ||||
int[] count = {0}; | int[] count = {0}; | ||||
f.accept(srcNodeId, (node) -> { | f.accept(srcNodeId, (node) -> { | ||||
count[0]++; | count[0]++; | ||||
}); | }); | ||||
return count[0]; | return count[0]; | ||||
} | } | ||||
public int count_leaves(String direction, String edgesFmt, long srcNodeId) { | public int count_leaves(String direction, String edgesFmt, String src) { | ||||
Traversal t = new Traversal(this.graph.copy(), direction, edgesFmt); | long srcNodeId = graph.getNodeId(new SWHID(src)); | ||||
Traversal t = new Traversal(graph.copy(), direction, edgesFmt); | |||||
return count_visitor(t::leavesVisitor, srcNodeId); | return count_visitor(t::leavesVisitor, srcNodeId); | ||||
} | } | ||||
public int count_neighbors(String direction, String edgesFmt, long srcNodeId) { | public int count_neighbors(String direction, String edgesFmt, String src) { | ||||
Traversal t = new Traversal(this.graph.copy(), direction, edgesFmt); | long srcNodeId = graph.getNodeId(new SWHID(src)); | ||||
Traversal t = new Traversal(graph.copy(), direction, edgesFmt); | |||||
return count_visitor(t::neighborsVisitor, srcNodeId); | return count_visitor(t::neighborsVisitor, srcNodeId); | ||||
} | } | ||||
public int count_visit_nodes(String direction, String edgesFmt, long srcNodeId) { | public int count_visit_nodes(String direction, String edgesFmt, String src) { | ||||
Traversal t = new Traversal(this.graph.copy(), direction, edgesFmt); | long srcNodeId = graph.getNodeId(new SWHID(src)); | ||||
Traversal t = new Traversal(graph.copy(), direction, edgesFmt); | |||||
return count_visitor(t::visitNodesVisitor, srcNodeId); | return count_visitor(t::visitNodesVisitor, srcNodeId); | ||||
} | } | ||||
public QueryHandler get_handler(String clientFIFO) { | public QueryHandler get_handler(String clientFIFO) { | ||||
return new QueryHandler(this.graph.copy(), clientFIFO); | return new QueryHandler(graph.copy(), clientFIFO); | ||||
} | } | ||||
private interface NodeCountVisitor { | private interface NodeCountVisitor { | ||||
void accept(long nodeId, Traversal.NodeIdConsumer consumer); | void accept(long nodeId, Traversal.NodeIdConsumer consumer); | ||||
} | } | ||||
public class QueryHandler { | public class QueryHandler { | ||||
Graph graph; | Graph graph; | ||||
DataOutputStream out; | BufferedWriter out; | ||||
String clientFIFO; | String clientFIFO; | ||||
public QueryHandler(Graph graph, String clientFIFO) { | public QueryHandler(Graph graph, String clientFIFO) { | ||||
this.graph = graph; | this.graph = graph; | ||||
this.clientFIFO = clientFIFO; | this.clientFIFO = clientFIFO; | ||||
this.out = null; | this.out = null; | ||||
} | } | ||||
public void writeNode(long nodeId) { | public void writeNode(SWHID swhid) { | ||||
try { | try { | ||||
out.writeLong(nodeId); | out.write(swhid.toString() + "\n"); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Cannot write response to client: " + e); | throw new RuntimeException("Cannot write response to client: " + e); | ||||
} | } | ||||
} | } | ||||
public void writeEdge(long srcId, long dstId) { | public void writeEdge(SWHID src, SWHID dst) { | ||||
writeNode(srcId); | try { | ||||
writeNode(dstId); | out.write(src.toString() + " " + dst.toString() + "\n"); | ||||
} | } catch (IOException e) { | ||||
throw new RuntimeException("Cannot write response to client: " + e); | |||||
public void writePath(ArrayList<Long> path) { | |||||
for (Long nodeId : path) { | |||||
writeNode(nodeId); | |||||
} | } | ||||
writeNode(PATH_SEPARATOR_ID); | |||||
} | } | ||||
public void open() { | public void open() { | ||||
try { | try { | ||||
FileOutputStream file = new FileOutputStream(this.clientFIFO); | FileOutputStream file = new FileOutputStream(this.clientFIFO); | ||||
this.out = new DataOutputStream(file); | this.out = new BufferedWriter(new OutputStreamWriter(file)); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Cannot open client FIFO: " + e); | throw new RuntimeException("Cannot open client FIFO: " + e); | ||||
} | } | ||||
} | } | ||||
public void close() { | public void close() { | ||||
try { | try { | ||||
out.close(); | out.close(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Cannot write response to client: " + e); | throw new RuntimeException("Cannot write response to client: " + e); | ||||
} | } | ||||
} | } | ||||
public void leaves(String direction, String edgesFmt, long srcNodeId, long maxEdges, String returnTypes) { | public void leaves(String direction, String edgesFmt, String src, long maxEdges, String returnTypes) { | ||||
long srcNodeId = graph.getNodeId(new SWHID(src)); | |||||
open(); | open(); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, maxEdges, returnTypes); | Traversal t = new Traversal(graph, direction, edgesFmt, maxEdges, returnTypes); | ||||
for (Long nodeId : t.leaves(srcNodeId)) { | for (Long nodeId : t.leaves(srcNodeId)) { | ||||
writeNode(nodeId); | writeNode(graph.getSWHID(nodeId)); | ||||
} | } | ||||
close(); | close(); | ||||
} | } | ||||
public void neighbors(String direction, String edgesFmt, long srcNodeId, long maxEdges, String returnTypes) { | public void neighbors(String direction, String edgesFmt, String src, long maxEdges, String returnTypes) { | ||||
long srcNodeId = graph.getNodeId(new SWHID(src)); | |||||
open(); | open(); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, maxEdges, returnTypes); | Traversal t = new Traversal(graph, direction, edgesFmt, maxEdges, returnTypes); | ||||
for (Long nodeId : t.neighbors(srcNodeId)) { | for (Long nodeId : t.neighbors(srcNodeId)) { | ||||
writeNode(nodeId); | writeNode(graph.getSWHID(nodeId)); | ||||
} | } | ||||
close(); | close(); | ||||
} | } | ||||
public void visit_nodes(String direction, String edgesFmt, long srcNodeId, long maxEdges, String returnTypes) { | public void visit_nodes(String direction, String edgesFmt, String src, long maxEdges, String returnTypes) { | ||||
long srcNodeId = graph.getNodeId(new SWHID(src)); | |||||
open(); | open(); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, maxEdges, returnTypes); | Traversal t = new Traversal(graph, direction, edgesFmt, maxEdges, returnTypes); | ||||
for (Long nodeId : t.visitNodes(srcNodeId)) { | for (Long nodeId : t.visitNodes(srcNodeId)) { | ||||
writeNode(nodeId); | writeNode(graph.getSWHID(nodeId)); | ||||
} | |||||
close(); | |||||
} | |||||
public void visit_edges(String direction, String edgesFmt, long srcNodeId, long maxEdges) { | |||||
open(); | |||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, maxEdges); | |||||
t.visitNodesVisitor(srcNodeId, null, this::writeEdge); | |||||
close(); | |||||
} | } | ||||
public void visit_paths(String direction, String edgesFmt, long srcNodeId, long maxEdges) { | |||||
open(); | |||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, maxEdges); | |||||
t.visitPathsVisitor(srcNodeId, this::writePath); | |||||
close(); | close(); | ||||
} | } | ||||
public void walk(String direction, String edgesFmt, String algorithm, long srcNodeId, long dstNodeId) { | public void visit_edges(String direction, String edgesFmt, String src, long maxEdges, String returnTypes) { | ||||
long srcNodeId = graph.getNodeId(new SWHID(src)); | |||||
open(); | open(); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt); | Traversal t = new Traversal(graph, direction, edgesFmt, maxEdges); | ||||
for (Long nodeId : t.walk(srcNodeId, dstNodeId, algorithm)) { | t.visitNodesVisitor(srcNodeId, null, (srcId, dstId) -> { | ||||
writeNode(nodeId); | writeEdge(graph.getSWHID(srcId), graph.getSWHID(dstId)); | ||||
} | }); | ||||
close(); | close(); | ||||
} | } | ||||
public void walk_type(String direction, String edgesFmt, String algorithm, long srcNodeId, String dst) { | public void walk(String direction, String edgesFmt, String algorithm, String src, String dst) { | ||||
long srcNodeId = graph.getNodeId(new SWHID(src)); | |||||
open(); | open(); | ||||
ArrayList<Long> res; | |||||
if (dst.matches("ori|snp|rel|rev|dir|cnt")) { | |||||
Node.Type dstType = Node.Type.fromStr(dst); | Node.Type dstType = Node.Type.fromStr(dst); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt); | Traversal t = new Traversal(graph, direction, edgesFmt); | ||||
for (Long nodeId : t.walk(srcNodeId, dstType, algorithm)) { | res = t.walk(srcNodeId, dstType, algorithm); | ||||
writeNode(nodeId); | } else { | ||||
long dstNodeId = graph.getNodeId(new SWHID(dst)); | |||||
Traversal t = new Traversal(graph, direction, edgesFmt); | |||||
res = t.walk(srcNodeId, dstNodeId, algorithm); | |||||
vlorentz: silent fallback on invalid `dst`? why? | |||||
Done Inline ActionsIt should be new SWHID(dst). It's very weird that the tests didn't catch that... seirl: It should be `new SWHID(dst)`. It's very weird that the tests didn't catch that... | |||||
} | } | ||||
close(); | for (Long nodeId : res) { | ||||
} | writeNode(graph.getSWHID(nodeId)); | ||||
public void random_walk(String direction, String edgesFmt, int retries, long srcNodeId, long dstNodeId, | |||||
String returnTypes) { | |||||
open(); | |||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, 0, returnTypes); | |||||
for (Long nodeId : t.randomWalk(srcNodeId, dstNodeId, retries)) { | |||||
writeNode(nodeId); | |||||
} | } | ||||
close(); | close(); | ||||
} | } | ||||
public void random_walk_type(String direction, String edgesFmt, int retries, long srcNodeId, String dst, | public void random_walk(String direction, String edgesFmt, int retries, String src, String dst) { | ||||
String returnTypes) { | long srcNodeId = graph.getNodeId(new SWHID(src)); | ||||
open(); | open(); | ||||
ArrayList<Long> res; | |||||
if (dst.matches("ori|snp|rel|rev|dir|cnt")) { | |||||
Node.Type dstType = Node.Type.fromStr(dst); | Node.Type dstType = Node.Type.fromStr(dst); | ||||
Traversal t = new Traversal(this.graph, direction, edgesFmt, 0, returnTypes); | Traversal t = new Traversal(graph, direction, edgesFmt); | ||||
for (Long nodeId : t.randomWalk(srcNodeId, dstType, retries)) { | res = t.randomWalk(srcNodeId, dstType, retries); | ||||
writeNode(nodeId); | } else { | ||||
long dstNodeId = graph.getNodeId(new SWHID(dst)); | |||||
Traversal t = new Traversal(graph, direction, edgesFmt); | |||||
res = t.randomWalk(srcNodeId, dstNodeId, retries); | |||||
Done Inline Actionsditto vlorentz: ditto | |||||
} | |||||
for (Long nodeId : res) { | |||||
writeNode(graph.getSWHID(nodeId)); | |||||
} | } | ||||
close(); | close(); | ||||
} | } | ||||
} | } | ||||
} | } |
silent fallback on invalid dst? why?