package com.eucalyptus.cluster.callback; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.log4j.Logger; import com.eucalyptus.cluster.Cluster; import com.eucalyptus.event.ClockTick; import com.eucalyptus.event.Event; import com.eucalyptus.event.EventListener; import com.eucalyptus.records.EventRecord; import com.eucalyptus.records.EventType; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; public class StateUpdateHandler implements EventListener { private static Logger LOG = Logger.getLogger( StateUpdateHandler.class ); private static final ConcurrentMap<String,StateUpdateHandler> clusterMap = Maps.newConcurrentHashMap( ); private final ConcurrentMap<Class,AtomicBoolean> inflightMap = Maps.newConcurrentHashMap( ); private final ConcurrentMap<Class,QueuedEventCallback> callbackMap = Maps.newConcurrentHashMap( ); private final Cluster cluster; public static void create( Cluster cluster, QueuedEventCallback callback ) { StateUpdateHandler handler = new StateUpdateHandler( cluster ); StateUpdateHandler.clusterMap.putIfAbsent( cluster.getName( ), handler ); handler = StateUpdateHandler.clusterMap.get( cluster.getName( ) ); EventRecord.here( StateUpdateHandler.class, EventType.CLUSTER_STATE_HANDLER_REGISTERED, cluster.getName( ), callback.getClass( ).getCanonicalName( ) ); } private StateUpdateHandler( Cluster cluster ) { this.cluster = cluster; } public boolean timedTrigger( Event c ) { if ( c instanceof ClockTick ) { return ( ( ClockTick ) c ).isBackEdge( ); } else { return false; } } public void addCallback( QueuedEventCallback cb ) { if( this.callbackMap.putIfAbsent( cb.getClass( ), cb ) == null ) { this.inflightMap.put( cb.getClass( ), new AtomicBoolean( false ) ); } else { LOG.debug( "Ignoring addition of timed callback for cluster "+ this.cluster.getName( )+ " which is already configured: " + cb.getClass( ) ); } } @Override public void advertiseEvent( Event event ) {} @Override public void fireEvent( Event event ) { if( this.timedTrigger( event ) ) { Iterables.all( callbackMap.keySet( ), new Predicate<Class>() { @Override public boolean apply( Class arg0 ) { if( StateUpdateHandler.this.inflightMap.get( arg0 ).compareAndSet( false, true ) ) { //TODO: RELEASE: wrap this up here. } return false; }} ); } } }