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.Ordering;
|
||||
import org.openhab.core.persistence.HistoricItem;
|
||||
import org.openhab.core.persistence.PersistedItem;
|
||||
import org.openhab.core.persistence.PersistenceItemInfo;
|
||||
import org.openhab.core.persistence.PersistenceService;
|
||||
import org.openhab.core.persistence.QueryablePersistenceService;
|
||||
import org.openhab.core.persistence.strategy.PersistenceCronStrategy;
|
||||
import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.osgi.framework.Constants;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
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
|
||||
public Set<PersistenceItemInfo> getItemInfo() {
|
||||
return Set.of();
|
||||
|
|
Loading…
Reference in New Issue