@Override public void reduce(IntWritable nid, Iterable<PageRankNode> values, Context context) throws IOException, InterruptedException { int massMessages = 0; // Remember, PageRank mass is stored as a log prob. float mass = Float.NEGATIVE_INFINITY; for (PageRankNode n : values) { if (n.getType() == PageRankNode.Type.Structure) { // Simply pass along node structure. context.write(nid, n); } else { // Accumulate PageRank mass contributions. mass = sumLogProbs(mass, n.getPageRank()); massMessages++; } } // Emit aggregated results. if (massMessages > 0) { intermediateMass.setNodeId(nid.get()); intermediateMass.setType(PageRankNode.Type.Mass); intermediateMass.setPageRank(mass); context.write(nid, intermediateMass); } }
@Override public void reduce(IntWritable nid, Iterable<PageRankNode> iterable, Context context) throws IOException, InterruptedException { Iterator<PageRankNode> values = iterable.iterator(); // Create the node structure that we're going to assemble back together from shuffled pieces. PageRankNode node = new PageRankNode(); node.setType(PageRankNode.Type.Complete); node.setNodeId(nid.get()); int massMessagesReceived = 0; int structureReceived = 0; float mass = Float.NEGATIVE_INFINITY; while (values.hasNext()) { PageRankNode n = values.next(); if (n.getType().equals(PageRankNode.Type.Structure)) { // This is the structure; update accordingly. ArrayListOfIntsWritable list = n.getAdjacenyList(); structureReceived++; node.setAdjacencyList(list); } else { // This is a message that contains PageRank mass; accumulate. mass = sumLogProbs(mass, n.getPageRank()); massMessagesReceived++; } } // Update the final accumulated PageRank mass. node.setPageRank(mass); context.getCounter(PageRank.massMessagesReceived).increment(massMessagesReceived); // Error checking. if (structureReceived == 1) { // Everything checks out, emit final node structure with updated PageRank value. context.write(nid, node); // Keep track of total PageRank mass. totalMass = sumLogProbs(totalMass, mass); } else if (structureReceived == 0) { // We get into this situation if there exists an edge pointing to a node which has no // corresponding node structure (i.e., PageRank mass was passed to a non-existent node)... // log and count but move on. context.getCounter(PageRank.missingStructure).increment(1); LOG.warn( "No structure received for nodeid: " + nid.get() + " mass: " + massMessagesReceived); // It's important to note that we don't add the PageRank mass to total... if PageRank mass // was sent to a non-existent node, it should simply vanish. } else { // This shouldn't happen! throw new RuntimeException( "Multiple structure received for nodeid: " + nid.get() + " mass: " + massMessagesReceived + " struct: " + structureReceived); } }