mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-24 10:30:22 +00:00
56fa13279e
RHEL8 will no longer tolerate implicit use of python. For now relent to being python2, though ideally one day it could be either. Unfortunately, this means once code is ready for python3, we have to probably implement build time changes for python3 enabled distros to have different shebangs than python2 distros.
200 lines
7.0 KiB
Python
200 lines
7.0 KiB
Python
#!/usr/bin/python2
|
|
import collections
|
|
import os
|
|
import struct
|
|
import sys
|
|
import time
|
|
import fcntl
|
|
import select
|
|
import termios
|
|
import tty
|
|
|
|
def writeout(data):
|
|
done = False
|
|
try:
|
|
sys.stdout.write(data)
|
|
done = True
|
|
except IOError:
|
|
time.sleep(0.1)
|
|
pass
|
|
|
|
|
|
class LogReplay(object):
|
|
def __init__(self, logfile, cblfile):
|
|
self.bin = open(cblfile, 'r')
|
|
self.txt = open(logfile, 'r')
|
|
self.cleardata = []
|
|
self.clearidx = 0
|
|
self.pendingdata = collections.deque([])
|
|
self.priordata = collections.deque([])
|
|
self.laststamp = None
|
|
self.needclear = False
|
|
|
|
def _rewind(self, datasize=None):
|
|
curroffset = self.bin.tell() - 16
|
|
if self.cleardata and self.clearidx > 1:
|
|
self.clearidx -= 1
|
|
priordata = self.cleardata[self.clearidx - 1]
|
|
return curroffset, priordata
|
|
self.cleardata = []
|
|
self.clearidx = 0
|
|
newoffset = curroffset - 32
|
|
if newoffset < 0: #TODO: Follow a log roll
|
|
newoffset = 0
|
|
if datasize:
|
|
while datasize > 0 and newoffset > 0:
|
|
self.bin.seek(newoffset)
|
|
tmprec = self.bin.read(16)
|
|
newoffset -= 32
|
|
tmprec = struct.unpack('!BBIHIBBH', tmprec)
|
|
if tmprec[1] == 2:
|
|
datasize -= tmprec[3]
|
|
if newoffset >= 0:
|
|
self.bin.seek(newoffset)
|
|
return curroffset, None
|
|
|
|
def debuginfo(self):
|
|
return '{0}, {1}'.format(self.bin.tell(), self.clearidx)
|
|
|
|
def get_output(self, reverse=False):
|
|
endoffset = None
|
|
output = ''
|
|
if reverse: # Forget the uncommited future, if present
|
|
output += '\x1b[2J\x1b[H'
|
|
endoffset, priordata = self._rewind(4096)
|
|
if priordata is not None:
|
|
return priordata, 1
|
|
elif self.needclear:
|
|
output += '\x1b[2J\x1b[H'
|
|
self.needclear = False
|
|
if self.cleardata and self.clearidx < len(self.cleardata):
|
|
datachunk = self.cleardata[self.clearidx]
|
|
self.clearidx += 1
|
|
return datachunk, 1
|
|
self.cleardata = []
|
|
self.clearidx = 0
|
|
while (not reverse) or (self.bin.tell() < endoffset):
|
|
record = self.bin.read(16)
|
|
if not record:
|
|
return '', 0
|
|
record = struct.unpack('!BBIHIBBH', record)
|
|
if record[0] > 16:
|
|
# Unsupported record, skip
|
|
self.bin.seek(record[0] - 16, 1)
|
|
continue
|
|
type = record[1]
|
|
offset = record[2]
|
|
size = record[3]
|
|
evtdata = record[5]
|
|
auxdata = record[6]
|
|
if type == 3:
|
|
#TODO: provide data for status bar
|
|
continue
|
|
elif type == 2:
|
|
self.laststamp = record[4]
|
|
self.txt.seek(offset)
|
|
txtout = self.txt.read(size)
|
|
if reverse and self.bin.tell() < endoffset:
|
|
output += txtout
|
|
continue
|
|
if '\x1b[2J' in txtout:
|
|
self.cleardata = txtout.split('\x1b[2J')
|
|
for idx in range(1, len(self.cleardata)):
|
|
self.cleardata[idx] = '\x1b[2J' + self.cleardata[idx]
|
|
self.clearidx = 0
|
|
if not self.cleardata[0]:
|
|
self.cleardata = self.cleardata[1:]
|
|
if self.cleardata:
|
|
if reverse:
|
|
output = self.cleardata[-1]
|
|
self.clearidx = len(self.cleardata)
|
|
else:
|
|
output += self.cleardata[0]
|
|
self.clearidx = 1
|
|
else:
|
|
output += txtout
|
|
break
|
|
if endoffset is not None and endoffset >= 0:
|
|
self.bin.seek(endoffset)
|
|
return output, 1
|
|
|
|
def begin(self):
|
|
self.needclear = True
|
|
self.bin.seek(0)
|
|
|
|
def end(self):
|
|
self.bin.seek(0, 2)
|
|
|
|
|
|
def main(txtfile, binfile):
|
|
replay = LogReplay(txtfile, binfile)
|
|
oldtcattr = termios.tcgetattr(sys.stdin.fileno())
|
|
tty.setraw(sys.stdin.fileno())
|
|
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
|
|
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl | os.O_NONBLOCK)
|
|
reverse = False
|
|
skipnext = False
|
|
quitit = False
|
|
writeout('\x1b[2J\x1b[;H')
|
|
try:
|
|
while not quitit:
|
|
if not skipnext:
|
|
newdata, delay = replay.get_output(reverse)
|
|
skipnext = False
|
|
reverse = False
|
|
if newdata:
|
|
writeout(newdata)
|
|
writeout('\x1b]0;[Time: {0}]\x07'.format(
|
|
time.strftime('%m/%d %H:%M:%S', time.localtime(replay.laststamp))))
|
|
sys.stdout.flush()
|
|
while True:
|
|
select.select((sys.stdin,), (), (), 86400)
|
|
myinput = sys.stdin.read()
|
|
if myinput.startswith('\x1b[C') or myinput.startswith('\x1bOC') or myinput == '\r': # right
|
|
break
|
|
elif myinput.startswith('\x1b[D') or myinput.startswith('\x1bOD') or myinput == 'y': # left
|
|
writeout('\x1b[2J\x1b[;H')
|
|
reverse = True
|
|
break
|
|
elif myinput == 'G' or myinput.startswith('\x1b[F'):
|
|
replay.end()
|
|
reverse = True
|
|
break
|
|
elif myinput == 'g' or myinput.startswith('\x1b[H'):
|
|
replay.begin()
|
|
break
|
|
elif myinput.lower() == 'q' or myinput == '\x03':
|
|
quitit = True
|
|
break
|
|
elif myinput.lower() == 'd':
|
|
writeout('\x1b];{0}\x07'.format(replay.debuginfo()))
|
|
sys.stdout.flush()
|
|
else:
|
|
pass # print(repr(myinput))
|
|
except Exception:
|
|
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
|
|
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl ^ os.O_NONBLOCK)
|
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
|
|
writeout('\x1b[m')
|
|
raise
|
|
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
|
|
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl ^ os.O_NONBLOCK)
|
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
|
|
writeout('\x1b[m')
|
|
|
|
if __name__ == '__main__':
|
|
txtfile = sys.argv[1]
|
|
if len(sys.argv) > 2:
|
|
binfile = sys.argv[2]
|
|
else:
|
|
if os.path.exists(txtfile + '.cbl'):
|
|
binfile = txtfile + '.cbl'
|
|
else:
|
|
fileparts = txtfile.split('.')
|
|
prefix = '.'.join(fileparts[:-1])
|
|
binfile = prefix + '.cbl.' + fileparts[-1]
|
|
if not os.path.exists(binfile):
|
|
sys.stderr.write('Unable to locate cbl file\n')
|
|
sys.exit(1)
|
|
main(txtfile, binfile)
|