Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9345631
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
29 KB
Subscribers
None
View Options
diff --git a/java/src/main/java/org/softwareheritage/graph/SwhBidirectionalGraph.java b/java/src/main/java/org/softwareheritage/graph/SwhBidirectionalGraph.java
index 824a389..7e70f9e 100644
--- a/java/src/main/java/org/softwareheritage/graph/SwhBidirectionalGraph.java
+++ b/java/src/main/java/org/softwareheritage/graph/SwhBidirectionalGraph.java
@@ -1,180 +1,180 @@
package org.softwareheritage.graph;
import it.unimi.dsi.big.webgraph.labelling.ArcLabelledNodeIterator;
import it.unimi.dsi.big.webgraph.BidirectionalImmutableGraph;
import it.unimi.dsi.logging.ProgressLogger;
import java.io.IOException;
import java.io.InputStream;
/**
* Class representing the compressed Software Heritage graph in both directions (forward and
* backward).
*
* This class uses the {@link BidirectionalImmutableGraph} class internally to implement the
* backward equivalent of graph operations ({@link SwhBidirectionalGraph#indegree(long)},
* {@link SwhBidirectionalGraph#predecessors(long)}, etc.) by holding a reference to two
* {@link SwhUnidirectionalGraph} (a forward graph and a backward graph).
*
* Both graphs share their graph properties in memory by storing references to the same
* {@link SwhGraphProperties} object.
*
* <pre>
* ┌──────────────┐
* │ImmutableGraph◄────────┐
* └────▲─────────┘ │extends
* │ │
* │ ┌──────────┴────────────────┐
* extends│ │BidirectionalImmutableGraph│
* │ └────────────▲──────────────┘
* │ │extends
* ┌──────────────┴───────┐ ┌──────┴──────────────┐
* │SwhUnidirectionalGraph│◄────┤SwhBidirectionalGraph│
* └──┬──────────────┬────┘ └────────┬───────────┬┘
* │ │ contains x2 │ │
* │ │ │ │
* │ implements│ │implements │
* │ ┌▼──────────┐ │ │
* │ │SwhGraph(I)◄────────┘ │
* contains │ └───────────┘ │contains
* │ │
* │ ┌──────────────────┐ │
* └────────────►SwhGraphProperties◄──────────────┘
* └──────────────────┘
* </pre>
*
* @author The Software Heritage developers
* @see SwhUnidirectionalGraph
*/
public class SwhBidirectionalGraph extends BidirectionalImmutableGraph implements SwhGraph {
/** Property data of the graph (id/type mappings etc.) */
public final SwhGraphProperties properties;
private final SwhUnidirectionalGraph forwardGraph;
private final SwhUnidirectionalGraph backwardGraph;
public SwhBidirectionalGraph(SwhUnidirectionalGraph forwardGraph, SwhUnidirectionalGraph backwardGraph,
SwhGraphProperties properties) {
super(forwardGraph, backwardGraph);
this.forwardGraph = forwardGraph;
this.backwardGraph = backwardGraph;
this.properties = properties;
}
private SwhBidirectionalGraph(BidirectionalImmutableGraph graph, SwhGraphProperties properties) {
super(graph.forward, graph.backward);
- this.forwardGraph = (SwhUnidirectionalGraph) graph.forward;
- this.backwardGraph = (SwhUnidirectionalGraph) graph.backward;
+ this.forwardGraph = new SwhUnidirectionalGraph(graph.forward, properties);
+ this.backwardGraph = new SwhUnidirectionalGraph(graph.backward, properties);
this.properties = properties;
}
public static SwhBidirectionalGraph load(LoadMethod method, String path, InputStream is, ProgressLogger pl)
throws IOException {
SwhUnidirectionalGraph forward = SwhUnidirectionalGraph.loadGraphOnly(method, path, is, pl);
SwhUnidirectionalGraph backward = SwhUnidirectionalGraph.loadGraphOnly(method, path + "-transposed", is, pl);
SwhGraphProperties properties = SwhGraphProperties.load(path);
forward.setProperties(properties);
backward.setProperties(properties);
return new SwhBidirectionalGraph(forward, backward, properties);
}
public static SwhBidirectionalGraph loadLabelled(LoadMethod method, String path, InputStream is, ProgressLogger pl)
throws IOException {
SwhUnidirectionalGraph forward = SwhUnidirectionalGraph.loadLabelledGraphOnly(method, path, is, pl);
SwhUnidirectionalGraph backward = SwhUnidirectionalGraph.loadLabelledGraphOnly(method, path + "-transposed", is,
pl);
SwhGraphProperties properties = SwhGraphProperties.load(path);
forward.setProperties(properties);
backward.setProperties(properties);
return new SwhBidirectionalGraph(forward, backward, properties);
}
// loadXXX methods from ImmutableGraph
public static SwhBidirectionalGraph load(String path, ProgressLogger pl) throws IOException {
return load(LoadMethod.STANDARD, path, null, pl);
}
public static SwhBidirectionalGraph load(String path) throws IOException {
return load(LoadMethod.STANDARD, path, null, null);
}
public static SwhBidirectionalGraph loadMapped(String path, ProgressLogger pl) throws IOException {
return load(LoadMethod.MAPPED, path, null, pl);
}
public static SwhBidirectionalGraph loadMapped(String path) throws IOException {
return load(LoadMethod.MAPPED, path, null, null);
}
public static SwhBidirectionalGraph loadOffline(String path, ProgressLogger pl) throws IOException {
return load(LoadMethod.OFFLINE, path, null, pl);
}
public static SwhBidirectionalGraph loadOffline(String path) throws IOException {
return load(LoadMethod.OFFLINE, path, null, null);
}
// Labelled versions of the loadXXX methods from ImmutableGraph
public static SwhBidirectionalGraph loadLabelled(String path, ProgressLogger pl) throws IOException {
return loadLabelled(LoadMethod.STANDARD, path, null, pl);
}
public static SwhBidirectionalGraph loadLabelled(String path) throws IOException {
return loadLabelled(LoadMethod.STANDARD, path, null, null);
}
public static SwhBidirectionalGraph loadLabelledMapped(String path, ProgressLogger pl) throws IOException {
return loadLabelled(LoadMethod.MAPPED, path, null, pl);
}
public static SwhBidirectionalGraph loadLabelledMapped(String path) throws IOException {
return loadLabelled(LoadMethod.MAPPED, path, null, null);
}
public static SwhBidirectionalGraph loadLabelledOffline(String path, ProgressLogger pl) throws IOException {
return loadLabelled(LoadMethod.OFFLINE, path, null, pl);
}
public static SwhBidirectionalGraph loadLabelledOffline(String path) throws IOException {
return loadLabelled(LoadMethod.OFFLINE, path, null, null);
}
@Override
public SwhBidirectionalGraph copy() {
return new SwhBidirectionalGraph(forwardGraph, backwardGraph, this.properties);
}
@Override
public SwhBidirectionalGraph transpose() {
return new SwhBidirectionalGraph(super.transpose(), this.properties);
}
@Override
public SwhBidirectionalGraph symmetrize() {
return new SwhBidirectionalGraph(super.symmetrize(), this.properties);
}
public SwhUnidirectionalGraph getForwardGraph() {
return this.forwardGraph;
}
public SwhUnidirectionalGraph getBackwardGraph() {
return this.backwardGraph;
}
/**
* Returns a *labelled* lazy iterator over the successors of a given node. The iteration terminates
* when -1 is returned.
*/
public ArcLabelledNodeIterator.LabelledArcIterator labelledSuccessors(long x) {
return forwardGraph.labelledSuccessors(x);
}
/**
* Returns a *labelled* lazy iterator over the predecessors of a given node. The iteration
* terminates when -1 is returned.
*/
public ArcLabelledNodeIterator.LabelledArcIterator labelledPredecessors(long x) {
return backwardGraph.labelledSuccessors(x);
}
public void close() throws IOException {
this.properties.close();
}
@Override
public SwhGraphProperties getProperties() {
return properties;
}
}
diff --git a/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java b/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java
index 5f50596..58aaf91 100644
--- a/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java
+++ b/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java
@@ -1,426 +1,429 @@
package org.softwareheritage.graph.rpc;
import it.unimi.dsi.big.webgraph.labelling.ArcLabelledNodeIterator;
import it.unimi.dsi.big.webgraph.labelling.Label;
import org.softwareheritage.graph.*;
import java.util.*;
public class Traversal {
private static ArcLabelledNodeIterator.LabelledArcIterator filterLabelledSuccessors(SwhUnidirectionalGraph g,
long nodeId, AllowedEdges allowedEdges) {
if (allowedEdges.restrictedTo == null) {
// All edges are allowed, bypass edge check
return g.labelledSuccessors(nodeId);
} else {
ArcLabelledNodeIterator.LabelledArcIterator allSuccessors = g.labelledSuccessors(nodeId);
return new ArcLabelledNodeIterator.LabelledArcIterator() {
@Override
public Label label() {
return allSuccessors.label();
}
@Override
public long nextLong() {
long neighbor;
while ((neighbor = allSuccessors.nextLong()) != -1) {
if (allowedEdges.isAllowed(g.getNodeType(nodeId), g.getNodeType(neighbor))) {
return neighbor;
}
}
return -1;
}
@Override
public long skip(final long n) {
long i = 0;
while (i < n && nextLong() != -1)
i++;
return i;
}
};
}
}
private static class NodeFilterChecker {
private final SwhUnidirectionalGraph g;
private final NodeFilter filter;
private final AllowedNodes allowedNodes;
private NodeFilterChecker(SwhUnidirectionalGraph graph, NodeFilter filter) {
this.g = graph;
this.filter = filter;
this.allowedNodes = new AllowedNodes(filter.hasTypes() ? filter.getTypes() : "*");
}
public boolean allowed(long nodeId) {
if (filter == null) {
return true;
}
if (!this.allowedNodes.isAllowed(g.getNodeType(nodeId))) {
return false;
}
return true;
}
}
public static SwhUnidirectionalGraph getDirectedGraph(SwhBidirectionalGraph g, GraphDirection direction) {
switch (direction) {
case FORWARD:
return g.getForwardGraph();
case BACKWARD:
return g.getBackwardGraph();
- case BOTH:
- return new SwhUnidirectionalGraph(g.symmetrize(), g.getProperties());
+ /*
+ * TODO: add support for BOTH case BOTH: return new SwhUnidirectionalGraph(g.symmetrize(),
+ * g.getProperties());
+ */
default :
throw new IllegalArgumentException("Unknown direction: " + direction);
}
}
public static GraphDirection reverseDirection(GraphDirection direction) {
switch (direction) {
case FORWARD:
return GraphDirection.BACKWARD;
case BACKWARD:
return GraphDirection.FORWARD;
- case BOTH:
- return GraphDirection.BOTH;
+ /*
+ * TODO: add support for BOTH case BOTH: return GraphDirection.BOTH;
+ */
default :
throw new IllegalArgumentException("Unknown direction: " + direction);
}
}
static class StopTraversalException extends RuntimeException {
}
static class BFSVisitor {
protected final SwhUnidirectionalGraph g;
protected long depth = 0;
protected long traversalSuccessors = 0;
protected long edgesAccessed = 0;
protected HashMap<Long, Long> parents = new HashMap<>();
protected ArrayDeque<Long> queue = new ArrayDeque<>();
private long maxDepth = -1;
private long maxEdges = -1;
BFSVisitor(SwhUnidirectionalGraph g) {
this.g = g;
}
public void addSource(long nodeId) {
queue.add(nodeId);
parents.put(nodeId, -1L);
}
public void setMaxDepth(long depth) {
maxDepth = depth;
}
public void setMaxEdges(long edges) {
maxEdges = edges;
}
public void visitSetup() {
edgesAccessed = 0;
depth = 0;
queue.add(-1L); // depth sentinel
}
public void visit() {
visitSetup();
try {
while (!queue.isEmpty()) {
visitStep();
}
} catch (StopTraversalException e) {
// Ignore
}
}
public void visitStep() {
assert !queue.isEmpty();
long curr = queue.poll();
if (curr == -1L) {
++depth;
if (!queue.isEmpty()) {
queue.add(-1L);
visitStep();
}
return;
}
if (maxDepth >= 0 && depth > maxDepth) {
throw new StopTraversalException();
}
edgesAccessed += g.outdegree(curr);
if (maxEdges >= 0 && edgesAccessed >= maxEdges) {
throw new StopTraversalException();
}
visitNode(curr);
}
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) {
return g.labelledSuccessors(nodeId);
}
protected void visitNode(long node) {
ArcLabelledNodeIterator.LabelledArcIterator it = getSuccessors(node);
traversalSuccessors = 0;
for (long succ; (succ = it.nextLong()) != -1;) {
traversalSuccessors++;
visitEdge(node, succ, it.label());
}
}
protected void visitEdge(long src, long dst, Label label) {
if (!parents.containsKey(dst)) {
queue.add(dst);
parents.put(dst, src);
}
}
}
static class SimpleTraversal extends BFSVisitor {
private final NodeFilterChecker nodeReturnChecker;
private final AllowedEdges allowedEdges;
private final TraversalRequest request;
private final NodePropertyBuilder.NodeDataMask nodeDataMask;
private final NodeObserver nodeObserver;
private Node.Builder nodeBuilder;
SimpleTraversal(SwhBidirectionalGraph bidirectionalGraph, TraversalRequest request, NodeObserver nodeObserver) {
super(getDirectedGraph(bidirectionalGraph, request.getDirection()));
this.request = request;
this.nodeObserver = nodeObserver;
this.nodeReturnChecker = new NodeFilterChecker(g, request.getReturnNodes());
this.nodeDataMask = new NodePropertyBuilder.NodeDataMask(request.hasMask() ? request.getMask() : null);
this.allowedEdges = new AllowedEdges(request.hasEdges() ? request.getEdges() : "*");
request.getSrcList().forEach(srcSwhid -> {
long srcNodeId = g.getNodeId(new SWHID(srcSwhid));
addSource(srcNodeId);
});
if (request.hasMaxDepth()) {
setMaxDepth(request.getMaxDepth());
}
if (request.hasMaxEdges()) {
setMaxEdges(request.getMaxEdges());
}
}
@Override
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) {
return filterLabelledSuccessors(g, nodeId, allowedEdges);
}
@Override
public void visitNode(long node) {
nodeBuilder = null;
if (nodeReturnChecker.allowed(node) && (!request.hasMinDepth() || depth >= request.getMinDepth())) {
nodeBuilder = Node.newBuilder();
NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, node);
}
super.visitNode(node);
if (request.getReturnNodes().hasMinTraversalSuccessors()
&& traversalSuccessors < request.getReturnNodes().getMinTraversalSuccessors()
|| request.getReturnNodes().hasMaxTraversalSuccessors()
&& traversalSuccessors > request.getReturnNodes().getMaxTraversalSuccessors()) {
nodeBuilder = null;
}
if (nodeBuilder != null) {
nodeObserver.onNext(nodeBuilder.build());
}
}
@Override
protected void visitEdge(long src, long dst, Label label) {
super.visitEdge(src, dst, label);
NodePropertyBuilder.buildSuccessorProperties(g, nodeDataMask, nodeBuilder, src, dst, label);
}
}
static class FindPathTo extends BFSVisitor {
private final AllowedEdges allowedEdges;
private final FindPathToRequest request;
private final NodePropertyBuilder.NodeDataMask nodeDataMask;
private final NodeFilterChecker targetChecker;
private Long targetNode = null;
FindPathTo(SwhBidirectionalGraph bidirectionalGraph, FindPathToRequest request) {
super(getDirectedGraph(bidirectionalGraph, request.getDirection()));
this.request = request;
this.targetChecker = new NodeFilterChecker(g, request.getTarget());
this.nodeDataMask = new NodePropertyBuilder.NodeDataMask(request.hasMask() ? request.getMask() : null);
this.allowedEdges = new AllowedEdges(request.hasEdges() ? request.getEdges() : "*");
if (request.hasMaxDepth()) {
setMaxDepth(request.getMaxDepth());
}
if (request.hasMaxEdges()) {
setMaxEdges(request.getMaxEdges());
}
request.getSrcList().forEach(srcSwhid -> {
long srcNodeId = g.getNodeId(new SWHID(srcSwhid));
addSource(srcNodeId);
});
}
@Override
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) {
return filterLabelledSuccessors(g, nodeId, allowedEdges);
}
@Override
public void visitNode(long node) {
if (targetChecker.allowed(node)) {
targetNode = node;
throw new StopTraversalException();
}
super.visitNode(node);
}
public Path getPath() {
if (targetNode == null) {
return null;
}
Path.Builder pathBuilder = Path.newBuilder();
long curNode = targetNode;
ArrayList<Long> path = new ArrayList<>();
while (curNode != -1) {
path.add(curNode);
curNode = parents.get(curNode);
}
Collections.reverse(path);
for (long nodeId : path) {
Node.Builder nodeBuilder = Node.newBuilder();
NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, nodeId);
pathBuilder.addNode(nodeBuilder.build());
}
return pathBuilder.build();
}
}
static class FindPathBetween extends BFSVisitor {
private final FindPathBetweenRequest request;
private final NodePropertyBuilder.NodeDataMask nodeDataMask;
private final AllowedEdges allowedEdgesSrc;
private final AllowedEdges allowedEdgesDst;
private final BFSVisitor srcVisitor;
private final BFSVisitor dstVisitor;
private Long middleNode = null;
FindPathBetween(SwhBidirectionalGraph bidirectionalGraph, FindPathBetweenRequest request) {
super(getDirectedGraph(bidirectionalGraph, request.getDirection()));
this.request = request;
this.nodeDataMask = new NodePropertyBuilder.NodeDataMask(request.hasMask() ? request.getMask() : null);
this.allowedEdgesSrc = new AllowedEdges(request.hasEdges() ? request.getEdges() : "*");
this.allowedEdgesDst = request.hasEdgesReverse()
? new AllowedEdges(request.getEdgesReverse())
: (request.hasEdges() ? new AllowedEdges(request.getEdges()).reverse() : new AllowedEdges("*"));
SwhUnidirectionalGraph srcGraph = getDirectedGraph(bidirectionalGraph, request.getDirection());
SwhUnidirectionalGraph dstGraph = getDirectedGraph(bidirectionalGraph,
request.hasDirectionReverse()
? request.getDirectionReverse()
: reverseDirection(request.getDirection()));
this.srcVisitor = new BFSVisitor(srcGraph) {
@Override
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) {
return filterLabelledSuccessors(g, nodeId, allowedEdgesSrc);
}
@Override
public void visitNode(long node) {
if (dstVisitor.parents.containsKey(node)) {
middleNode = node;
throw new StopTraversalException();
}
super.visitNode(node);
}
};
this.dstVisitor = new BFSVisitor(dstGraph) {
@Override
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) {
return filterLabelledSuccessors(g, nodeId, allowedEdgesDst);
}
@Override
public void visitNode(long node) {
if (dstVisitor.parents.containsKey(node)) {
middleNode = node;
throw new StopTraversalException();
}
super.visitNode(node);
}
};
if (request.hasMaxDepth()) {
this.srcVisitor.setMaxDepth(request.getMaxDepth());
this.dstVisitor.setMaxDepth(request.getMaxDepth());
}
if (request.hasMaxEdges()) {
this.srcVisitor.setMaxEdges(request.getMaxEdges());
this.dstVisitor.setMaxEdges(request.getMaxEdges());
}
request.getSrcList().forEach(srcSwhid -> {
long srcNodeId = g.getNodeId(new SWHID(srcSwhid));
srcVisitor.addSource(srcNodeId);
});
request.getDstList().forEach(srcSwhid -> {
long srcNodeId = g.getNodeId(new SWHID(srcSwhid));
dstVisitor.addSource(srcNodeId);
});
}
@Override
public void visit() {
srcVisitor.visitSetup();
dstVisitor.visitSetup();
while (!srcVisitor.queue.isEmpty() || !dstVisitor.queue.isEmpty()) {
try {
if (!srcVisitor.queue.isEmpty()) {
srcVisitor.visitStep();
}
} catch (StopTraversalException e) {
srcVisitor.queue.clear();
}
try {
if (!dstVisitor.queue.isEmpty()) {
dstVisitor.visitStep();
}
} catch (StopTraversalException e) {
dstVisitor.queue.clear();
}
}
}
public Path getPath() {
if (middleNode == null) {
return null;
}
Path.Builder pathBuilder = Path.newBuilder();
ArrayList<Long> path = new ArrayList<>();
long curNode = middleNode;
while (curNode != -1) {
path.add(curNode);
curNode = srcVisitor.parents.get(curNode);
}
Collections.reverse(path);
curNode = dstVisitor.parents.get(middleNode);
while (curNode != -1) {
path.add(curNode);
curNode = dstVisitor.parents.get(curNode);
}
for (long nodeId : path) {
Node.Builder nodeBuilder = Node.newBuilder();
NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, nodeId);
pathBuilder.addNode(nodeBuilder.build());
}
return pathBuilder.build();
}
}
public interface NodeObserver {
void onNext(Node nodeId);
}
}
diff --git a/proto/swhgraph.proto b/proto/swhgraph.proto
index 3687c8e..95ec45c 100644
--- a/proto/swhgraph.proto
+++ b/proto/swhgraph.proto
@@ -1,155 +1,154 @@
syntax = "proto3";
import "google/protobuf/field_mask.proto";
option java_multiple_files = true;
option java_package = "org.softwareheritage.graph.rpc";
option java_outer_classname = "GraphService";
package swh.graph;
service TraversalService {
rpc Traverse (TraversalRequest) returns (stream Node);
rpc FindPathTo (FindPathToRequest) returns (Path);
rpc FindPathBetween (FindPathBetweenRequest) returns (Path);
rpc CountNodes (TraversalRequest) returns (CountResponse);
rpc CountEdges (TraversalRequest) returns (CountResponse);
rpc Stats (StatsRequest) returns (StatsResponse);
rpc CheckSwhid (CheckSwhidRequest) returns (CheckSwhidResponse);
rpc GetNode (GetNodeRequest) returns (Node);
}
enum GraphDirection {
FORWARD = 0;
BACKWARD = 1;
- BOTH = 2;
}
message TraversalRequest {
repeated string src = 1;
GraphDirection direction = 2;
optional string edges = 3;
optional int64 max_edges = 4;
optional int64 min_depth = 5;
optional int64 max_depth = 6;
optional NodeFilter return_nodes = 7;
optional google.protobuf.FieldMask mask = 8;
}
message FindPathToRequest {
repeated string src = 1;
optional NodeFilter target = 2;
GraphDirection direction = 3;
optional string edges = 4;
optional int64 max_edges = 5;
optional int64 max_depth = 6;
optional google.protobuf.FieldMask mask = 7;
}
message FindPathBetweenRequest {
repeated string src = 1;
repeated string dst = 2;
GraphDirection direction = 3;
optional GraphDirection direction_reverse = 4;
optional string edges = 5;
optional string edges_reverse = 6;
optional int64 max_edges = 7;
optional int64 max_depth = 8;
optional google.protobuf.FieldMask mask = 9;
}
message NodeFilter {
optional string types = 1;
optional int64 min_traversal_successors = 2;
optional int64 max_traversal_successors = 3;
}
message Node {
string swhid = 1;
repeated Successor successor = 2;
oneof data {
ContentData cnt = 3;
RevisionData rev = 5;
ReleaseData rel = 6;
OriginData ori = 8;
};
}
message Path {
repeated Node node = 1;
}
message Successor {
optional string swhid = 1;
repeated EdgeLabel label = 2;
}
message ContentData {
optional int64 length = 1;
optional bool is_skipped = 2;
}
message RevisionData {
optional int64 author = 1;
optional int64 author_date = 2;
optional int32 author_date_offset = 3;
optional int64 committer = 4;
optional int64 committer_date = 5;
optional int32 committer_date_offset = 6;
optional bytes message = 7;
}
message ReleaseData {
optional int64 author = 1;
optional int64 author_date = 2;
optional int32 author_date_offset = 3;
optional bytes name = 4;
optional bytes message = 5;
}
message OriginData {
optional string url = 1;
}
message EdgeLabel {
bytes name = 1;
int32 permission = 2;
}
message CountResponse {
int64 count = 1;
}
message StatsRequest {
}
message StatsResponse {
int64 num_nodes = 1;
int64 num_edges = 2;
double compression = 3;
double bits_per_node = 4;
double bits_per_edge = 5;
double avg_locality = 6;
int64 indegree_min = 7;
int64 indegree_max = 8;
double indegree_avg = 9;
int64 outdegree_min = 10;
int64 outdegree_max = 11;
double outdegree_avg = 12;
}
message CheckSwhidRequest {
string swhid = 1;
}
message GetNodeRequest {
string swhid = 1;
optional google.protobuf.FieldMask mask = 8;
}
message CheckSwhidResponse {
bool exists = 1;
string details = 2;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jul 4, 3:27 PM (1 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3295067
Attached To
rDGRPH Compressed graph representation
Event Timeline
Log In to Comment