package com.ldbc.driver.runtime.coordination; import java.util.HashMap; import java.util.Map; import java.util.Set; import static java.lang.String.format; public class ExternalCompletionTimeStateManager implements ExternalCompletionTimeReader, ExternalCompletionTimeWriter { private final Map<String,Long> peerCompletionTimesAsMilli = new HashMap<>(); private long completionTimeAsMilli = -1; private boolean notModifiedSinceLastGet = false; ExternalCompletionTimeStateManager( Set<String> peerIds ) throws CompletionTimeException { for ( String peerId : peerIds ) { if ( null == peerId ) { throw new CompletionTimeException( format( "Peer ID cannot be null\n%s", peerIds.toString() ) ); } peerCompletionTimesAsMilli.put( peerId, -1l ); } } @Override public void submitPeerCompletionTime( String peerId, long timeAsMilli ) throws CompletionTimeException { if ( null == peerId ) { throw new CompletionTimeException( "Peer ID can not be null" ); } if ( -1 == timeAsMilli ) { throw new CompletionTimeException( "Invalid completion time " + timeAsMilli ); } if ( false == peerCompletionTimesAsMilli.containsKey( peerId ) ) { throw new CompletionTimeException( format( "Unrecognized peer ID: %s", peerId ) ); } long previousPeerCompletionTimeAsMilli = peerCompletionTimesAsMilli.get( peerId ); if ( -1 != previousPeerCompletionTimeAsMilli && timeAsMilli < previousPeerCompletionTimeAsMilli ) { throw new CompletionTimeException( format( "Completion Time received from Peer(%s) is not monotonically increasing\n" + " Previous Completion Time: %s\n" + " Current Completion Time: %s", peerId, timeAsMilli, previousPeerCompletionTimeAsMilli ) ); } notModifiedSinceLastGet = false; peerCompletionTimesAsMilli.put( peerId, timeAsMilli ); } @Override public long externalCompletionTimeAsMilli() { if ( notModifiedSinceLastGet ) { return completionTimeAsMilli; } notModifiedSinceLastGet = true; completionTimeAsMilli = minPeerCompletionTimeOrNegativeOne(); return completionTimeAsMilli; } private long minPeerCompletionTimeOrNegativeOne() { long externalCompletionTimeAsMilli = -1; for ( long peerCompletionTimeAsMilli : peerCompletionTimesAsMilli.values() ) { if ( -1 == peerCompletionTimeAsMilli ) { return -1; } if ( -1 == externalCompletionTimeAsMilli ) { externalCompletionTimeAsMilli = peerCompletionTimeAsMilli; } else if ( peerCompletionTimeAsMilli < externalCompletionTimeAsMilli ) { externalCompletionTimeAsMilli = peerCompletionTimeAsMilli; } } return externalCompletionTimeAsMilli; } }