private void onItemRemoved(ItemType item, NodeType parentContainer, boolean rebalanceNow) { if (LOG.isTraceEnabled()) LOG.trace("{} recording removal of item {}", this, item); subscriptions().unsubscribe(item); model.onItemRemoved(item); if (rebalanceNow) scheduleRebalance(); }
subscriptions().subscribeToMembers((Group)entity, failureSensorToMonitor, new SensorEventListener<Object>() { @Override public void onEvent(final SensorEvent<Object> event) {
"Subscribing to group "+group+", for memberAdded, memberRemoved, and {}", getSensorsToTrack()); subscriptions().subscribe(group, DynamicGroup.MEMBER_ADDED, new SensorEventListener<Entity>() { @Override public void onEvent(SensorEvent<Entity> event) { onEntityEvent(EventType.ENTITY_ADDED, event.getValue()); subscriptions().subscribe(group, DynamicGroup.MEMBER_REMOVED, new SensorEventListener<Entity>() { @Override public void onEvent(SensorEvent<Entity> event) { entitySensorCache.remove(event.getSource().getId()); subscriptions().subscribeToMembers(group, sensor, new SensorEventListener<Object>() { @Override public void onEvent(SensorEvent<Object> event) { boolean notifyOnDuplicates = getRequiredConfig(NOTIFY_ON_DUPLICATES);
protected void startSubscriptions(EntityLocal entity) { if (getConfig(REQUIRE_SERVICE_UP)) { subscriptions().subscribe(entity, Startable.SERVICE_UP, new SensorEventListener<Boolean>() { @Override public void onEvent(SensorEvent<Boolean> event) { subscriptions().subscribe(entity, urlSensor, new SensorEventListener<Object>() { @Override public void onEvent(SensorEvent<Object> event) {
subscriptions().subscribe(entity, AbstractEntity.LOCATION_ADDED, new SensorEventListener<Location>() { @Override public void onEvent(SensorEvent<Location> event) { LOG.debug("{} attempting transformations, triggered by location-added {}, to {}", new Object[] {AbstractOnNetworkEnricher.this, event.getValue(), entity}); subscriptions().subscribe(entity, sensor, new SensorEventListener<Object>() { @Override public void onEvent(SensorEvent<Object> event) { LOG.debug("{} attempting transformations, triggered by sensor-event {}->{}, to {}", subscriptions().subscribe(entity, wildcardSensor, new SensorEventListener<Object>() { @Override public void onEvent(SensorEvent<Object> event) { if (mapMatching.get().apply(event.getSensor())) {
@Override public void setEntity(EntityLocal entity) { /* * A warning to future modifiers of this method: it is called on rebind * so any changes must be compatible with existing persisted state. */ super.setEntity(entity); Sensor<? extends Collection<?>> sensor = checkNotNull(getConfig(TRIGGER_SENSOR), "Value required for " + TRIGGER_SENSOR.getName()); checkArgument(Strings.isNonBlank(getConfig(PARAMETER_NAME)), "Value required for " + PARAMETER_NAME.getName()); // Fail straight away if neither effector is found. if (getEffector(getOnAddedEffector()).isAbsentOrNull() && getEffector(getOnRemovedEffector()).isAbsentOrNull()) { throw new IllegalArgumentException("Value required for one or both of " + ON_ADDED_EFFECTOR_NAME.getName() + " and " + ON_REMOVED_EFFECTOR_NAME.getName()); } // Initialise `present` before subscribing. Collection<?> current = entity.sensors().get(getTriggerSensor()); synchronized (updateLock) { previous = (current != null) ? new HashSet<>(current) : Collections.emptySet(); } subscriptions().subscribe(entity, sensor, this); }
@SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void setEntity(EntityLocal entity) { super.setEntity(entity); this.transformation = (Function<? super Collection<T>, ? extends U>) getRequiredConfig(TRANSFORMATION); this.producer = getConfig(PRODUCER) == null ? entity: getConfig(PRODUCER); this.sourceSensors = (Set) getRequiredConfig(SOURCE_SENSORS); this.targetSensor = (Sensor<U>) getRequiredConfig(TARGET_SENSOR); this.valueFilter = (Predicate<? super T>) (getConfig(VALUE_FILTER) == null ? Predicates.alwaysTrue() : getConfig(VALUE_FILTER)); checkState(sourceSensors.size() > 0, "must specify at least one sourceSensor"); for (Sensor<T> sourceSensor : sourceSensors) { subscriptions().subscribe(producer, sourceSensor, this); } for (Sensor<T> sourceSensor : sourceSensors) { if (sourceSensor instanceof AttributeSensor) { Object value = producer.getAttribute((AttributeSensor<?>)sourceSensor); // TODO Aled didn't you write a convenience to "subscribeAndRunIfSet" ? (-Alex) // Unfortunately not yet! if (value != null) { onEvent(new BasicSensorEvent(sourceSensor, producer, value, -1)); } } } highlightTriggers(sourceSensors, producer); }
@Override public void setEntity(final EntityLocal entity) { Preconditions.checkArgument(entity instanceof Startable, "Restarter must take a Startable, not "+entity); super.setEntity(entity); subscriptions().subscribe(entity, getConfig(FAILURE_SENSOR_TO_MONITOR), new SensorEventListener<Object>() { @Override public void onEvent(final SensorEvent<Object> event) { // Must execute in another thread - if we called entity.restart in the event-listener's thread // then we'd block all other events being delivered to this entity's other subscribers. // Relies on synchronization of `onDetectedFailure`. // See same pattern used in ServiceReplacer. // TODO Could use BasicExecutionManager.setTaskSchedulerForTag to prevent race of two // events being received in rapid succession, and onDetectedFailure being executed out-of-order // for them; or could write events to a blocking queue and have onDetectedFailure read from that. if (isRunning()) { LOG.info("ServiceRestarter notified; dispatching job for "+entity+" ("+event.getValue()+")"); ((EntityInternal)entity).getExecutionContext().submit(MutableMap.of(), new Runnable() { @Override public void run() { onDetectedFailure(event); }}); } else { LOG.warn("ServiceRestarter not running, so not acting on failure detected at "+entity+" ("+event.getValue()+")"); } } }); highlightTriggers(getConfig(FAILURE_SENSOR_TO_MONITOR), entity); }
private void subscribe() { subscriptions().subscribe(entity, getConfig(SUSPEND_SENSOR), new SensorEventListener<Object>() { @Override public void onEvent(final SensorEvent<Object> event) { if (isRunning()) { Policy target = getTargetPolicy(); target.suspend(); LOG.debug("Suspended policy " + target + ", triggered by " + event.getSensor() + " = " + event.getValue()); } } }); subscriptions().subscribe(entity, getConfig(RESUME_SENSOR), new SensorEventListener<Object>() { @Override public void onEvent(final SensorEvent<Object> event) { if (isRunning()) { Policy target = getTargetPolicy(); target.resume(); LOG.debug("Resumed policy " + target + ", triggered by " + event.getSensor() + " = " + event.getValue()); } } }); }
@SuppressWarnings({"unchecked", "rawtypes"}) @Override public void setEntity(EntityLocal entity) { super.setEntity(entity); sourceCurrentSensor = Preconditions.checkNotNull(config().get(SOURCE_CURRENT_SENSOR), "Can't add percentage enricher to entity %s as it has no %s", entity, SOURCE_CURRENT_SENSOR.getName()); sourceTotalSensor = Preconditions.checkNotNull(config().get(SOURCE_TOTAL_SENSOR), "Can't add percentage enricher to entity %s as it has no %s", entity, SOURCE_TOTAL_SENSOR.getName()); targetSensor = Preconditions.checkNotNull(config().get(TARGET_SENSOR), "Can't add percentage enricher to entity %s as it has no %s", entity, TARGET_SENSOR.getName()); producer = Objects.firstNonNull(config().get(PRODUCER), entity); if (targetSensor.equals(sourceCurrentSensor) && entity.equals(producer)) { throw new IllegalArgumentException("Can't add percentage enricher to entity " + entity + " as cycle detected with " + SOURCE_CURRENT_SENSOR.getName()); } if (targetSensor.equals(sourceTotalSensor) && entity.equals(producer)) { throw new IllegalArgumentException("Can't add percentage enricher to entity " + entity + " as cycle detected with " + SOURCE_TOTAL_SENSOR.getName()); } subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), producer, sourceCurrentSensor, this); subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), producer, sourceTotalSensor, this); if (RendererHints.getHintsFor(targetSensor).isEmpty()) { RendererHints.register(targetSensor, RendererHints.displayValue(MathFunctions.percent(2))); } }
@SuppressWarnings("unchecked") @Override public void setEntity(EntityLocal entity) { Preconditions.checkArgument(entity instanceof BalanceableWorkerPool, "Provided entity must be a BalanceableWorkerPool"); super.setEntity(entity); this.poolEntity = (BalanceableWorkerPool) entity; // Detect when containers are added to or removed from the pool. subscriptions().subscribe(poolEntity, BalanceableWorkerPool.CONTAINER_ADDED, eventHandler); subscriptions().subscribe(poolEntity, BalanceableWorkerPool.CONTAINER_REMOVED, eventHandler); subscriptions().subscribe(poolEntity, BalanceableWorkerPool.ITEM_ADDED, eventHandler); subscriptions().subscribe(poolEntity, BalanceableWorkerPool.ITEM_REMOVED, eventHandler); subscriptions().subscribe(poolEntity, BalanceableWorkerPool.ITEM_MOVED, eventHandler); // Take heed of any extant containers. for (Entity container : poolEntity.getContainerGroup().getMembers()) { onContainerAdded((NodeType)container, false); } for (Entity item : poolEntity.getItemGroup().getMembers()) { onItemAdded((ItemType)item, (NodeType)item.getAttribute(Movable.CONTAINER), false); } scheduleRebalance(); }
@Override public void setEntity(EntityLocal entity) { checkArgument(entity instanceof FollowTheSunPool, "Provided entity must be a FollowTheSunPool"); super.setEntity(entity); this.poolEntity = (FollowTheSunPool) entity; // Detect when containers are added to or removed from the pool. subscriptions().subscribe(poolEntity, FollowTheSunPool.CONTAINER_ADDED, eventHandler); subscriptions().subscribe(poolEntity, FollowTheSunPool.CONTAINER_REMOVED, eventHandler); subscriptions().subscribe(poolEntity, FollowTheSunPool.ITEM_ADDED, eventHandler); subscriptions().subscribe(poolEntity, FollowTheSunPool.ITEM_REMOVED, eventHandler); subscriptions().subscribe(poolEntity, FollowTheSunPool.ITEM_MOVED, eventHandler); // Take heed of any extant containers. for (Entity container : poolEntity.getContainerGroup().getMembers()) { onContainerAdded(container, false); } for (Entity item : poolEntity.getItemGroup().getMembers()) { onItemAdded((Movable)item, false); } scheduleLatencyReductionJig(); }
@Override public void setEntity(EntityLocal entity) { if (!(entity instanceof AsyncApplicationImpl)) { throw new IllegalArgumentException("enricher designed to work only with async-apps"); } if (!isRebinding() && Boolean.FALSE.equals(config().get(SUPPRESS_DUPLICATES))) { throw new IllegalArgumentException("Must not set "+SUPPRESS_DUPLICATES+" to false when using "+this); } super.setEntity(entity); if (suppressDuplicates==null) { // only publish on changes, unless it is configured otherwise suppressDuplicates = true; } // Need to update again, e.g. if stop() effector marks this as expected=stopped. // There'd be a risk of infinite loop if we didn't suppressDuplicates! subscriptions().subscribe(entity, Attributes.SERVICE_STATE_EXPECTED, new SensorEventListener<Lifecycle.Transition>() { @Override public void onEvent(SensorEvent<Lifecycle.Transition> event) { onUpdated(); }}); }
@Override public void setEntity(EntityLocal entity) { Preconditions.checkArgument(entity instanceof DockerInfrastructure, "Entity must be a DockerInfrastructure: %s", entity); super.setEntity(entity); Integer headroom = config().get(CONTAINER_HEADROOM); Double percent = config().get(CONTAINER_HEADROOM_PERCENTAGE); Preconditions.checkArgument((headroom != null) ^ (percent != null), "Headroom must be configured as either number or percentage for this enricher"); if (headroom != null) { Preconditions.checkArgument(headroom > 0, "Headroom must be a positive integer: %d", headroom); } if (percent != null) { Preconditions.checkArgument(percent > 0d && percent < 1d, "Headroom percentage must be between 0.0 and 1.0: %f", percent); } subscriptions().subscribe(entity, DockerInfrastructure.DOCKER_CONTAINER_COUNT, new Listener()); subscriptions().subscribe(entity, DockerInfrastructure.DOCKER_HOST_COUNT, new Listener()); }
@Test public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() throws Exception { policy.subscriptions().subscribe(entity, TestEntity.SEQUENCE, listener); policy.subscriptions().subscribe(entity, TestEntity.NAME, listener); policy.subscriptions().subscribe(entity, TestEntity.MY_NOTIF, listener); policy.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener); policy.subscriptions().unsubscribe(entity); entity.sensors().set(TestEntity.SEQUENCE, 123); entity.sensors().set(TestEntity.NAME, "myname"); entity.sensors().emit(TestEntity.MY_NOTIF, 456); otherEntity.sensors().set(TestEntity.SEQUENCE, 789); Thread.sleep(SHORT_WAIT_MS); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 789))); }}); }
@Test public void testSubscriptionReceivesEvents() throws Exception { policy.subscriptions().subscribe(entity, TestEntity.SEQUENCE, listener); policy.subscriptions().subscribe(entity, TestEntity.NAME, listener); policy.subscriptions().subscribe(entity, TestEntity.MY_NOTIF, listener); otherEntity.sensors().set(TestEntity.SEQUENCE, 456); entity.sensors().set(TestEntity.SEQUENCE, 123); entity.sensors().set(TestEntity.NAME, "myname"); entity.sensors().emit(TestEntity.MY_NOTIF, 789); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123), new BasicSensorEvent<String>(TestEntity.NAME, entity, "myname"), new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, entity, 789))); }}); }
protected void setEntitySubscribeProducerMemberEvents() { subscriptions().subscribe(producer, Changeable.MEMBER_ADDED, new SensorEventListener<Entity>() { @Override public void onEvent(SensorEvent<Entity> event) { if (entityFilter.apply(event.getValue())) { addProducerMember(event.getValue()); onUpdated(); } } }); subscriptions().subscribe(producer, Changeable.MEMBER_REMOVED, new SensorEventListener<Entity>() { @Override public void onEvent(SensorEvent<Entity> event) { removeProducer(event.getValue()); onUpdated(); } }); }
@Override public void setEntity(EntityLocal entity) { if (!config().getRaw(RESIZE_OPERATOR).isPresentAndNonNull()) { Preconditions.checkArgument(entity instanceof Resizable, "Provided entity "+entity+" must be an instance of Resizable, because no custom-resizer operator supplied"); } super.setEntity(entity); this.poolEntity = entity; if (getMetric() != null) { Entity entityToSubscribeTo = (getEntityWithMetric() != null) ? getEntityWithMetric() : entity; subscriptions().subscribe(entityToSubscribeTo, getMetric(), metricEventHandler); highlightTriggers(getMetric(), entityToSubscribeTo); } else { highlightTriggers("Listening for standard size and pool hot/cold sensors (no specific metric)"); } subscriptions().subscribe(poolEntity, getPoolColdSensor(), utilizationEventHandler); subscriptions().subscribe(poolEntity, getPoolHotSensor(), utilizationEventHandler); subscriptions().subscribe(poolEntity, getPoolOkSensor(), utilizationEventHandler); subscriptions().subscribe(poolEntity, DynamicCluster.GROUP_SIZE, poolEventHandler); }