Further fixes related to the previous commit

This commit is contained in:
Zaid Abdulla committed 2017-06-30 03:55:50 -07:00
1 parent ec1360217b
commit 9dd6980da2
1 file changed
+62 -36
+62 -36
View File
@@ -142,15 +142,17 @@ fetchDevice = (id, timestamp, patterns, callback) ->
children = {}
for pat in pats
fragment = pat[0][path.length] or '*'
load = 0
if fragment == '*'
projection[path.join('.')] = 1
projection[path.join('.')] = 1 if pat[1] << path.length
return
projTree[fragment] ?= {}
if pat[1] & (1 << path.length)
projection[path.concat('_timestamp').join('.')] = 1
projection[path.concat('_object').join('.')] = 1
projection[path.concat('_instance').join('.')] = 1
projection[path.concat([fragment, '_timestamp']).join('.')] = 1
projection[path.concat([fragment, '_value']).join('.')] = 1
projection[path.concat([fragment, '_type']).join('.')] = 1
@@ -189,18 +191,20 @@ fetchDevice = (id, timestamp, patterns, callback) ->
projection['_lastBootstrap'] = 1
projection['_registered'] = 1
loaded.push([['Events'], ((1 << MAX_DEPTH) - 1)])
if k == 'Events.Inform._writable' or k == 'Events.Inform'
else if k == 'Events.Inform._writable' or k == 'Events.Inform'
projection['_lastInform'] = 1
loaded.push([['Events', 'Inform'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'Events.1_BOOT._writable' or k == 'Events.1_BOOT'
else if k == 'Events.1_BOOT._writable' or k == 'Events.1_BOOT'
projection['_lastBoot'] = 1
loaded.push([['Events', '1_BOOT'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'Events.0_BOOTSTRAP._writable' or k == 'Events.0_BOOTSTRAP'
else if k == 'Events.0_BOOTSTRAP._writable' or k == 'Events.0_BOOTSTRAP'
projection['_lastBootstrap'] = 1
loaded.push([['Events', '0_BOOTSTRAP'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'Events.Registered._writable' or k == 'Events.Registered'
else if k == 'Events.Registered._writable' or k == 'Events.Registered'
projection['_registered'] = 1
loaded.push([['Events', 'Registered'], 1 ^ ((1 << MAX_DEPTH) - 1)])
else if k.endsWith('._writable') and k != 'Events._writable'
loaded.push([k.split('.').slice(0, 2), 1 ^ ((1 << MAX_DEPTH) - 1)])
delete projection[k] if k != ''
if k == '' or k == 'DeviceID' or k.startsWith('DeviceID.')
@@ -212,30 +216,37 @@ fetchDevice = (id, timestamp, patterns, callback) ->
projection['_id'] = 1
projection['_deviceId'] = 1
loaded.push([['DeviceID'], ((1 << MAX_DEPTH) - 1)])
if k == 'DeviceID.ID._writable' or k == 'DeviceID.ID'
else if k == 'DeviceID.ID._writable' or k == 'DeviceID.ID'
projection['_id'] = 1
loaded.push([['DeviceID', 'ID'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'DeviceID.Manufacturer._writable' or k == 'DeviceID.DeManufacturer'
else if k == 'DeviceID.Manufacturer._writable' or k == 'DeviceID.DeManufacturer'
projection['_deviceId._Manufacturer'] = 1
loaded.push([['DeviceID', 'Manufacturer'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'DeviceID.ProductClass._writable' or k == 'DeviceID.ProductClass'
else if k == 'DeviceID.ProductClass._writable' or k == 'DeviceID.ProductClass'
projection['_deviceId._ProductClass'] = 1
loaded.push([['DeviceID', 'ProductClass'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'DeviceID.OUI._writable' or k == 'DeviceID.OUI'
else if k == 'DeviceID.OUI._writable' or k == 'DeviceID.OUI'
projection['_deviceId._OUI'] = 1
loaded.push([['DeviceID', 'ProductClass'], 1 ^ ((1 << MAX_DEPTH) - 1)])
if k == 'DeviceID.SerialNumber._writable' or k == 'DeviceID.SerialNumber'
else if k == 'DeviceID.SerialNumber._writable' or k == 'DeviceID.SerialNumber'
projection['_deviceId._SerialNumber'] = 1
loaded.push([['DeviceID', 'SerialNumber'], 1 ^ ((1 << MAX_DEPTH) - 1)])
else if k.endsWith('._writable') and k != 'DeviceID._writable'
loaded.push([k.split('.').slice(0, 2), 1 ^ ((1 << MAX_DEPTH) - 1)])
delete projection[k] if k != ''
if k == 'Tags' or k.startsWith('Tags.')
if not projection['_tags']
projection['_tags'] = 1
loaded.push([['Tags'], ((1 << MAX_DEPTH) - 1)])
delete projection[k] if k != ''
delete projection[k]
proj = if projection[''] then {} else projection
if projection['']
proj = {}
else if Object.keys(projection).length == 0
proj = {'_id': 1}
else
proj = projection
devicesCollection.findOne({'_id' : id}, proj, (err, device) ->
return callback(err) if err or not device?
@@ -246,18 +257,27 @@ fetchDevice = (id, timestamp, patterns, callback) ->
else
if projection[path.join('.')]
descendantsFetched = true
loaded.push([path, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
if projection[path.concat('_writable').join('.')]
if path.length and projection[path.slice(0, -1).concat("_timestamp").join('.')]
thisFetched = true
loaded.push([path, ((1 << (path.length - 1)) - 1) ^ ((1 << MAX_DEPTH) - 1)])
else
loaded.push([path, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
else if projection[path.concat('_writable').join('.')]
loaded.push([path, 1 << (path.length - 1)])
thisFetched = true
if obj['_timestamp']?
obj['_timestamp'] = +obj['_timestamp']
# For compatibility with v1.0 database
if obj['_instance'] and not obj['_object']?
obj['_object'] = true
if thisFetched
attrs = {}
t = if obj['_timestamp'] > timestamp then obj['_timestamp'] else timestamp
t = obj['_timestamp'] or 1
t = timestamp if timestamp > t
if obj['_value']?
attrs.value = [obj['_timestamp'] or 1, [obj['_value'], obj['_type']]]
@@ -265,28 +285,28 @@ fetchDevice = (id, timestamp, patterns, callback) ->
obj['_object'] = false
if obj['_writable']?
attrs.writable = [timestamp, if obj['_writable'] then 1 else 0]
attrs.writable = [timestamp or 1, if obj['_writable'] then 1 else 0]
if obj['_object']? or obj['_instance']?
attrs.object = [t, if (obj['_object'] or obj['_instance']) then 1 else 0]
if obj['_object']?
attrs.object = [t, if obj['_object'] then 1 else 0]
res.push([path, t, attrs])
for k, v of obj
if k[0] != '_'
if not k.startsWith('_')
kk = k
obj['_object'] = true
storeParams(v, path.concat(k), obj['_timestamp'] or 1, descendantsFetched, projTree?[k])
storeParams(v, path.concat(k), obj['_timestamp'], descendantsFetched, projTree?[k])
delete projTree[kk] if projTree
if obj['_timestamp']
if descendantsFetched
res.push([path.concat('*'), obj['_timestamp']])
else
for k, v of projTree
p = path.concat(k)
if not descendantsFetched
for k, v of projTree
p = path.concat(k)
loaded.push([p, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
if (obj['_object'] or path.length == 0) and obj['_timestamp']
res.push([p, obj['_timestamp']])
loaded.push([p, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)])
else if (obj['_object'] or path.length == 0) and obj['_timestamp']
res.push([path.concat('*'), obj['_timestamp']])
for k, v of device
switch k
@@ -413,17 +433,17 @@ saveDevice = (deviceId, deviceData, isNew, callback) ->
continue
for attrName of diff[2]
if diff[2][attrName][1]? or diff[1]?[attrName]?[1]?
if diff[2][attrName][1]?
switch attrName
when 'value'
if not diff[1] or diff[2].value[1][0] != diff[1].value?[1][0]
if diff[2].value[1][0] != diff[1]?.value?[1]?[0]
if diff[2].value[1][1] == 'xsd:dateTime' and Number.isInteger(diff[2].value[1][0])
update['$set'][path.concat('_value').join('.')] = new Date(diff[2].value[1][0])
else
update['$set'][path.concat('_value').join('.')] = diff[2].value[1][0]
if not diff[1] or diff[2].value[1][1] != diff[1].value?[1][1]
if diff[2].value[1][1] != diff[1]?.value?[1]?[1]
update['$set'][path.concat('_type').join('.')] = diff[2].value[1][1]
if not diff[1] or diff[2].value[0] != diff[1].value?[0]
if diff[2].value[0] != diff[1]?.value?[0]
update['$set'][path.concat('_timestamp').join('.')] = new Date(diff[2].value[0])
when 'object'
if not diff[1]?.object or diff[2].object[1] != diff[1].object?[1]
@@ -434,12 +454,21 @@ saveDevice = (deviceId, deviceData, isNew, callback) ->
if diff[1]
for attrName of diff[1]
if attrName not of diff[2]
if diff[1][attrName][1]? and not diff[2]?[attrName]?[1]?
update['$unset'][path.concat("_#{attrName}").join('.')] = 1
if attrName is 'value'
update['$unset'][path.concat('_type').join('.')] = 1
update['$unset'][path.concat('_timestamp').join('.')] = 1
update['$unset'] = optimizeProjection(update['$unset'])
# Remove overlap possibly caused by parameters changing from objects
# to regular parameters or vice versa. Reason being that _timestamp
# represents two different things depending on whether the parameter
# is an object or not.
for k of update['$unset']
delete update['$unset'][k] if update['$set'][k]?
# Remove empty keys
for k of update
if k == '$addToSet'
@@ -452,9 +481,6 @@ saveDevice = (deviceId, deviceData, isNew, callback) ->
return callback() if Object.keys(update).length == 0
if (update['$unset']?)
update['$unset'] = optimizeProjection(update['$unset'])
if update['$addToSet'] and update['$pull']
# Mongo doesn't allow $addToSet and $pull at the same time
update2 = {'$pull': update['$pull']}