You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:50:56 UTC

[14/51] [abbrv] [partial] brooklyn-server git commit: move subdir from incubator up a level as it is promoted to its own repo (first non-incubator commit!)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
deleted file mode 100644
index e64e41e..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * 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.brooklyn.core.entity.lifecycle;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.effector.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.Enricher;
-import org.apache.brooklyn.api.sensor.EnricherSpec;
-import org.apache.brooklyn.api.sensor.EnricherSpec.ExtensibleEnricherSpec;
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.config.ConfigInheritance;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.BrooklynLogging;
-import org.apache.brooklyn.core.BrooklynLogging.LoggingLevel;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.enricher.AbstractEnricher;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityAdjuncts;
-import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.entity.EntityPredicates;
-import org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition;
-import org.apache.brooklyn.enricher.stock.AbstractMultipleSensorAggregator;
-import org.apache.brooklyn.enricher.stock.Enrichers;
-import org.apache.brooklyn.enricher.stock.UpdatingMap;
-import org.apache.brooklyn.util.collections.CollectionFunctionals;
-import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.collections.QuorumCheck;
-import org.apache.brooklyn.util.core.task.ValueResolver;
-import org.apache.brooklyn.util.guava.Functionals;
-import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.repeat.Repeater;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
-
-/** Logic, sensors and enrichers, and conveniences, for computing service status */ 
-public class ServiceStateLogic {
-
-    private static final Logger log = LoggerFactory.getLogger(ServiceStateLogic.class);
-    
-    public static final AttributeSensor<Boolean> SERVICE_UP = Attributes.SERVICE_UP;
-    public static final AttributeSensor<Map<String,Object>> SERVICE_NOT_UP_INDICATORS = Attributes.SERVICE_NOT_UP_INDICATORS;
-    public static final AttributeSensor<Map<String,Object>> SERVICE_NOT_UP_DIAGNOSTICS = Attributes.SERVICE_NOT_UP_DIAGNOSTICS;
-    
-    public static final AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
-    public static final AttributeSensor<Lifecycle.Transition> SERVICE_STATE_EXPECTED = Attributes.SERVICE_STATE_EXPECTED;
-    public static final AttributeSensor<Map<String,Object>> SERVICE_PROBLEMS = Attributes.SERVICE_PROBLEMS;
-
-    /** static only; not for instantiation */
-    private ServiceStateLogic() {}
-
-    public static <TKey,TVal> TVal getMapSensorEntry(EntityLocal entity, AttributeSensor<Map<TKey,TVal>> sensor, TKey key) {
-        Map<TKey, TVal> map = entity.getAttribute(sensor);
-        if (map==null) return null;
-        return map.get(key);
-    }
-    
-    @SuppressWarnings("unchecked")
-    public static <TKey,TVal> void clearMapSensorEntry(EntityLocal entity, AttributeSensor<Map<TKey,TVal>> sensor, TKey key) {
-        updateMapSensorEntry(entity, sensor, key, (TVal)Entities.REMOVE);
-    }
-
-    /** update the given key in the given map sensor */
-    public static <TKey,TVal> void updateMapSensorEntry(EntityLocal entity, AttributeSensor<Map<TKey,TVal>> sensor, final TKey key, final TVal v) {
-        /*
-         * Important to *not* modify the existing attribute value; must make a copy, modify that, and publish.
-         * This is because a Propagator enricher will set this same value on another entity. There was very
-         * strange behaviour when this was done for a SERVICE_UP_INDICATORS sensor - the updates done here 
-         * applied to the attribute of both entities!
-         * 
-         * Need to do this update atomically (i.e. sequentially) because there is no threading control for
-         * what is calling updateMapSensorEntity. It is called directly on start, on initialising enrichers,
-         * and in event listeners. These calls could be concurrent.
-         */
-        Function<Map<TKey,TVal>, Maybe<Map<TKey,TVal>>> modifier = new Function<Map<TKey,TVal>, Maybe<Map<TKey,TVal>>>() {
-            @Override public Maybe<Map<TKey, TVal>> apply(Map<TKey, TVal> map) {
-                boolean created = (map==null);
-                if (created) map = MutableMap.of();
-                
-                boolean changed;
-                if (v == Entities.REMOVE) {
-                    changed = map.containsKey(key);
-                    if (changed) {
-                        map = MutableMap.copyOf(map);
-                        map.remove(key);
-                    }
-                } else {
-                    TVal oldV = map.get(key);
-                    if (oldV==null) {
-                        changed = (v!=null || !map.containsKey(key));
-                    } else {
-                        changed = !oldV.equals(v);
-                    }
-                    if (changed) {
-                        map = MutableMap.copyOf(map);
-                        map.put(key, (TVal)v);
-                    }
-                }
-                if (changed || created) {
-                    return Maybe.of(map);
-                } else {
-                    return Maybe.absent();
-                }
-            }
-        };
-        
-        if (!Entities.isNoLongerManaged(entity)) { 
-            entity.sensors().modify(sensor, modifier);
-        }
-    }
-    
-    public static void setExpectedState(Entity entity, Lifecycle state) {
-        if (state==Lifecycle.RUNNING) {
-            Boolean up = ((EntityInternal)entity).getAttribute(Attributes.SERVICE_UP);
-            if (!Boolean.TRUE.equals(up) && !Boolean.TRUE.equals(Entities.isReadOnly(entity))) {
-                // pause briefly to allow any recent problem-clearing processing to complete
-                Stopwatch timer = Stopwatch.createStarted();
-                boolean nowUp = Repeater.create()
-                        .every(ValueResolver.REAL_QUICK_PERIOD)
-                        .limitTimeTo(ValueResolver.PRETTY_QUICK_WAIT)
-                        .until(entity, EntityPredicates.attributeEqualTo(Attributes.SERVICE_UP, true))
-                        .run();
-                if (nowUp) {
-                    log.debug("Had to wait "+Duration.of(timer)+" for "+entity+" "+Attributes.SERVICE_UP+" to be true before setting "+state);
-                } else {
-                    log.warn("Service is not up when setting "+state+" on "+entity+"; delayed "+Duration.of(timer)+" "
-                        + "but "+Attributes.SERVICE_UP+" did not recover from "+up+"; not-up-indicators="+entity.getAttribute(Attributes.SERVICE_NOT_UP_INDICATORS));
-                }
-            }
-        }
-        ((EntityInternal)entity).sensors().set(Attributes.SERVICE_STATE_EXPECTED, new Lifecycle.Transition(state, new Date()));
-        
-        Maybe<Enricher> enricher = EntityAdjuncts.tryFindWithUniqueTag(entity.enrichers(), ComputeServiceState.DEFAULT_ENRICHER_UNIQUE_TAG);
-        if (enricher.isPresent() && enricher.get() instanceof ComputeServiceState) {
-            ((ComputeServiceState)enricher.get()).onEvent(null);
-        }
-    }
-    public static Lifecycle getExpectedState(Entity entity) {
-        Transition expected = entity.getAttribute(Attributes.SERVICE_STATE_EXPECTED);
-        if (expected==null) return null;
-        return expected.getState();
-    }
-    public static boolean isExpectedState(Entity entity, Lifecycle state) {
-        return getExpectedState(entity)==state;
-    }
-    
-    public static class ServiceNotUpLogic {
-        public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "service.isUp if no service.notUp.indicators";
-        
-        /** static only; not for instantiation */
-        private ServiceNotUpLogic() {}
-        
-        public static final EnricherSpec<?> newEnricherForServiceUpIfNotUpIndicatorsEmpty() {
-            return Enrichers.builder()
-                .transforming(SERVICE_NOT_UP_INDICATORS).<Object>publishing(Attributes.SERVICE_UP)
-                .suppressDuplicates(true)
-                .computing(
-                    Functionals.<Map<String,?>>
-                        ifNotEquals(null).<Object>apply(Functions.forPredicate(CollectionFunctionals.<String>mapSizeEquals(0)))
-                        .defaultValue(Entities.REMOVE) )
-                .uniqueTag(DEFAULT_ENRICHER_UNIQUE_TAG)
-                .build();
-        }
-        
-        /** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map as if the 
-         * {@link UpdatingMap} enricher for the given key */
-        public static void updateNotUpIndicator(EntityLocal entity, String key, Object value) {
-            updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key, value);
-        }
-        /** clears any entry for the given key in the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map */
-        public static void clearNotUpIndicator(EntityLocal entity, String key) {
-            clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key);
-        }
-        /** as {@link #updateNotUpIndicator(EntityLocal, String, Object)} using the given sensor as the key */
-        public static void updateNotUpIndicator(EntityLocal entity, Sensor<?> sensor, Object value) {
-            updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName(), value);
-        }
-        /** as {@link #clearNotUpIndicator(EntityLocal, String)} using the given sensor as the key */
-        public static void clearNotUpIndicator(EntityLocal entity, Sensor<?> sensor) {
-            clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName());
-        }
-
-        public static void updateNotUpIndicatorRequiringNonEmptyList(EntityLocal entity, AttributeSensor<? extends Collection<?>> collectionSensor) {
-            Collection<?> nodes = entity.getAttribute(collectionSensor);
-            if (nodes==null || nodes.isEmpty()) ServiceNotUpLogic.updateNotUpIndicator(entity, collectionSensor, "Should have at least one entry");
-            else ServiceNotUpLogic.clearNotUpIndicator(entity, collectionSensor);
-        }
-        public static void updateNotUpIndicatorRequiringNonEmptyMap(EntityLocal entity, AttributeSensor<? extends Map<?,?>> mapSensor) {
-            Map<?, ?> nodes = entity.getAttribute(mapSensor);
-            if (nodes==null || nodes.isEmpty()) ServiceNotUpLogic.updateNotUpIndicator(entity, mapSensor, "Should have at least one entry");
-            else ServiceNotUpLogic.clearNotUpIndicator(entity, mapSensor);
-        }
-        
-    }
-    
-    /** Enricher which sets {@link Attributes#SERVICE_STATE_ACTUAL} on changes to 
-     * {@link Attributes#SERVICE_STATE_EXPECTED}, {@link Attributes#SERVICE_PROBLEMS}, and {@link Attributes#SERVICE_UP}
-     * <p>
-     * The default implementation uses {@link #computeActualStateWhenExpectedRunning(Map, Boolean)} if the last expected transition
-     * was to {@link Lifecycle#RUNNING} and 
-     * {@link #computeActualStateWhenNotExpectedRunning(Map, Boolean, org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition)} otherwise.
-     * If these methods return null, the {@link Attributes#SERVICE_STATE_ACTUAL} sensor will be cleared (removed).
-     * Either of these methods can be overridden for custom logic, and that custom enricher can be created using 
-     * {@link ServiceStateLogic#newEnricherForServiceState(Class)} and added to an entity.
-     */
-    public static class ComputeServiceState extends AbstractEnricher implements SensorEventListener<Object> {
-        
-        public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "service.state.actual";
-
-        public ComputeServiceState() {}
-        public ComputeServiceState(Map<?,?> flags) { super(flags); }
-            
-        @Override
-        public void init() {
-            super.init();
-            if (uniqueTag==null) uniqueTag = DEFAULT_ENRICHER_UNIQUE_TAG;
-        }
-        
-        @Override
-        public void setEntity(EntityLocal entity) {
-            super.setEntity(entity);
-            if (suppressDuplicates==null) {
-                // only publish on changes, unless it is configured otherwise
-                suppressDuplicates = true;
-            }
-            
-            subscriptions().subscribe(entity, SERVICE_PROBLEMS, this);
-            subscriptions().subscribe(entity, SERVICE_UP, this);
-            subscriptions().subscribe(entity, SERVICE_STATE_EXPECTED, this);
-            onEvent(null);
-        }
-
-        @Override
-        public void onEvent(@Nullable SensorEvent<Object> event) {
-            Preconditions.checkNotNull(entity, "Cannot handle subscriptions or compute state until associated with an entity");
-            
-            Map<String, Object> serviceProblems = entity.getAttribute(SERVICE_PROBLEMS);
-            Boolean serviceUp = entity.getAttribute(SERVICE_UP);
-            Lifecycle.Transition serviceExpected = entity.getAttribute(SERVICE_STATE_EXPECTED);
-            
-            if (serviceExpected!=null && serviceExpected.getState()==Lifecycle.RUNNING) {
-                setActualState( computeActualStateWhenExpectedRunning(serviceProblems, serviceUp) );
-            } else {
-                setActualState( computeActualStateWhenNotExpectedRunning(serviceProblems, serviceUp, serviceExpected) );
-            }
-        }
-
-        protected Lifecycle computeActualStateWhenExpectedRunning(Map<String, Object> problems, Boolean serviceUp) {
-            if (Boolean.TRUE.equals(serviceUp) && (problems==null || problems.isEmpty())) {
-                return Lifecycle.RUNNING;
-            } else {
-                if (!Lifecycle.ON_FIRE.equals(entity.getAttribute(SERVICE_STATE_ACTUAL))) {
-                    BrooklynLogging.log(log, BrooklynLogging.levelDependingIfReadOnly(entity, LoggingLevel.WARN, LoggingLevel.TRACE, LoggingLevel.DEBUG),
-                        "Setting "+entity+" "+Lifecycle.ON_FIRE+" due to problems when expected running, up="+serviceUp+", "+
-                            (problems==null || problems.isEmpty() ? "not-up-indicators: "+entity.getAttribute(SERVICE_NOT_UP_INDICATORS) : "problems: "+problems));
-                }
-                return Lifecycle.ON_FIRE;
-            }
-        }
-        
-        protected Lifecycle computeActualStateWhenNotExpectedRunning(Map<String, Object> problems, Boolean up, Lifecycle.Transition stateTransition) {
-            if (stateTransition!=null) {
-                // if expected state is present but not running, just echo the expected state (ignore problems and up-ness)
-                return stateTransition.getState();
-                
-            } else if (problems!=null && !problems.isEmpty()) {
-                // if there is no expected state, then if service is not up, say stopped, else say on fire (whether service up is true or not present)
-                if (Boolean.FALSE.equals(up)) {
-                    return Lifecycle.STOPPED;
-                } else {
-                    BrooklynLogging.log(log, BrooklynLogging.levelDependingIfReadOnly(entity, LoggingLevel.WARN, LoggingLevel.TRACE, LoggingLevel.DEBUG),
-                        "Setting "+entity+" "+Lifecycle.ON_FIRE+" due to problems when expected "+stateTransition+" / up="+up+": "+problems);
-                    return Lifecycle.ON_FIRE;
-                }
-            } else {
-                // no expected transition and no problems
-                // if the problems map is non-null, then infer from service up;
-                // if there is no problems map, then leave unchanged (user may have set it explicitly)
-                if (problems!=null)
-                    return (up==null ? null /* remove if up is not set */ : 
-                        up ? Lifecycle.RUNNING : Lifecycle.STOPPED);
-                else
-                    return entity.getAttribute(SERVICE_STATE_ACTUAL);
-            }
-        }
-
-        protected void setActualState(@Nullable Lifecycle state) {
-            if (log.isTraceEnabled()) log.trace("{} setting actual state {}", this, state);
-            if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) {
-                // won't catch everything, but catches some
-                BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
-                    entity+" is no longer managed when told to set actual state to "+state+"; suppressing");
-                return;
-            }
-            emit(SERVICE_STATE_ACTUAL, (state==null ? Entities.REMOVE : state));
-        }
-
-    }
-    
-    public static final EnricherSpec<?> newEnricherForServiceStateFromProblemsAndUp() {
-        return newEnricherForServiceState(ComputeServiceState.class);
-    }
-    public static final EnricherSpec<?> newEnricherForServiceState(Class<? extends Enricher> type) {
-        return EnricherSpec.create(type);
-    }
-    
-    public static class ServiceProblemsLogic {
-        /** static only; not for instantiation */
-        private ServiceProblemsLogic() {}
-        
-        /** puts the given value into the {@link Attributes#SERVICE_PROBLEMS} map as if the 
-         * {@link UpdatingMap} enricher for the given sensor reported this value */
-        public static void updateProblemsIndicator(EntityLocal entity, Sensor<?> sensor, Object value) {
-            updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, sensor.getName(), value);
-        }
-        /** clears any entry for the given sensor in the {@link Attributes#SERVICE_PROBLEMS} map */
-        public static void clearProblemsIndicator(EntityLocal entity, Sensor<?> sensor) {
-            clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, sensor.getName());
-        }
-        /** as {@link #updateProblemsIndicator(EntityLocal, Sensor, Object)} */
-        public static void updateProblemsIndicator(EntityLocal entity, Effector<?> eff, Object value) {
-            updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, eff.getName(), value);
-        }
-        /** as {@link #clearProblemsIndicator(EntityLocal, Sensor)} */
-        public static void clearProblemsIndicator(EntityLocal entity, Effector<?> eff) {
-            clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, eff.getName());
-        }
-        /** as {@link #updateProblemsIndicator(EntityLocal, Sensor, Object)} */
-        public static void updateProblemsIndicator(EntityLocal entity, String key, Object value) {
-            updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key, value);
-        }
-        /** as {@link #clearProblemsIndicator(EntityLocal, Sensor)} */
-        public static void clearProblemsIndicator(EntityLocal entity, String key) {
-            clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key);
-        }
-    }
-    
-    public static class ComputeServiceIndicatorsFromChildrenAndMembers extends AbstractMultipleSensorAggregator<Void> implements SensorEventListener<Object> {
-        /** standard unique tag identifying instances of this enricher at runtime, also used for the map sensor if no unique tag specified */
-        public final static String DEFAULT_UNIQUE_TAG = "service-lifecycle-indicators-from-children-and-members";
-        
-        /** as {@link #DEFAULT_UNIQUE_TAG}, but when a second distinct instance is responsible for computing service up */
-        public final static String DEFAULT_UNIQUE_TAG_UP = "service-not-up-indicators-from-children-and-members";
-
-        public static final ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ConfigKeys.builder(QuorumCheck.class, "enricher.service_state.children_and_members.quorum.up")
-            .description("Logic for checking whether this service is up, based on children and/or members, defaulting to allowing none but if there are any requiring at least one to be up")
-            .defaultValue(QuorumCheck.QuorumChecks.atLeastOneUnlessEmpty())
-            .inheritance(ConfigInheritance.NONE)
-            .build();
-        public static final ConfigKey<QuorumCheck> RUNNING_QUORUM_CHECK = ConfigKeys.builder(QuorumCheck.class, "enricher.service_state.children_and_members.quorum.running") 
-            .description("Logic for checking whether this service is healthy, based on children and/or members running, defaulting to requiring none to be ON-FIRE")
-            .defaultValue(QuorumCheck.QuorumChecks.all())
-            .inheritance(ConfigInheritance.NONE)
-            .build();
-        // TODO items below should probably also have inheritance NONE ?
-        public static final ConfigKey<Boolean> DERIVE_SERVICE_NOT_UP = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.service_up.publish", "Whether to derive a service-not-up indicator from children", true);
-        public static final ConfigKey<Boolean> DERIVE_SERVICE_PROBLEMS = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.service_problems.publish", "Whether to derive a service-problem indicator from children", true);
-        public static final ConfigKey<Boolean> IGNORE_ENTITIES_WITH_SERVICE_UP_NULL = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.ignore_entities.service_up_null", "Whether to ignore children reporting null values for service up", true);
-        @SuppressWarnings("serial")
-        public static final ConfigKey<Set<Lifecycle>> IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES = ConfigKeys.newConfigKey(new TypeToken<Set<Lifecycle>>() {},
-            "enricher.service_state.children_and_members.ignore_entities.service_state_values", 
-            "Service states (including null) which indicate an entity should be ignored when looking at children service states; anything apart from RUNNING not in this list will be treated as not healthy (by default just ON_FIRE will mean not healthy)", 
-            MutableSet.<Lifecycle>builder().addAll(Lifecycle.values()).add(null).remove(Lifecycle.RUNNING).remove(Lifecycle.ON_FIRE).build().asUnmodifiable());
-
-        protected String getKeyForMapSensor() {
-            return Preconditions.checkNotNull(super.getUniqueTag());
-        }
-
-        @Override
-        protected void setEntityLoadingConfig() {
-            fromChildren = true;
-            fromMembers = true;
-            // above sets default
-            super.setEntityLoadingConfig();
-            if (isAggregatingMembers() && (!(entity instanceof Group))) {
-                if (fromChildren) fromMembers=false;
-                else throw new IllegalStateException("Cannot monitor only members for non-group entity "+entity+": "+this);
-            }
-            Preconditions.checkNotNull(getKeyForMapSensor());
-        }
-
-        @Override
-        protected void setEntityLoadingTargetConfig() {
-            if (getConfig(TARGET_SENSOR)!=null)
-                throw new IllegalArgumentException("Must not set "+TARGET_SENSOR+" when using "+this);
-        }
-
-        @Override
-        public void setEntity(EntityLocal entity) {
-            super.setEntity(entity);
-            if (suppressDuplicates==null) {
-                // only publish on changes, unless it is configured otherwise
-                suppressDuplicates = true;
-            }
-        }
-
-        final static Set<ConfigKey<?>> RECONFIGURABLE_KEYS = ImmutableSet.<ConfigKey<?>>of(
-            UP_QUORUM_CHECK, RUNNING_QUORUM_CHECK,
-            DERIVE_SERVICE_NOT_UP, DERIVE_SERVICE_NOT_UP, 
-            IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
-        
-        @Override
-        protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
-            if (RECONFIGURABLE_KEYS.contains(key)) {
-                return;
-            } else {
-                super.doReconfigureConfig(key, val);
-            }
-        }
-        
-        @Override
-        protected void onChanged() {
-            super.onChanged();
-            if (entity != null && isRunning())
-                onUpdated();
-        }
-        
-        private final List<Sensor<?>> SOURCE_SENSORS = ImmutableList.<Sensor<?>>of(SERVICE_UP, SERVICE_STATE_ACTUAL);
-        @Override
-        protected Collection<Sensor<?>> getSourceSensors() {
-            return SOURCE_SENSORS;
-        }
-
-        @Override
-        protected void onUpdated() {
-            if (entity==null || !Entities.isManaged(entity)) {
-                // either invoked during setup or entity has become unmanaged; just ignore
-                BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
-                    "Ignoring {} onUpdated when entity is not in valid state ({})", this, entity);
-                return;
-            }
-
-            // override superclass to publish multiple sensors
-            if (getConfig(DERIVE_SERVICE_PROBLEMS)) {
-                updateMapSensor(SERVICE_PROBLEMS, computeServiceProblems());
-            }
-
-            if (getConfig(DERIVE_SERVICE_NOT_UP)) {
-                updateMapSensor(SERVICE_NOT_UP_INDICATORS, computeServiceNotUp());
-            }
-        }
-
-        protected Object computeServiceNotUp() {
-            Map<Entity, Boolean> values = getValues(SERVICE_UP);
-            List<Entity> violators = MutableList.of();
-            boolean ignoreNull = getConfig(IGNORE_ENTITIES_WITH_SERVICE_UP_NULL);
-            Set<Lifecycle> ignoreStates = getConfig(IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
-            int entries=0;
-            int numUp=0;
-            for (Map.Entry<Entity, Boolean> state: values.entrySet()) {
-                if (ignoreNull && state.getValue()==null)
-                    continue;
-                entries++;
-                Lifecycle entityState = state.getKey().getAttribute(SERVICE_STATE_ACTUAL);
-                
-                if (Boolean.TRUE.equals(state.getValue())) numUp++;
-                else if (!ignoreStates.contains(entityState)) {
-                    violators.add(state.getKey());
-                }
-            }
-
-            QuorumCheck qc = getConfig(UP_QUORUM_CHECK);
-            if (qc!=null) {
-                if (qc.isQuorate(numUp, violators.size()+numUp))
-                    // quorate
-                    return null;
-
-                if (values.isEmpty()) return "No entities present";
-                if (entries==0) return "No entities publishing service up";
-                if (violators.isEmpty()) return "Not enough entities";
-            } else {
-                if (violators.isEmpty())
-                    return null;
-            }
-
-            if (violators.size()==1) return violators.get(0)+" is not up";
-            if (violators.size()==entries) return "None of the entities are up";
-            return violators.size()+" entities are not up, including "+violators.get(0);
-        }
-
-        protected Object computeServiceProblems() {
-            Map<Entity, Lifecycle> values = getValues(SERVICE_STATE_ACTUAL);
-            int numRunning=0;
-            List<Entity> onesNotHealthy=MutableList.of();
-            Set<Lifecycle> ignoreStates = getConfig(IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
-            for (Map.Entry<Entity,Lifecycle> state: values.entrySet()) {
-                if (state.getValue()==Lifecycle.RUNNING) numRunning++;
-                else if (!ignoreStates.contains(state.getValue())) 
-                    onesNotHealthy.add(state.getKey());
-            }
-
-            QuorumCheck qc = getConfig(RUNNING_QUORUM_CHECK);
-            if (qc!=null) {
-                if (qc.isQuorate(numRunning, onesNotHealthy.size()+numRunning))
-                    // quorate
-                    return null;
-
-                if (onesNotHealthy.isEmpty())
-                    return "Not enough entities running to be quorate";
-            } else {
-                if (onesNotHealthy.isEmpty())
-                    return null;
-            }
-
-            return "Required entit"+Strings.ies(onesNotHealthy.size())+" not healthy: "+
-                (onesNotHealthy.size()>3 ? onesNotHealthy.get(0)+" and "+(onesNotHealthy.size()-1)+" others"
-                    : Strings.join(onesNotHealthy, ", "));
-        }
-
-        protected void updateMapSensor(AttributeSensor<Map<String, Object>> sensor, Object value) {
-            if (log.isTraceEnabled()) log.trace("{} updating map sensor {} with {}", new Object[] { this, sensor, value });
-
-            if (value!=null) {
-                updateMapSensorEntry(entity, sensor, getKeyForMapSensor(), value);
-            } else {
-                clearMapSensorEntry(entity, sensor, getKeyForMapSensor());
-            }
-        }
-
-        /** not used; see specific `computeXxx` methods, invoked by overridden onUpdated */
-        @Override
-        protected Object compute() {
-            return null;
-        }
-    }
-    
-    public static class ComputeServiceIndicatorsFromChildrenAndMembersSpec extends ExtensibleEnricherSpec<ComputeServiceIndicatorsFromChildrenAndMembers,ComputeServiceIndicatorsFromChildrenAndMembersSpec> {
-        private static final long serialVersionUID = -607444925297963712L;
-        
-        protected ComputeServiceIndicatorsFromChildrenAndMembersSpec() {
-            this(ComputeServiceIndicatorsFromChildrenAndMembers.class);
-        }
-        
-        protected ComputeServiceIndicatorsFromChildrenAndMembersSpec(Class<? extends ComputeServiceIndicatorsFromChildrenAndMembers> clazz) {
-            super(clazz);
-        }
-
-        public void addTo(Entity entity) {
-            entity.enrichers().add(this);
-        }
-
-        public ComputeServiceIndicatorsFromChildrenAndMembersSpec checkChildrenAndMembers() {
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_MEMBERS, true);
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_CHILDREN, true);
-            return self();
-        }
-        public ComputeServiceIndicatorsFromChildrenAndMembersSpec checkMembersOnly() {
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_MEMBERS, true);
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_CHILDREN, false);
-            return self();
-        }
-        public ComputeServiceIndicatorsFromChildrenAndMembersSpec checkChildrenOnly() {
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_MEMBERS, false);
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_CHILDREN, true);
-            return self();
-        }
-
-        public ComputeServiceIndicatorsFromChildrenAndMembersSpec requireUpChildren(QuorumCheck check) {
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, check);
-            return self();
-        }
-        public ComputeServiceIndicatorsFromChildrenAndMembersSpec requireRunningChildren(QuorumCheck check) {
-            configure(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, check);
-            return self();
-        }
-    }
-
-    /** provides the default {@link ComputeServiceIndicatorsFromChildrenAndMembers} enricher, 
-     * using the default unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG}),
-     * configured here to require none on fire, and either no children or at least one up child,
-     * the spec can be further configured as appropriate */
-    public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildren() {
-        return new ComputeServiceIndicatorsFromChildrenAndMembersSpec()
-            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG);
-    }
-
-    /** as {@link #newEnricherFromChildren()} but only publishing service not-up indicators, 
-     * using a different unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG_UP}),
-     * listening to children only, ignoring lifecycle/service-state,
-     * and using the same logic 
-     * (viz looking only at children (not members) and requiring either no children or at least one child up) by default */
-    public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildrenUp() {
-        return newEnricherFromChildren()
-            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG_UP)
-            .checkChildrenOnly()
-            .configure(ComputeServiceIndicatorsFromChildrenAndMembers.DERIVE_SERVICE_PROBLEMS, false);
-    }
-    
-    /** as {@link #newEnricherFromChildren()} but only publishing service problems,
-     * listening to children and members, ignoring service up,
-     * and using the same logic 
-     * (viz looking at children and members and requiring none are on fire) by default */
-    public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildrenState() {
-        return newEnricherFromChildren()
-            .configure(ComputeServiceIndicatorsFromChildrenAndMembers.DERIVE_SERVICE_NOT_UP, false);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Changeable.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Changeable.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Changeable.java
deleted file mode 100644
index 388eb17..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Changeable.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.brooklyn.core.entity.trait;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.core.sensor.BasicNotificationSensor;
-import org.apache.brooklyn.core.sensor.Sensors;
-
-/**
- * A collection of entities that can change.
- */
-public interface Changeable {
-
-    AttributeSensor<Integer> GROUP_SIZE = Sensors.newIntegerSensor("group.members.count", "Number of members");
-
-    BasicNotificationSensor<Entity> MEMBER_ADDED = new BasicNotificationSensor<Entity>(Entity.class, "group.members.added", "Entity added to group members");
-    BasicNotificationSensor<Entity> MEMBER_REMOVED = new BasicNotificationSensor<Entity>(Entity.class, "group.members.removed", "Entity removed from group members");
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java
deleted file mode 100644
index 238e261..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.brooklyn.core.entity.trait;
-
-import java.util.NoSuchElementException;
-
-import org.apache.brooklyn.core.annotation.Effector;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.effector.MethodEffector;
-import org.apache.brooklyn.entity.group.StopFailedRuntimeException;
-
-public interface MemberReplaceable {
-
-    MethodEffector<String> REPLACE_MEMBER = new MethodEffector<String>(MemberReplaceable.class, "replaceMember");
-
-    /**
-     * Replaces the entity with the given ID, if it is a member.
-     * <p>
-     * First adds a new member, then removes this one. 
-     *
-     * @param memberId entity id of a member to be replaced
-     * @return the id of the new entity
-     * @throws NoSuchElementException If entity cannot be resolved, or it is not a member
-     * @throws StopFailedRuntimeException If stop failed, after successfully starting replacement
-     */
-    @Effector(description="Replaces the entity with the given ID, if it is a member; first adds a new member, then removes this one. "+
-            "Returns id of the new entity; or throws exception if couldn't be replaced.")
-    String replaceMember(@EffectorParam(name="memberId", description="The entity id of a member to be replaced") String memberId);
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java
deleted file mode 100644
index 36e6ba8..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.brooklyn.core.entity.trait;
-
-
-import org.apache.brooklyn.core.annotation.Effector;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.effector.MethodEffector;
-
-/**
- * Defines an entity group that can be re-sized dynamically.
- * <p/>
- * By invoking the {@link #resize(Integer)} effector, the number of child nodes
- * can be reduced (by shutting down some of them) or increased (by provisioning new entities.)
- */
-public interface Resizable {
-
-    /**
-     * Indicates that resizing up to the desired size is not possible - only resized to the 
-     * {@link Resizable#getCurrentSize()}, because there is insufficient capacity.
-     */
-    public static class InsufficientCapacityException extends RuntimeException {
-        private static final long serialVersionUID = 953230498564942446L;
-        
-        public InsufficientCapacityException(String msg) {
-            super(msg);
-        }
-        public InsufficientCapacityException(String msg, Throwable cause) {
-            super(msg, cause);
-        }
-    }
-    
-    MethodEffector<Integer> RESIZE = new MethodEffector<Integer>(Resizable.class, "resize");
-
-    /**
-     * Grow or shrink this entity to the desired size.
-     *
-     * @param desiredSize the new size of the entity group.
-     * @return the new size of the group.
-     * 
-     * @throws InsufficientCapacityException If the request was to grow, but there is no capacity to grow to
-     *         the desired size.
-     */
-    @Effector(description="Changes the size of the entity (e.g. the number of nodes in a cluster)")
-    Integer resize(@EffectorParam(name="desiredSize", description="The new size of the cluster") Integer desiredSize);
-
-    /**
-     * @return the current size of the group.
-     */
-    Integer getCurrentSize();
-}
-

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java
deleted file mode 100644
index 96812ce..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.brooklyn.core.entity.trait;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.effector.Effector;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.effector.EffectorBody;
-import org.apache.brooklyn.core.effector.Effectors;
-import org.apache.brooklyn.core.effector.MethodEffector;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This interface describes an {@link org.apache.brooklyn.api.entity.Entity} that can be started and stopped.
- *
- * The {@link Effector}s are {@link #START}, {@link #STOP} and {@link #RESTART}. The start effector takes
- * a collection of {@link Location} objects as an argument which will cause the entity to be started or stopped in all
- * these locations. The other effectors will stop or restart the entity in the location(s) it is already running in.
- */
-public interface Startable {
-
-    
-    AttributeSensor<Boolean> SERVICE_UP = Attributes.SERVICE_UP;
-
-    public static class StartEffectorBody extends EffectorBody<Void> {
-        public static final ConfigKey<Object> LOCATIONS = ConfigKeys.newConfigKey(Object.class, "locations",
-            "The location or locations to start in, as a string, a location object, a list of strings, "
-            + "or a list of location objects");
-        @Override public Void call(ConfigBag parameters) {
-            parameters.put(LOCATIONS, entity().getManagementContext().getLocationRegistry().resolveList(parameters.get(LOCATIONS)));
-            return new MethodEffector<Void>(Startable.class, "start").call(entity(), parameters.getAllConfig());
-        }
-    }
-
-    public static class StopEffectorBody extends EffectorBody<Void> {
-        private static final Logger log = LoggerFactory.getLogger(Startable.class);
-        
-        @Override public Void call(ConfigBag parameters) {
-            if (!parameters.isEmpty()) {
-                log.warn("Parameters "+parameters+" not supported for call to "+entity()+" - "+Tasks.current());
-            }
-            
-            return new MethodEffector<Void>(Startable.class, "stop").call(entity(), parameters.getAllConfig());
-        }
-    }
-
-    public static class RestartEffectorBody extends EffectorBody<Void> {
-        private static final Logger log = LoggerFactory.getLogger(Startable.class);
-
-        @Override public Void call(ConfigBag parameters) {
-            if (!parameters.isEmpty()) {
-                log.warn("Parameters "+parameters+" not supported for call to "+entity()+" - "+Tasks.current());
-            }
-            return new MethodEffector<Void>(Startable.class, "restart").call(entity(), parameters.getAllConfig());
-        }
-    }
-
-    org.apache.brooklyn.api.effector.Effector<Void> START = Effectors.effector(new MethodEffector<Void>(Startable.class, "start"))
-        // override start to take strings etc
-        .parameter(StartEffectorBody.LOCATIONS)
-        .impl(new StartEffectorBody())
-        .build();
-    
-    org.apache.brooklyn.api.effector.Effector<Void> STOP = Effectors.effector(new MethodEffector<Void>(Startable.class, "stop"))
-        .impl(new StopEffectorBody())
-        .build();
-    
-    org.apache.brooklyn.api.effector.Effector<Void> RESTART = Effectors.effector(new MethodEffector<Void>(Startable.class, "restart"))
-        .impl(new RestartEffectorBody())
-        .build();
-
-    /**
-     * Start the entity in the given collection of locations.
-     * <p>
-     * Some entities may define custom {@link Effector} implementations which support
-     * a richer set of parameters.  See the entity-specific {@link #START} effector declaration.
-     */
-    @org.apache.brooklyn.core.annotation.Effector(description="Start the process/service represented by an entity")
-    void start(@EffectorParam(name="locations") Collection<? extends Location> locations);
-
-    /**
-     * Stop the entity.
-     * <p>
-     * Some entities may define custom {@link Effector} implementations which support
-     * a richer set of parameters.  See the entity-specific {@link #STOP} effector declaration.
-     */
-    @org.apache.brooklyn.core.annotation.Effector(description="Stop the process/service represented by an entity")
-    void stop();
-
-    /**
-     * Restart the entity.
-     * <p>
-     * Some entities may define custom {@link Effector} implementations which support
-     * a richer set of parameters.  See the entity-specific {@link #RESTART} effector declaration.
-     */
-    @org.apache.brooklyn.core.annotation.Effector(description="Restart the process/service represented by an entity")
-    void restart();
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java
deleted file mode 100644
index b49d259..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.brooklyn.core.entity.trait;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.mgmt.TaskAdaptable;
-import org.apache.brooklyn.core.effector.Effectors;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityPredicates;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.core.task.TaskTags;
-import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-public class StartableMethods {
-
-    public static final Logger log = LoggerFactory.getLogger(StartableMethods.class);
-        
-    private StartableMethods() {}
-
-    /** Common implementation for start in parent nodes; just invokes start on all children of the entity */
-    public static void start(EntityLocal e, Collection<? extends Location> locations) {
-        log.debug("Starting entity "+e+" at "+locations);
-        DynamicTasks.queueIfPossible(startingChildren(e, locations)).orSubmitAsync(e).getTask().getUnchecked();
-    }
-    
-    /** Common implementation for stop in parent nodes; just invokes stop on all children of the entity */
-    public static void stop(EntityLocal e) {
-        log.debug("Stopping entity "+e);
-        DynamicTasks.queueIfPossible(stoppingChildren(e)).orSubmitAsync(e).getTask().getUnchecked();
-        if (log.isDebugEnabled()) log.debug("Stopped entity "+e);
-    }
-
-    /** Common implementation for restart in parent nodes; just invokes restart on all children of the entity */
-    public static void restart(EntityLocal e) {
-        log.debug("Restarting entity "+e);
-        DynamicTasks.queueIfPossible(restartingChildren(e)).orSubmitAsync(e).getTask().getUnchecked();
-        if (log.isDebugEnabled()) log.debug("Restarted entity "+e);
-    }
-    
-    private static <T extends Entity> Iterable<T> filterStartableManagedEntities(Iterable<T> contenders) {
-        return Iterables.filter(contenders, Predicates.and(Predicates.instanceOf(Startable.class), EntityPredicates.isManaged()));
-    }
-
-    public static void stopSequentially(Iterable<? extends Startable> entities) {
-        List<Exception> exceptions = Lists.newArrayList();
-        List<Startable> failedEntities = Lists.newArrayList();
-        
-        for (final Startable entity : entities) {
-            if (!Entities.isManaged((Entity)entity)) {
-                log.debug("Not stopping {} because it is not managed; continuing", entity);
-                continue;
-            }
-            try {
-                TaskAdaptable<Void> task = TaskTags.markInessential(Effectors.invocation((Entity)entity, Startable.STOP, Collections.emptyMap()));
-                DynamicTasks.submit(task, (Entity)entity).getUnchecked();
-            } catch (Exception e) {
-                log.warn("Error stopping "+entity+"; continuing with shutdown", e);
-                exceptions.add(e);
-                failedEntities.add(entity);
-            }
-        }
-        
-        if (exceptions.size() > 0) {
-            throw new CompoundRuntimeException("Error stopping "+(failedEntities.size() > 1 ? "entities" : "entity")+": "+failedEntities, exceptions);
-        }
-    }
-
-    /** unsubmitted task for starting children of the given entity at the same location as the entity */
-    public static TaskAdaptable<?> startingChildren(Entity entity) {
-        return startingChildren(entity, entity.getLocations());
-    }
-    /** unsubmitted task for starting children of the given entity at the given location */
-    public static TaskAdaptable<?> startingChildren(Entity entity, Location location) {
-        return startingChildren(entity, Collections.singleton(location));
-    }
-    /** unsubmitted task for starting children of the given entity at the given locations */
-    public static TaskAdaptable<?> startingChildren(Entity entity, Iterable<? extends Location> locations) {
-        return Effectors.invocation(Startable.START, MutableMap.of("locations", locations), filterStartableManagedEntities(entity.getChildren()));
-    }
-
-    /** unsubmitted task for stopping children of the given entity */
-    public static TaskAdaptable<?> stoppingChildren(Entity entity) {
-        return Effectors.invocation(Startable.STOP, Collections.emptyMap(), filterStartableManagedEntities(entity.getChildren()));
-    }
-
-    /** unsubmitted task for restarting children of the given entity */
-    public static TaskAdaptable<?> restartingChildren(Entity entity, ConfigBag parameters) {
-        return Effectors.invocation(Startable.RESTART, parameters.getAllConfig(), filterStartableManagedEntities(entity.getChildren()));
-    }
-    /** as {@link #restartingChildren(Entity, ConfigBag)} with no parameters */
-    public static TaskAdaptable<?> restartingChildren(Entity entity) {
-        return restartingChildren(entity, ConfigBag.EMPTY);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
deleted file mode 100644
index 5b057dd..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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.brooklyn.core.feed;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
-import org.apache.brooklyn.api.mgmt.rebind.mementos.FeedMemento;
-import org.apache.brooklyn.api.sensor.Feed;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.BrooklynFeatureEnablement;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.mgmt.rebind.BasicFeedRebindSupport;
-import org.apache.brooklyn.core.objs.AbstractEntityAdjunct;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.apache.brooklyn.util.text.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** 
- * Captures common fields and processes for sensor feeds.
- * These generally poll or subscribe to get sensor values for an entity.
- * They make it easy to poll over http, jmx, etc.
- */
-public abstract class AbstractFeed extends AbstractEntityAdjunct implements Feed {
-
-    private static final Logger log = LoggerFactory.getLogger(AbstractFeed.class);
-
-    public static final ConfigKey<Boolean> ONLY_IF_SERVICE_UP = ConfigKeys.newBooleanConfigKey("feed.onlyIfServiceUp", "", false);
-    
-    private final Object pollerStateMutex = new Object();
-    private transient volatile Poller<?> poller;
-    private transient volatile boolean activated;
-    private transient volatile boolean suspended;
-
-    public AbstractFeed() {
-    }
-    
-    /**
-     * @deprecated since 0.7.0; use no-arg constructor; call {@link #setEntity(EntityLocal)}
-     */
-    @Deprecated
-    public AbstractFeed(EntityLocal entity) {
-        this(entity, false);
-    }
-    
-    /**
-     * @deprecated since 0.7.0; use no-arg constructor; call {@link #setEntity(EntityLocal)} and {@code setConfig(ONLY_IF_SERVICE_UP, onlyIfServiceUp)}
-     */
-    @Deprecated
-    public AbstractFeed(EntityLocal entity, boolean onlyIfServiceUp) {
-        this.entity = checkNotNull(entity, "entity");
-        setConfig(ONLY_IF_SERVICE_UP, onlyIfServiceUp);
-    }
-
-    // Ensure idempotent, as called in builders (in case not registered with entity), and also called
-    // when registering with entity
-    @Override
-    public void setEntity(EntityLocal entity) {
-        super.setEntity(entity);
-        if (BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_FEED_REGISTRATION_PROPERTY)) {
-            ((EntityInternal)entity).feeds().addFeed(this);
-        }
-    }
-
-    protected void initUniqueTag(String uniqueTag, Object ...valsForDefault) {
-        if (Strings.isNonBlank(uniqueTag)) this.uniqueTag = uniqueTag;
-        else this.uniqueTag = getDefaultUniqueTag(valsForDefault);
-    }
-
-    protected String getDefaultUniqueTag(Object ...valsForDefault) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(JavaClassNames.simpleClassName(this));
-        if (valsForDefault.length==0) {
-            sb.append("@");
-            sb.append(hashCode());
-        } else if (valsForDefault.length==1 && valsForDefault[0] instanceof Collection){
-            sb.append(Strings.toUniqueString(valsForDefault[0], 80));
-        } else {
-            sb.append("[");
-            boolean first = true;
-            for (Object x: valsForDefault) {
-                if (!first) sb.append(";");
-                else first = false;
-                sb.append(Strings.toUniqueString(x, 80));
-            }
-            sb.append("]");
-        }
-        return sb.toString(); 
-    }
-
-    @Override
-    public void start() {
-        if (log.isDebugEnabled()) log.debug("Starting feed {} for {}", this, entity);
-        if (activated) { 
-            throw new IllegalStateException(String.format("Attempt to start feed %s of entity %s when already running", 
-                    this, entity));
-        }
-        if (poller != null) {
-            throw new IllegalStateException(String.format("Attempt to re-start feed %s of entity %s", this, entity));
-        }
-        
-        poller = new Poller<Object>(entity, getConfig(ONLY_IF_SERVICE_UP));
-        activated = true;
-        preStart();
-        synchronized (pollerStateMutex) {
-            // don't start poller if we are suspended
-            if (!suspended) {
-                poller.start();
-            }
-        }
-    }
-
-    @Override
-    public void suspend() {
-        synchronized (pollerStateMutex) {
-            if (activated && !suspended) {
-                poller.stop();
-            }
-            suspended = true;
-        }
-    }
-    
-    @Override
-    public void resume() {
-        synchronized (pollerStateMutex) {
-            if (activated && suspended) {
-                poller.start();
-            }
-            suspended = false;
-        }
-    }
-    
-    @Override
-    public void destroy() {
-        stop();
-    }
-
-    @Override
-    public void stop() {
-        if (!activated) { 
-            log.debug("Ignoring attempt to stop feed {} of entity {} when not running", this, entity);
-            return;
-        }
-        if (log.isDebugEnabled()) log.debug("stopping feed {} for {}", this, entity);
-        
-        activated = false;
-        preStop();
-        synchronized (pollerStateMutex) {
-            if (!suspended) {
-                poller.stop();
-            }
-        }
-        postStop();
-        super.destroy();
-    }
-
-    @Override
-    public boolean isActivated() {
-        return activated;
-    }
-    
-    public EntityLocal getEntity() {
-        return entity;
-    }
-    
-    protected boolean isConnected() {
-        // TODO Default impl will result in multiple logs for same error if becomes unreachable
-        // (e.g. if ssh gets NoRouteToHostException, then every AttributePollHandler for that
-        // feed will log.warn - so if polling for 10 sensors/attributes will get 10 log messages).
-        // Would be nice if reduced this logging duplication.
-        // (You can reduce it by providing a better 'isConnected' implementation of course.)
-        return isRunning() && entity!=null && !((EntityInternal)entity).getManagementSupport().isNoLongerManaged();
-    }
-
-    @Override
-    public boolean isSuspended() {
-        return suspended;
-    }
-
-    @Override
-    public boolean isRunning() {
-        return isActivated() && !isSuspended() && !isDestroyed() && getPoller()!=null && getPoller().isRunning();
-    }
-
-    @Override
-    public RebindSupport<FeedMemento> getRebindSupport() {
-        return new BasicFeedRebindSupport(this);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public RelationSupportInternal<Feed> relations() {
-        return (RelationSupportInternal<Feed>) super.relations();
-    }
-    
-    @Override
-    protected void onChanged() {
-        // TODO Auto-generated method stub
-    }
-
-    /**
-     * For overriding.
-     */
-    protected void preStart() {
-    }
-    
-    /**
-     * For overriding.
-     */
-    protected void preStop() {
-    }
-    
-    /**
-     * For overriding.
-     */
-    protected void postStop() {
-    }
-    
-    /**
-     * For overriding, where sub-class can change return-type generics!
-     */
-    protected Poller<?> getPoller() {
-        return poller;
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AttributePollHandler.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AttributePollHandler.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AttributePollHandler.java
deleted file mode 100644
index a82f5d9..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/AttributePollHandler.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.brooklyn.core.feed;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
-import org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition;
-import org.apache.brooklyn.util.core.flags.TypeCoercions;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-
-/**
- * Handler for when polling an entity's attribute. On each poll result the entity's attribute is set.
- * 
- * Calls to onSuccess and onError will happen sequentially, but may be called from different threads 
- * each time. Note that no guarantees of a synchronized block exist, so additional synchronization 
- * would be required for the Java memory model's "happens before" relationship.
- * 
- * @author aled
- */
-public class AttributePollHandler<V> implements PollHandler<V> {
-
-    public static final Logger log = LoggerFactory.getLogger(AttributePollHandler.class);
-
-    private final FeedConfig<V,?,?> config;
-    private final EntityLocal entity;
-    @SuppressWarnings("rawtypes")
-    private final AttributeSensor sensor;
-    private final AbstractFeed feed;
-    private final boolean suppressDuplicates;
-    
-    // allow 30 seconds before logging at WARN, if there has been no success yet;
-    // after success WARN immediately
-    // TODO these should both be configurable
-    private Duration logWarningGraceTimeOnStartup = Duration.THIRTY_SECONDS;
-    private Duration logWarningGraceTime = Duration.millis(0);
-    
-    // internal state to look after whether to log warnings
-    private volatile Long lastSuccessTime = null;
-    private volatile Long currentProblemStartTime = null;
-    private volatile boolean currentProblemLoggedAsWarning = false;
-    private volatile boolean lastWasProblem = false;
-
-    
-    public AttributePollHandler(FeedConfig<V,?,?> config, EntityLocal entity, AbstractFeed feed) {
-        this.config = checkNotNull(config, "config");
-        this.entity = checkNotNull(entity, "entity");
-        this.sensor = checkNotNull(config.getSensor(), "sensor");
-        this.feed = checkNotNull(feed, "feed");
-        this.suppressDuplicates = config.getSupressDuplicates();
-    }
-
-    @Override
-    public boolean checkSuccess(V val) {
-        // Always true if no checkSuccess predicate was configured.
-        return !config.hasCheckSuccessHandler() || config.getCheckSuccess().apply(val);
-    }
-
-    @Override
-    public void onSuccess(V val) {
-        if (lastWasProblem) {
-            if (currentProblemLoggedAsWarning) { 
-                log.info("Success (following previous problem) reading "+getBriefDescription());
-            } else {
-                log.debug("Success (following previous problem) reading "+getBriefDescription());
-            }
-            lastWasProblem = false;
-            currentProblemStartTime = null;
-            currentProblemLoggedAsWarning = false;
-        }
-        lastSuccessTime = System.currentTimeMillis();
-        if (log.isTraceEnabled()) log.trace("poll for {} got: {}", new Object[] {getBriefDescription(), val});
-        
-        try {
-            setSensor(transformValueOnSuccess(val));
-        } catch (Exception e) {
-            if (feed.isConnected()) {
-                log.warn("unable to compute "+getBriefDescription()+"; on val="+val, e);
-            } else {
-                if (log.isDebugEnabled()) log.debug("unable to compute "+getBriefDescription()+"; val="+val+" (when inactive)", e);
-            }
-        }
-    }
-
-    /** allows post-processing, such as applying a success handler; 
-     * default applies the onSuccess handler (which is recommended) */
-    protected Object transformValueOnSuccess(V val) {
-        return config.hasSuccessHandler() ? config.getOnSuccess().apply(val) : val;
-    }
-
-    @Override
-    public void onFailure(V val) {
-        if (!config.hasFailureHandler()) {
-            onException(new Exception("checkSuccess of "+this+" for "+getBriefDescription()+" was false but poller has no failure handler"));
-        } else {
-            logProblem("failure", val);
-
-            try {
-                setSensor(config.hasFailureHandler() ? config.getOnFailure().apply((V)val) : val);
-            } catch (Exception e) {
-                if (feed.isConnected()) {
-                    log.warn("Error computing " + getBriefDescription() + "; val=" + val+": "+ e, e);
-                } else {
-                    if (log.isDebugEnabled())
-                        log.debug("Error computing " + getBriefDescription() + "; val=" + val + " (when inactive)", e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onException(Exception exception) {
-        if (!feed.isConnected()) {
-            if (log.isTraceEnabled()) log.trace("Read of {} in {} gave exception (while not connected or not yet connected): {}", new Object[] {this, getBriefDescription(), exception});
-        } else {
-            logProblem("exception", exception);
-        }
-
-        if (config.hasExceptionHandler()) {
-            try {
-                setSensor( config.getOnException().apply(exception) );
-            } catch (Exception e) {
-                if (feed.isConnected()) {
-                    log.warn("unable to compute "+getBriefDescription()+"; on exception="+exception, e);
-                } else {
-                    if (log.isDebugEnabled()) log.debug("unable to compute "+getBriefDescription()+"; exception="+exception+" (when inactive)", e);
-                }
-            }
-        }
-    }
-
-    protected void logProblem(String type, Object val) {
-        if (lastWasProblem && currentProblemLoggedAsWarning) {
-            if (log.isTraceEnabled())
-                log.trace("Recurring {} reading {} in {}: {}", new Object[] {type, this, getBriefDescription(), val});
-        } else {
-            long nowTime = System.currentTimeMillis();
-            // get a non-volatile value
-            Long currentProblemStartTimeCache = currentProblemStartTime;
-            long expiryTime = 
-                    (lastSuccessTime!=null && !isTransitioningOrStopped()) ? lastSuccessTime+logWarningGraceTime.toMilliseconds() :
-                    currentProblemStartTimeCache!=null ? currentProblemStartTimeCache+logWarningGraceTimeOnStartup.toMilliseconds() :
-                    nowTime+logWarningGraceTimeOnStartup.toMilliseconds();
-            if (!lastWasProblem) {
-                if (expiryTime <= nowTime) {
-                    currentProblemLoggedAsWarning = true;
-                    if (entity==null || !Entities.isNoLongerManaged(entity)) {
-                        log.warn("Read of " + getBriefDescription() + " gave " + type + ": " + val);
-                    } else {
-                        log.debug("Read of " + getBriefDescription() + " gave " + type + ": " + val);
-                    }
-                    if (log.isDebugEnabled() && val instanceof Throwable)
-                        log.debug("Trace for "+type+" reading "+getBriefDescription()+": "+val, (Throwable)val);
-                } else {
-                    if (log.isDebugEnabled())
-                        log.debug("Read of " + getBriefDescription() + " gave " + type + " (in grace period): " + val);
-                }
-                lastWasProblem = true;
-                currentProblemStartTime = nowTime;
-            } else {
-                if (expiryTime <= nowTime) {
-                    currentProblemLoggedAsWarning = true;
-                    log.warn("Read of " + getBriefDescription() + " gave " + type + 
-                            " (grace period expired, occurring for "+Duration.millis(nowTime - currentProblemStartTimeCache)+
-                            (config.hasExceptionHandler() ? "" : ", no exception handler set for sensor")+
-                            ")"+
-                            ": " + val);
-                    if (log.isDebugEnabled() && val instanceof Throwable)
-                        log.debug("Trace for "+type+" reading "+getBriefDescription()+": "+val, (Throwable)val);
-                } else {
-                    if (log.isDebugEnabled()) 
-                        log.debug("Recurring {} reading {} in {} (still in grace period): {}", new Object[] {type, this, getBriefDescription(), val});
-                }
-            }
-        }
-    }
-
-    protected boolean isTransitioningOrStopped() {
-        if (entity==null) return false;
-        Transition expected = entity.getAttribute(Attributes.SERVICE_STATE_EXPECTED);
-        if (expected==null) return false;
-        return (expected.getState()==Lifecycle.STARTING || expected.getState()==Lifecycle.STOPPING || expected.getState()==Lifecycle.STOPPED);
-    }
-
-    @SuppressWarnings("unchecked")
-    protected void setSensor(Object v) {
-        if (Entities.isNoLongerManaged(entity)) {
-            if (Tasks.isInterrupted()) return;
-            log.warn(""+entity+" is not managed; feed "+this+" setting "+sensor+" to "+v+" at this time is not supported ("+Tasks.current()+")");
-        }
-        
-        if (v == FeedConfig.UNCHANGED) {
-            // nothing
-        } else if (v == FeedConfig.REMOVE) {
-            ((EntityInternal)entity).removeAttribute(sensor);
-        } else if (sensor == FeedConfig.NO_SENSOR) {
-            // nothing
-        } else {
-            Object coercedV = TypeCoercions.coerce(v, sensor.getType());
-            if (suppressDuplicates && Objects.equal(coercedV, entity.getAttribute(sensor))) {
-                // no change; nothing
-            } else {
-                entity.sensors().set(sensor, coercedV);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        return super.toString()+"["+getDescription()+"]";
-    }
-    
-    @Override
-    public String getDescription() {
-        return sensor.getName()+" @ "+entity.getId()+" <- "+config;
-    }
-    
-    protected String getBriefDescription() {
-        return ""+entity+"->"+(sensor==FeedConfig.NO_SENSOR ? "(dynamic sensors)" : ""+sensor);
-    }
-        
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/ConfigToAttributes.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/ConfigToAttributes.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/ConfigToAttributes.java
deleted file mode 100644
index dc81d2a..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/ConfigToAttributes.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.brooklyn.core.feed;
-
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
-import org.apache.brooklyn.core.sensor.TemplatedStringAttributeSensorAndConfigKey;
-
-
-/** Simple config adapter for setting {@link AttributeSensorAndConfigKey} sensor values from the config value or config default */ 
-public class ConfigToAttributes {
-
-    //normally just applied once, statically, not registered...
-    public static void apply(EntityLocal entity) {
-        for (Sensor<?> it : entity.getEntityType().getSensors()) {
-            if (it instanceof AttributeSensorAndConfigKey) {
-                apply(entity, (AttributeSensorAndConfigKey<?,?>)it);
-            }
-        }
-    }
-
-    /**
-     * Convenience for ensuring an individual sensor is set from its config key
-     * (e.g. sub-classes of DynamicWebAppCluster that don't want to set HTTP_PORT etc!)
-     */
-    public static <T> T apply(EntityLocal entity, AttributeSensorAndConfigKey<?,T> key) {
-        T v = entity.getAttribute(key);
-        if (v!=null) return v;
-        v = key.getAsSensorValue(entity);
-        if (v!=null) entity.sensors().set(key, v);
-        return v;
-    }
-
-    /**
-     * Convenience for transforming a config value (e.g. processing a {@link TemplatedStringAttributeSensorAndConfigKey}),
-     * outside of the context of an entity.
-     */
-    public static <T> T transform(ManagementContext managementContext, AttributeSensorAndConfigKey<?,T> key) {
-        return key.getAsSensorValue(managementContext);
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/DelegatingPollHandler.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/DelegatingPollHandler.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/DelegatingPollHandler.java
deleted file mode 100644
index fae7dd6..0000000
--- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/feed/DelegatingPollHandler.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.brooklyn.core.feed;
-
-import java.util.List;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * A poll handler that delegates each call to a set of poll handlers.
- * 
- * @author aled
- */
-public class DelegatingPollHandler<V> implements PollHandler<V> {
-
-    private final List<AttributePollHandler<? super V>> delegates;
-
-    public DelegatingPollHandler(Iterable<AttributePollHandler<? super V>> delegates) {
-        super();
-        this.delegates = ImmutableList.copyOf(delegates);
-    }
-
-    @Override
-    public boolean checkSuccess(V val) {
-        for (AttributePollHandler<? super V> delegate : delegates) {
-            if (!delegate.checkSuccess(val))
-                return false;
-        }
-        return true;
-    }
-
-    @Override
-    public void onSuccess(V val) {
-        for (AttributePollHandler<? super V> delegate : delegates) {
-            delegate.onSuccess(val);
-        }
-    }
-
-    @Override
-    public void onFailure(V val) {
-        for (AttributePollHandler<? super V> delegate : delegates) {
-            delegate.onFailure(val);
-        }
-    }
-
-    @Override
-    public void onException(Exception exception) {
-        for (AttributePollHandler<? super V> delegate : delegates) {
-            delegate.onException(exception);
-        }
-    }
-    
-    @Override
-    public String toString() {
-        return super.toString()+"["+getDescription()+"]";
-    }
-    
-    @Override
-    public String getDescription() {
-        if (delegates.isEmpty())
-            return "(empty delegate list)";
-        if (delegates.size()==1) 
-            return delegates.get(0).getDescription();
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        int count = 0;
-        for (AttributePollHandler<? super V> delegate : delegates) {
-            if (count>0) sb.append("; ");
-            sb.append(delegate.getDescription());
-            if (count>2) {
-                sb.append("; ...");
-                break;
-            }
-            count++;
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-    
-}