fix rrd4j restore on startup (#18308)
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>pull/18013/merge
parent
fa22df38ef
commit
1cefae42fd
|
@ -64,12 +64,14 @@ import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.persistence.FilterCriteria;
|
import org.openhab.core.persistence.FilterCriteria;
|
||||||
import org.openhab.core.persistence.FilterCriteria.Ordering;
|
import org.openhab.core.persistence.FilterCriteria.Ordering;
|
||||||
import org.openhab.core.persistence.HistoricItem;
|
import org.openhab.core.persistence.HistoricItem;
|
||||||
|
import org.openhab.core.persistence.PersistedItem;
|
||||||
import org.openhab.core.persistence.PersistenceItemInfo;
|
import org.openhab.core.persistence.PersistenceItemInfo;
|
||||||
import org.openhab.core.persistence.PersistenceService;
|
import org.openhab.core.persistence.PersistenceService;
|
||||||
import org.openhab.core.persistence.QueryablePersistenceService;
|
import org.openhab.core.persistence.QueryablePersistenceService;
|
||||||
import org.openhab.core.persistence.strategy.PersistenceCronStrategy;
|
import org.openhab.core.persistence.strategy.PersistenceCronStrategy;
|
||||||
import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.osgi.framework.Constants;
|
import org.osgi.framework.Constants;
|
||||||
import org.osgi.service.component.annotations.Activate;
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
@ -539,6 +541,118 @@ public class RRD4jPersistenceService implements QueryablePersistenceService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link PersistedItem} representing the persisted state, last update and change timestamps and previous
|
||||||
|
* persisted state. This can be used to restore the full state of an item.
|
||||||
|
* The default implementation queries the service and iterates backward to find the last change and previous
|
||||||
|
* persisted state. Persistence services can override this default implementation with a more specific or efficient
|
||||||
|
* algorithm.
|
||||||
|
*
|
||||||
|
* This method overrides the default implementation in the interface as queries without a begin date are not allowed
|
||||||
|
* in the rrd4j database. If the last change cannot be found in half the length of the first archive, a null value
|
||||||
|
* for the last change and previous persisted state will be returned with {@link PersistedItem}.
|
||||||
|
*
|
||||||
|
* @param itemName name of item
|
||||||
|
* @param alias alias of item
|
||||||
|
*
|
||||||
|
* @return a {@link PersistedItem} or null if the item has not been persisted
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @Nullable PersistedItem persistedItem(String itemName, @Nullable String alias) {
|
||||||
|
State currentState = UnDefType.NULL;
|
||||||
|
State previousState = null;
|
||||||
|
ZonedDateTime lastUpdate = null;
|
||||||
|
ZonedDateTime lastChange = null;
|
||||||
|
|
||||||
|
// Avoid query with open begin date. Don't look further back than half of the first archive.
|
||||||
|
// Only half of the archive is considered to avoid accidently querying the next archive with lower granularity.
|
||||||
|
String localAlias = alias != null ? alias : itemName;
|
||||||
|
RrdDefConfig rrdDefConfig = getRrdDefConfig(localAlias);
|
||||||
|
if (rrdDefConfig == null) {
|
||||||
|
logger.warn("No rrd4j database definition found for {}", itemName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<RrdArchiveDef> rrdArchiveDefs = rrdDefConfig.archives;
|
||||||
|
if (rrdArchiveDefs.isEmpty()) {
|
||||||
|
logger.warn("No rrd4j archive definition found for {}", itemName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
RrdArchiveDef rrdArchiveDef = rrdArchiveDefs.get(0);
|
||||||
|
long archiveLength = (rrdArchiveDef.rows * rrdArchiveDef.steps) / 2;
|
||||||
|
ZonedDateTime endDate = ZonedDateTime.now();
|
||||||
|
ZonedDateTime beginDate = endDate.minusSeconds(archiveLength);
|
||||||
|
|
||||||
|
int pageNumber = 0;
|
||||||
|
FilterCriteria filter = new FilterCriteria().setItemName(itemName).setBeginDate(beginDate).setEndDate(endDate)
|
||||||
|
.setOrdering(Ordering.DESCENDING).setPageSize(1000).setPageNumber(pageNumber);
|
||||||
|
Iterable<HistoricItem> items = query(filter, alias);
|
||||||
|
while (items != null) {
|
||||||
|
Iterator<HistoricItem> it = items.iterator();
|
||||||
|
int itemCount = 0;
|
||||||
|
if (UnDefType.NULL.equals(currentState) && it.hasNext()) {
|
||||||
|
HistoricItem historicItem = it.next();
|
||||||
|
itemCount++;
|
||||||
|
currentState = historicItem.getState();
|
||||||
|
lastUpdate = historicItem.getTimestamp();
|
||||||
|
lastChange = lastUpdate;
|
||||||
|
}
|
||||||
|
while (it.hasNext()) {
|
||||||
|
HistoricItem historicItem = it.next();
|
||||||
|
itemCount++;
|
||||||
|
if (!historicItem.getState().equals(currentState)) {
|
||||||
|
previousState = historicItem.getState();
|
||||||
|
items = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastChange = historicItem.getTimestamp();
|
||||||
|
}
|
||||||
|
if (itemCount == filter.getPageSize()) {
|
||||||
|
filter.setPageNumber(++pageNumber);
|
||||||
|
items = query(filter);
|
||||||
|
} else {
|
||||||
|
items = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnDefType.NULL.equals(currentState) || lastUpdate == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final State state = currentState;
|
||||||
|
final ZonedDateTime lastStateUpdate = lastUpdate;
|
||||||
|
final State lastState = previousState;
|
||||||
|
// if we don't find a previous state in persistence, we also don't know when it last changed
|
||||||
|
final ZonedDateTime lastStateChange = previousState != null ? lastChange : null;
|
||||||
|
|
||||||
|
return new PersistedItem() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime getTimestamp() {
|
||||||
|
return lastStateUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return itemName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ZonedDateTime getLastStateChange() {
|
||||||
|
return lastStateChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable State getLastState() {
|
||||||
|
return lastState;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<PersistenceItemInfo> getItemInfo() {
|
public Set<PersistenceItemInfo> getItemInfo() {
|
||||||
return Set.of();
|
return Set.of();
|
||||||
|
|
Loading…
Reference in New Issue