package edu.cmu.graphchi.shards; import java.io.*; import java.util.ArrayList; import java.util.Arrays; /** * Encapsulates a sparse index to shard's edges. * Can be used for fast queries or for parallelizing access (memoryshard). */ public class ShardIndex { File indexFile; private int[] vertices; private int[] edgePointer; private int[] fileOffset; public ShardIndex(File adjFile) throws IOException { this.indexFile = new File(adjFile.getAbsolutePath() + ".index"); load(); } private void load() throws IOException { int n = (int) (indexFile.length() / 12) + 1; vertices = new int[n]; edgePointer = new int[n]; fileOffset = new int[n]; vertices[0] = 0; edgePointer[0] = 0; fileOffset[0] = 0; DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(indexFile))); int i = 1; while (i < n) { vertices[i] = dis.readInt(); fileOffset[i] = dis.readInt(); edgePointer[i] = dis.readInt(); i++; } } /** * Returns a sparsified index, which starts with a zero-pointer (and is thus always non-empty) */ public ArrayList<IndexEntry> sparserIndex(int edgeDistance) { ArrayList<IndexEntry> spIdx = new ArrayList<IndexEntry>(); spIdx.add(new IndexEntry(0, 0, 0)); int lastEdgePointer = 0; for(int j=0; j<vertices.length; j++) { if (edgePointer[j] - lastEdgePointer >= edgeDistance) { spIdx.add(new IndexEntry(vertices[j], edgePointer[j], fileOffset[j])); lastEdgePointer = edgePointer[j]; } } return spIdx; } /** * Finds closest index entry for given vertex id, which is before the vertex. * @param vertexId * @return */ public IndexEntry lookup(int vertexId) { int idx = Arrays.binarySearch(vertices, vertexId); if (idx >= 0) { return new IndexEntry(vertexId, edgePointer[idx], fileOffset[idx]); } else { idx = -(idx + 1) - 1; return new IndexEntry(vertices[idx], edgePointer[idx], fileOffset[idx]); } } public static class IndexEntry { public int vertex, edgePointer, fileOffset; IndexEntry(int vertex, int edgePointer, int fileOffset) { this.vertex = vertex; this.edgePointer = edgePointer; this.fileOffset = fileOffset; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; IndexEntry that = (IndexEntry) o; if (edgePointer != that.edgePointer) return false; if (fileOffset != that.fileOffset) return false; if (vertex != that.vertex) return false; return true; } @Override public int hashCode() { int result = vertex; result = 31 * result + edgePointer; result = 31 * result + fileOffset; return result; } public String toString() { return "vertex: " + vertex + ", offset=" + fileOffset; } } }