/** * Copyright 2007 the dCache team */ package org.dcache.services.info.base; import java.util.Date; /** * A base-type for all metric values within the dCache state. The different metrics types * all extend this base Class. * <p> * * @author Paul Millar <paul.millar@desy.de> */ public abstract class StateValue implements StateComponent { private static final boolean DUMMY_ISEPHEMERAL_VALUE = false; /** The granularity of expiryTime, in milliseconds */ private static final int _granularity = 500; private static final int _millisecondsInSecond = 1000; private final Date _expiryTime; private final boolean _isEphemeral; /** * Create a StateValue that is either Immortal or Ephemeral * @param isImmortal true if the StateValue is immortal */ protected StateValue(boolean isImmortal) { _expiryTime = null; _isEphemeral = !isImmortal; } /** * Create a StateValue that will expire some point in * the future. This allows "soft state" registration of * information. * @param duration the length of time, in seconds, this information will be held. */ protected StateValue(long duration) { if (duration < 0) { duration = 0; } long tim = System.currentTimeMillis(); if (duration > 0) { tim += duration * _millisecondsInSecond; /** * round up to nearest _granularity milliseconds. This is to allow * metrics to be purged at the same time. */ tim = Math.round((double)tim / _granularity) * _granularity; } _expiryTime = new Date(tim); _isEphemeral = DUMMY_ISEPHEMERAL_VALUE; } /** * Make the actual data/time this value will expire available. * @return when this StateValue will expire */ @Override public Date getExpiryDate() { return _expiryTime != null ? new Date(_expiryTime.getTime()) : null; } /** * Discover whether the expiry time has elapsed. For static StateValues * (those without an expiry date), this will always return false. * @return True if this value is scheduled to expiry and that time has elapsed, * false otherwise. */ @Override public boolean hasExpired() { if (_expiryTime == null) { return false; } Date now = new Date(); return !now.before(_expiryTime); } /** Provide a generic name for subclasses of StateValue */ public abstract String getTypeName(); /** Sub-classes must provide a leaf-node's visitor support */ @Override public abstract void acceptVisitor(StatePath path, StateVisitor visitor); /** Force subclasses to override equals and hashCode */ @Override public abstract boolean equals(Object other); @Override public abstract int hashCode(); /** * Sub-classes of StateValue all ignore the transition when being visited: the StateComposite takes * care of all effects from processing the transition. */ @Override public void acceptVisitor(StateTransition transition, StatePath path, StateVisitor visitor) { acceptVisitor(path, visitor); } @Override public void applyTransition(StatePath ourPath, StateTransition transition) { // Simply do nothing. All activity takes place in StateComposite. } @Override public void buildTransition(StatePath ourPath, StatePath childPath, StateComponent newChild, StateTransition transition) throws MetricStatePathException { // If we're here, the user has specified a path with a metric in it. throw new MetricStatePathException(ourPath.toString()); } @Override public void buildRemovalTransition(StatePath ourPath, StateTransition transition, boolean forced) { // Simply do nothing, all activity takes place in StateComposites } @Override public boolean predicateHasBeenTriggered(StatePath ourPath, StatePathPredicate predicate, StateTransition transition) { /* * If we've iterated down to a metric then we <i>know</i> * that nothing's changed: any change that might satisfy this predicate would happen * within the StateComposite that this StateValue is (or is to be) located within. */ return false; } @Override public void buildPurgeTransition(StateTransition transition, StatePath ourPath, StatePath remainingPath) { // Simply do nothing, all activity takes place in parent StateComposite } @Override public boolean isMortal() { return _expiryTime != null; } @Override public boolean isEphemeral() { return _expiryTime == null && _isEphemeral; } @Override public boolean isImmortal() { return _expiryTime == null && !_isEphemeral; } @Override public Date getEarliestChildExpiryDate() { return null; // we never have children. } }