Implement path alias unpacking
This commit is contained in:
1 parent
788bd98c8c
commit
1537603945
7 files changed
+691
-541
No files matched your search
@@ -235,18 +235,22 @@ parseAlias = (pattern, start, res) ->
|
|||||||
|
|
||||||
parsePath = (pattern, start, res) ->
|
parsePath = (pattern, start, res) ->
|
||||||
path = []
|
path = []
|
||||||
|
path.wildcard = 0
|
||||||
|
path.alias = 0
|
||||||
i = start ? 0
|
i = start ? 0
|
||||||
|
|
||||||
# Colon separator is needed for parseAlias
|
# Colon separator is needed for parseAlias
|
||||||
if i < pattern.length and pattern[i] != ':'
|
if i < pattern.length and pattern[i] != ':'
|
||||||
while true
|
while true
|
||||||
if pattern[i] == '['
|
if pattern[i] == '['
|
||||||
|
path.alias |= 1 << path.length
|
||||||
i = parseAlias(pattern, i + 1, path) + 1
|
i = parseAlias(pattern, i + 1, path) + 1
|
||||||
else
|
else
|
||||||
j = i
|
j = i
|
||||||
while i < pattern.length and pattern[i] != ':' and pattern[i] != '.'
|
while i < pattern.length and pattern[i] != ':' and pattern[i] != '.'
|
||||||
++ i
|
++ i
|
||||||
n = pattern.slice(j, i)
|
n = pattern.slice(j, i)
|
||||||
|
path.wildcard |= 1 << path.length if n == '*'
|
||||||
path.push(n)
|
path.push(n)
|
||||||
|
|
||||||
if i >= pattern.length or pattern[i] == ':'
|
if i >= pattern.length or pattern[i] == ':'
|
||||||
@@ -256,6 +260,8 @@ parsePath = (pattern, start, res) ->
|
|||||||
|
|
||||||
++ i
|
++ i
|
||||||
|
|
||||||
|
Object.freeze(path)
|
||||||
|
|
||||||
if not res?
|
if not res?
|
||||||
return path
|
return path
|
||||||
|
|
||||||
@@ -263,6 +269,22 @@ parsePath = (pattern, start, res) ->
|
|||||||
return i
|
return i
|
||||||
|
|
||||||
|
|
||||||
|
addPathMeta = (path) ->
|
||||||
|
path.alias = 0
|
||||||
|
path.wildcard = 0
|
||||||
|
|
||||||
|
for p, i in path
|
||||||
|
if typeOf(p) is ARRAY_TYPE
|
||||||
|
path.alias |= 1 << i
|
||||||
|
for j in [0...p.length] by 2
|
||||||
|
addPathMeta(p[j])
|
||||||
|
else if p == '*'
|
||||||
|
path.wildcard |= 1 << i
|
||||||
|
|
||||||
|
Object.freeze(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
hammingWeight = (flags) ->
|
hammingWeight = (flags) ->
|
||||||
flags -= ((flags >> 1) & 0x55555555)
|
flags -= ((flags >> 1) & 0x55555555)
|
||||||
flags = (((flags >> 2) & 0x33333333) + (flags & 0x33333333))
|
flags = (((flags >> 2) & 0x33333333) + (flags & 0x33333333))
|
||||||
@@ -283,4 +305,5 @@ exports.REGEXP_TYPE = REGEXP_TYPE
|
|||||||
exports.typeOf = typeOf
|
exports.typeOf = typeOf
|
||||||
exports.pathOverlap = pathOverlap
|
exports.pathOverlap = pathOverlap
|
||||||
exports.parsePath = parsePath
|
exports.parsePath = parsePath
|
||||||
|
exports.addPathMeta = addPathMeta
|
||||||
exports.hammingWeight = hammingWeight
|
exports.hammingWeight = hammingWeight
|
||||||
+11
-6
@@ -127,8 +127,9 @@ applyPresets = (currentRequest) ->
|
|||||||
return sendRpcRequest(currentRequest, id, rpcRequest)
|
return sendRpcRequest(currentRequest, id, rpcRequest)
|
||||||
|
|
||||||
for k, v of parameters
|
for k, v of parameters
|
||||||
if (vv = device.getAll(currentRequest.sessionData.deviceData, v)[0]?[8]?[0])
|
unpacked = device.unpack(currentRequest.sessionData.deviceData, v)
|
||||||
parameters[k] = vv
|
if unpacked[0] and (vv = deviceData.values.value.get(unpacked[0]))?
|
||||||
|
parameters[k] = vv[0]
|
||||||
|
|
||||||
for p in presets
|
for p in presets
|
||||||
if query.test(parameters, p.precondition)
|
if query.test(parameters, p.precondition)
|
||||||
@@ -272,8 +273,9 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
return body
|
return body
|
||||||
|
|
||||||
stream.on('end', () ->
|
stream.on('end', () ->
|
||||||
getSession(httpRequest, (sessionId, sessionData) ->
|
cwmpRequest = null
|
||||||
cwmpRequest = soap.request(httpRequest, session?.cwmpVersion)
|
getSession(httpRequest, f = (sessionId, sessionData) ->
|
||||||
|
cwmpRequest ?= soap.request(httpRequest, sessionData?.cwmpVersion)
|
||||||
if not sessionData?
|
if not sessionData?
|
||||||
if cwmpRequest.methodRequest?.type isnt 'Inform'
|
if cwmpRequest.methodRequest?.type isnt 'Inform'
|
||||||
httpResponse.writeHead(400)
|
httpResponse.writeHead(400)
|
||||||
@@ -281,8 +283,11 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
return
|
return
|
||||||
|
|
||||||
deviceId = common.generateDeviceId(cwmpRequest.methodRequest.deviceId)
|
deviceId = common.generateDeviceId(cwmpRequest.methodRequest.deviceId)
|
||||||
sessionData = session.init(deviceId, cwmpRequest.cwmpVersion, cwmpRequest.sessionTimeout ? config.get('SESSION_TIMEOUT', deviceId))
|
return session.init(deviceId, cwmpRequest.cwmpVersion, cwmpRequest.sessionTimeout ? config.get('SESSION_TIMEOUT', deviceId), (err, sessionData) ->
|
||||||
httpRequest.connection.setTimeout(sessionData.timeout * 1000)
|
throw err if err
|
||||||
|
httpRequest.connection.setTimeout(sessionData.timeout * 1000)
|
||||||
|
f(null, sessionData)
|
||||||
|
)
|
||||||
|
|
||||||
currentRequest = {
|
currentRequest = {
|
||||||
httpRequest : httpRequest,
|
httpRequest : httpRequest,
|
||||||
|
|||||||
+1
-1
@@ -452,7 +452,7 @@ saveDevice = (deviceId, deviceData, isNew, callback) ->
|
|||||||
# Set object's children timestamps
|
# Set object's children timestamps
|
||||||
iter = deviceData.timestamps.exist.diff()
|
iter = deviceData.timestamps.exist.diff()
|
||||||
while not (diff = iter.next()).done
|
while not (diff = iter.next()).done
|
||||||
continue if diff.value[0].wildcards != (1 << (diff.value[0].length - 1))
|
continue if diff.value[0].wildcard != (1 << (diff.value[0].length - 1))
|
||||||
continue if diff.value[0][0] in ['Events', 'DeviceID', 'Tags']
|
continue if diff.value[0][0] in ['Events', 'DeviceID', 'Tags']
|
||||||
|
|
||||||
if not diff.value[2]? and diff.value[1]?
|
if not diff.value[2]? and diff.value[1]?
|
||||||
|
|||||||
+86
-17
@@ -61,12 +61,6 @@ function sanitizeParameterValue(parameterValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getAliasDeclarations(path) {
|
|
||||||
// TODO Return declarations necessary for unpacking aliases
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function inferTimestamps(deviceData, path) {
|
function inferTimestamps(deviceData, path) {
|
||||||
var res = {};
|
var res = {};
|
||||||
|
|
||||||
@@ -79,14 +73,14 @@ function inferTimestamps(deviceData, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = path.length - 1; i > 0; -- i) {
|
for (let i = path.length - 1; i > 0; -- i) {
|
||||||
if (path.wildcards & ((2 << i) - 1) === 0)
|
if (path.wildcard & ((2 << i) - 1) === 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
let param = null;
|
let param = null;
|
||||||
let ancestor = path.slice(0, i);
|
let ancestor = path.slice(0, i);
|
||||||
let ancestorTimestamp = 0;
|
let ancestorTimestamp = 0;
|
||||||
for (let sup of deviceData.paths.superset(ancestor)) {
|
for (let sup of deviceData.paths.superset(ancestor)) {
|
||||||
if (!sup.wildcards)
|
if (!sup.wildcard)
|
||||||
param = sup;
|
param = sup;
|
||||||
|
|
||||||
let t = deviceData.timestamps.exist.get(sup);
|
let t = deviceData.timestamps.exist.get(sup);
|
||||||
@@ -108,7 +102,7 @@ function inferTimestamps(deviceData, path) {
|
|||||||
newt[attrName] = ancestorTimestamp;
|
newt[attrName] = ancestorTimestamp;
|
||||||
|
|
||||||
for (let sub of deviceData.paths.subset(ancestor)) {
|
for (let sub of deviceData.paths.subset(ancestor)) {
|
||||||
if (sub.wildcards)
|
if (sub.wildcard)
|
||||||
continue;
|
continue;
|
||||||
let subt = inferTimestamps(deviceData, sub.concat(path.slice(sub.length, path.length)));
|
let subt = inferTimestamps(deviceData, sub.concat(path.slice(sub.length, path.length)));
|
||||||
for (let attrName in newt) {
|
for (let attrName in newt) {
|
||||||
@@ -128,9 +122,84 @@ function inferTimestamps(deviceData, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getAliasDeclarations(path, timestamp) {
|
||||||
|
var decs = [];
|
||||||
|
|
||||||
|
function recursive(pattern, prefix) {
|
||||||
|
var pattern = prefix.concat(pattern);
|
||||||
|
|
||||||
|
for (let i = prefix.length; i < pattern.length; ++ i) {
|
||||||
|
if (Array.isArray(pattern[i])) {
|
||||||
|
let pat = pattern[i];
|
||||||
|
pattern[i] = '*';
|
||||||
|
for (let j = 0; j < pat.length; j += 2)
|
||||||
|
recursive(pat[j], pattern.slice(0, i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix.length)
|
||||||
|
decs.push([pattern, {exist: timestamp, value: timestamp}]);
|
||||||
|
else
|
||||||
|
decs.push([pattern, {exist: timestamp}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive(path, []);
|
||||||
|
|
||||||
|
return decs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function unpack(deviceData, path, revision) {
|
function unpack(deviceData, path, revision) {
|
||||||
// TODO implement alias unpacking
|
let allMatches = [];
|
||||||
return [path];
|
if (path.alias == 0) {
|
||||||
|
for (let p of deviceData.paths.subset(path, 0))
|
||||||
|
if (deviceData.values.exist.get(p, revision))
|
||||||
|
allMatches.push(p);
|
||||||
|
return allMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wildcardPath = path.slice();
|
||||||
|
wildcardPath.wildcard = path.wildcard;
|
||||||
|
for (let i = 0; i < wildcardPath.length; ++ i)
|
||||||
|
if (Array.isArray(wildcardPath[i])) {
|
||||||
|
wildcardPath[i] = '*';
|
||||||
|
wildcardPath.wildcard |= 1 << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let p of deviceData.paths.subset(wildcardPath, 0))
|
||||||
|
if (deviceData.values.exist.get(p, revision))
|
||||||
|
allMatches.push(p);
|
||||||
|
|
||||||
|
for (let i = path.length - 1; i >= 0; -- i) {
|
||||||
|
if (Array.isArray(path[i])) {
|
||||||
|
for (let j = 0; j < path[i].length; j += 2) {
|
||||||
|
let p = wildcardPath.slice(0, i + 1).concat(path[i][j]);
|
||||||
|
p.alias = (wildcardPath.alias & ((1 << (i + 1)) - 1)) + path[i][j].alias << (i + 1);
|
||||||
|
p.wildcard = (wildcardPath.wildcard & ((1 << (i + 1)) - 1)) + path[i][j].wildcard << (i + 1);
|
||||||
|
let unpacked = unpack(deviceData, p, revision);
|
||||||
|
let filtered = [];
|
||||||
|
for (let up of unpacked) {
|
||||||
|
let v = deviceData.values.value.get(up, revision);
|
||||||
|
if (v && sanitizeParameterValue([path[i][j + 1], v[1]])[0] == v[0]) {
|
||||||
|
for (let m = 0; m < allMatches.length; ++ m) {
|
||||||
|
let k;
|
||||||
|
for (k = i; k >= 0; -- k)
|
||||||
|
if (allMatches[m][k] != up[k])
|
||||||
|
break
|
||||||
|
|
||||||
|
if (k < 0) {
|
||||||
|
filtered.push(allMatches[m]);
|
||||||
|
allMatches[m] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allMatches = filtered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allMatches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -176,7 +245,7 @@ function set(deviceData, path, timestamps, values) {
|
|||||||
// TODO Allow overwriting attribute value with same timestamp
|
// TODO Allow overwriting attribute value with same timestamp
|
||||||
path = deviceData.paths.add(path);
|
path = deviceData.paths.add(path);
|
||||||
|
|
||||||
if (!path.wildcards) {
|
if (!path.wildcard) {
|
||||||
normalizeAttributes(timestamps, values);
|
normalizeAttributes(timestamps, values);
|
||||||
if (values.exist && path.length > 1)
|
if (values.exist && path.length > 1)
|
||||||
set(deviceData, path.slice(0, path.length - 1),
|
set(deviceData, path.slice(0, path.length - 1),
|
||||||
@@ -187,7 +256,7 @@ function set(deviceData, path, timestamps, values) {
|
|||||||
var current = inferTimestamps(deviceData, path);
|
var current = inferTimestamps(deviceData, path);
|
||||||
|
|
||||||
for (let c in current)
|
for (let c in current)
|
||||||
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcards > 0))//!deviceData.values[c].has(path)))
|
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcard > 0))
|
||||||
delete timestamps[c];
|
delete timestamps[c];
|
||||||
|
|
||||||
if (timestamps.exist != null) {
|
if (timestamps.exist != null) {
|
||||||
@@ -199,19 +268,19 @@ function set(deviceData, path, timestamps, values) {
|
|||||||
current = inferTimestamps(deviceData, path);
|
current = inferTimestamps(deviceData, path);
|
||||||
|
|
||||||
for (let c in current)
|
for (let c in current)
|
||||||
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcards > 0))//!deviceData.values[c].has(path)))
|
if (current[c] > timestamps[c] || (current[c] == timestamps[c] && path.wildcard > 0))
|
||||||
delete timestamps[c];
|
delete timestamps[c];
|
||||||
|
|
||||||
let toInvalidate = new Map();
|
let toInvalidate = new Map();
|
||||||
|
|
||||||
for (let sub of deviceData.paths.subset(path, 0)) {
|
for (let sub of deviceData.paths.subset(path, 0)) {
|
||||||
if (path.wildcards == sub.wildcards)
|
if (path.wildcard == sub.wildcard)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (let attrName in timestamps) {
|
for (let attrName in timestamps) {
|
||||||
if (deviceData.timestamps[attrName].get(sub) <= timestamps[attrName]) {
|
if (deviceData.timestamps[attrName].get(sub) <= timestamps[attrName]) {
|
||||||
|
|
||||||
if (sub.wildcards || !deviceData.values[attrName].has(sub))
|
if (sub.wildcard || !deviceData.values[attrName].has(sub))
|
||||||
deviceData.timestamps[attrName].delete(sub);
|
deviceData.timestamps[attrName].delete(sub);
|
||||||
else if (deviceData.timestamps[attrName].get(sub) < timestamps[attrName]) {
|
else if (deviceData.timestamps[attrName].get(sub) < timestamps[attrName]) {
|
||||||
deviceData.timestamps[attrName].delete(sub);
|
deviceData.timestamps[attrName].delete(sub);
|
||||||
@@ -263,7 +332,7 @@ function set(deviceData, path, timestamps, values) {
|
|||||||
// depth = 99;
|
// depth = 99;
|
||||||
//
|
//
|
||||||
// for (let sup of deviceData.paths.superset(path, depth)) {
|
// for (let sup of deviceData.paths.superset(path, depth)) {
|
||||||
// if ((sup.wildcards && (3 << path.length) - 1) != path.wildcards) {
|
// if ((sup.wildcard && (3 << path.length) - 1) != path.wildcard) {
|
||||||
// throw new Error('Not implemented');
|
// throw new Error('Not implemented');
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
+5
-4
@@ -79,18 +79,19 @@ class PathSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var wildcards = 0;
|
var wildcard = 0;
|
||||||
this.lengthIndex[path.length].add(path);
|
this.lengthIndex[path.length].add(path);
|
||||||
for (let i = 0; i < path.length; ++ i) {
|
for (let i = 0; i < path.length; ++ i) {
|
||||||
let fragment = path[i];
|
let fragment = path[i];
|
||||||
if (fragment === '*')
|
if (fragment === '*')
|
||||||
wildcards |= 1 << i;
|
wildcard |= 1 << i;
|
||||||
|
|
||||||
this.fragmentIndex[i][fragment].add(path);
|
this.fragmentIndex[i][fragment].add(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.wildcards == null) {
|
if (path.wildcard == null) {
|
||||||
path.wildcards = wildcards;
|
path.alias = 0;
|
||||||
|
path.wildcard = wildcard;
|
||||||
Object.freeze(path);
|
Object.freeze(path);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
|||||||
+15
-14
@@ -83,23 +83,24 @@ sandbox.context.declare = (decs) ->
|
|||||||
res = {}
|
res = {}
|
||||||
for k, v of decs
|
for k, v of decs
|
||||||
path = common.parsePath(k)
|
path = common.parsePath(k)
|
||||||
|
single = true
|
||||||
|
for p in path
|
||||||
|
if p == '*' or common.typeOf(p) isnt common.STRING_TYPE
|
||||||
|
single = false
|
||||||
|
break
|
||||||
|
|
||||||
res[k] = {}
|
|
||||||
unpacked = device.unpack(sandbox.deviceData, path, sandbox.revision)
|
unpacked = device.unpack(sandbox.deviceData, path, sandbox.revision)
|
||||||
for path in unpacked
|
for param in unpacked
|
||||||
iter = sandbox.deviceData.paths.subset(path)
|
r = {}
|
||||||
while (param = iter.next().value)?
|
for attrName, dec of v
|
||||||
if param.wildcards == 0 and sandbox.deviceData.values.exist.get(param, sandbox.revision)
|
if (attrValue = sandbox.deviceData.values[attrName].get(param, sandbox.revision))?
|
||||||
r = {}
|
r[attrName] = [sandbox.deviceData.timestamps[attrName].get(param, sandbox.revision), attrValue]
|
||||||
for attrName, dec of v
|
|
||||||
if (attrValue = sandbox.deviceData.values[attrName].get(param, sandbox.revision))?
|
|
||||||
r[attrName] = [sandbox.deviceData.timestamps[attrName].get(param, sandbox.revision), attrValue]
|
|
||||||
|
|
||||||
p = param.join('.')
|
if single
|
||||||
if p == k
|
res[k] = r
|
||||||
res[k] = r
|
else
|
||||||
else
|
res[k] ?= {}
|
||||||
res[k][p] = r
|
res[k][param.join('.')] = r
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
+550
-499
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user