Improve paramter set and load routines

This commit is contained in:
Zaid Abdulla committed 2016-09-21 17:26:21 -07:00
1 parent de1a62b481
commit 739d215a92
4 files changed
+282 -225

No files matched your search

+1
View File
@@ -49,6 +49,7 @@ options = {
SESSION_TIMEOUT : {type : 'int', default : 30}, SESSION_TIMEOUT : {type : 'int', default : 30},
GET_PARAMETER_NAMES_DEPTH_THRESHOLD : {type : 'int', default : 0}, GET_PARAMETER_NAMES_DEPTH_THRESHOLD : {type : 'int', default : 0},
TASK_PARAMETERS_BATCH_SIZE : {type : 'int', default : 32}, TASK_PARAMETERS_BATCH_SIZE : {type : 'int', default : 32},
MAX_DEPTH : {type: 'int', default : 16},
COOKIES_PATH : {type : 'string'}, COOKIES_PATH : {type : 'string'},
# Libxml related configuration # Libxml related configuration
+83 -79
View File
@@ -126,94 +126,98 @@ optimizeProjection = (obj) ->
fetchDevice = (id, timestamp, patterns, callback) -> fetchDevice = (id, timestamp, patterns, callback) ->
MAX_DEPTH = config.get('MAX_DEPTH', id)
res = [] res = []
loaded = [] loaded = []
# Build projection # Build projection
projection = {_id: 1} projection = {_id: 1}
for pattern in patterns for [pattern, depth] in patterns
loaded.push([pattern, 1]) loaded.push([pattern, depth])
if pattern.length == 0 if depth & 1 and (pattern.length < 1 or pattern[0] == '*')
projection['_timestamp'] = 1
else if pattern[0] == '*'
projection[''] = 1 projection[''] = 1
else if pattern[0] == 'Events'
if pattern.length == 1
res.push([['Events'],
{exist: timestamp, object: timestamp, writable: timestamp},
{exist: 1, object: 1, writable: 0}])
else if pattern.length == 2
if pattern[1] == '*'
projection['_registered'] = 1
projection['_lastInform'] = 1
projection['_lastBootstrap'] = 1
projection['_lastBoot'] = 1
res.push([['Events', '*'], {exist: timestamp}])
else if pattern[1] == 'Registered'
projection['_registered'] = 1
else if pattern[1] == 'Inform'
projection['_lastInform'] = 1
else if pattern[1] == '0_BOOTSTRAP'
projection['_lastBootstrap'] = 1
else if pattern[1] == '1_BOOT'
projection['_lastBoot'] = 1
else if pattern[0] == 'DeviceID'
if pattern.length == 1
res.push([['DeviceID'],
{exist: timestamp, object: timestamp, writable: timestamp},
{exist: 1, object: 1, writable: 0}])
else if pattern.length == 2 if depth & 1 and (pattern.length < 1 or pattern[0] == '*' or pattern[0] == 'Events')
if pattern[1] == '*' res.push([['Events'],
projection['_id'] = 1 {exist: timestamp, object: timestamp, writable: timestamp},
projection['_deviceId._Manufacturer'] = 1 {exist: 1, object: 1, writable: 0}])
projection['_deviceId._ProductClass'] = 1
projection['_deviceId._SerialNumber'] = 1
projection['_deviceId._OUI'] = 1
res.push([['DeviceID', '*'], {exist: timestamp}])
else if pattern[1] == 'ID' if depth & 2 and (pattern.length < 2 or pattern[0] == '*' or pattern[0] == 'Events')
projection['_id'] = 1 if not pattern[1]? or pattern[1] == '*'
else if pattern[1] == 'Manufacturer' projection['_registered'] = 1
projection['_deviceId._Manufacturer'] = 1 projection['_lastInform'] = 1
else if pattern[1] == 'ProductClass' projection['_lastBootstrap'] = 1
projection['_deviceId._ProductClass'] = 1 projection['_lastBoot'] = 1
else if pattern[1] == 'OUI' res.push([['Events', '*'], {exist: timestamp}])
projection['_deviceId._OUI'] = 1 else if pattern[1] == 'Registered'
else if pattern[1] == 'SerialNumber' projection['_registered'] = 1
projection['_deviceId._SerialNumber'] = 1 else if pattern[1] == 'Inform'
else if pattern[0] == 'Tags' projection['_lastInform'] = 1
if pattern.length == 1 else if pattern[1] == '0_BOOTSTRAP'
res.push([['Tags'], projection['_lastBootstrap'] = 1
{exist: timestamp, object: timestamp, writable: timestamp}, else if pattern[1] == '1_BOOT'
{exist: 1, object: 1, writable: 0}]) projection['_lastBoot'] = 1
else if pattern.length == 2 if depth & 1 and (pattern.length < 1 or pattern[0] == '*' or pattern[0] == 'DeviceID')
res.push([['Tags', '*'], {exist: timestamp}]) res.push([['DeviceID'],
projection['_tags'] = 1 {exist: timestamp, object: timestamp, writable: timestamp},
else {exist: 1, object: 1, writable: 0}])
wildcardIndex = pattern.indexOf('*')
if wildcardIndex == -1 if depth & 2 and (pattern.length < 2 or pattern[0] == '*' or pattern[0] == 'DeviceID')
s = pattern.join('.') if not pattern[1]? or pattern[1] == '*'
projection["#{s}._value"] = 1 projection['_id'] = 1
projection["#{s}._timestamp"] = 1 projection['_deviceId._Manufacturer'] = 1
projection["#{s}._type"] = 1 projection['_deviceId._ProductClass'] = 1
projection["#{s}._writable"] = 1 projection['_deviceId._SerialNumber'] = 1
projection["#{s}._object"] = 1 projection['_deviceId._OUI'] = 1
projection["#{s}._orig"] = 1 res.push([['DeviceID', '*'], {exist: timestamp}])
else if pattern[1] == 'ID'
projection['_id'] = 1
else if pattern[1] == 'Manufacturer'
projection['_deviceId._Manufacturer'] = 1
else if pattern[1] == 'ProductClass'
projection['_deviceId._ProductClass'] = 1
else if pattern[1] == 'OUI'
projection['_deviceId._OUI'] = 1
else if pattern[1] == 'SerialNumber'
projection['_deviceId._SerialNumber'] = 1
# Timestamp from parent is needed for writable timestamp if depth & 1 and (pattern.length < 1 or pattern[0] == '*' or pattern[0] == 'Tags')
if pattern.length <= 1 res.push([['Tags'],
projection['_timestamp'] = 1 {exist: timestamp, object: timestamp, writable: timestamp},
else {exist: 1, object: 1, writable: 0}])
projection["#{pattern.slice(0, -1).join('.')}._timestamp"] = 1
else if depth & 2 and (pattern.length < 1 or pattern[0] == '*' or pattern[0] == 'Tags')
p = pattern.slice(0, wildcardIndex) res.push([['Tags', '*'], {exist: timestamp}])
loaded.push([p, 99]) projection['_tags'] = 1
s = p.join('.')
projection[s] = 1 if pattern[0] not in ['Tags', 'Events', 'DeviceID']
projection[pattern.slice(0, wildcardIndex - 1).concat('_timestamp').join('.')] = 1 i = 0
while (1 << i) <= depth
if pattern.length <= i or pattern[i] == '*'
p = pattern.slice(0, i)
loaded.push([p, ((1 << p.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
s = p.join('.')
projection[s] = 1
projection[pattern.slice(0, i - 1).concat('_timestamp').join('.')] = 1
break
if depth & (1 << i)
s = pattern.slice(0, i + 1).join('.')
projection["#{s}._value"] = 1
projection["#{s}._timestamp"] = 1
projection["#{s}._orig"] = 1
projection["#{s}._type"] = 1
projection["#{s}._writable"] = 1
projection["#{s}._object"] = 1
# Timestamp from parent is needed for writable timestamp
if i <= 1
projection['_timestamp'] = 1
else
projection["#{pattern.slice(0, i).join('.')}._timestamp"] = 1
++ i
if projection[''] if projection['']
projection = {} projection = {}
@@ -253,8 +257,8 @@ fetchDevice = (id, timestamp, patterns, callback) ->
t.exist = Math.max(t.exist || 0, t.object) t.exist = Math.max(t.exist || 0, t.object)
v.exist = 1 v.exist = 1
if not obj['_object'] if not descendantsFetched and v.object == 0
loaded.push([path, 99]) loaded.push([path, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
res.push([path, t, v]) res.push([path, t, v])
+102 -85
View File
@@ -226,26 +226,6 @@ function unpack(deviceData, path, revision) {
} }
function invalidateSuperset(deviceData, path, attributes) {
let depth = 0;
if (attributes.exist != null)
depth = 99;
for (let sup of deviceData.paths.superset(path, 99)) {
if (sup.wildcard == path.wildcard && sup.length == path.length)
continue;
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);
}
}
}
}
function normalizeAttributes(timestamps, values) { function normalizeAttributes(timestamps, values) {
if ('value' in values && timestamps.value >= (timestamps.object || 0)) { if ('value' in values && timestamps.value >= (timestamps.object || 0)) {
values.object = 0; values.object = 0;
@@ -274,97 +254,132 @@ function normalizeAttributes(timestamps, values) {
} }
function set(deviceData, path, timestamps, values) { function clear(deviceData, path, timestamps, toClear) {
if (!toClear)
toClear = new Map();
// Clear redundant subsets and deleted params
for (let sub of deviceData.paths.subset(path)) {
if (path.wildcard == sub.wildcard)
continue;
if (deviceData.values.exist.has(sub)) {
let existTimestamp = deviceData.timestamps.exist.get(sub);
for (let attrName in timestamps) {
if (timestamps[attrName] > existTimestamp) {
let inv = toClear.get(sub);
if (inv == null)
toClear.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 = toClear.get(sub);
if (inv == null)
toClear.set(sub, inv = {});
inv[attrName] = timestamps[attrName];
deviceData.values[attrName].delete(sub);
}
deviceData.timestamps[attrName].set(sub, timestamps[attrName]);
}
}
}
else {
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 (timestamps[attrName] > deviceData.timestamps[attrName].get(sub))
deviceData.timestamps[attrName].delete(sub);
}
}
}
return toClear;
}
function clearSupersets(deviceData, path, timestamps) {
let depth = 0;
if (timestamps.exist != null)
depth = 99;
for (let sup of deviceData.paths.superset(path, 99)) {
if (sup.wildcard == path.wildcard && sup.length == path.length)
continue;
for (let attrName in deviceData.timestamps) {
let t = deviceData.timestamps[attrName].get(sup);
if (t <= timestamps[attrName] || t <= timestamps.exist) {
deviceData.timestamps[attrName].delete(sup);
deviceData.values[attrName].delete(sup);
}
}
}
}
function set(deviceData, path, timestamps, values, toClear) {
path = deviceData.paths.add(path); path = deviceData.paths.add(path);
if (path.wildcard || values == null) if (path.wildcard || values == null)
values = {}; values = {};
let toInvalidate = new Map();
if (values.exist) { if (values.exist) {
normalizeAttributes(timestamps, values); normalizeAttributes(timestamps, values);
if (timestamps.exist && path.length > 1) { if (timestamps.exist && path.length > 1)
set(deviceData, path.slice(0, path.length - 1), toClear = set(deviceData, path.slice(0, path.length - 1),
{exist: timestamps.exist, object: timestamps.exist}, {exist: timestamps.exist, object: timestamps.exist},
{exist: 1, object: 1}); {exist: 1, object: 1},
} toClear);
else if (!toClear)
toClear = new Map();
// Clear attribute patterns
for (let attrName in timestamps) { for (let attrName in timestamps) {
if (deviceData.values[attrName].has(path) != (attrName in values)) { if (deviceData.values[attrName].has(path) != (attrName in values)) {
let inv = toInvalidate.get(path); let inv = toClear.get(path);
if (inv == null) if (inv == null)
toInvalidate.set(path, inv = {}); toClear.set(path, inv = {});
inv[attrName] = timestamps[attrName]; inv[attrName] = timestamps[attrName];
if (!(attrName in values)) if (!(attrName in values))
deviceData.values[attrName].delete(path); 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];
// Clear redundant subsets and deleted params for (let attrName in timestamps) {
for (let sub of deviceData.paths.subset(path)) { deviceData.timestamps[attrName].set(path, timestamps[attrName]);
if (path.wildcard == sub.wildcard) if (attrName in values)
continue; 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 {
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 (timestamps[attrName] > deviceData.timestamps[attrName].get(sub))
deviceData.timestamps[attrName].delete(sub);
}
}
} }
return toClear;
} }
toInvalidate.forEach(function(a, p) { // Clear redundant timestamps
invalidateSuperset(deviceData, p, a); 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) { for (let attrName in timestamps) {
deviceData.timestamps[attrName].set(path, timestamps[attrName]); deviceData.timestamps[attrName].set(path, timestamps[attrName]);
if (attrName in values) if (attrName in values)
deviceData.values[attrName].set(path, values[attrName]); deviceData.values[attrName].set(path, values[attrName]);
} }
return clear(deviceData, path, timestamps, toClear);
} }
@@ -373,3 +388,5 @@ exports.getAliasDeclarations = getAliasDeclarations;
exports.inferTimestamps = inferTimestamps; exports.inferTimestamps = inferTimestamps;
exports.unpack = unpack; exports.unpack = unpack;
exports.set = set; exports.set = set;
exports.clear = clear;
exports.clearSupersets = clearSupersets
+96 -61
View File
@@ -77,7 +77,7 @@ loadParameters = (sessionData, callback) ->
if not parameters? if not parameters?
# Device not available in database, mark as new # Device not available in database, mark as new
sessionData.new = true sessionData.new = true
loaded = [[[], 99]] loaded = [[[], (1 << config.get('MAX_DEPTH', sessionData.deviceId)) - 1]]
parameters = [ parameters = [
[['DeviceID', '*'], {exist: sessionData.timestamp}], [['DeviceID', '*'], {exist: sessionData.timestamp}],
[['Events', '*'], {exist: sessionData.timestamp}] [['Events', '*'], {exist: sessionData.timestamp}]
@@ -89,19 +89,17 @@ loadParameters = (sessionData, callback) ->
path = sessionData.deviceData.paths.add(p[0]) path = sessionData.deviceData.paths.add(p[0])
if p[1] if p[1]
l = sessionData.deviceData.loaded.get(path) || 0 l = sessionData.deviceData.loaded.get(path) | 0
sessionData.deviceData.loaded.set(path, Math.max(l, p[1])) sessionData.deviceData.loaded.set(path, l | p[1])
if path.length <= 2 and path.length + p[1] > 2 if p[1] & 2 and (path.length < 1 or path[0] == '*' or path[0] == 'VirtualParameters')
if path.length < 1 or path[0] == '*' or path[0] == 'VirtualParameters' if path.length < 2 or path[1] == '*'
if path.length < 2 or path[1] == '*' vparams['*'] = 1
vparams['*'] = 1 else
else vparams[path[1]] = 1
vparams[path[1]] = 1
if path.length <= 1 and path.length + p[1] > 1 if p[1] & 1 and (path.length < 1 or path[0] == '*' or path[0] == 'VirtualParameters')
if path.length < 1 or path[0] == '*' or path[0] == 'VirtualParameters' vparams[''] = 1
vparams[''] = 1
for p in parameters for p in parameters
path = sessionData.deviceData.paths.add(p[0]) path = sessionData.deviceData.paths.add(p[0])
@@ -112,32 +110,37 @@ loadParameters = (sessionData, callback) ->
for k, v of p[2] for k, v of p[2]
sessionData.deviceData.values[k].set(path, v, 0) sessionData.deviceData.values[k].set(path, v, 0)
toClear = null
# Virtual parameters # Virtual parameters
if vparams[''] if vparams['']
device.set(sessionData.deviceData, ['VirtualParameters'], toClear = device.set(sessionData.deviceData, ['VirtualParameters'],
{exist: sessionData.timestamp, object: sessionData.timestamp, writable: sessionData.timestamp}, {exist: sessionData.timestamp, object: sessionData.timestamp, writable: sessionData.timestamp},
{exist: 1, object: 1, writable: 0}) {exist: 1, object: 1, writable: 0},
toClear)
delete vparams[''] delete vparams['']
if vparams['*'] if vparams['*']
for k, v of sessionData.cache.virtualParameters for k, v of sessionData.cache.virtualParameters
device.set(sessionData.deviceData, ['VirtualParameters', k], toClear = device.set(sessionData.deviceData, ['VirtualParameters', k],
{exist: sessionData.timestamp, object: sessionData.timestamp}, {exist: sessionData.timestamp, object: sessionData.timestamp},
{exist: 1, object: 0}) {exist: 1, object: 0},
toClear)
device.set(sessionData.deviceData, ['VirtualParameters', '*'], toClear = device.set(sessionData.deviceData, ['VirtualParameters', '*'],
{exist: sessionData.timestamp}) {exist: sessionData.timestamp}, toClear)
else else
for k of vparams for k of vparams
if k of sessionData.cache.virtualParameters if k of sessionData.cache.virtualParameters
device.set(sessionData.deviceData, ['VirtualParameters', k] toClear = device.set(sessionData.deviceData, ['VirtualParameters', k]
{exist: sessionData.timestamp, object: sessionData.timestamp}, {exist: sessionData.timestamp, object: sessionData.timestamp},
{exist: 1, object: 0}) {exist: 1, object: 0},
toClear)
else else
device.set(sessionData.deviceData, ['VirtualParameters', k], {exist: sessionData.timestamp}) toClear = device.set(sessionData.deviceData, ['VirtualParameters', k], {exist: sessionData.timestamp}, toClear)
delete sessionData.toLoad delete sessionData.toLoad
return callback()
return clear(sessionData, toClear, callback)
) )
@@ -192,10 +195,13 @@ inform = (sessionData, rpcReq, callback) ->
v.revision = 1 for k, v of sessionData.deviceData.timestamps v.revision = 1 for k, v of sessionData.deviceData.timestamps
v.revision = 1 for k, v of sessionData.deviceData.values v.revision = 1 for k, v of sessionData.deviceData.values
toClear = null
for p in params for p in params
device.set(sessionData.deviceData, p[0], p[1], p[2]) toClear = device.set(sessionData.deviceData, p[0], p[1], p[2], toClear)
return callback(null, {type : 'InformResponse'}) clear(sessionData, toClear, (err) ->
return callback(err, {type : 'InformResponse'})
)
) )
@@ -323,11 +329,14 @@ runVirtualParameters = (sessionData, provisions, startRevision, endRevision, cal
return runVirtualParameters(sessionData, provisions, startRevision, endRevision, callback) return runVirtualParameters(sessionData, provisions, startRevision, endRevision, callback)
) )
toClear = null
if virtualParameterUpdates.length == provisions.length if virtualParameterUpdates.length == provisions.length
for vpu, i in virtualParameterUpdates for vpu, i in virtualParameterUpdates
commitVirtualParameter(sessionData, vpu[0], provisions[i][1], vpu[1]) toClear = commitVirtualParameter(sessionData, vpu[0], provisions[i][1], vpu[1], toClear)
return callback(null, done, decs) clear(sessionData, toClear, (err) ->
return callback(err, done, decs)
)
runDeclarations = (sessionData, declarations, callback) -> runDeclarations = (sessionData, declarations, callback) ->
@@ -865,29 +874,27 @@ processDeclaration = (sessionData, path, _timestamps, values) ->
return ret return ret
loadPath = (sessionData, path) -> loadPath = (sessionData, path, depth) ->
return true if sessionData.new return true if sessionData.new
tl = [] depth ?= (1 << path.length) - 1
for i in [path.length...0] by -1
p = path.slice(0, i) # Trim trailing wildcards
loaded = 0 trimWildcard = path.length
iter = sessionData.deviceData.paths.superset(p) -- trimWildcard while trimWildcard and path[trimWildcard - 1] != '*'
path = path.slice(0, trimWildcard) if trimWildcard < path.length
for i in [0..path.length] by 1
iter = sessionData.deviceData.paths.superset(path.slice(0, i))
while sup = iter.next().value while sup = iter.next().value
if (l = sessionData.deviceData.loaded.get(sup)) > loaded v = sessionData.deviceData.loaded.get(sup)
loaded = l depth &= depth ^ sessionData.deviceData.loaded.get(sup)
if loaded return true if depth == 0
tl = tl.slice(0, tl.length - (loaded - 1))
break
tl.push(p)
if not tl.length
return true
sessionData.toLoad ?= [] sessionData.toLoad ?= []
sessionData.toLoad = sessionData.toLoad.concat(tl) sessionData.toLoad.push([path, depth])
return false return false
@@ -991,7 +998,27 @@ applyDeclaration = (sessionData, path, timestamps, values) ->
return true return true
commitVirtualParameter = (sessionData, name, declaration, update) -> clear = (sessionData, toClear, callback) ->
return callback() if not toClear?.size
MAX_DEPTH = config.get('MAX_DEPTH', sessionData.deviceId)
toClear.forEach((t, p) ->
if t.exist?
loadPath(sessionData, p, ((1 << p.length) - 1) ^ (1 << MAX_DEPTH) - 1)
else
loadPath(sessionData, p, 1 << (p.length - 1))
)
loadParameters(sessionData, (err) ->
return callback(err) if err
toClear.forEach((t, p) ->
device.clearSupersets(sessionData.deviceData, p, t)
)
return callback()
)
commitVirtualParameter = (sessionData, name, declaration, update, toClear) ->
t = {} t = {}
v = {} v = {}
if update.writable? if update.writable?
@@ -1020,7 +1047,7 @@ commitVirtualParameter = (sessionData, name, declaration, update) ->
else if declaration.timestamps.value? else if declaration.timestamps.value?
throw new Error('Virtual parameter must provide declared attributes') throw new Error('Virtual parameter must provide declared attributes')
device.set(sessionData.deviceData, ['VirtualParameters', name], t, v) return device.set(sessionData.deviceData, ['VirtualParameters', name], t, v, toClear)
runExtensions = (sessionData, revision, _extensions, callback) -> runExtensions = (sessionData, revision, _extensions, callback) ->
@@ -1093,14 +1120,17 @@ rpcResponse = (sessionData, id, rpcRes, callback) ->
v.revision = revision for k, v of sessionData.deviceData.timestamps v.revision = revision for k, v of sessionData.deviceData.timestamps
v.revision = revision for k, v of sessionData.deviceData.values v.revision = revision for k, v of sessionData.deviceData.values
toClear = null
switch rpcRes.type switch rpcRes.type
when 'GetParameterValuesResponse' when 'GetParameterValuesResponse'
return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'GetParameterValues' return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'GetParameterValues'
for p in rpcRes.parameterList for p in rpcRes.parameterList
device.set(sessionData.deviceData, common.parsePath(p[0]), toClear = device.set(sessionData.deviceData, common.parsePath(p[0]),
{exist: timestamp, object: timestamp, value: timestamp}, {exist: timestamp, object: timestamp, value: timestamp},
{exist: 1, object: 0, value: p.slice(1)}) {exist: 1, object: 0, value: p.slice(1)},
toClear)
when 'GetParameterNamesResponse' when 'GetParameterNamesResponse'
return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'GetParameterNames' return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'GetParameterNames'
@@ -1137,16 +1167,18 @@ rpcResponse = (sessionData, id, rpcRes, callback) ->
return al - bl return al - bl
) )
for p in params if rpcReq.nextLevel
loadPath(sessionData, p[0]) loadPath(sessionData, root, (1 << (root.length + 1)) - 1)
else
loadPath(sessionData, root, (1 << config.get('MAX_DEPTH', sessionData.deviceId) - 1))
loadParameters(sessionData, (err) -> loadParameters(sessionData, (err) ->
return callback(err) if err return callback(err) if err
for p in params for p in params
device.set(sessionData.deviceData, p[0], p[1], p[2]) toClear = device.set(sessionData.deviceData, p[0], p[1], p[2], toClear)
return callback() clear(sessionData, toClear, callback)
) )
return return
@@ -1154,33 +1186,36 @@ rpcResponse = (sessionData, id, rpcRes, callback) ->
return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'SetParameterValues' return callback(new Error('Response type does not match request type')) if rpcReq.type isnt 'SetParameterValues'
for p in rpcReq.parameterList for p in rpcReq.parameterList
device.set(sessionData.deviceData, common.parsePath(p[0]), toClear = device.set(sessionData.deviceData, common.parsePath(p[0]),
{exist: timestamp, object: timestamp, writable: timestamp, value: timestamp}, {exist: timestamp, object: timestamp, writable: timestamp, value: timestamp},
{exist: 1, object: 0, writable: 1, value: p.slice(1)}) {exist: 1, object: 0, writable: 1, value: p.slice(1)}, toClear)
when 'AddObjectResponse' when 'AddObjectResponse'
device.set(sessionData.deviceData, common.parsePath(rpcReq.objectName + rpcRes.instanceNumber), toClear = device.set(sessionData.deviceData, common.parsePath(rpcReq.objectName + rpcRes.instanceNumber),
{exist: timestamp, object: timestamp}, {exist: timestamp, object: timestamp},
{exist: 1, object: 1}) {exist: 1, object: 1},
toClear)
when 'DeleteObjectResponse' when 'DeleteObjectResponse'
device.set(sessionData.deviceData, common.parsePath(rpcReq.objectName.slice(0, -1)), toClear = device.set(sessionData.deviceData, common.parsePath(rpcReq.objectName.slice(0, -1)),
{exist: timestamp}) {exist: timestamp}, toClear)
when 'RebootResponse' when 'RebootResponse'
device.set(sessionData.deviceData, common.parsePath('Reboot'), toClear = device.set(sessionData.deviceData, common.parsePath('Reboot'),
{exist: sessionData.timestamp, value: sessionData.timestamp}, {exist: sessionData.timestamp, value: sessionData.timestamp},
{exist: 1, value: [sessionData.timestamp, 'xsd:unsignedInt']}) {exist: 1, value: [sessionData.timestamp, 'xsd:unsignedInt']},
toClear)
when 'FactoryResetResponse' when 'FactoryResetResponse'
device.set(sessionData.deviceData, common.parsePath('FactoryReset'), toClear = device.set(sessionData.deviceData, common.parsePath('FactoryReset'),
{exist: sessionData.timestamp, value: sessionData.timestamp}, {exist: sessionData.timestamp, value: sessionData.timestamp},
{exist: 1, value: [sessionData.timestamp, 'xsd:unsignedInt']}) {exist: 1, value: [sessionData.timestamp, 'xsd:unsignedInt']},
toClear)
else else
return callback(new Error('Response type not recognized')) return callback(new Error('Response type not recognized'))
return callback() return clear(sessionData, toClear, callback)
rpcFault = (sessionData, id, faultResponse, callback) -> rpcFault = (sessionData, id, faultResponse, callback) ->