/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.giraph.examples; import org.apache.giraph.aggregators.LongSumAggregator; import org.apache.giraph.graph.BasicComputation; import org.apache.giraph.edge.Edge; import org.apache.giraph.edge.EdgeFactory; import org.apache.giraph.master.DefaultMasterCompute; import org.apache.giraph.graph.Vertex; import org.apache.giraph.worker.WorkerContext; import org.apache.hadoop.io.FloatWritable; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Writable; import org.apache.log4j.Logger; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; /** * An example that simply uses its id, value, and edges to compute new data * every iteration to verify that messages are sent and received at the * appropriate location and superstep. */ public class VerifyMessage { /** * Message that will be sent in {@link VerifyMessageComputation}. */ public static class VerifiableMessage implements Writable { /** Superstep sent on */ private long superstep; /** Source vertex id */ private long sourceVertexId; /** Value */ private float value; /** * Default constructor used with reflection. */ public VerifiableMessage() { } /** * Constructor with verifiable arguments. * @param superstep Superstep this message was created on. * @param sourceVertexId Who send this message. * @param value A value associated with this message. */ public VerifiableMessage( long superstep, long sourceVertexId, float value) { this.superstep = superstep; this.sourceVertexId = sourceVertexId; this.value = value; } @Override public void readFields(DataInput input) throws IOException { superstep = input.readLong(); sourceVertexId = input.readLong(); value = input.readFloat(); } @Override public void write(DataOutput output) throws IOException { output.writeLong(superstep); output.writeLong(sourceVertexId); output.writeFloat(value); } @Override public String toString() { return "(superstep=" + superstep + ",sourceVertexId=" + sourceVertexId + ",value=" + value + ")"; } } /** * Send and verify messages. */ public static class VerifyMessageComputation extends BasicComputation<LongWritable, IntWritable, FloatWritable, VerifiableMessage> { /** Dynamically set number of SUPERSTEPS */ public static final String SUPERSTEP_COUNT = "verifyMessageVertex.superstepCount"; /** User can access this after the application finishes if local */ private static long FINAL_SUM; /** Number of SUPERSTEPS to run (6 by default) */ private static int SUPERSTEPS = 6; /** Class logger */ private static Logger LOG = Logger.getLogger(VerifyMessageComputation.class); public static long getFinalSum() { return FINAL_SUM; } /** * Worker context used with {@link VerifyMessageComputation}. */ public static class VerifyMessageVertexWorkerContext extends WorkerContext { @Override public void preApplication() throws InstantiationException, IllegalAccessException { SUPERSTEPS = getContext().getConfiguration().getInt( SUPERSTEP_COUNT, SUPERSTEPS); } @Override public void postApplication() { LongWritable sumAggregatorValue = getAggregatedValue(LongSumAggregator.class.getName()); FINAL_SUM = sumAggregatorValue.get(); } @Override public void preSuperstep() { } @Override public void postSuperstep() { } } @Override public void compute( Vertex<LongWritable, IntWritable, FloatWritable> vertex, Iterable<VerifiableMessage> messages) throws IOException { String sumAggregatorName = LongSumAggregator.class.getName(); if (getSuperstep() > SUPERSTEPS) { vertex.voteToHalt(); return; } if (LOG.isDebugEnabled()) { LOG.debug("compute: " + getAggregatedValue(sumAggregatorName)); } aggregate(sumAggregatorName, new LongWritable(vertex.getId().get())); if (LOG.isDebugEnabled()) { LOG.debug("compute: sum = " + this.<LongWritable>getAggregatedValue(sumAggregatorName).get() + " for vertex " + vertex.getId()); } float msgValue = 0.0f; for (VerifiableMessage message : messages) { msgValue += message.value; if (LOG.isDebugEnabled()) { LOG.debug("compute: got msg = " + message + " for vertex id " + vertex.getId() + ", vertex value " + vertex.getValue() + " on superstep " + getSuperstep()); } if (message.superstep != getSuperstep() - 1) { throw new IllegalStateException( "compute: Impossible to not get a messsage from " + "the previous superstep, current superstep = " + getSuperstep()); } if ((message.sourceVertexId != vertex.getId().get() - 1) && (vertex.getId().get() != 0)) { throw new IllegalStateException( "compute: Impossible that this message didn't come " + "from the previous vertex and came from " + message.sourceVertexId); } } int vertexValue = vertex.getValue().get(); vertex.setValue(new IntWritable(vertexValue + (int) msgValue)); if (LOG.isDebugEnabled()) { LOG.debug("compute: vertex " + vertex.getId() + " has value " + vertex.getValue() + " on superstep " + getSuperstep()); } for (Edge<LongWritable, FloatWritable> edge : vertex.getEdges()) { FloatWritable newEdgeValue = new FloatWritable( edge.getValue().get() + (float) vertexValue); Edge<LongWritable, FloatWritable> newEdge = EdgeFactory.create(edge.getTargetVertexId(), newEdgeValue); if (LOG.isDebugEnabled()) { LOG.debug("compute: vertex " + vertex.getId() + " sending edgeValue " + edge.getValue() + " vertexValue " + vertexValue + " total " + newEdgeValue + " to vertex " + edge.getTargetVertexId() + " on superstep " + getSuperstep()); } vertex.addEdge(newEdge); sendMessage(edge.getTargetVertexId(), new VerifiableMessage( getSuperstep(), vertex.getId().get(), newEdgeValue.get())); } } } /** * Master compute associated with {@link VerifyMessageComputation}. * It registers required aggregators. */ public static class VerifyMessageMasterCompute extends DefaultMasterCompute { @Override public void initialize() throws InstantiationException, IllegalAccessException { registerAggregator(LongSumAggregator.class.getName(), LongSumAggregator.class); } } }