mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
150 lines
5.4 KiB
Python
Executable file
150 lines
5.4 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
import argparse, re, sys
|
|
from os import path
|
|
from enum import IntEnum
|
|
"""Given 2-4 logs from the same game (likely created by discon_ok2.py),
|
|
track all the messages they send (or don't.)
|
|
|
|
Let's track by msg (checksum). For each, track when
|
|
|
|
"""
|
|
|
|
|
|
class Message():
|
|
def __init__(self, msgID, sum, msgLen):
|
|
self.msgID = msgID
|
|
self.sum = sum
|
|
self.len = msgLen
|
|
self.sends = []
|
|
self.receives = []
|
|
self.sender = None
|
|
self.receiver = None
|
|
|
|
def __repr__(self):
|
|
str = '{}: '.format(self.key())
|
|
str += ' {} => {}'.format(self.sender, self.receiver)
|
|
firstReceipt = self.receives and self.receives[0][0] or None
|
|
str += ' sent: {}; arrived: {}'.format(self.firstSendTime(), firstReceipt)
|
|
(nReceives, nDrops) = self.countReceives();
|
|
str += '; nSents: {}; nReceives: {}; nDrops: {}'.format(len(self.sends), \
|
|
nReceives, nDrops)
|
|
str += '; nLost: {}'.format(len(self.sends) - (len(self.receives)))
|
|
return str
|
|
|
|
def addSend(self, sender, ts):
|
|
if not self.sender:
|
|
self.sender = sender
|
|
else:
|
|
assert(self.sender == sender)
|
|
self.sends.append(ts)
|
|
|
|
def addReceive(self, receiver, ts, dropped):
|
|
if not self.receiver:
|
|
self.receiver = receiver
|
|
else:
|
|
assert(self.receiver == receiver)
|
|
self.receives.append((ts, dropped))
|
|
|
|
def pruneEarlySends(self):
|
|
firstReceipt = self.receives and self.receives[0][0] or None
|
|
if firstReceipt:
|
|
while 1 < len(self.sends) and self.sends[1] < firstReceipt:
|
|
# print('{} < {}: removing from {}'.format(self.sends[1], firstReceipt, self.key()))
|
|
self.sends.pop()
|
|
|
|
def firstSendTime(self):
|
|
return self.sends[0]
|
|
|
|
def countReceives(self):
|
|
nAccepts = nDrops = 0
|
|
for tup in self.receives:
|
|
if tup[1]: nDrops += 1
|
|
else: nAccepts += 1
|
|
return (nAccepts, nDrops)
|
|
|
|
def key(self):
|
|
return Message.mkKey(self.msgID, self.sum, self.len)
|
|
|
|
@staticmethod
|
|
def mkKey(id, sum, len):
|
|
return '{:02d}:{}.{:03d}'.format(int(id), sum, len)
|
|
|
|
def errExit(msg):
|
|
print(msg, file=sys.stderr)
|
|
sys.exit(-1)
|
|
|
|
def mkParser():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--logs', nargs = '*', dest = 'LOGS',
|
|
help = 'two or more logfiles to scan')
|
|
parser.add_argument('--skip-below', dest = 'SKIP_BELOW', default = 16,
|
|
help = 'ignore messages this length or below (acks?)')
|
|
parser.add_argument('--drop-part', dest = 'DROP_PART', default = '_LOG.txt',
|
|
help = 'remove this from filename to shorten')
|
|
|
|
return parser
|
|
|
|
def getMkMessage(msgs, msgID, len, sum):
|
|
key = Message.mkKey(msgID, sum, len)
|
|
msg = msgs.get(key)
|
|
if not msg:
|
|
msg = Message(msgID, sum, len)
|
|
msgs[key] = msg
|
|
return msg
|
|
|
|
# pull everything relevant out of logfile
|
|
|
|
# <16330:7fcf30445a80> 07:54:24:953 <> sendMsg(): sending message of len 135 on cno: 674C|1 with sum 8b8b58399159afdcd54a106d3546423f
|
|
# sSendRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*sending message of len (\d+) on cno: (.*) with sum (.*)')
|
|
|
|
# <18137:7f9b3c16ba80> 08:52:56:750 <> sendMsg(): sending message on cno: C824|1: id: 1; len: 135; sum: e2eb9c89ad6062e1a1d65e9da649957f
|
|
sSendRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*sending message on cno: (.*): id: (\d+); len: (\d+); sum: (.*)')
|
|
|
|
# <16327:7f54562f4a80> 07:54:25:359 <> comms_checkIncomingStream(): got message of len 135 with sum 8b8b58399159afdcd54a106d3546423f
|
|
# sReceiveRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*got message of len (\d+) with sum (.*)')
|
|
|
|
# <23256:7fafba33fa80> 11:53:48:976 ../common/comms.c:comms_msgProcessed(): id: 0; len: 14; sum: 56ba9311510efffe43729241fad1a9b6; rejected: true
|
|
sProcessedRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*comms_msgProcessed.*: id: (\d+); len: (\d+); sum: (.+); rejected: (.+)')
|
|
|
|
def parse(logfile, shortName, msgs, skipLen):
|
|
print('parse({})'.format(shortName))
|
|
with open(logfile, 'r') as log:
|
|
for line in log:
|
|
line = line.strip()
|
|
|
|
match = sSendRE.match(line)
|
|
if match:
|
|
msgLen = int(match.group(5))
|
|
if msgLen > skipLen:
|
|
msg = getMkMessage(msgs, match.group(4), msgLen, match.group(6))
|
|
msg.addSend(shortName, match.group(2))
|
|
|
|
match = sProcessedRE.match(line)
|
|
if match:
|
|
msgLen = int(match.group(4))
|
|
if msgLen > skipLen:
|
|
msgID = match.group(3)
|
|
msg = getMkMessage(msgs, msgID, msgLen, match.group(5))
|
|
rejected = match.group(6)
|
|
msg.addReceive(shortName, match.group(2), rejected=='true')
|
|
|
|
def main():
|
|
args = mkParser().parse_args()
|
|
|
|
msgs = {}
|
|
for log in args.LOGS:
|
|
if not path.exists(log): errExit('file {} not found'.format(log))
|
|
shortName = path.basename(log).replace(args.DROP_PART, '')
|
|
parse(log, shortName, msgs, args.SKIP_BELOW)
|
|
|
|
asArr = [msgs[key] for key in msgs]
|
|
asArr.sort(key = lambda msg: msg.firstSendTime())
|
|
for msg in asArr:
|
|
# msg.pruneEarlySends()
|
|
print(msg)
|
|
|
|
|
|
##############################################################################
|
|
if __name__ == '__main__':
|
|
main()
|