package edu.ucsb.jpregel.system; import api.Aggregator; import api.Vertex; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.infinispan.util.concurrent.jdk8backported.ConcurrentHashMapV8; /** * * @author Peter Cappello */ public final class Part { private final int partId; private final Job job; private Worker worker; private Map<Object, VertexImpl> vertexIdToVertexMap = new ConcurrentHashMapV8<Object, VertexImpl>( 8000 , 0.9f, 2); private OntoMap<Set<VertexImpl>> superstepToActiveSetMap = new OntoMap<Set<VertexImpl>>( new ActiveSet() ); // superStep parameters private long superStep; private Map<Integer, Map<Object, MessageQ>> workerNumToVertexIdToMessageQMapMap; private ComputeInput computeInput; // superStep parameters modified by each vertex.compute() private Aggregator problemAggregator; private Aggregator stepAggregator; private int numMessagesSent; Part( int partId, Job job, Worker worker ) { this.partId = partId; this.job = job; this.worker = worker; } /* * FIXME: For graph mutation (add vertex), also need void addVertexToActiveSet( Long superStep, VertexImpl vertex ) */ void add( VertexImpl vertex ) { vertex.setPart( this ); vertexIdToVertexMap.put( vertex.getVertexId(), vertex ); if ( vertex.isInitiallyActive() ) { addToActiveSet( 0L, vertex ); } } void addToActiveSet( long superStep, VertexImpl vertex ) { superstepToActiveSetMap.get( superStep ).add( vertex ); } void aggregateOutputProblemAggregator( Aggregator aggregator ) { problemAggregator.aggregate(aggregator); } void aggregateOutputStepAggregator( Aggregator aggregator ) { stepAggregator.aggregate(aggregator); } ComputeOutput doSuperStep( long superStep, ComputeInput computeInput ) { this.superStep = superStep; this.computeInput = computeInput; workerNumToVertexIdToMessageQMapMap = new HashMap<Integer, Map<Object, MessageQ>>(); numMessagesSent = 0; stepAggregator = job.makeStepAggregator(); problemAggregator = job.makeProblemAggregator(); Set<VertexImpl> activeSet = superstepToActiveSetMap.get( superStep ); for ( VertexImpl vertex : activeSet ) { vertex.compute(); vertex.removeMessageQ( superStep ); // MessageQ now is garbage } superstepToActiveSetMap.remove( superStep ); // active vertex set now is garbage boolean thereIsNextStep = numMessagesSent > 0; return new ComputeOutput( thereIsNextStep, workerNumToVertexIdToMessageQMapMap, stepAggregator, problemAggregator ); } ComputeInput getComputeInput() { return computeInput; } int getPartId() { return partId; } Aggregator getStepAggregator() { return stepAggregator; } long getSuperStep() { return superStep; } Vertex getVertex( int vertexId ) { return vertexIdToVertexMap.get( vertexId ); } Map<Object, VertexImpl> getVertexIdToVertexMap() { return vertexIdToVertexMap; } public Collection<VertexImpl> getVertices() { return vertexIdToVertexMap.values(); } void incrementNumMessagesSent() { numMessagesSent++; } void receiveMessage( Object vertexId, Message message, long superStep ) { VertexImpl vertex = vertexIdToVertexMap.get( vertexId ); assert vertex != null : vertexId; if ( vertex == null ) { System.out.println( "VertexID null: " + vertexId ); } vertex.receiveMessage( message, superStep ); addToActiveSet( superStep, vertex ); } void receiveMessageQ( Object vertexId, MessageQ messageQ, long superStep ) { VertexImpl vertex = vertexIdToVertexMap.get( vertexId ); vertex.receiveMessageQ( messageQ, superStep ); addToActiveSet( superStep, vertex ); } void removeFromActiveSet( long superStep, VertexImpl vertex ) { superstepToActiveSetMap.get( superStep ).remove( vertex ); } void removeVertex( Object vertexId ) { vertexIdToVertexMap.remove( vertexId ); worker.removeVertex(); } void sendMessage( Object receivingVertexId, Message message, long superStep ) { numMessagesSent++; int receivingPartId = job.getPartId( receivingVertexId ); if ( receivingPartId == partId ) { // message is for vertex in this Part receiveMessage( receivingVertexId, message, superStep ); return; } // message is for a vertex in another part Part receivingPart = worker.getPart( receivingPartId ); if ( receivingPart != null ) { // receivingPart is internal to this Worker receivingPart.receiveMessage( receivingVertexId, message, superStep ); return; } // receivingPart is external to this Worker int workerNum = worker.getWorkerNum( receivingPartId ); assert workerNum != worker.getWorkerNum(); // get vertexIdToMessageQMap for destination Worker Map<Object, MessageQ> vertexIdToMessageQMap = workerNumToVertexIdToMessageQMapMap.get( workerNum ); if ( vertexIdToMessageQMap == null ) { vertexIdToMessageQMap = new HashMap<Object, MessageQ>(); workerNumToVertexIdToMessageQMapMap.put( workerNum, vertexIdToMessageQMap ); } // get receivingVertex's MessageQ MessageQ receivingVertexMessageQ = vertexIdToMessageQMap.get( receivingVertexId ); if ( receivingVertexMessageQ == null ) { receivingVertexMessageQ = new MessageQ( job.getVertexFactory().getCombiner() ); vertexIdToMessageQMap.put( receivingVertexId, receivingVertexMessageQ ); } receivingVertexMessageQ.add( message ); } }