Much more efficient and clean way to get the last n messages from history
This commit is contained in:
parent
07ab1138a7
commit
4b662ffa67
1 changed files with 22 additions and 22 deletions
|
@ -6,6 +6,7 @@
|
|||
# it under the terms of the zlib license. See the COPYING file.
|
||||
|
||||
from os import environ, makedirs
|
||||
import mmap
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
@ -89,7 +90,10 @@ class Logger(object):
|
|||
|
||||
def get_logs(self, jid, nb=10):
|
||||
"""
|
||||
Get the log history for the given jid
|
||||
Get the nb last messages from the log history for the given jid.
|
||||
Note that a message may be more than one line in these files, so
|
||||
this function is a little bit more complicated than “read the last
|
||||
nb lines”.
|
||||
"""
|
||||
if config.get_by_tabname('load_log', 10, jid) <= 0:
|
||||
return
|
||||
|
@ -112,31 +116,27 @@ class Logger(object):
|
|||
if not fd:
|
||||
return
|
||||
|
||||
pos = fd.seek(0, 2)
|
||||
reads = 0
|
||||
check_next = False
|
||||
while reads < nb:
|
||||
if pos == 0:
|
||||
break
|
||||
pos -= 1
|
||||
if pos < 0:
|
||||
pos = 0
|
||||
fd.seek(pos)
|
||||
char = fd.read(1)
|
||||
if char == b'\n':
|
||||
if fd.read(2) in (b'MR', b'MI'):
|
||||
reads += 1
|
||||
fd.seek(-2, 1)
|
||||
logs = fd.readlines()
|
||||
fd.close()
|
||||
lines = []
|
||||
|
||||
for line in logs:
|
||||
lines.append(line.decode(errors='replace')[:-1])
|
||||
# read the needed data from the file, we just search nb messages by
|
||||
# searching "\nM" nb times from the end of the file. We use mmap to
|
||||
# do that efficiently, instead of seek()s and read()s which are costly.
|
||||
with fd:
|
||||
m = mmap.mmap(fd.fileno(), 0, prot=mmap.PROT_READ)
|
||||
pos = m.rfind(b"\nM") # start of messages begin with MI or MR,
|
||||
# after a \n
|
||||
# number of message found so far
|
||||
count = 0
|
||||
while pos != -1 and count < nb-1:
|
||||
count += 1
|
||||
pos = m.rfind(b"\nM", 0, pos)
|
||||
if pos == -1: # If we don't have enough lines in the file
|
||||
pos = 1 # 1, because we do -1 just on the next line
|
||||
# to get 0 (start of the file)
|
||||
lines = m[pos-1:].decode(errors='replace').split("\n")[:-1]
|
||||
|
||||
messages = []
|
||||
color = '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
|
||||
|
||||
# now convert that data into actual Message objects
|
||||
idx = 0
|
||||
while idx < len(lines):
|
||||
if lines[idx].startswith(' '): # should not happen ; skip
|
||||
|
|
Loading…
Reference in a new issue