public String getDescription() { Long lastUpTime = connectionLastUp.get(); Long lastDownTime = connectionLastDown.get(); Duration serviceFailedStabilizationDelay = getConnectionFailedStabilizationDelay(); Duration serviceRecoveredStabilizationDelay = getConnectionRecoveredStabilizationDelay(); return String.format( "endpoint=%s; connected=%s; timeNow=%s; lastUp=%s; lastDown=%s; lastPublished=%s; " + "currentFailurePeriod=%s; currentRecoveryPeriod=%s", getConfig(ENDPOINT), connected, Time.makeDateString(System.currentTimeMillis()), (lastUpTime != null ? Time.makeDateString(lastUpTime) : "<never>"), (lastDownTime != null ? Time.makeDateString(lastDownTime) : "<never>"), lastPublished, (currentFailureStartTime != null ? getTimeStringSince(currentFailureStartTime) : "<none>") + " (stabilization " + makeTimeStringRounded(serviceFailedStabilizationDelay) + ")", (currentRecoveryStartTime != null ? getTimeStringSince(currentRecoveryStartTime) : "<none>") + " (stabilization " + makeTimeStringRounded(serviceRecoveredStabilizationDelay) + ")"); }
@Override public void start(Collection<? extends Location> locations) { super.start(locations); connectSensors(); Time.sleep(getConfig(DELAY_BEFORE_ADVERTISING_CLUSTER)); // FIXME: add a quorum to tolerate failed nodes before setting on fire. Optional<Entity> anyNode = Iterables.tryFind( getMembers(), new Predicate<Entity>() { @Override public boolean apply(@Nullable Entity entity) { return (entity instanceof RiakNode && hasMemberJoinedCluster(entity) && entity.getAttribute(RiakNode.SERVICE_UP)); } }); if (anyNode.isPresent()) { log.info( "Planning and Committing cluster changes on node: {}, cluster: {}", anyNode.get().getId(), getId()); Entities.invokeEffector(this, anyNode.get(), RiakNode.COMMIT_RIAK_CLUSTER); setAttribute(IS_CLUSTER_INIT, true); } else { log.warn("No Riak Nodes are found on the cluster: {}. Initialization Failed", getId()); setAttribute(SERVICE_STATE, Lifecycle.ON_FIRE); } }
@Test public void testSimple() throws InterruptedException, ExecutionException { Callable<String> mainJob = new Callable<String>() { public String call() { log.info("main job - " + Tasks.current()); messages.add("main"); DynamicTasks.queue(sayTask("world")); return "bye"; } }; DynamicSequentialTask<String> t = new DynamicSequentialTask<String>(mainJob); // this should be added before anything added when the task is invoked t.queue(sayTask("hello")); Assert.assertEquals(messages, Lists.newArrayList()); Assert.assertEquals(t.isBegun(), false); Assert.assertEquals(Iterables.size(t.getChildren()), 1); ec.submit(t); Assert.assertEquals(t.isSubmitted(), true); Assert.assertEquals(t.getUnchecked(Duration.ONE_SECOND), "bye"); long elapsed = t.getEndTimeUtc() - t.getSubmitTimeUtc(); Assert.assertTrue( elapsed < 1000, "elapsed time should have been less than 1s but was " + Time.makeTimeString(elapsed, true)); Assert.assertEquals(Iterables.size(t.getChildren()), 2); Assert.assertEquals(messages.size(), 3, "expected 3 entries, but had " + messages); // either main or hello can be first, but world should be last Assert.assertEquals(messages.get(2), "world"); }
@Test public void testCancelled() throws InterruptedException, ExecutionException { Task<List<?>> t = Tasks.sequential(sayTask("1"), sayTask("2a", Duration.THIRTY_SECONDS, "2b"), sayTask("3")); ec.submit(t); synchronized (messages) { while (messages.size() <= 1) messages.wait(); } Assert.assertEquals(messages, Arrays.asList("1", "2a")); Time.sleep(Duration.millis(50)); t.cancel(true); Assert.assertTrue(t.isDone()); // 2 should get cancelled, and invoke the cancellation semaphore // 3 should get cancelled and not run at all Assert.assertEquals(messages, Arrays.asList("1", "2a")); // Need to ensure that 2 has been started; race where we might cancel it before its run method // is even begun. Hence doing "2a; pause; 2b" where nothing is interruptable before pause. Assert.assertTrue(cancellations.tryAcquire(10, TimeUnit.SECONDS)); Iterator<Task<?>> ci = ((HasTaskChildren) t).getChildren().iterator(); Assert.assertEquals(ci.next().get(), "1"); Task<?> task2 = ci.next(); Assert.assertTrue(task2.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); Task<?> task3 = ci.next(); Assert.assertFalse(task3.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); // but we do _not_ get a mutex from task3 as it does not run (is not interrupted) Assert.assertEquals(cancellations.availablePermits(), 0); }
protected String getExplanation(Lifecycle state) { Duration serviceFailedStabilizationDelay = getConfig(ENTITY_FAILED_STABILIZATION_DELAY); Duration serviceRecoveredStabilizationDelay = getConfig(ENTITY_RECOVERED_STABILIZATION_DELAY); return String.format( "location=%s; status=%s; lastPublished=%s; timeNow=%s; " + "currentFailurePeriod=%s; currentRecoveryPeriod=%s", entity.getLocations(), (state != null ? state : "<unreported>"), lastPublished, Time.makeDateString(System.currentTimeMillis()), (currentFailureStartTime != null ? getTimeStringSince(currentFailureStartTime) : "<none>") + " (stabilization " + Time.makeTimeStringRounded(serviceFailedStabilizationDelay) + ")", (currentRecoveryStartTime != null ? getTimeStringSince(currentRecoveryStartTime) : "<none>") + " (stabilization " + Time.makeTimeStringRounded(serviceRecoveredStabilizationDelay) + ")"); }
/** Setup renderer hints for the MXBean attributes. */ public static void init() { if (initialized.get()) return; synchronized (initialized) { if (initialized.get()) return; RendererHints.register( UsesJavaMXBeans.USED_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.INIT_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.MAX_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.COMMITTED_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.NON_HEAP_MEMORY_USAGE, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.TOTAL_PHYSICAL_MEMORY_SIZE, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.FREE_PHYSICAL_MEMORY_SIZE, RendererHints.displayValue(ByteSizeStrings.metric())); RendererHints.register( UsesJavaMXBeans.START_TIME, RendererHints.displayValue(Time.toDateString())); RendererHints.register( UsesJavaMXBeans.UP_TIME, RendererHints.displayValue(Duration.millisToStringRounded())); RendererHints.register( UsesJavaMXBeans.PROCESS_CPU_TIME, RendererHints.displayValue(Duration.millisToStringRounded())); RendererHints.register( UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_LAST, RendererHints.displayValue(MathFunctions.percent(4))); RendererHints.register( UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_IN_WINDOW, RendererHints.displayValue(MathFunctions.percent(4))); initialized.set(true); } }
/** Setup renderer hints. */ public static void init() { if (initialized.getAndSet(true)) return; final Function<Double, Long> longValue = new Function<Double, Long>() { @Override public Long apply(@Nullable Double input) { if (input == null) return null; return input.longValue(); } }; RendererHints.register(UPTIME, RendererHints.displayValue(Time.toTimeStringRounded())); RendererHints.register(CPU_USAGE, RendererHints.displayValue(MathFunctions.percent(2))); RendererHints.register(AVERAGE_CPU_USAGE, RendererHints.displayValue(MathFunctions.percent(2))); RendererHints.register( FREE_MEMORY, RendererHints.displayValue( Functionals.chain(MathFunctions.times(1000L), ByteSizeStrings.metric()))); RendererHints.register( TOTAL_MEMORY, RendererHints.displayValue( Functionals.chain(MathFunctions.times(1000L), ByteSizeStrings.metric()))); RendererHints.register( USED_MEMORY, RendererHints.displayValue( Functionals.chain(MathFunctions.times(1000L), ByteSizeStrings.metric()))); RendererHints.register( USED_MEMORY_DELTA_PER_SECOND_LAST, RendererHints.displayValue(Functionals.chain(longValue, ByteSizeStrings.metric()))); RendererHints.register( USED_MEMORY_DELTA_PER_SECOND_IN_WINDOW, RendererHints.displayValue(Functionals.chain(longValue, ByteSizeStrings.metric()))); }
private String getTimeStringSince(Long time) { return time == null ? null : Time.makeTimeStringRounded(System.currentTimeMillis() - time); }
@Override protected void setActualState(Lifecycle state) { long now = System.currentTimeMillis(); synchronized (mutex) { if (state == Lifecycle.ON_FIRE) { if (lastPublished == LastPublished.FAILED) { if (currentRecoveryStartTime != null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component was recovering, now failing: {}", new Object[] {this, entity, getExplanation(state)}); currentRecoveryStartTime = null; publishEntityRecoveredTime = null; } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component still failed: {}", new Object[] {this, entity, getExplanation(state)}); } } else { if (firstUpTime == null && getConfig(ENTITY_FAILED_ONLY_IF_PREVIOUSLY_UP)) { // suppress; won't publish } else if (currentFailureStartTime == null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component now failing: {}", new Object[] {this, entity, getExplanation(state)}); currentFailureStartTime = now; publishEntityFailedTime = currentFailureStartTime + getConfig(ENTITY_FAILED_STABILIZATION_DELAY).toMilliseconds(); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component continuing failing: {}", new Object[] {this, entity, getExplanation(state)}); } } if (setEntityOnFireTime == null) { setEntityOnFireTime = now + getConfig(SERVICE_ON_FIRE_STABILIZATION_DELAY).toMilliseconds(); } currentRecoveryStartTime = null; publishEntityRecoveredTime = null; } else if (state == Lifecycle.RUNNING) { if (lastPublished == LastPublished.FAILED) { if (currentRecoveryStartTime == null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component now recovering: {}", new Object[] {this, entity, getExplanation(state)}); currentRecoveryStartTime = now; publishEntityRecoveredTime = currentRecoveryStartTime + getConfig(ENTITY_RECOVERED_STABILIZATION_DELAY).toMilliseconds(); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component continuing recovering: {}", new Object[] {this, entity, getExplanation(state)}); } } else { if (currentFailureStartTime != null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component was failing, now healthy: {}", new Object[] {this, entity, getExplanation(state)}); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component still healthy: {}", new Object[] {this, entity, getExplanation(state)}); } } currentFailureStartTime = null; publishEntityFailedTime = null; setEntityOnFireTime = null; } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, in unconfirmed sate: {}", new Object[] {this, entity, getExplanation(state)}); } long recomputeIn = Long.MAX_VALUE; // For whether to call recomputeAfterDelay if (publishEntityFailedTime != null) { long delayBeforeCheck = publishEntityFailedTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} publishing failed (state={}; currentFailureStartTime={}; now={}", new Object[] { this, state, Time.makeDateString(currentFailureStartTime), Time.makeDateString(now) }); publishEntityFailedTime = null; lastPublished = LastPublished.FAILED; entity.emit( HASensors.ENTITY_FAILED, new HASensors.FailureDescriptor(entity, getFailureDescription(now))); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } else if (publishEntityRecoveredTime != null) { long delayBeforeCheck = publishEntityRecoveredTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} publishing recovered (state={}; currentRecoveryStartTime={}; now={}", new Object[] { this, state, Time.makeDateString(currentRecoveryStartTime), Time.makeDateString(now) }); publishEntityRecoveredTime = null; lastPublished = LastPublished.RECOVERED; entity.emit(HASensors.ENTITY_RECOVERED, new HASensors.FailureDescriptor(entity, null)); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } if (setEntityOnFireTime != null) { long delayBeforeCheck = setEntityOnFireTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} setting on-fire, now that deferred period has passed (state={})", new Object[] {this, state}); setEntityOnFireTime = null; super.setActualState(state); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } else { super.setActualState(state); } if (recomputeIn < Long.MAX_VALUE) { recomputeAfterDelay(recomputeIn); } } }