blob: d2f86cd29f8e95a3c638e9921bd31d96cb23f24b [file] [log] [blame]
/*
* 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.graph;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
import org.apache.log4j.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* User applications can subclass {@link HashMapVertex}, which stores
* the outbound edges in a HashMap, for efficient edge random-access. Note
* that {@link EdgeListVertex} is much more memory efficient for static graphs.
* User applications which need to implement their own
* in-memory data structures should subclass {@link MutableVertex}.
*
* Package access will prevent users from accessing internal methods.
*
* @param <I> Vertex index value
* @param <V> Vertex value
* @param <E> Edge value
* @param <M> Message value
*/
@SuppressWarnings("rawtypes")
public abstract class HashMapVertex<I extends WritableComparable,
V extends Writable, E extends Writable, M extends Writable>
extends MutableVertex<I, V, E, M> {
/** Class logger */
private static final Logger LOG = Logger.getLogger(HashMapVertex.class);
/** Vertex id */
private I vertexId = null;
/** Vertex value */
private V vertexValue = null;
/** Map of destination vertices and their edge values */
protected final Map<I, Edge<I, E>> destEdgeMap =
new HashMap<I, Edge<I, E>>();
/** List of incoming messages from the previous superstep */
private final List<M> msgList = Lists.newArrayList();
@Override
public void initialize(
I vertexId, V vertexValue, Map<I, E> edges, Iterable<M> messages) {
if (vertexId != null) {
setVertexId(vertexId);
}
if (vertexValue != null) {
setVertexValue(vertexValue);
}
if (edges != null && !edges.isEmpty()) {
for (Map.Entry<I, E> entry : edges.entrySet()) {
destEdgeMap.put(
entry.getKey(),
new Edge<I, E>(entry.getKey(), entry.getValue()));
}
}
if (messages != null) {
Iterables.<M>addAll(msgList, messages);
}
}
@Override
public final boolean addEdge(I targetVertexId, E edgeValue) {
if (destEdgeMap.put(
targetVertexId,
new Edge<I, E>(targetVertexId, edgeValue)) != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("addEdge: Vertex=" + vertexId +
": already added an edge value for dest vertex id " +
targetVertexId);
}
return false;
} else {
return true;
}
}
@Override
public long getSuperstep() {
return getGraphState().getSuperstep();
}
@Override
public final void setVertexId(I vertexId) {
this.vertexId = vertexId;
}
@Override
public final I getVertexId() {
return vertexId;
}
@Override
public final V getVertexValue() {
return vertexValue;
}
@Override
public final void setVertexValue(V vertexValue) {
this.vertexValue = vertexValue;
}
@Override
public E getEdgeValue(I targetVertexId) {
Edge<I, E> edge = destEdgeMap.get(targetVertexId);
return edge != null ? edge.getEdgeValue() : null;
}
@Override
public boolean hasEdge(I targetVertexId) {
return destEdgeMap.containsKey(targetVertexId);
}
/**
* Get an iterator to the edges on this vertex.
*
* @return A <em>sorted</em> iterator, as defined by the sort-order
* of the vertex ids
*/
@Override
public Iterator<I> iterator() {
return destEdgeMap.keySet().iterator();
}
@Override
public int getNumOutEdges() {
return destEdgeMap.size();
}
@Override
public E removeEdge(I targetVertexId) {
Edge<I, E> edge = destEdgeMap.remove(targetVertexId);
if (edge != null) {
return edge.getEdgeValue();
} else {
return null;
}
}
@Override
public final void sendMsgToAllEdges(M msg) {
if (msg == null) {
throw new IllegalArgumentException(
"sendMsgToAllEdges: Cannot send null message to all edges");
}
for (Edge<I, E> edge : destEdgeMap.values()) {
sendMsg(edge.getDestVertexId(), msg);
}
}
@Override
final public void readFields(DataInput in) throws IOException {
vertexId = BspUtils.<I>createVertexIndex(getConf());
vertexId.readFields(in);
boolean hasVertexValue = in.readBoolean();
if (hasVertexValue) {
vertexValue = BspUtils.<V>createVertexValue(getConf());
vertexValue.readFields(in);
}
long edgeMapSize = in.readLong();
for (long i = 0; i < edgeMapSize; ++i) {
Edge<I, E> edge = new Edge<I, E>();
edge.setConf(getConf());
edge.readFields(in);
addEdge(edge.getDestVertexId(), edge.getEdgeValue());
}
long msgListSize = in.readLong();
for (long i = 0; i < msgListSize; ++i) {
M msg = BspUtils.<M>createMessageValue(getConf());
msg.readFields(in);
msgList.add(msg);
}
halt = in.readBoolean();
}
@Override
final public void write(DataOutput out) throws IOException {
vertexId.write(out);
out.writeBoolean(vertexValue != null);
if (vertexValue != null) {
vertexValue.write(out);
}
out.writeLong(destEdgeMap.size());
for (Edge<I, E> edge : destEdgeMap.values()) {
edge.write(out);
}
out.writeLong(msgList.size());
for (M msg : msgList) {
msg.write(out);
}
out.writeBoolean(halt);
}
@Override
void putMessages(Iterable<M> messages) {
msgList.clear();
for (M message : messages) {
msgList.add(message);
}
}
@Override
public Iterable<M> getMessages() {
return Iterables.unmodifiableIterable(msgList);
}
@Override
void releaseResources() {
// Hint to GC to free the messages
msgList.clear();
}
@Override
public String toString() {
return "Vertex(id=" + getVertexId() + ",value=" + getVertexValue() +
",#edges=" + destEdgeMap.size() + ")";
}
}