/** as {@link #updateProblemsIndicator(Entity, Sensor, Object)} */ public static void updateProblemsIndicator(Entity entity, String key, Object value) { updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key, value); } /** as {@link #clearProblemsIndicator(Entity, Sensor)} */
/** 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(Entity 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 */
@SuppressWarnings("unchecked") public static <TKey,TVal> void clearMapSensorEntry(Entity entity, AttributeSensor<Map<TKey,TVal>> sensor, TKey key) { updateMapSensorEntry(entity, sensor, key, (TVal)Entities.REMOVE); }
@Override public Void apply(Entity input) { ServiceStateLogic.updateMapSensorEntry(input, mapSensor, key, valueSupplier.get()); return null; } }
/** 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(Entity 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 */
/** as {@link #updateNotUpIndicator(Entity, String, Object)} using the given sensor as the key */ public static void updateNotUpIndicator(Entity entity, Sensor<?> sensor, Object value) { updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName(), value); } /** as {@link #clearNotUpIndicator(Entity, String)} using the given sensor as the key */
/** as {@link #updateProblemsIndicator(Entity, Sensor, Object)} */ public static void updateProblemsIndicator(Entity entity, Effector<?> eff, Object value) { updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, eff.getName(), value); } /** as {@link #clearProblemsIndicator(Entity, Sensor)} */
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()); } }
@Override public Void apply(Object input) { ServiceStateLogic.updateMapSensorEntry(self, Attributes.SERVICE_PROBLEMS, "mirror-feed", "error contacting service"); if (input instanceof HttpToolResponse) { int responseCode = ((HttpToolResponse)input).getResponseCode(); if (responseCode == HttpStatus.SC_NOT_FOUND) { //the remote entity no longer exists Entities.unmanage(self); } } return null; } }))
/** * Called whenever the values for the set of producers changes (e.g. on an event, or on a member added/removed). */ @SuppressWarnings("unchecked") protected void onUpdated() { try { Object v = computing.apply(producer.getAttribute(sourceSensor)); if (v == null && Boolean.TRUE.equals(removingIfResultIsNull)) { v = Entities.REMOVE; } if (v == Entities.UNCHANGED) { // nothing } else { TKey key = this.key; if (key==null) key = (TKey) sourceSensor.getName(); ServiceStateLogic.updateMapSensorEntry(entity, targetSensor, key, (TVal) v); } } catch (Throwable t) { LOG.warn("Error calculating map update for enricher "+this, t); throw Exceptions.propagate(t); } }
@Override public void populateServiceNotUpDiagnostics() { if (getDriver() == null) { ServiceStateLogic.updateMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "driver", "No driver"); ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "sshable"); ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, SERVICE_PROCESS_IS_RUNNING.getName()); ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "sshable"); } else { ServiceStateLogic.updateMapSensorEntry( this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, SERVICE_PROCESS_IS_RUNNING.getName()); } else { ServiceStateLogic.updateMapSensorEntry( this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS,
clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, DEFAULT_UNIQUE_TAG); } else { updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, DEFAULT_UNIQUE_TAG, newServiceUp.reason); updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, DEFAULT_UNIQUE_TAG, newServiceState.reason); } else { clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, DEFAULT_UNIQUE_TAG);
@Test public void testWaitForServiceUpDefaultsToNotChecking() throws Exception { DynamicCluster cluster = app.addChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TestEntity.class)) .configure("initialSize", 1)); // Indicate that the cluster is not healthy ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", "myVal"); // Start - expect it to complete promptly Stopwatch stopwatch = Stopwatch.createStarted(); app.start(ImmutableList.of()); Duration startTime = Duration.of(stopwatch); LOG.info("start-time "+startTime); assertTrue(startTime.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "startTime="+startTime); // Should be on-fire EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, false); // Clearing the notUp indicator should allow it to recover ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", Entities.REMOVE); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true); }
@Test public void testWaitForServiceFails() throws Exception { DynamicCluster cluster = app.addChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.START_TIMEOUT, Duration.ONE_MILLISECOND) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TestEntity.class)) .configure("initialSize", 1)); // Indicate that the cluster is not healthy ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", "myVal"); // Start - expect it to fail promptly Stopwatch stopwatch = Stopwatch.createStarted(); try { app.start(ImmutableList.of()); Asserts.shouldHaveFailedPreviously(); } catch (Exception e) { Asserts.expectedFailureContains(e, "Timeout waiting for SERVICE_UP"); } Duration startTime = Duration.of(stopwatch); LOG.info("start-time "+startTime); assertTrue(startTime.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "startTime="+startTime); // Should be on-fire EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, false); // Clearing the notUp indicator should allow it to recover ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", Entities.REMOVE); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); }
@Test public void testWaitForServiceSucceedsEventually() throws Exception { Map<?,?> veryShortWait = ImmutableMap.of("timeout", Duration.millis(50)); DynamicCluster cluster = app.addChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.START_TIMEOUT, Asserts.DEFAULT_LONG_TIMEOUT.multiply(2)) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TestEntity.class)) .configure("initialSize", 1)); // Indicate that the cluster is not healthy ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", "myVal"); // Start in a background thread Task<Void> task = app.invoke(Startable.START, ImmutableMap.of("locations", ImmutableList.of())); // The member should start, but we should still be waiting for the cluster's service.isUp EntityAsserts.assertGroupSizeEqualsEventually(cluster, 1); TestEntity member = (TestEntity) Iterables.find(cluster.getChildren(), Predicates.instanceOf(TestEntity.class)); EntityAsserts.assertAttributeEqualsEventually(member, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); EntityAsserts.assertAttributeEqualsContinually(veryShortWait, cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING); EntityAsserts.assertAttributeEqualsContinually(veryShortWait, cluster, Attributes.SERVICE_UP, false); assertFalse(task.isDone()); // Clearing the not-up-indicator will allow it to return successfully ServiceStateLogic.updateMapSensorEntry(cluster, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, "simulateNotUpKey", Entities.REMOVE); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); task.get(Asserts.DEFAULT_LONG_TIMEOUT); }