hostile-takeover/syncerror/sync.py
2014-07-06 17:47:28 -07:00

130 lines
3.5 KiB
Python

import simplejson as json
import sys
import re
import os
# Uses a customized version of simplejson, because the dump json has entries
# with the same key, and the order of the keys is important. The customized
# version adds a counter to each key name, for uniqueness, and to recover
# order by sorting. Then at pretty print time, this is removed. Hacky but it
# works.
sys.path.insert(0, '.')
class Frame:
def __init__(self, d):
self.d = d
def GetHash(self):
keys = self.d.keys()
keys.sort()
for key in keys:
if key[13:] == 'hash':
return self.d[key]
return None
def GetUpdate(self):
keys = self.d.keys()
keys.sort()
for key in keys:
if key[13:] == 'updates':
return int(self.d[key])
return 0
def PrettyPrint(self):
# Example: "__00000000__-updates": "9951",
s = json.dumps(self.d, sort_keys=True, indent=4)
p = re.compile('^.*(?P<remove>__.*__-).*$')
lines = []
for line in s.splitlines():
line = line.rstrip()
m = p.match(line)
if not m:
lines.append(line)
else:
index = line.find(m.group('remove'))
line2 = line[0:index] + line[index+len(m.group('remove')):]
lines.append(line2)
return '\n'.join(lines)
class Dump:
def __init__(self, filename):
f = file(filename)
self.j = json.loads(f.read().rstrip('\x00'))
f.close()
def GetFrameNumbers(self):
numbers = []
keys = self.j.keys()
keys.sort()
for key in keys:
if key[13:].startswith('frame'):
numbers.append(int(key[18:]))
return numbers
def GetFrame(self, framenumber):
keys = self.j.keys()
keys.sort()
for key in keys:
if key[13:].startswith('frame'):
if framenumber == int(key[18:]):
return Frame(self.j[key])
return None
class Differ:
def __init__(self, file0, file1):
self.badupdate = -1
try:
dump0 = Dump(file0)
dump1 = Dump(file1)
for number in dump0.GetFrameNumbers():
frame0 = dump0.GetFrame(number)
frame1 = dump1.GetFrame(number)
if not frame0:
break
if not frame1:
break
if frame0.GetHash() != frame1.GetHash():
self.badupdate = frame0.GetUpdate()
self.frame0 = frame0
self.frame1 = frame1
break
except:
print 'ERROR loading %s or %s' % (file0, file1)
def GetBadUpdateNumber(self):
return self.badupdate
def Diff(self, frame0file, frame1file, outfile):
f = file(frame0file, 'w')
f.write(self.frame0.PrettyPrint())
f.close()
f = file(frame1file, 'w')
f.write(self.frame1.PrettyPrint())
f.close()
os.system('diff %s %s > %s' % (frame0file, frame1file, outfile))
if __name__ == '__main__':
# Find the frame that is not matching
d = Differ(sys.argv[1], sys.argv[2])
out0 = '/tmp/foo'
if len(sys.argv) > 3:
out0 = sys.argv[3]
out1 = '/tmp/bar'
if len(sys.argv) > 4:
out1 = sys.argv[4]
d.Diff(out0, out1, '/tmp/diff')
f = file('/tmp/diff')
for line in f.read().splitlines():
print line
f.close()