<commit_before>package brooklyn.event.adapter

import groovy.lang.Closure

import java.util.List
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

import org.slf4j.Logger
import org.slf4j.LoggerFactory

import brooklyn.entity.basic.EntityLocal
import brooklyn.event.AttributeSensor
import brooklyn.event.Sensor
import brooklyn.event.adapter.legacy.ValueProvider


/**
 * This class manages the periodic polling of a set of sensors, to update the attribute values 
 * of a particular {@link Entity}.
 */
public class SensorRegistry {
    static final Logger log = LoggerFactory.getLogger(SensorRegistry.class);
 
    final EntityLocal entity
	
	@Deprecated
    final Map<?, ?> properties  = [
            period : 500,
            connectDelay : 1000
        ]
 
	@Deprecated
    ScheduledExecutorService exec = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors())
 
	@Deprecated
    private final Map<AttributeSensor, ValueProvider> providers = [:]
	@Deprecated
    private final Map<AttributeSensor, ScheduledFuture> scheduled = [:]

	private final Set<AbstractSensorAdapter> adapters = []
	
    public SensorRegistry(EntityLocal entity, Map properties = [:]) {
        this.entity = entity
        this.properties << properties
    }

	/** records an adapter that has been created for use with this registry;
	 * implementations may return a compatible adapter if one is already registered */
	public <T extends AbstractSensorAdapter> T register(T adapter) {
		if (!adapters.add(adapter)) /* already known */ return;
		adapter.register(this)
		return adapter
	}

	// TODO might be useful to have a lookup mechanism, or register ignore duplicates
	//	sensorRegistry.adapters.find({ it in OldJmxSensorAdapter })?.connect(block: true, publish: (getEntityClass().hasSensor(JMX_URL)))
	
	boolean activated = false;
	
	private List<Closure> activationListeners = []
	private List<Closure> deactivationListeners = []
	void addActivationLifecycleListeners(Closure onUp, Closure onDown) {
		activationListeners << onUp
		deactivationListeners << onDown
	}
	public void activateAdapters() {
		if (log.isDebugEnabled()) log.debug "activating adapters at sensor registry for {}", this, entity
		activated = true;
		activationListeners.each { it.call() }
	}
	public void deactivateAdapters() {
		if (log.isDebugEnabled()) log.debug "deactivating adapters at sensor registry for {}", this, entity
		deactivationListeners.each { it.call() }
	}

	public void close() {
		activated = false;
		deactivateAdapters();
		exec.shutdownNow()
		scheduled.each { key, ScheduledFuture future -> future.cancel(true) }
	}

	@Deprecated
    public <T> void addSensor(AttributeSensor<T> sensor, ValueProvider<? extends T> provider) {
        addSensor(sensor, provider, properties.period)
    }

	@Deprecated
    public <T> void addSensor(AttributeSensor<T> sensor, ValueProvider<? extends T> provider, long period) {
        if (log.isDebugEnabled()) log.debug "adding calculated sensor {} with delay {} to {}", sensor.name, period, entity
        providers.put(sensor, provider)
        
        Closure safeCalculate = {
            try {
                T newValue = provider.compute()
                entity.setAttribute(sensor, newValue)
            } catch (Exception e) {
				if (activated)
                	log.error "Error calculating value for sensor ${sensor} on entity ${entity}", e
				else 
                    if (log.isDebugEnabled()) log.debug "Error (post deactivation) calculating value for sensor ${sensor} on entity ${entity}", e
            }
        }
        
        scheduled[sensor] = exec.scheduleWithFixedDelay(safeCalculate, 0L, period, TimeUnit.MILLISECONDS)
    }

	@Deprecated
    public <T> void removeSensor(AttributeSensor<T> sensor) {
        if (log.isDebugEnabled()) log.debug "removing sensor {} from {}", sensor.name, entity
        providers.remove(sensor)
        scheduled.remove(sensor)?.cancel(true)
    }

	@Deprecated
    private void updateAll() {
        if (log.isDebugEnabled()) log.debug "updating all sensors for {}", entity
        providers.each {
                AttributeSensor sensor, ValueProvider provider ->
                def newValue = provider.compute()
                if (log.isDebugEnabled()) log.debug "update for attribute {} to {}", sensor.name, newValue
                entity.setAttribute(sensor, newValue)
            }
    }
    
	@Deprecated
    private void update(Sensor sensor) {
        if (!providers.containsKey(sensor)) throw new IllegalStateException("Sensor ${sensor.name} not found");
        ValueProvider<?> provider = providers.get(sensor)
        def newValue = provider.compute()
        if (log.isDebugEnabled()) log.debug "update for attribute {} on {}: new value {}", sensor.name, entity, newValue
        entity.setAttribute(sensor, newValue)<commit_msg>comments and efficiency fixes for legacy compatibiity<commit_after>package brooklyn.event.adapter

import groovy.lang.Closure

import java.util.List
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

import org.slf4j.Logger
import org.slf4j.LoggerFactory

import brooklyn.entity.basic.EntityLocal
import brooklyn.event.AttributeSensor
import brooklyn.event.Sensor
import brooklyn.event.adapter.legacy.ValueProvider


/**
 * This class manages the periodic polling of a set of sensors, to update the attribute values 
 * of a particular {@link Entity}.
 */
public class SensorRegistry {
    static final Logger log = LoggerFactory.getLogger(SensorRegistry.class);
 
    final EntityLocal entity
	
	@Deprecated
    final Map<?, ?> properties  = [
            period : 500,
            connectDelay : 1000
        ]
 
	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    private ScheduledExecutorService _exec = null;
    synchronized ScheduledExecutorService getExec() {
        if (_exec==null) {
            log.warn("using legacy executor service sensor model in $entity .  class should be updated to use adapters.");
            _exec = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
        }
        return _exec;
    }
 
	@Deprecated
    private final Map<AttributeSensor, ValueProvider> providers = [:]
	@Deprecated
    private final Map<AttributeSensor, ScheduledFuture> scheduled = [:]

	private final Set<AbstractSensorAdapter> adapters = []
	
    public SensorRegistry(EntityLocal entity, Map properties = [:]) {
        this.entity = entity
        this.properties << properties
    }

	/** records an adapter that has been created for use with this registry;
	 * implementations may return a compatible adapter if one is already registered */
	public <T extends AbstractSensorAdapter> T register(T adapter) {
		if (!adapters.add(adapter)) /* already known */ return;
		adapter.register(this)
		return adapter
	}

	// TODO might be useful to have a lookup mechanism, or register ignore duplicates
	//	sensorRegistry.adapters.find({ it in OldJmxSensorAdapter })?.connect(block: true, publish: (getEntityClass().hasSensor(JMX_URL)))
	
	boolean activated = false;
	
	private List<Closure> activationListeners = []
	private List<Closure> deactivationListeners = []
	void addActivationLifecycleListeners(Closure onUp, Closure onDown) {
		activationListeners << onUp
		deactivationListeners << onDown
	}
	public void activateAdapters() {
		if (log.isDebugEnabled()) log.debug "activating adapters at sensor registry for {}", this, entity
		activated = true;
		activationListeners.each { it.call() }
	}
	public void deactivateAdapters() {
		if (log.isDebugEnabled()) log.debug "deactivating adapters at sensor registry for {}", this, entity
		deactivationListeners.each { it.call() }
	}

	public void close() {
		activated = false;
		deactivateAdapters();
		exec.shutdownNow()
		scheduled.each { key, ScheduledFuture future -> future.cancel(true) }
	}

	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    public <T> void addSensor(AttributeSensor<T> sensor, ValueProvider<? extends T> provider) {
        addSensor(sensor, provider, properties.period)
    }

	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    public <T> void addSensor(AttributeSensor<T> sensor, ValueProvider<? extends T> provider, long period) {
        if (log.isDebugEnabled()) log.debug "adding calculated sensor {} with delay {} to {}", sensor.name, period, entity
        providers.put(sensor, provider)
        
        Closure safeCalculate = {
            try {
                T newValue = provider.compute()
                entity.setAttribute(sensor, newValue)
            } catch (Exception e) {
				if (activated)
                	log.error "Error calculating value for sensor ${sensor} on entity ${entity}", e
				else 
                    if (log.isDebugEnabled()) log.debug "Error (post deactivation) calculating value for sensor ${sensor} on entity ${entity}", e
            }
        }
        
        scheduled[sensor] = exec.scheduleWithFixedDelay(safeCalculate, 0L, period, TimeUnit.MILLISECONDS)
    }

	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    public <T> void removeSensor(AttributeSensor<T> sensor) {
        if (log.isDebugEnabled()) log.debug "removing sensor {} from {}", sensor.name, entity
        providers.remove(sensor)
        scheduled.remove(sensor)?.cancel(true)
    }

	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    private void updateAll() {
        if (log.isDebugEnabled()) log.debug "updating all sensors for {}", entity
        providers.each {
                AttributeSensor sensor, ValueProvider provider ->
                def newValue = provider.compute()
                if (log.isDebugEnabled()) log.debug "update for attribute {} to {}", sensor.name, newValue
                entity.setAttribute(sensor, newValue)
            }
    }
    
	@Deprecated /** @deprecated new sensor "adapter" model used, with scheduled tasks */
    private void update(Sensor sensor) {
        if (!providers.containsKey(sensor)) throw new IllegalStateException("Sensor ${sensor.name} not found");
        ValueProvider<?> provider = providers.get(sensor)
        def newValue = provider.compute()
        if (log.isDebugEnabled()) log.debug "update for attribute {} on {}: new value {}", sensor.name, entity, newValue
        entity.setAttribute(sensor, newValue)
{'fraction_non_alphanumeric': 0.09975691847419596, 'fraction_numerical': 0.0018698578908002991, 'mean_word_length': 3.405683690280066, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4626268', 'n_tokens_mistral': 2942, 'n_tokens_neox': 2821, 'n_words': 848}