Reimplement and optimize device.set

This commit is contained in:
Zaid Abdulla committed 2016-09-12 02:22:25 -07:00
1 parent f0b7fb3ec0
commit b7370a6fb9
2 files changed
+75 -83

No files matched your search

+2
View File
@@ -270,6 +270,8 @@ parsePath = (pattern, start, res) ->
addPathMeta = (path) ->
return path if path.alias? or path.wildcard?
path.alias = 0
path.wildcard = 0
+73 -83
View File
@@ -16,6 +16,8 @@
*/
"use strict";
const common = require('./common');
function sanitizeParameterValue(parameterValue) {
if (parameterValue[0] != null) {
@@ -62,6 +64,7 @@ function sanitizeParameterValue(parameterValue) {
function inferTimestamps(deviceData, path) {
common.addPathMeta(path);
var res = {};
for (let sup of deviceData.paths.superset(path)) {
@@ -73,7 +76,7 @@ function inferTimestamps(deviceData, path) {
}
for (let i = path.length - 1; i > 0; -- i) {
if (path.wildcard & ((2 << i) - 1) === 0)
if ((path.wildcard & ((1 << i) - 1)) == 0)
break;
let param = null;
@@ -235,8 +238,8 @@ function invalidateSuperset(deviceData, path, attributes) {
for (let attrName in deviceData.timestamps) {
let t = deviceData.timestamps[attrName].get(sup);
if (t <= attributes[attrName] || t <= attributes.exist) {
deviceData.timestamps[attrName].delete(sup);
deviceData.values[attrName].delete(sup);
deviceData.timestamps[attrName].delete(sup);
deviceData.values[attrName].delete(sup);
}
}
}
@@ -244,10 +247,6 @@ function invalidateSuperset(deviceData, path, attributes) {
function normalizeAttributes(timestamps, values) {
// TODO Consider moving implemention within set function
if (!values)
return;
if ('value' in values && timestamps.value >= (timestamps.object || 0)) {
values.object = 0;
timestamps.object = timestamps.value;
@@ -276,86 +275,82 @@ function normalizeAttributes(timestamps, values) {
function set(deviceData, path, timestamps, values) {
// TODO Optimize
// TODO Allow overwriting attribute value with same timestamp
if (values == null)
values = {};
path = deviceData.paths.add(path);
if (!path.wildcard) {
normalizeAttributes(timestamps, values);
if (values.exist && path.length > 1)
set(deviceData, path.slice(0, path.length - 1),
{exist: timestamps.exist, object: timestamps.exist},
{exist: 1, object: 1});
}
var current = inferTimestamps(deviceData, path);
for (let c in current)
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcard > 0))
delete timestamps[c];
if (timestamps.exist != null) {
deviceData.timestamps.exist.set(path, timestamps.exist);
if (values.exist != null)
deviceData.values.exist.set(path, values.exist);
}
current = inferTimestamps(deviceData, path);
for (let c in current)
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcard > 0))
delete timestamps[c];
if (path.wildcard || values == null)
values = {};
let toInvalidate = new Map();
for (let sub of deviceData.paths.subset(path, 0)) {
if (path.wildcard == sub.wildcard)
continue;
if (values.exist) {
normalizeAttributes(timestamps, values);
if (timestamps.exist && path.length > 1) {
set(deviceData, path.slice(0, path.length - 1),
{exist: timestamps.exist, object: timestamps.exist},
{exist: 1, object: 1});
}
for (let attrName in timestamps) {
if (deviceData.timestamps[attrName].get(sub) <= timestamps[attrName]) {
if (sub.wildcard || !deviceData.values[attrName].has(sub))
deviceData.timestamps[attrName].delete(sub);
else if (deviceData.timestamps[attrName].get(sub) < timestamps[attrName]) {
deviceData.timestamps[attrName].delete(sub);
deviceData.values[attrName].delete(sub);
let inv = toInvalidate.get(sub) || {};
if (!timestamps[attrName] <= inv[attrName]) {
inv[attrName] = timestamps[attrName];
toInvalidate.set(sub, inv);
}
}
if (deviceData.values[attrName].has(path) != (attrName in values)) {
let inv = toInvalidate.get(path);
if (inv == null)
toInvalidate.set(path, inv = {});
inv[attrName] = timestamps[attrName];
if (!(attrName in values))
deviceData.values[attrName].delete(path);
}
}
}
else {
// Clear redundant timestamps
let current = inferTimestamps(deviceData, path);
for (let c in timestamps)
if (timestamps[c] <= current[c])
delete timestamps[c];
else if (c != 'exist' &&
(timestamps[c] <= timestamps.exist || timestamps[c] <= current.exist))
delete timetamps[c];
for (let attrName in timestamps) {
let existing = deviceData.timestamps[attrName].get(path);
// Clear redundant subsets and deleted params
for (let sub of deviceData.paths.subset(path)) {
if (path.wildcard == sub.wildcard)
continue;
if (existing == null || timestamps[attrName] >= existing) {
deviceData.timestamps[attrName].set(path, timestamps[attrName]);
let invalidate = false;
if (values[attrName] != null) {
if (!deviceData.values[attrName].has(path))
invalidate = true;
deviceData.values[attrName].set(path, values[attrName]);
if (deviceData.values.exist.has(sub)) {
let existTimestamp = deviceData.timestamps.exist.get(sub);
for (let attrName in timestamps) {
if (timestamps[attrName] > existTimestamp) {
let inv = toInvalidate.get(sub);
if (inv == null)
toInvalidate.set(sub, inv = {});
for (let attrName in deviceData.timestamps) {
inv[attrName] = timestamps[attrName];
deviceData.timestamps[attrName].delete(sub);
deviceData.values[attrName].delete(sub);
}
break;
}
if (timestamps[attrName] > deviceData.timestamps[attrName].get(sub))
if (deviceData.values[attrName].has(sub)) {
let inv = toInvalidate.get(sub);
if (inv == null)
toInvalidate.set(sub, inv = {});
inv[attrName] = timestamps[attrName];
deviceData.values[attrName].delete(sub);
}
}
}
else {
if (deviceData.values[attrName].has(path)) {
invalidate = true;
deviceData.values[attrName].delete(path);
}
}
for (let attrName in timestamps) {
if (attrName == 'exist') {
for (let an in deviceData.timestamps)
if (timestamps[attrName] > deviceData.timestamps[an].get(sub))
deviceData.timestamps[an].delete(sub);
continue;
}
if (invalidate) {
let inv = toInvalidate.get(path) || {};
if (!(timestamps[attrName] <= inv[attrName])) {
inv[attrName] = timestamps[attrName];
toInvalidate.set(path, inv);
if (timestamps[attrName] > deviceData.timestamps[attrName].get(sub))
deviceData.timestamps[attrName].delete(sub);
}
}
}
@@ -365,16 +360,11 @@ function set(deviceData, path, timestamps, values) {
invalidateSuperset(deviceData, p, a);
});
// TODO recalculate descendant superset
// var depth = 0;
// if (timestamps.exist != null)
// depth = 99;
//
// for (let sup of deviceData.paths.superset(path, depth)) {
// if ((sup.wildcard && (3 << path.length) - 1) != path.wildcard) {
// throw new Error('Not implemented');
// }
// }
for (let attrName in timestamps) {
deviceData.timestamps[attrName].set(path, timestamps[attrName]);
if (attrName in values)
deviceData.values[attrName].set(path, values[attrName]);
}
}