From 2ac37ea694e1d1275453fca638291b7046973962 Mon Sep 17 00:00:00 2001 From: Kamil Jarmusik Date: Mon, 21 Feb 2022 22:52:58 +0100 Subject: [PATCH 1/5] #2101 Avoided duplicate values - added datapoint.runtime.synchronized --- .../serotonin/mango/rt/RuntimeManager.java | 16 +- .../rt/dataImage/DataPointSynchronizedRT.java | 634 ++++++++++++++++++ .../mango/rt/dataImage/IDataPointCache.java | 11 + .../mango/rt/dataImage/IDataPointRT.java | 28 + src/org/scada_lts/dao/SystemSettingsDAO.java | 4 + .../mango/service/PointValueService.java | 10 +- .../mango/service/SystemSettingsService.java | 9 + .../scada_lts/utils/SystemSettingsUtils.java | 14 + .../web/mvc/api/SystemSettingsAPI.java | 33 + webapp-resources/env.properties | 4 +- 10 files changed, 749 insertions(+), 14 deletions(-) create mode 100644 src/com/serotonin/mango/rt/dataImage/DataPointSynchronizedRT.java create mode 100644 src/com/serotonin/mango/rt/dataImage/IDataPointCache.java create mode 100644 src/com/serotonin/mango/rt/dataImage/IDataPointRT.java diff --git a/src/com/serotonin/mango/rt/RuntimeManager.java b/src/com/serotonin/mango/rt/RuntimeManager.java index d946184e0e..aa854b198c 100644 --- a/src/com/serotonin/mango/rt/RuntimeManager.java +++ b/src/com/serotonin/mango/rt/RuntimeManager.java @@ -26,6 +26,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import com.serotonin.mango.db.dao.*; +import com.serotonin.mango.rt.dataImage.*; import com.serotonin.mango.rt.event.*; import com.serotonin.mango.rt.event.schedule.ResetDailyLimitSendingEventRT; import com.serotonin.mango.rt.event.schedule.ScheduledExecuteInactiveEventRT; @@ -48,11 +49,6 @@ import com.serotonin.ShouldNeverHappenException; import com.serotonin.mango.Common; -import com.serotonin.mango.rt.dataImage.DataPointEventMulticaster; -import com.serotonin.mango.rt.dataImage.DataPointListener; -import com.serotonin.mango.rt.dataImage.DataPointRT; -import com.serotonin.mango.rt.dataImage.PointValueTime; -import com.serotonin.mango.rt.dataImage.SetPointSource; import com.serotonin.mango.rt.dataImage.types.MangoValue; import com.serotonin.mango.rt.dataSource.DataSourceRT; import com.serotonin.mango.rt.dataSource.meta.MetaDataSourceRT; @@ -472,8 +468,7 @@ private void startDataPoint(DataPointVO vo) { DataSourceRT ds = getRunningDataSource(vo.getDataSourceId()); if (ds != null) { // Change the VO into a data point implementation. - DataPointRT dataPoint = new DataPointRT(vo, vo - .getPointLocator().createRuntime()); + DataPointRT dataPoint = createDataPointRT(vo); // Add/update it in the data image. dataPoints.put(dataPoint.getId(), dataPoint); @@ -490,6 +485,13 @@ private void startDataPoint(DataPointVO vo) { } } + public static DataPointRT createDataPointRT(DataPointVO vo) { + boolean dataPointRtSynchronized = new SystemSettingsService().isDataPointRtSynchronized(); + if(dataPointRtSynchronized) + return new DataPointSynchronizedRT(vo, vo.getPointLocator().createRuntime()); + return new DataPointRT(vo, vo.getPointLocator().createRuntime()); + } + private void startDataPointSafe(DataPointVO vo) { try { startDataPoint(vo); diff --git a/src/com/serotonin/mango/rt/dataImage/DataPointSynchronizedRT.java b/src/com/serotonin/mango/rt/dataImage/DataPointSynchronizedRT.java new file mode 100644 index 0000000000..f647d2e0dd --- /dev/null +++ b/src/com/serotonin/mango/rt/dataImage/DataPointSynchronizedRT.java @@ -0,0 +1,634 @@ +/* + Mango - Open Source M2M - http://mango.serotoninsoftware.com + Copyright (C) 2006-2011 Serotonin Software Technologies Inc. + @author Matthew Lohbihler + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +package com.serotonin.mango.rt.dataImage; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.serotonin.ShouldNeverHappenException; +import com.serotonin.mango.Common; +import com.serotonin.mango.DataTypes; +import com.serotonin.mango.db.dao.PointValueDao; +import org.scada_lts.dao.SystemSettingsDAO; +import com.serotonin.mango.rt.RuntimeManager; +import com.serotonin.mango.rt.dataImage.types.MangoValue; +import com.serotonin.mango.rt.dataImage.types.NumericValue; +import com.serotonin.mango.rt.dataSource.PointLocatorRT; +import com.serotonin.mango.rt.event.detectors.PointEventDetectorRT; +import com.serotonin.mango.rt.maint.work.WorkItem; +import com.serotonin.mango.util.timeout.TimeoutTask; +import com.serotonin.mango.view.stats.AnalogStatistics; +import com.serotonin.mango.view.stats.IValueTime; +import com.serotonin.mango.vo.DataPointVO; +import com.serotonin.mango.vo.event.PointEventDetectorVO; +import com.serotonin.timer.FixedRateTrigger; +import com.serotonin.timer.TimerTask; +import com.serotonin.util.ObjectUtils; +import org.scada_lts.web.ws.ScadaWebSocketListener; + +public class DataPointSynchronizedRT extends DataPointRT implements IDataPointRT { + private static final Log LOG = LogFactory.getLog(DataPointSynchronizedRT.class); + + private static final PvtTimeComparator pvtTimeComparator = new PvtTimeComparator(); + + // Configuration data. + private final DataPointVO vo; + private final PointLocatorRT pointLocator; + + // Runtime data. + private PointValueTime pointValue; + private final PointValueCache valueCache; + private RuntimeManager rm; + private List detectors; + private final Map attributes = new HashMap(); + + // Interval logging data. + private PointValueTime intervalValue; + private long intervalStartTime = -1; + private List averagingValues; + private final Object intervalLoggingLock = new Object(); + private TimerTask intervalLoggingTask; + + // WebSocket notification + private final List> scadaWebSocketListeners = new CopyOnWriteArrayList<>(); + + /** + * This is the value around which tolerance decisions will be made when + * determining whether to log numeric values. + */ + private double toleranceOrigin; + + public DataPointSynchronizedRT(DataPointVO vo, PointLocatorRT pointLocator) { + super(vo, pointLocator); + this.vo = vo; + this.pointLocator = pointLocator; + valueCache = new PointValueCache(vo.getId(), vo.getDefaultCacheSize()); + } + public DataPointSynchronizedRT(DataPointVO vo, PointLocatorRT pointLocator, int cacheSize, int maxSize) { + super(vo, pointLocator, cacheSize, maxSize); + this.vo = vo; + this.pointLocator = pointLocator; + valueCache = new PointValueCache(cacheSize); + valueCache.setMaxSize(maxSize); + } + + public DataPointSynchronizedRT(DataPointVO vo) { + super(vo); + this.vo = vo; + this.pointLocator = null; + valueCache = new PointValueCache(); + } + + @Override + public PointValueCache getPointValueCache(){ + return this.valueCache; + } + + @Override + public List getLatestPointValues(int limit) { + return valueCache.getLatestPointValues(limit); + } + + @Override + public List getLatestPointValuesUsedForJunitTest(int limit) { + return valueCache.getLatestPointValuesUsedForTest(limit); + } + + @Override + public void addCollectionIntoCache(PointValueTime pvt){ + valueCache.addPointValueTimeIntoCacheForTest(pvt); + } + + @Override + public PointValueTime getPointValueBefore(long time) { + for (PointValueTime pvt : valueCache.getCacheContents()) { + if (pvt.getTime() < time) + return pvt; + } + + return new PointValueDao().getPointValueBefore(vo.getId(), time); + } + + @Override + public PointValueTime getPointValueAt(long time) { + for (PointValueTime pvt : valueCache.getCacheContents()) { + if (pvt.getTime() == time) + return pvt; + } + + return new PointValueDao().getPointValueAt(vo.getId(), time); + } + + @Override + public List getPointValues(long since) { + List result = new PointValueDao().getPointValues( + vo.getId(), since); + + for (PointValueTime pvt : valueCache.getCacheContents()) { + if (pvt.getTime() >= since) { + int index = Collections.binarySearch(result, pvt, + pvtTimeComparator); + if (index < 0) + result.add(-index - 1, pvt); + } + } + + return result; + } + + @Override + public List getPointValuesBetween(long from, long to) { + List result = new PointValueDao() + .getPointValuesBetween(vo.getId(), from, to); + + for (PointValueTime pvt : valueCache.getCacheContents()) { + if (pvt.getTime() >= from && pvt.getTime() < to) { + int index = Collections.binarySearch(result, pvt, + pvtTimeComparator); + if (index < 0) + result.add(-index - 1, pvt); + } + } + + return result; + } + + /** + * This method should only be called by the data source. Other types of + * point setting should include a set point source object so that the + * annotation can be logged. + * + * @param newValue + */ + + @Override + public void updatePointValue(PointValueTime newValue) { + savePointValue(newValue, null, true); + } + + @Override + public void updatePointValue(PointValueTime newValue, boolean async) { + savePointValue(newValue, null, async); + } + + /** + * Use this method to update a data point for reasons other than just data + * source update. + * + * @param newValue + * the value to set + * @param source + * the source of the set. This can be a user object if the point + * was set from the UI, or could be a program run by schedule or + * on event. + */ + @Override + public void setPointValue(PointValueTime newValue, SetPointSource source) { + if (source == null) + savePointValue(newValue, source, true); + else + savePointValue(newValue, source, false); + } + + private void savePointValue(PointValueTime newValue, SetPointSource source, + boolean async) { + // Null values are not very nice, and since they don't have a specific + // meaning they are hereby ignored. + if (newValue == null) + return; + + // Check the data type of the value against that of the locator, just + // for fun. + int valueDataType = DataTypes.getDataType(newValue.getValue()); + if (valueDataType != DataTypes.UNKNOWN + && valueDataType != vo.getPointLocator().getDataTypeId()) + // This should never happen, but if it does it can have serious + // downstream consequences. Also, we need + // to know how it happened, and the stack trace here provides the + // best information. + throw new ShouldNeverHappenException( + "Data type mismatch between new value and point locator: newValue=" + + DataTypes.getDataType(newValue.getValue()) + + ", locator=" + + vo.getPointLocator().getDataTypeId()); + + // Check if this value qualifies for discardation. + if (vo.isDiscardExtremeValues() + && DataTypes.getDataType(newValue.getValue()) == DataTypes.NUMERIC) { + double newd = newValue.getDoubleValue(); + if (newd < vo.getDiscardLowLimit() + || newd > vo.getDiscardHighLimit()) + // Discard the value + return; + } + + if (newValue.getTime() > System.currentTimeMillis() + + SystemSettingsDAO.getFutureDateLimit()) { + // Too far future dated. Toss it. But log a message first. + LOG.warn( + "Future dated value detected: pointId=" + vo.getId() + + ", value=" + newValue.getStringValue() + + ", type=" + vo.getPointLocator().getDataTypeId() + + ", ts=" + newValue.getTime(), new Exception()); + return; + } + + PointValueTime oldValue = getOldAndSetNew(newValue); + + boolean backdated = oldValue != null + && newValue.getTime() < oldValue.getTime(); + + // Determine whether the new value qualifies for logging. + boolean logValue; + // ... or even saving in the cache. + boolean saveValue = true; + switch (vo.getLoggingType()) { + case DataPointVO.LoggingTypes.ON_CHANGE: + if (oldValue == null) + logValue = true; + else if (backdated) + // Backdated. Ignore it + logValue = false; + else { + if (newValue.getValue() instanceof NumericValue) { + // Get the new double + double newd = newValue.getDoubleValue(); + + // See if the new value is outside of the tolerance. + double diff = toleranceOrigin - newd; + if (diff < 0) + diff = -diff; + + if (diff > vo.getTolerance()) { + toleranceOrigin = newd; + logValue = true; + } else + logValue = false; + } else + logValue = !ObjectUtils.isEqual(newValue.getValue(), + oldValue.getValue()); + } + + saveValue = logValue; + break; + case DataPointVO.LoggingTypes.ALL: + logValue = true; + break; + case DataPointVO.LoggingTypes.ON_TS_CHANGE: + if (oldValue == null) + logValue = true; + else + logValue = newValue.getTime() != oldValue.getTime(); + + saveValue = logValue; + break; + case DataPointVO.LoggingTypes.INTERVAL: + if (!backdated) + intervalSave(newValue); + default: + logValue = false; + } + + if (saveValue){ + this.notifyWebSocketListeners(newValue.getValue().toString()); + valueCache.savePointValueIntoDaoAndCacheUpdate(newValue, source, logValue, async); + } + + + // Ignore historical values. + if (oldValue == null || newValue.getTime() >= oldValue.getTime()) { + fireEvents(oldValue, newValue, source != null, false); + } else + fireEvents(null, newValue, false, true); + } + + // + // / Interval logging + // + private void initializeIntervalLogging() { + synchronized (intervalLoggingLock) { + if (vo.getLoggingType() != DataPointVO.LoggingTypes.INTERVAL) + return; + + intervalLoggingTask = new TimeoutTask(new FixedRateTrigger(0, + Common.getMillis(vo.getIntervalLoggingPeriodType(), + vo.getIntervalLoggingPeriod())), this); + + intervalValue = getPointValue(); + if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.AVERAGE) { + intervalStartTime = System.currentTimeMillis(); + averagingValues = new ArrayList(); + } + } + } + + private void terminateIntervalLogging() { + synchronized (intervalLoggingLock) { + if (vo.getLoggingType() != DataPointVO.LoggingTypes.INTERVAL) + return; + + intervalLoggingTask.cancel(); + } + } + + private void intervalSave(PointValueTime pvt) { + synchronized (intervalLoggingLock) { + if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MAXIMUM) { + if (intervalValue == null) + intervalValue = pvt; + else if (pvt != null) { + if (intervalValue.getDoubleValue() < pvt.getDoubleValue()) + intervalValue = pvt; + } + } else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MINIMUM) { + if (intervalValue == null) + intervalValue = pvt; + else if (pvt != null) { + if (intervalValue.getDoubleValue() > pvt.getDoubleValue()) + intervalValue = pvt; + } + } else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.AVERAGE) + averagingValues.add(pvt); + } + } + + @Override + public void scheduleTimeout(long fireTime) { + synchronized (intervalLoggingLock) { + MangoValue value; + if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.INSTANT) + value = PointValueTime.getValue(getPointValue()); + else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MAXIMUM + || vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MINIMUM) { + value = PointValueTime.getValue(intervalValue); + intervalValue = getPointValue(); + } else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.AVERAGE) { + AnalogStatistics stats = new AnalogStatistics(intervalValue, + averagingValues, intervalStartTime, fireTime); + value = new NumericValue(stats.getAverage()); + + intervalValue = getPointValue(); + averagingValues.clear(); + intervalStartTime = fireTime; + } else + throw new ShouldNeverHappenException( + "Unknown interval logging type: " + + vo.getIntervalLoggingType()); + + if (value != null) + valueCache.logPointValueAsync(new PointValueTime(value, + fireTime), null); + } + } + + // + // / Purging + // + @Override + public void resetValues() { + valueCache.reset(); + if (vo.getLoggingType() != DataPointVO.LoggingTypes.NONE) + getOldAndSetNew(valueCache.getLatestPointValue()); + } + + // + // / + // / Properties + // / + // + @Override + public int getId() { + return vo.getId(); + } + + @Override + public PointValueTime getPointValue() { + return getOldAndSetNew(null); + } + + private synchronized PointValueTime getOldAndSetNew(PointValueTime newValue) { + if(newValue == null) { + return pointValue; + } + PointValueTime oldValue = pointValue; + pointValue = newValue; + return oldValue; + } + + @SuppressWarnings("unchecked") + @Override + public T getPointLocator() { + return (T) pointLocator; + } + + @Override + public int getDataSourceId() { + return vo.getDataSourceId(); + } + + @Override + public DataPointVO getVO() { + return vo; + } + + @Override + public int getDataTypeId() { + return vo.getPointLocator().getDataTypeId(); + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public void setAttribute(String key, Object value) { + attributes.put(key, value); + } + + @Override + public Object getAttribute(String key) { + return attributes.get(key); + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + getId(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final DataPointSynchronizedRT other = (DataPointSynchronizedRT) obj; + if (getId() != other.getId()) + return false; + return true; + } + + @Override + public String toString() { + return "DataPointRT(id=" + getId() + ", name=" + vo.getName() + ")"; + } + + // + // / + // / Listeners + // / + // + private void fireEvents(PointValueTime oldValue, PointValueTime newValue, + boolean set, boolean backdate) { + DataPointListener l = rm.getDataPointListeners(vo.getId()); + if (l != null) + Common.ctx.getBackgroundProcessing().addWorkItem( + new EventNotifyWorkItem(l, oldValue, newValue, set, + backdate)); + } + + @Override + public void addWebSocketListener(ScadaWebSocketListener listener) { + scadaWebSocketListeners.add(listener); + } + + @Override + public void removeWebSocketListener(ScadaWebSocketListener listener) { + scadaWebSocketListeners.remove(listener); + } + + @Override + public void notifyWebSocketListeners(String message) { + if(!scadaWebSocketListeners.isEmpty()) { + scadaWebSocketListeners.forEach(observer -> { + observer.sendWebSocketMessage(message, this.vo.getId()); + }); + } + } + + static class EventNotifyWorkItem implements WorkItem { + private final DataPointListener listener; + private final PointValueTime oldValue; + private final PointValueTime newValue; + private final boolean set; + private final boolean backdate; + + EventNotifyWorkItem(DataPointListener listener, + PointValueTime oldValue, PointValueTime newValue, boolean set, + boolean backdate) { + this.listener = listener; + this.oldValue = oldValue; + this.newValue = newValue; + this.set = set; + this.backdate = backdate; + } + + @Override + public void execute() { + if (backdate) + listener.pointBackdated(newValue); + else { + // Always fire this. + listener.pointUpdated(newValue); + + // Fire if the point has changed. + if (!PointValueTime.equalValues(oldValue, newValue)) + listener.pointChanged(oldValue, newValue); + + // Fire if the point was set. + if (set) + listener.pointSet(oldValue, newValue); + } + } + + @Override + public int getPriority() { + return WorkItem.PRIORITY_MEDIUM; + } + } + + // + // + // Lifecycle + // + @Override + public void initialize() { + rm = Common.ctx.getRuntimeManager(); + + // Get the latest value for the point from the database. + PointValueTime pointValue = getOldAndSetNew(valueCache.getLatestPointValue()); + + // Set the tolerance origin if this is a numeric + if (pointValue != null && pointValue.getValue() instanceof NumericValue) + toleranceOrigin = pointValue.getDoubleValue(); + + // Add point event listeners + for (PointEventDetectorVO ped : vo.getEventDetectors()) { + if (detectors == null) + detectors = new ArrayList(); + + PointEventDetectorRT pedRT = ped.createRuntime(); + detectors.add(pedRT); + rm.addPointEventDetector(pedRT); + rm.addDataPointListener(vo.getId(), pedRT); + } + + initializeIntervalLogging(); + } + @Override + public void terminate() { + terminateIntervalLogging(); + + if (detectors != null) { + for (PointEventDetectorRT pedRT : detectors) { + rm.removeDataPointListener(vo.getId(), pedRT); + rm.removePointEventDetector(pedRT.getEventDetectorKey()); + } + } + Common.ctx.getEventManager().cancelEventsForDataPoint(vo.getId()); + } + + @Override + public void joinTermination() { + // no op + } + + @Override + public void initializeHistorical() { + rm = Common.ctx.getRuntimeManager(); + initializeIntervalLogging(); + } + + @Override + public void terminateHistorical() { + terminateIntervalLogging(); + } +} diff --git a/src/com/serotonin/mango/rt/dataImage/IDataPointCache.java b/src/com/serotonin/mango/rt/dataImage/IDataPointCache.java new file mode 100644 index 0000000000..85be1d622e --- /dev/null +++ b/src/com/serotonin/mango/rt/dataImage/IDataPointCache.java @@ -0,0 +1,11 @@ +package com.serotonin.mango.rt.dataImage; + +import java.util.List; + +interface IDataPointCache { + PointValueCache getPointValueCache(); + List getLatestPointValuesUsedForJunitTest(int limit); + void addCollectionIntoCache(PointValueTime pvt); + PointValueTime getPointValueAt(long time); + void resetValues(); +} \ No newline at end of file diff --git a/src/com/serotonin/mango/rt/dataImage/IDataPointRT.java b/src/com/serotonin/mango/rt/dataImage/IDataPointRT.java new file mode 100644 index 0000000000..d8e1fb4b66 --- /dev/null +++ b/src/com/serotonin/mango/rt/dataImage/IDataPointRT.java @@ -0,0 +1,28 @@ +package com.serotonin.mango.rt.dataImage; + +import com.serotonin.mango.rt.dataSource.PointLocatorRT; +import com.serotonin.mango.util.timeout.TimeoutClient; +import com.serotonin.mango.vo.DataPointVO; +import com.serotonin.util.ILifecycle; +import org.scada_lts.web.ws.ScadaWebSocket; + +import java.util.Map; + + +public interface IDataPointRT extends IDataPoint, ILifecycle, TimeoutClient, + ScadaWebSocket, IDataPointCache { + int getId(); + int getDataSourceId(); + void setAttribute(String key, Object value); + Object getAttribute(String key); + Map getAttributes(); + void initializeHistorical(); + void terminateHistorical(); + T getPointLocator(); + DataPointVO getVO(); + + @Override + void initialize(); + @Override + void terminate(); +} diff --git a/src/org/scada_lts/dao/SystemSettingsDAO.java b/src/org/scada_lts/dao/SystemSettingsDAO.java index b0d167c898..80e22f6a69 100644 --- a/src/org/scada_lts/dao/SystemSettingsDAO.java +++ b/src/org/scada_lts/dao/SystemSettingsDAO.java @@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory; import org.scada_lts.utils.ApplicationBeans; import org.scada_lts.utils.ColorUtils; +import org.scada_lts.utils.SystemSettingsUtils; import org.scada_lts.web.mvc.api.AggregateSettings; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.transaction.annotation.Isolation; @@ -119,6 +120,8 @@ public class SystemSettingsDAO { public static final String AGGREGATION_VALUES_LIMIT = "aggregationValuesLimit"; public static final String AGGREGATION_LIMIT_FACTOR = "aggregationLimitFactor"; + public static final String DATAPOINT_RUNTIME_SYNCHRONIZED = "dataPointRuntimeSynchronized"; + private static final String DELETE_WATCH_LISTS = "delete from watchLists"; private static final String DELETE_MANGO_VIEWS = "delete from mangoViews"; private static final String DELETE_POINT_EVENT_DETECTORS = "delete from pointEventDetectors"; @@ -370,6 +373,7 @@ public String getDatabaseSchemaVersion(String key, String defaultValue) { DEFAULT_VALUES.put(AGGREGATION_ENABLED, aggregateSettings.isEnabled()); DEFAULT_VALUES.put(AGGREGATION_LIMIT_FACTOR, String.valueOf(aggregateSettings.getLimitFactor())); DEFAULT_VALUES.put(AGGREGATION_VALUES_LIMIT, aggregateSettings.getValuesLimit()); + DEFAULT_VALUES.put(DATAPOINT_RUNTIME_SYNCHRONIZED, SystemSettingsUtils.isDataPointRtSynchronized()); } @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, rollbackFor = SQLException.class) diff --git a/src/org/scada_lts/mango/service/PointValueService.java b/src/org/scada_lts/mango/service/PointValueService.java index e752e2f472..f1e133920a 100644 --- a/src/org/scada_lts/mango/service/PointValueService.java +++ b/src/org/scada_lts/mango/service/PointValueService.java @@ -28,13 +28,12 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.RejectedExecutionException; -import com.serotonin.mango.rt.dataImage.DataPointRT; -import com.serotonin.mango.rt.dataImage.IDataPoint; +import com.serotonin.mango.rt.RuntimeManager; +import com.serotonin.mango.rt.dataImage.*; import com.serotonin.mango.rt.dataImage.types.*; import com.serotonin.mango.rt.dataSource.meta.MetaDataSourceRT; import com.serotonin.mango.rt.dataSource.meta.MetaPointLocatorRT; import com.serotonin.mango.rt.dataSource.meta.ScriptExecutor; -import com.serotonin.mango.util.LoggingScriptUtils; import com.serotonin.mango.vo.DataPointVO; import com.serotonin.mango.vo.dataSource.DataSourceVO; import com.serotonin.mango.vo.dataSource.meta.MetaDataSourceVO; @@ -58,8 +57,6 @@ import com.serotonin.mango.Common; import com.serotonin.mango.DataTypes; import com.serotonin.mango.ImageSaveException; -import com.serotonin.mango.rt.dataImage.PointValueTime; -import com.serotonin.mango.rt.dataImage.SetPointSource; import com.serotonin.mango.rt.maint.work.WorkItem; import com.serotonin.mango.vo.AnonymousUser; import com.serotonin.mango.vo.bean.LongPair; @@ -635,7 +632,8 @@ public void updateMetaDataPointByScript(String xid) { MetaDataSourceRT metaDataSourceRT = new MetaDataSourceRT(metaDataSourceVO); - DataPointRT dataPointRT = new DataPointRT(dataPoint, metaPointLocatorRT); + dataPoint.setPointLocator(metaPointLocatorVO); + DataPointRT dataPointRT = RuntimeManager.createDataPointRT(dataPoint); metaPointLocatorRT.initialize(Common.timer, metaDataSourceRT, dataPointRT); diff --git a/src/org/scada_lts/mango/service/SystemSettingsService.java b/src/org/scada_lts/mango/service/SystemSettingsService.java index 83604ebd88..e43914a1c0 100644 --- a/src/org/scada_lts/mango/service/SystemSettingsService.java +++ b/src/org/scada_lts/mango/service/SystemSettingsService.java @@ -52,6 +52,7 @@ public Map getSettings() { settings.put("databaseType", this.getDatabaseType()); settings.put("scadaConfig", this.getScadaConfig()); settings.put("aggregateSettings", this.getAggregateSettings()); + settings.put("dataPointRuntimeSynchronized", this.isDataPointRtSynchronized()); return settings; } @@ -332,4 +333,12 @@ public void saveAggregateSettings(AggregateSettings aggregateSettings) { systemSettingsDAO.setValue(SystemSettingsDAO.AGGREGATION_LIMIT_FACTOR, String.valueOf(aggregateSettings.getLimitFactor())); systemSettingsDAO.setValue(SystemSettingsDAO.AGGREGATION_ENABLED, String.valueOf(aggregateSettings.isEnabled())); } + + public void saveDataPointRtSynchronized(boolean dataPointRtSynchronized) { + systemSettingsDAO.setValue(SystemSettingsDAO.DATAPOINT_RUNTIME_SYNCHRONIZED, String.valueOf(dataPointRtSynchronized)); + } + + public boolean isDataPointRtSynchronized() { + return SystemSettingsDAO.getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_SYNCHRONIZED); + } } diff --git a/src/org/scada_lts/utils/SystemSettingsUtils.java b/src/org/scada_lts/utils/SystemSettingsUtils.java index 9dc0047b1d..c54e758c22 100644 --- a/src/org/scada_lts/utils/SystemSettingsUtils.java +++ b/src/org/scada_lts/utils/SystemSettingsUtils.java @@ -1,9 +1,23 @@ package org.scada_lts.utils; +import org.apache.commons.logging.LogFactory; +import org.scada_lts.config.ScadaConfig; import org.scada_lts.web.mvc.api.AggregateSettings; public class SystemSettingsUtils { + private static final String DATAPOINT_RUNTIME_SYNCHRONIZED_KEY = "datapoint.runtime.synchronized"; + private static final org.apache.commons.logging.Log LOG = LogFactory.getLog(SystemSettingsUtils.class); + + public static boolean isDataPointRtSynchronized() { + try { + return ScadaConfig.getInstance().getBoolean(DATAPOINT_RUNTIME_SYNCHRONIZED_KEY, false); + } catch (Exception e) { + LOG.error(e.getMessage()); + return false; + } + } + public static String validateAggregateSettings(AggregateSettings body) { String msg = ValidationUtils.msgIfNullOrInvalid("valuesLimit must be >= 0; ", body.getValuesLimit(), a -> a <= 0); msg += ValidationUtils.msgIfNullOrInvalid("limitFactor must be > 0; ", body.getLimitFactor(), a -> a <= 0.0); diff --git a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java index 288ad47555..64b436b452 100644 --- a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java +++ b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java @@ -544,4 +544,37 @@ public ResponseEntity saveAggregateSettings(HttpServletRequest request, return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } + + @GetMapping(value = "/dataPointRtSynchronized", produces = "application/json") + public ResponseEntity getDataPointRtSynchronized(HttpServletRequest request) { + LOG.info("/api/systemSettings/getAggregateSettings"); + try { + User user = Common.getUser(request); + if (user != null && user.isAdmin()) { + return new ResponseEntity<>(systemSettingsService.isDataPointRtSynchronized(), HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + } catch (Exception e) { + LOG.error(e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @PostMapping(value = "/dataPointRtSynchronized/{dataPointRtSynchronized}", consumes = "application/json") + public ResponseEntity saveDataPointRtSynchronized(HttpServletRequest request, @PathVariable Boolean dataPointRtSynchronized) { + LOG.info("/api/systemSettings/dataPointRtSynchronized"); + try { + User user = Common.getUser(request); + if (user != null && user.isAdmin()) { + systemSettingsService.saveDataPointRtSynchronized(dataPointRtSynchronized); + return new ResponseEntity<>(SAVED_MSG, HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + } catch (Exception e) { + LOG.error(e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } } diff --git a/webapp-resources/env.properties b/webapp-resources/env.properties index 6d8fa45ffe..755a1ff3e6 100644 --- a/webapp-resources/env.properties +++ b/webapp-resources/env.properties @@ -91,4 +91,6 @@ api.amcharts.aggregation.limitFactor=1.5 user.cache.enabled=true usersprofile.cache.enabled=true permissions.cache.enabled=true -shareuser.cache.enabled=true \ No newline at end of file +shareuser.cache.enabled=true + +datapoint.runtime.synchronized=true \ No newline at end of file From 5b42c03dabac326e10701a523a55b457a58d4bf6 Mon Sep 17 00:00:00 2001 From: kamiljarmusik Date: Tue, 22 Feb 2022 08:27:38 +0100 Subject: [PATCH 2/5] #2101 Avoided duplicate values - correct log in SystemSettingsAPI --- src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java index 64b436b452..e50973c8bb 100644 --- a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java +++ b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java @@ -547,7 +547,7 @@ public ResponseEntity saveAggregateSettings(HttpServletRequest request, @GetMapping(value = "/dataPointRtSynchronized", produces = "application/json") public ResponseEntity getDataPointRtSynchronized(HttpServletRequest request) { - LOG.info("/api/systemSettings/getAggregateSettings"); + LOG.info("/api/systemSettings/dataPointRtSynchronized"); try { User user = Common.getUser(request); if (user != null && user.isAdmin()) { From 2402f7795ca6f844d9fc6254757b4bd505edf4c9 Mon Sep 17 00:00:00 2001 From: Kamil Jarmusik Date: Thu, 24 Feb 2022 20:36:19 +0100 Subject: [PATCH 3/5] #2101 Avoided duplicate values - change name on datapoint.runtime.value.synchronized --- src/com/serotonin/mango/rt/RuntimeManager.java | 2 +- src/org/scada_lts/dao/SystemSettingsDAO.java | 4 ++-- .../scada_lts/mango/service/SystemSettingsService.java | 10 +++++----- src/org/scada_lts/utils/SystemSettingsUtils.java | 10 ++++++---- src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java | 4 ++-- webapp-resources/env.properties | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/com/serotonin/mango/rt/RuntimeManager.java b/src/com/serotonin/mango/rt/RuntimeManager.java index aa854b198c..f38e921bf7 100644 --- a/src/com/serotonin/mango/rt/RuntimeManager.java +++ b/src/com/serotonin/mango/rt/RuntimeManager.java @@ -486,7 +486,7 @@ private void startDataPoint(DataPointVO vo) { } public static DataPointRT createDataPointRT(DataPointVO vo) { - boolean dataPointRtSynchronized = new SystemSettingsService().isDataPointRtSynchronized(); + boolean dataPointRtSynchronized = new SystemSettingsService().isDataPointRtValueSynchronized(); if(dataPointRtSynchronized) return new DataPointSynchronizedRT(vo, vo.getPointLocator().createRuntime()); return new DataPointRT(vo, vo.getPointLocator().createRuntime()); diff --git a/src/org/scada_lts/dao/SystemSettingsDAO.java b/src/org/scada_lts/dao/SystemSettingsDAO.java index 80e22f6a69..b9fc8184f5 100644 --- a/src/org/scada_lts/dao/SystemSettingsDAO.java +++ b/src/org/scada_lts/dao/SystemSettingsDAO.java @@ -120,7 +120,7 @@ public class SystemSettingsDAO { public static final String AGGREGATION_VALUES_LIMIT = "aggregationValuesLimit"; public static final String AGGREGATION_LIMIT_FACTOR = "aggregationLimitFactor"; - public static final String DATAPOINT_RUNTIME_SYNCHRONIZED = "dataPointRuntimeSynchronized"; + public static final String DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED = "dataPointRuntimeValueSynchronized"; private static final String DELETE_WATCH_LISTS = "delete from watchLists"; private static final String DELETE_MANGO_VIEWS = "delete from mangoViews"; @@ -373,7 +373,7 @@ public String getDatabaseSchemaVersion(String key, String defaultValue) { DEFAULT_VALUES.put(AGGREGATION_ENABLED, aggregateSettings.isEnabled()); DEFAULT_VALUES.put(AGGREGATION_LIMIT_FACTOR, String.valueOf(aggregateSettings.getLimitFactor())); DEFAULT_VALUES.put(AGGREGATION_VALUES_LIMIT, aggregateSettings.getValuesLimit()); - DEFAULT_VALUES.put(DATAPOINT_RUNTIME_SYNCHRONIZED, SystemSettingsUtils.isDataPointRtSynchronized()); + DEFAULT_VALUES.put(DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, SystemSettingsUtils.isDataPointRtValueSynchronized()); } @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, rollbackFor = SQLException.class) diff --git a/src/org/scada_lts/mango/service/SystemSettingsService.java b/src/org/scada_lts/mango/service/SystemSettingsService.java index e43914a1c0..697d0b2fe7 100644 --- a/src/org/scada_lts/mango/service/SystemSettingsService.java +++ b/src/org/scada_lts/mango/service/SystemSettingsService.java @@ -52,7 +52,7 @@ public Map getSettings() { settings.put("databaseType", this.getDatabaseType()); settings.put("scadaConfig", this.getScadaConfig()); settings.put("aggregateSettings", this.getAggregateSettings()); - settings.put("dataPointRuntimeSynchronized", this.isDataPointRtSynchronized()); + settings.put("dataPointRuntimeValueSynchronized", this.isDataPointRtValueSynchronized()); return settings; } @@ -334,11 +334,11 @@ public void saveAggregateSettings(AggregateSettings aggregateSettings) { systemSettingsDAO.setValue(SystemSettingsDAO.AGGREGATION_ENABLED, String.valueOf(aggregateSettings.isEnabled())); } - public void saveDataPointRtSynchronized(boolean dataPointRtSynchronized) { - systemSettingsDAO.setValue(SystemSettingsDAO.DATAPOINT_RUNTIME_SYNCHRONIZED, String.valueOf(dataPointRtSynchronized)); + public void saveDataPointRtValueSynchronized(boolean dataPointRtValueSynchronized) { + systemSettingsDAO.setValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, String.valueOf(dataPointRtValueSynchronized)); } - public boolean isDataPointRtSynchronized() { - return SystemSettingsDAO.getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_SYNCHRONIZED); + public boolean isDataPointRtValueSynchronized() { + return SystemSettingsDAO.getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED); } } diff --git a/src/org/scada_lts/utils/SystemSettingsUtils.java b/src/org/scada_lts/utils/SystemSettingsUtils.java index c54e758c22..be3e14db58 100644 --- a/src/org/scada_lts/utils/SystemSettingsUtils.java +++ b/src/org/scada_lts/utils/SystemSettingsUtils.java @@ -4,14 +4,16 @@ import org.scada_lts.config.ScadaConfig; import org.scada_lts.web.mvc.api.AggregateSettings; -public class SystemSettingsUtils { +public final class SystemSettingsUtils { - private static final String DATAPOINT_RUNTIME_SYNCHRONIZED_KEY = "datapoint.runtime.synchronized"; + private SystemSettingsUtils() {} + + private static final String DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED_KEY = "datapoint.runtime.value.synchronized"; private static final org.apache.commons.logging.Log LOG = LogFactory.getLog(SystemSettingsUtils.class); - public static boolean isDataPointRtSynchronized() { + public static boolean isDataPointRtValueSynchronized() { try { - return ScadaConfig.getInstance().getBoolean(DATAPOINT_RUNTIME_SYNCHRONIZED_KEY, false); + return ScadaConfig.getInstance().getBoolean(DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED_KEY, false); } catch (Exception e) { LOG.error(e.getMessage()); return false; diff --git a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java index e50973c8bb..bd79afde88 100644 --- a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java +++ b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java @@ -551,7 +551,7 @@ public ResponseEntity getDataPointRtSynchronized(HttpServletRequest req try { User user = Common.getUser(request); if (user != null && user.isAdmin()) { - return new ResponseEntity<>(systemSettingsService.isDataPointRtSynchronized(), HttpStatus.OK); + return new ResponseEntity<>(systemSettingsService.isDataPointRtValueSynchronized(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } @@ -567,7 +567,7 @@ public ResponseEntity saveDataPointRtSynchronized(HttpServletRequest req try { User user = Common.getUser(request); if (user != null && user.isAdmin()) { - systemSettingsService.saveDataPointRtSynchronized(dataPointRtSynchronized); + systemSettingsService.saveDataPointRtValueSynchronized(dataPointRtSynchronized); return new ResponseEntity<>(SAVED_MSG, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); diff --git a/webapp-resources/env.properties b/webapp-resources/env.properties index 755a1ff3e6..9c2973d459 100644 --- a/webapp-resources/env.properties +++ b/webapp-resources/env.properties @@ -93,4 +93,4 @@ usersprofile.cache.enabled=true permissions.cache.enabled=true shareuser.cache.enabled=true -datapoint.runtime.synchronized=true \ No newline at end of file +datapoint.runtime.value.synchronized=false \ No newline at end of file From 6e8d7f98b02e88114be2b71394dca62c59b3a542 Mon Sep 17 00:00:00 2001 From: Kamil Jarmusik Date: Fri, 25 Feb 2022 15:14:58 +0100 Subject: [PATCH 4/5] #2101 Avoided duplicate values - added option dataPointRuntimeValueSynchronized in system settings new and old ui; correct: SystemSettingsDwr.saveMiscSettings, rename object from SystemSettingsDAO to systemSettingsDAO --- WebContent/WEB-INF/jsp/systemSettings.jsp | 12 +++++-- scadalts-ui/src/locales/en.json | 3 +- .../SystemSettings/MiscSettingsComponent.vue | 11 +++++++ .../mango/web/dwr/SystemSettingsDwr.java | 32 +++++++++++------- src/org/scada_lts/dao/SystemSettingsDAO.java | 2 +- .../mango/service/SystemSettingsService.java | 7 ++-- .../web/mvc/api/SystemSettingsAPI.java | 33 ------------------- .../web/mvc/api/json/JsonSettingsMisc.java | 14 +++++++- webapp-resources/messages_de.properties | 1 + webapp-resources/messages_en.properties | 1 + webapp-resources/messages_es.properties | 1 + webapp-resources/messages_fi.properties | 1 + webapp-resources/messages_fr.properties | 1 + webapp-resources/messages_lu.properties | 1 + webapp-resources/messages_nl.properties | 1 + webapp-resources/messages_pl.properties | 1 + webapp-resources/messages_pt.properties | 1 + webapp-resources/messages_ru.properties | 1 + webapp-resources/messages_zh.properties | 1 + 19 files changed, 70 insertions(+), 55 deletions(-) diff --git a/WebContent/WEB-INF/jsp/systemSettings.jsp b/WebContent/WEB-INF/jsp/systemSettings.jsp index 2a6c7761fc..e2e2c4707b 100644 --- a/WebContent/WEB-INF/jsp/systemSettings.jsp +++ b/WebContent/WEB-INF/jsp/systemSettings.jsp @@ -88,9 +88,10 @@ $set("", settings.); $set("", settings.); - + $set("", settings.); + $set("", settings.); - + var sel = $(""); sel.options[sel.options.length] = new Option("${lang.value}", "${lang.key}"); @@ -260,6 +261,7 @@ 1, $get(""), $get(""), + $get(""), function() { stopImageFader("saveMiscSettingsImg"); setUserMessage("miscMessage", ""); @@ -715,6 +717,12 @@ + + + + "/>" type="checkbox" class="formShort"/> + + diff --git a/scadalts-ui/src/locales/en.json b/scadalts-ui/src/locales/en.json index a452f9853b..d8b817a8e3 100644 --- a/scadalts-ui/src/locales/en.json +++ b/scadalts-ui/src/locales/en.json @@ -445,5 +445,6 @@ "watchdog.response.badRequest": "Check your request data!", "watchdog.response.unauthorized": "You do not have permission to this action!", "watchdog.response.unavailable": "Watchdog server is unreachable!", - "watchdog.response.unexpected": "Scada server error occurred!" + "watchdog.response.unexpected": "Scada server error occurred!", + "systemsettings.misc.dataPointRuntimeValueSynchronized": "Datapoint runtime value synchronized" } diff --git a/scadalts-ui/src/views/SystemSettings/MiscSettingsComponent.vue b/scadalts-ui/src/views/SystemSettings/MiscSettingsComponent.vue index 268b8a8c9c..5285d2667c 100644 --- a/scadalts-ui/src/views/SystemSettings/MiscSettingsComponent.vue +++ b/scadalts-ui/src/views/SystemSettings/MiscSettingsComponent.vue @@ -88,6 +88,16 @@ dense > + + + @@ -132,6 +142,7 @@ export default { status: false, message: '', }, + dataPointRuntimeValueSynchronized: false, }; }, diff --git a/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java b/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java index 97106244d2..c063fadb0d 100644 --- a/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java +++ b/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java @@ -144,6 +144,9 @@ public Map getSettings() { settings.put(SystemSettingsDAO.PLOT_GRIDLINE_COLOUR, SystemSettingsDAO .getValue(SystemSettingsDAO.PLOT_GRIDLINE_COLOUR)); + settings.put(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, SystemSettingsDAO + .getBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); + return settings; } @@ -285,31 +288,36 @@ public void saveHttpSettings(boolean useProxy, String host, int port, @MethodFilter public void saveMiscSettings(int eventPurgePeriodType, - int eventPurgePeriods, int reportPurgePeriodType, - int reportPurgePeriods, int uiPerformance, boolean groveLogging, - int futureDateLimitPeriodType, int futureDateLimitPeriods) { + int eventPurgePeriods, int reportPurgePeriodType, + int reportPurgePeriods, int uiPerformance, boolean groveLogging, + int futureDateLimitPeriodType, int futureDateLimitPeriods, + boolean dataPointRtValueSynchronized) { Permissions.ensureAdmin(); - SystemSettingsDAO SystemSettingsDAO = new SystemSettingsDAO(); - SystemSettingsDAO + SystemSettingsDAO systemSettingsDAO = new SystemSettingsDAO(); + systemSettingsDAO .setIntValue(SystemSettingsDAO.EVENT_PURGE_PERIOD_TYPE, eventPurgePeriodType); - SystemSettingsDAO.setIntValue(SystemSettingsDAO.EVENT_PURGE_PERIODS, + systemSettingsDAO.setIntValue(SystemSettingsDAO.EVENT_PURGE_PERIODS, eventPurgePeriods); - SystemSettingsDAO.setIntValue( + systemSettingsDAO.setIntValue( SystemSettingsDAO.REPORT_PURGE_PERIOD_TYPE, reportPurgePeriodType); - SystemSettingsDAO.setIntValue(SystemSettingsDAO.REPORT_PURGE_PERIODS, + systemSettingsDAO.setIntValue(SystemSettingsDAO.REPORT_PURGE_PERIODS, reportPurgePeriods); - SystemSettingsDAO.setIntValue(SystemSettingsDAO.UI_PERFORMANCE, + systemSettingsDAO.setIntValue(SystemSettingsDAO.UI_PERFORMANCE, uiPerformance); - SystemSettingsDAO.setBooleanValue(SystemSettingsDAO.GROVE_LOGGING, + systemSettingsDAO.setBooleanValue(SystemSettingsDAO.GROVE_LOGGING, groveLogging); - SystemSettingsDAO.setIntValue( + systemSettingsDAO.setIntValue( SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIOD_TYPE, futureDateLimitPeriodType); - SystemSettingsDAO.setIntValue( + systemSettingsDAO.setIntValue( SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS, futureDateLimitPeriods); + + systemSettingsDAO.setBooleanValue( + SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, + dataPointRtValueSynchronized); } @MethodFilter diff --git a/src/org/scada_lts/dao/SystemSettingsDAO.java b/src/org/scada_lts/dao/SystemSettingsDAO.java index b9fc8184f5..83b303f2bd 100644 --- a/src/org/scada_lts/dao/SystemSettingsDAO.java +++ b/src/org/scada_lts/dao/SystemSettingsDAO.java @@ -120,7 +120,7 @@ public class SystemSettingsDAO { public static final String AGGREGATION_VALUES_LIMIT = "aggregationValuesLimit"; public static final String AGGREGATION_LIMIT_FACTOR = "aggregationLimitFactor"; - public static final String DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED = "dataPointRuntimeValueSynchronized"; + public static final String DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED = "dataPointRtValueSynchronized"; private static final String DELETE_WATCH_LISTS = "delete from watchLists"; private static final String DELETE_MANGO_VIEWS = "delete from mangoViews"; diff --git a/src/org/scada_lts/mango/service/SystemSettingsService.java b/src/org/scada_lts/mango/service/SystemSettingsService.java index 697d0b2fe7..7d2b2864ff 100644 --- a/src/org/scada_lts/mango/service/SystemSettingsService.java +++ b/src/org/scada_lts/mango/service/SystemSettingsService.java @@ -52,7 +52,6 @@ public Map getSettings() { settings.put("databaseType", this.getDatabaseType()); settings.put("scadaConfig", this.getScadaConfig()); settings.put("aggregateSettings", this.getAggregateSettings()); - settings.put("dataPointRuntimeValueSynchronized", this.isDataPointRtValueSynchronized()); return settings; } @@ -129,6 +128,7 @@ public JsonSettingsMisc getMiscSettings() { json.setFutureDateLimitPeriodType(SystemSettingsDAO.getIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIOD_TYPE)); json.setFutureDateLimitPeriods(SystemSettingsDAO.getIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS)); json.setUiPerformance(SystemSettingsDAO.getIntValue(SystemSettingsDAO.UI_PERFORMANCE)); + json.setDataPointRuntimeValueSynchronized(SystemSettingsDAO.getBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); return json; } @@ -141,6 +141,7 @@ public void saveMiscSettings(JsonSettingsMisc json) { systemSettingsDAO.setIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIOD_TYPE, json.getFutureDateLimitPeriodType()); systemSettingsDAO.setIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS, json.getFutureDateLimitPeriods()); systemSettingsDAO.setIntValue(SystemSettingsDAO.UI_PERFORMANCE, json.getUiPerformance()); + systemSettingsDAO.setBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, json.isDataPointRuntimeValueSynchronized()); } public List getAuditEventAlarmLevels() { @@ -334,10 +335,6 @@ public void saveAggregateSettings(AggregateSettings aggregateSettings) { systemSettingsDAO.setValue(SystemSettingsDAO.AGGREGATION_ENABLED, String.valueOf(aggregateSettings.isEnabled())); } - public void saveDataPointRtValueSynchronized(boolean dataPointRtValueSynchronized) { - systemSettingsDAO.setValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, String.valueOf(dataPointRtValueSynchronized)); - } - public boolean isDataPointRtValueSynchronized() { return SystemSettingsDAO.getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED); } diff --git a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java index bd79afde88..288ad47555 100644 --- a/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java +++ b/src/org/scada_lts/web/mvc/api/SystemSettingsAPI.java @@ -544,37 +544,4 @@ public ResponseEntity saveAggregateSettings(HttpServletRequest request, return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } - - @GetMapping(value = "/dataPointRtSynchronized", produces = "application/json") - public ResponseEntity getDataPointRtSynchronized(HttpServletRequest request) { - LOG.info("/api/systemSettings/dataPointRtSynchronized"); - try { - User user = Common.getUser(request); - if (user != null && user.isAdmin()) { - return new ResponseEntity<>(systemSettingsService.isDataPointRtValueSynchronized(), HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } - } catch (Exception e) { - LOG.error(e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - @PostMapping(value = "/dataPointRtSynchronized/{dataPointRtSynchronized}", consumes = "application/json") - public ResponseEntity saveDataPointRtSynchronized(HttpServletRequest request, @PathVariable Boolean dataPointRtSynchronized) { - LOG.info("/api/systemSettings/dataPointRtSynchronized"); - try { - User user = Common.getUser(request); - if (user != null && user.isAdmin()) { - systemSettingsService.saveDataPointRtValueSynchronized(dataPointRtSynchronized); - return new ResponseEntity<>(SAVED_MSG, HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } - } catch (Exception e) { - LOG.error(e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } } diff --git a/src/org/scada_lts/web/mvc/api/json/JsonSettingsMisc.java b/src/org/scada_lts/web/mvc/api/json/JsonSettingsMisc.java index 712915d3bd..a4e0defebc 100644 --- a/src/org/scada_lts/web/mvc/api/json/JsonSettingsMisc.java +++ b/src/org/scada_lts/web/mvc/api/json/JsonSettingsMisc.java @@ -12,10 +12,13 @@ public class JsonSettingsMisc implements Serializable { private int uiPerformance; private int futureDateLimitPeriodType; private int futureDateLimitPeriods; + private boolean dataPointRuntimeValueSynchronized; public JsonSettingsMisc() {} - public JsonSettingsMisc(boolean groveLogging, int eventPurgePeriodType, int eventPurgePeriods, int reportPurgePeriodType, int reportPurgePeriods, int uiPerformance, int futureDateLimitPeriodType, int futureDateLimitPeriods) { + public JsonSettingsMisc(boolean groveLogging, int eventPurgePeriodType, int eventPurgePeriods, + int reportPurgePeriodType, int reportPurgePeriods, int uiPerformance, + int futureDateLimitPeriodType, int futureDateLimitPeriods, boolean dataPointRuntimeValueSynchronized) { this.groveLogging = groveLogging; this.eventPurgePeriodType = eventPurgePeriodType; this.eventPurgePeriods = eventPurgePeriods; @@ -24,6 +27,7 @@ public JsonSettingsMisc(boolean groveLogging, int eventPurgePeriodType, int even this.uiPerformance = uiPerformance; this.futureDateLimitPeriodType = futureDateLimitPeriodType; this.futureDateLimitPeriods = futureDateLimitPeriods; + this.dataPointRuntimeValueSynchronized = dataPointRuntimeValueSynchronized; } public boolean isGroveLogging() { @@ -89,4 +93,12 @@ public int getFutureDateLimitPeriods() { public void setFutureDateLimitPeriods(int futureDateLimitPeriods) { this.futureDateLimitPeriods = futureDateLimitPeriods; } + + public boolean isDataPointRuntimeValueSynchronized() { + return dataPointRuntimeValueSynchronized; + } + + public void setDataPointRuntimeValueSynchronized(boolean dataPointRuntimeValueSynchronized) { + this.dataPointRuntimeValueSynchronized = dataPointRuntimeValueSynchronized; + } } diff --git a/webapp-resources/messages_de.properties b/webapp-resources/messages_de.properties index 7957877de3..ce1473b500 100644 --- a/webapp-resources/messages_de.properties +++ b/webapp-resources/messages_de.properties @@ -3201,3 +3201,4 @@ dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_en.properties b/webapp-resources/messages_en.properties index 3e041b5993..4fb65f6e23 100644 --- a/webapp-resources/messages_en.properties +++ b/webapp-resources/messages_en.properties @@ -3216,3 +3216,4 @@ emport.profilePermission.prefix=Permissions for profile ''{0}'': {1} dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_es.properties b/webapp-resources/messages_es.properties index 7002c1bba7..43217f4121 100644 --- a/webapp-resources/messages_es.properties +++ b/webapp-resources/messages_es.properties @@ -3128,3 +3128,4 @@ dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_fi.properties b/webapp-resources/messages_fi.properties index d054618708..b57c5480cd 100644 --- a/webapp-resources/messages_fi.properties +++ b/webapp-resources/messages_fi.properties @@ -2919,3 +2919,4 @@ viewEdit.position.y=Position Y ftl.subject.default={0} {1}{2} - {3} ftl.subject.default.id=Scada-LTS {0} notification - id:{1} ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_fr.properties b/webapp-resources/messages_fr.properties index 79e1838452..d909e85231 100644 --- a/webapp-resources/messages_fr.properties +++ b/webapp-resources/messages_fr.properties @@ -3198,3 +3198,4 @@ dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_lu.properties b/webapp-resources/messages_lu.properties index 81bed2d7f1..1dae7a1bfc 100644 --- a/webapp-resources/messages_lu.properties +++ b/webapp-resources/messages_lu.properties @@ -3218,3 +3218,4 @@ dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_nl.properties b/webapp-resources/messages_nl.properties index ea57afd9c3..de74f837b7 100644 --- a/webapp-resources/messages_nl.properties +++ b/webapp-resources/messages_nl.properties @@ -2756,3 +2756,4 @@ viewEdit.position.y=Position Y ftl.subject.default={0} {1}{2} - {3} ftl.subject.default.id=Scada-LTS {0} notification - id:{1} ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_pl.properties b/webapp-resources/messages_pl.properties index 60aeda19f8..5395968938 100644 --- a/webapp-resources/messages_pl.properties +++ b/webapp-resources/messages_pl.properties @@ -3067,3 +3067,4 @@ dox.anonymousView=Dost0119p anonimowy viewEdit.position.x=Położenie X viewEdit.position.y=Położenie Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_pt.properties b/webapp-resources/messages_pt.properties index 45c4e7287e..f39d8e658b 100644 --- a/webapp-resources/messages_pt.properties +++ b/webapp-resources/messages_pt.properties @@ -3197,3 +3197,4 @@ dox.anonymousView=Anonymous access viewEdit.position.x=Position X viewEdit.position.y=Position Y ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_ru.properties b/webapp-resources/messages_ru.properties index f28a3c061f..f6dae35a38 100644 --- a/webapp-resources/messages_ru.properties +++ b/webapp-resources/messages_ru.properties @@ -3116,3 +3116,4 @@ viewEdit.position.y=Position Y ftl.subject.default={0} {1}{2} - {3} ftl.subject.default.id=Scada-LTS {0} notification - id:{1} ftl.subject.default.log=Scada-LTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file diff --git a/webapp-resources/messages_zh.properties b/webapp-resources/messages_zh.properties index 91d397ae65..06ebd7f3f5 100644 --- a/webapp-resources/messages_zh.properties +++ b/webapp-resources/messages_zh.properties @@ -2067,3 +2067,4 @@ viewEdit.position.y=Position Y ftl.subject.default={0} {1}{2} - {3} ftl.subject.default.id=Scada-LTS {0} notification - id:{1} ftl.subject.default.log=ScadaLTS {0} +systemsettings.misc.dataPointRuntimeValueSynchronized=Datapoint runtime value synchronized \ No newline at end of file From 05ee3c5c2e492a85cabfa881fb59b79dfd881618 Mon Sep 17 00:00:00 2001 From: kamiljarmusik Date: Thu, 3 Mar 2022 11:31:45 +0100 Subject: [PATCH 5/5] #2101 Avoided duplicate values - use: SystemSettingsDAO.setValue SystemSettingsDAO.getBooleanValueOrDefault --- src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java | 7 +++---- src/org/scada_lts/mango/service/SystemSettingsService.java | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java b/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java index c063fadb0d..0425804f54 100644 --- a/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java +++ b/src/com/serotonin/mango/web/dwr/SystemSettingsDwr.java @@ -145,7 +145,7 @@ public Map getSettings() { .getValue(SystemSettingsDAO.PLOT_GRIDLINE_COLOUR)); settings.put(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, SystemSettingsDAO - .getBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); + .getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); return settings; } @@ -314,10 +314,9 @@ public void saveMiscSettings(int eventPurgePeriodType, systemSettingsDAO.setIntValue( SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS, futureDateLimitPeriods); - - systemSettingsDAO.setBooleanValue( + systemSettingsDAO.setValue( SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, - dataPointRtValueSynchronized); + String.valueOf(dataPointRtValueSynchronized)); } @MethodFilter diff --git a/src/org/scada_lts/mango/service/SystemSettingsService.java b/src/org/scada_lts/mango/service/SystemSettingsService.java index 7d2b2864ff..580a65d270 100644 --- a/src/org/scada_lts/mango/service/SystemSettingsService.java +++ b/src/org/scada_lts/mango/service/SystemSettingsService.java @@ -128,7 +128,7 @@ public JsonSettingsMisc getMiscSettings() { json.setFutureDateLimitPeriodType(SystemSettingsDAO.getIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIOD_TYPE)); json.setFutureDateLimitPeriods(SystemSettingsDAO.getIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS)); json.setUiPerformance(SystemSettingsDAO.getIntValue(SystemSettingsDAO.UI_PERFORMANCE)); - json.setDataPointRuntimeValueSynchronized(SystemSettingsDAO.getBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); + json.setDataPointRuntimeValueSynchronized(SystemSettingsDAO.getBooleanValueOrDefault(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED)); return json; } @@ -141,7 +141,7 @@ public void saveMiscSettings(JsonSettingsMisc json) { systemSettingsDAO.setIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIOD_TYPE, json.getFutureDateLimitPeriodType()); systemSettingsDAO.setIntValue(SystemSettingsDAO.FUTURE_DATE_LIMIT_PERIODS, json.getFutureDateLimitPeriods()); systemSettingsDAO.setIntValue(SystemSettingsDAO.UI_PERFORMANCE, json.getUiPerformance()); - systemSettingsDAO.setBooleanValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, json.isDataPointRuntimeValueSynchronized()); + systemSettingsDAO.setValue(SystemSettingsDAO.DATAPOINT_RUNTIME_VALUE_SYNCHRONIZED, String.valueOf(json.isDataPointRuntimeValueSynchronized())); } public List getAuditEventAlarmLevels() {