diff --git a/java/server/pom.xml b/java/server/pom.xml
index 99ff2b1..5cd22a0 100644
--- a/java/server/pom.xml
+++ b/java/server/pom.xml
@@ -1,141 +1,146 @@
4.0.0
org.softwareheritage.graph
swh-graph
1.0
swh-graph
https://www.softwareheritage.org/
UTF-8
11
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+
junit
junit
4.11
test
org.hamcrest
hamcrest
2.1
test
io.javalin
javalin
3.0.0
org.slf4j
slf4j-simple
1.7.26
com.fasterxml.jackson.core
jackson-databind
2.9.8
it.unimi.dsi
webgraph-big
3.5.1
it.unimi.dsi
fastutil
8.2.2
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
-verbose
-Xlint:all
maven-surefire-plugin
2.22.1
maven-jar-plugin
3.0.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
maven-site-plugin
3.7.1
maven-project-info-reports-plugin
3.0.0
maven-assembly-plugin
org.softwareheritage.graph.App
jar-with-dependencies
make-assembly
package
single
org.apache.maven.plugins
maven-javadoc-plugin
3.1.1
diff --git a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java
index a851291..17b7541 100644
--- a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java
+++ b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java
@@ -1,166 +1,230 @@
package org.softwareheritage.graph;
import java.util.ArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import org.softwareheritage.graph.Graph;
import org.softwareheritage.graph.SwhId;
import org.softwareheritage.graph.SwhPath;
import org.softwareheritage.graph.algo.Traversal;
/**
* REST API endpoints wrapper functions.
*
* @author Thibault Allançon
* @version 1.0
* @since 1.0
*/
public class Endpoint {
/** Graph where traversal endpoint is performed */
Graph graph;
/** Internal traversal API */
Traversal traversal;
+ /** Timings logger */
+ private static final Logger logger = LoggerFactory.getLogger(Endpoint.class);
+
/**
* Constructor.
*
* @param graph the graph used for traversal endpoint
* @param direction a string (either "forward" or "backward") specifying edge orientation
* @param edgesFmt a formatted string describing allowed edges (TODO: link API doc)
*/
public Endpoint(Graph graph, String direction, String edgesFmt) {
this.graph = graph;
this.traversal = new Traversal(graph, direction, edgesFmt);
}
+ /**
+ * Returns measurement starting timestamp for logging purposes.
+ *
+ * @return timestamp used for time measurement
+ */
+ private long startTiming() {
+ return System.nanoTime();
+ }
+
+ /**
+ * Ends timing measurement and returns total duration in seconds for logging purposes.
+ *
+ * @param startTime measurement starting timestamp
+ * @return time in seconds elapsed since starting point
+ */
+ private float stopTiming(long startTime) {
+ long endTime = System.nanoTime();
+ float duration = (float) (endTime - startTime) / 1_000_000_000;
+ return duration;
+ }
+
/**
* Converts a list of (internal) long node ids to a list of corresponding (external) SWH PIDs.
*
* @param nodeIds the list of long node ids
* @return a list of corresponding SWH PIDs
*/
private ArrayList convertNodesToSwhIds(ArrayList nodeIds) {
+ long startTime = this.startTiming();
ArrayList swhIds = new ArrayList<>();
for (long nodeId : nodeIds) {
swhIds.add(graph.getSwhId(nodeId));
}
+ float duration = this.stopTiming(startTime);
+ logger.debug("convertNodesToSwhIds() took {} s.", duration);
return swhIds;
}
/**
* Converts a list of (internal) long node ids to the corresponding {@link SwhPath}.
*
* @param nodeIds the list of long node ids
* @return the corresponding {@link SwhPath}
* @see org.softwareheritage.graph.SwhPath
*/
private SwhPath convertNodesToSwhPath(ArrayList nodeIds) {
+ long startTime = this.startTiming();
SwhPath path = new SwhPath();
for (long nodeId : nodeIds) {
path.add(graph.getSwhId(nodeId));
}
+ float duration = this.stopTiming(startTime);
+ logger.debug("convertNodesToSwhPath() took {} s.", duration);
return path;
}
/**
* Converts a list of paths made of (internal) long node ids to one made of {@link SwhPath}-s.
*
* @param pathsNodeId the list of paths with long node ids
* @return a list of corresponding {@link SwhPath}
* @see org.softwareheritage.graph.SwhPath
*/
private ArrayList convertPathsToSwhIds(ArrayList> pathsNodeId) {
+ long startTime = this.startTiming();
ArrayList paths = new ArrayList<>();
for (ArrayList path : pathsNodeId) {
paths.add(convertNodesToSwhPath(path));
}
+ float duration = this.stopTiming(startTime);
+ logger.debug("convertPathsToSwhIds() took {} s.", duration);
return paths;
}
/**
* Leaves endpoint wrapper (performs input/output node ids conversions).
*
* @param src source node of endpoint call specified as a SwhId
* @return the resulting list of SwhId from endpoint call
* @see org.softwareheritage.graph.SwhId
* @see org.softwareheritage.graph.algo.Traversal#leaves(long)
*/
public ArrayList leaves(SwhId src) {
long srcNodeId = graph.getNodeId(src);
+
+ long startTime = this.startTiming();
ArrayList nodeIds = traversal.leaves(srcNodeId);
+ float duration = this.stopTiming(startTime);
+ logger.debug("leaves({}) took {} s.", src, duration);
+
return convertNodesToSwhIds(nodeIds);
}
/**
* Neighbors endpoint wrapper (performs input/output node ids conversions).
*
* @param src source node of endpoint call specified as a SwhId
* @return the resulting list of SwhId from endpoint call
* @see org.softwareheritage.graph.SwhId
* @see org.softwareheritage.graph.algo.Traversal#neighbors(long)
*/
public ArrayList neighbors(SwhId src) {
long srcNodeId = graph.getNodeId(src);
+
+ long startTime = this.startTiming();
ArrayList nodeIds = traversal.neighbors(srcNodeId);
+ float duration = this.stopTiming(startTime);
+ logger.debug("neighbors({}) took {} s.", src, duration);
+
return convertNodesToSwhIds(nodeIds);
}
/**
* Walk endpoint wrapper (performs input/output node ids conversions).
*
* @param src source node of endpoint call specified as a SwhId
* @param dstFmt destination used in endpoint call (TODO: link to API doc)
* @param algorithm traversal algorithm used in endpoint call (either "dfs" or "bfs")
* @return the resulting {@link SwhPath} from endpoint call
* @see org.softwareheritage.graph.SwhId
* @see org.softwareheritage.graph.SwhPath
* @see org.softwareheritage.graph.algo.Traversal#walk
*/
public SwhPath walk(SwhId src, String dstFmt, String algorithm) {
long srcNodeId = graph.getNodeId(src);
ArrayList nodeIds = null;
// Destination is either a SWH ID or a node type
try {
SwhId dstSwhId = new SwhId(dstFmt);
long dstNodeId = graph.getNodeId(dstSwhId);
+
+ long startTime = this.startTiming();
nodeIds = traversal.walk(srcNodeId, dstNodeId, algorithm);
+ float duration = this.stopTiming(startTime);
+ logger.debug("walk({}) took {} s.", src, duration);
} catch (IllegalArgumentException ignored1) {
try {
Node.Type dstType = Node.Type.fromStr(dstFmt);
+
+ long startTime = this.startTiming();
nodeIds = traversal.walk(srcNodeId, dstType, algorithm);
+ float duration = this.stopTiming(startTime);
+ logger.debug("walk({}) took {} s.", src, duration);
} catch (IllegalArgumentException ignored2) { }
}
return convertNodesToSwhPath(nodeIds);
}
/**
* VisitNodes endpoint wrapper (performs input/output node ids conversions).
*
* @param src source node of endpoint call specified as a SwhId
* @return the resulting list of SwhId from endpoint call
* @see org.softwareheritage.graph.SwhId
* @see org.softwareheritage.graph.algo.Traversal#visitNodes(long)
*/
public ArrayList visitNodes(SwhId src) {
long srcNodeId = graph.getNodeId(src);
+
+ long startTime = this.startTiming();
ArrayList nodeIds = traversal.visitNodes(srcNodeId);
+ float duration = this.stopTiming(startTime);
+ logger.debug("visitNodes({}) took {} s.", src, duration);
+
return convertNodesToSwhIds(nodeIds);
}
/**
* VisitPaths endpoint wrapper (performs input/output node ids conversions).
*
* @param src source node of endpoint call specified as a SwhId
* @return the resulting list of {@link SwhPath} from endpoint call
* @see org.softwareheritage.graph.SwhId
* @see org.softwareheritage.graph.SwhPath
* @see org.softwareheritage.graph.algo.Traversal#visitPaths(long)
*/
public ArrayList visitPaths(SwhId src) {
long srcNodeId = graph.getNodeId(src);
+
+ long startTime = this.startTiming();
ArrayList> paths = traversal.visitPaths(srcNodeId);
+ float duration = this.stopTiming(startTime);
+ logger.debug("visitPaths({}) took {} s.", src, duration);
+
return convertPathsToSwhIds(paths);
}
}