Improve set and clear data model functions
This commit is contained in:
1 parent
4eb1c61c4b
commit
7306f7a8a5
2 files changed
+106
-98
No files matched your search
+88
-94
@@ -22,9 +22,9 @@ const common = require('./common');
|
||||
|
||||
|
||||
const CHANGE_FLAGS = {
|
||||
object: 4,
|
||||
writable: 16,
|
||||
value: 64
|
||||
object: 2,
|
||||
writable: 4,
|
||||
value: 8
|
||||
};
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ function sanitizeParameterValue(parameterValue) {
|
||||
throw new Error(`Parameter value type "${parameterValue[1]}" not recognized.`);
|
||||
|
||||
parameterValue[0] = JSON.parse(JSON.stringify(parameterValue[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parameterValue;
|
||||
@@ -171,36 +172,59 @@ function unpack(deviceData, path, revision) {
|
||||
}
|
||||
|
||||
|
||||
function clear(deviceData, path, timestamp, attributes) {
|
||||
for (let p of deviceData.paths.find(path, true, true, timestamp ? 99 : path.length)) {
|
||||
for (let k in deviceData.trackers.get(p))
|
||||
deviceData.changes.add(k);
|
||||
function clear(deviceData, path, timestamp, attributes, changeFlags = 0) {
|
||||
let changeTrackers = {};
|
||||
|
||||
let t = deviceData.timestamps.get(p);
|
||||
if (!t)
|
||||
timestamp = timestamp || 0;
|
||||
|
||||
let descendantsTimestamp = timestamp;
|
||||
if (attributes && attributes.object) {
|
||||
if (attributes.object > descendantsTimestamp)
|
||||
descendantsTimestamp = attributes.object;
|
||||
if (!(attributes.object <= attributes.value))
|
||||
attributes.value = attributes.object;
|
||||
}
|
||||
|
||||
for (let p of deviceData.paths.find(path, true, true, descendantsTimestamp ? 99 : path.length)) {
|
||||
let tracker = deviceData.trackers.get(p);
|
||||
for (let k in tracker)
|
||||
changeTrackers[k] |= tracker[k];
|
||||
|
||||
let currentTimestamp = deviceData.timestamps.get(p);
|
||||
if (currentTimestamp === undefined)
|
||||
continue;
|
||||
|
||||
if (!(timestamp <= t)) {
|
||||
if (timestamp > currentTimestamp ||
|
||||
(descendantsTimestamp > currentTimestamp && p.length > path.length)) {
|
||||
deviceData.timestamps.delete(p);
|
||||
deviceData.attributes.delete(p);
|
||||
} else if (t && attributes) {
|
||||
changeFlags |= 1;
|
||||
}
|
||||
else if (attributes && p.length == path.length) {
|
||||
let currentAttributes = deviceData.attributes.get(p);
|
||||
if (currentAttributes) {
|
||||
let newAttrs;
|
||||
for (let attrName in attributes) {
|
||||
if (attrName in currentAttributes &&
|
||||
attributes[attrName][0] > currentAttributes[attrName][0]) {
|
||||
if (!newAttrs)
|
||||
newAttrs = JSON.parse(JSON.stringify(currentAttributes));
|
||||
attributes[attrName] > currentAttributes[attrName][0]) {
|
||||
changeFlags |= CHANGE_FLAGS[attrName];
|
||||
if (!newAttrs) {
|
||||
newAttrs = Object.assign({}, currentAttributes);
|
||||
deviceData.attributes.set(p, newAttrs);
|
||||
}
|
||||
delete newAttrs[attrName];
|
||||
}
|
||||
}
|
||||
|
||||
if (newAttrs)
|
||||
deviceData.attributes.set(p, newAttrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note: For performance, we're merging all changes together rather than
|
||||
// mark changes based the exact parameters affected.
|
||||
for (let k in changeTrackers) {
|
||||
if (changeTrackers[k] & changeFlags)
|
||||
deviceData.changes.add(k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,9 +251,11 @@ function set(deviceData, path, timestamp, attributes, toClear) {
|
||||
|
||||
if (path.wildcard)
|
||||
attributes = undefined;
|
||||
else
|
||||
else if (currentTimestamp)
|
||||
currentAttributes = deviceData.attributes.get(path);
|
||||
|
||||
let changeFlags = 0;
|
||||
|
||||
if (attributes) {
|
||||
if (attributes.value && attributes.value[1]
|
||||
&& attributes.value[0] >= (attributes.object ? attributes.object[0] : 0))
|
||||
@@ -239,67 +265,29 @@ function set(deviceData, path, timestamp, attributes, toClear) {
|
||||
&& attributes.object[0] >= (attributes.value ? attributes.value[0] : 0))
|
||||
attributes.value = [attributes.object[0]];
|
||||
|
||||
if (currentAttributes) {
|
||||
let changeFlags = 0;
|
||||
let newAttributes = Object.assign({}, currentAttributes, attributes);
|
||||
|
||||
if (currentAttributes) {
|
||||
for (let attrName in attributes) {
|
||||
timestamp = Math.max(timestamp, attributes[attrName][0]);
|
||||
if (attrName in currentAttributes) {
|
||||
if (attributes[attrName][0] > currentAttributes[attrName][0]) {
|
||||
changeFlags |= CHANGE_FLAGS[attrName];
|
||||
if (!compareEquality(attributes[attrName][1], currentAttributes[attrName][1]))
|
||||
changeFlags |= CHANGE_FLAGS[attrName] << 1;
|
||||
}
|
||||
else
|
||||
delete attributes[attrName];
|
||||
}
|
||||
else {
|
||||
if (!(attrName in currentAttributes))
|
||||
changeFlags |= CHANGE_FLAGS[attrName];
|
||||
else if (attributes[attrName][0] <= currentAttributes[attrName][0])
|
||||
newAttributes[attrName] = currentAttributes[attrName];
|
||||
else if (!compareEquality(attributes[attrName][1], currentAttributes[attrName][1]))
|
||||
changeFlags |= CHANGE_FLAGS[attrName];
|
||||
changeFlags |= CHANGE_FLAGS[attrName] << 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(attributes).length) {
|
||||
if (attributes.object && currentAttributes.object &&
|
||||
attributes.object[1] !== currentAttributes.object[1]) {
|
||||
toClear = toClear || [];
|
||||
toClear.push([path.concat('*'), attributes.object[0]]);
|
||||
}
|
||||
for (let attrName in currentAttributes)
|
||||
if (!(attrName in attributes))
|
||||
attributes[attrName] = currentAttributes[attrName];
|
||||
|
||||
deviceData.attributes.set(path, attributes);
|
||||
}
|
||||
|
||||
if (timestamp > currentTimestamp) {
|
||||
changeFlags |= 1;
|
||||
deviceData.timestamps.set(path, timestamp);
|
||||
|
||||
if (path.length > 1)
|
||||
toClear = set(deviceData, path.slice(0, path.length - 1), timestamp,
|
||||
{object: [timestamp, 1]}, toClear);
|
||||
}
|
||||
|
||||
if (changeFlags)
|
||||
for (let sup of deviceData.paths.find(path, true, false)) {
|
||||
let c = deviceData.trackers.get(sup);
|
||||
for (let k in c)
|
||||
if (c[k] & changeFlags) {
|
||||
deviceData.changes.add(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(timestamp <= currentTimestamp)) {
|
||||
deviceData.timestamps.set(path, timestamp);
|
||||
deviceData.attributes.set(path, attributes);
|
||||
else
|
||||
changeFlags |= 1;
|
||||
|
||||
deviceData.attributes.set(path, newAttributes);
|
||||
|
||||
if (!(timestamp <= currentTimestamp)) {
|
||||
deviceData.timestamps.set(path, timestamp);
|
||||
if (path.length > 1)
|
||||
toClear = set(deviceData, path.slice(0, path.length - 1), timestamp,
|
||||
{object: [timestamp, 1]}, toClear);
|
||||
|
||||
toClear = toClear || [];
|
||||
toClear.push([path, timestamp]);
|
||||
}
|
||||
}
|
||||
else if (!(timestamp <= currentTimestamp)) {
|
||||
@@ -307,43 +295,49 @@ function set(deviceData, path, timestamp, attributes, toClear) {
|
||||
|
||||
if (currentAttributes) {
|
||||
deviceData.attributes.delete(path);
|
||||
toClear = toClear || [];
|
||||
toClear.push([path, timestamp]);
|
||||
changeFlags |= 1;
|
||||
}
|
||||
|
||||
if (path.wildcard)
|
||||
for (let sub of deviceData.paths.find(path, false, true))
|
||||
if (timestamp > deviceData.timestamps.get(sub)) {
|
||||
deviceData.timestamps.delete(sub);
|
||||
if (deviceData.attributes.delete(sub)) {
|
||||
toClear = toClear || [];
|
||||
toClear.push([sub, timestamp]);
|
||||
}
|
||||
else if (path.wildcard) {
|
||||
for (let p of deviceData.paths.find(path, false, true, path.length))
|
||||
if (timestamp > deviceData.timestamps.get(p)) {
|
||||
toClear = toClear || [];
|
||||
toClear.push([p, timestamp]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changeFlags) {
|
||||
if (changeFlags & 1) {
|
||||
toClear = toClear || [];
|
||||
toClear.push([path, timestamp, null, changeFlags]);
|
||||
}
|
||||
else if (changeFlags & CHANGE_FLAGS.object) {
|
||||
toClear = toClear || [];
|
||||
toClear.push([path, 0, {object: attributes.object[0]}, changeFlags]);
|
||||
}
|
||||
else {
|
||||
for (let p of deviceData.paths.find(path, true, false, path.length)) {
|
||||
let tracker = deviceData.trackers.get(p);
|
||||
for (let k in tracker) {
|
||||
if (tracker[k] & changeFlags)
|
||||
deviceData.changes.add(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toClear;
|
||||
}
|
||||
|
||||
|
||||
function track(deviceData, path, marker, timestamp, attributeTimestamps, exist, attributeValues) {
|
||||
function track(deviceData, path, marker, attributes) {
|
||||
path = deviceData.paths.add(path);
|
||||
let f = 0;
|
||||
let f = 1;
|
||||
|
||||
if (timestamp)
|
||||
f |= 1;
|
||||
|
||||
if (exist)
|
||||
f |= 2;
|
||||
|
||||
if (attributeTimestamps)
|
||||
for (let attrName of attributeTimestamps)
|
||||
if (attributes)
|
||||
for (let attrName of attributes)
|
||||
f |= CHANGE_FLAGS[attrName];
|
||||
|
||||
if (attributeValues)
|
||||
for (let attrName of attributeValues)
|
||||
f |= CHANGE_FLAGS[attrName] << 1;
|
||||
|
||||
let cur = deviceData.trackers.get(path);
|
||||
if (!cur) {
|
||||
cur = {};
|
||||
|
||||
Reference in new issue
Block a user