summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2013-09-06 14:24:05 +0200
committerFlorent Le Coz <louiz@louiz.org>2013-09-06 14:24:05 +0200
commit4b662ffa6787ac81a62e28e5e23b859cc9ed68a9 (patch)
tree2110efd04c3dbee4c705c6eec74ae9688f9a4a42 /src
parent07ab1138a7f0598dd6ab9923ec876c5c24519e99 (diff)
downloadpoezio-4b662ffa6787ac81a62e28e5e23b859cc9ed68a9.tar.gz
poezio-4b662ffa6787ac81a62e28e5e23b859cc9ed68a9.tar.bz2
poezio-4b662ffa6787ac81a62e28e5e23b859cc9ed68a9.tar.xz
poezio-4b662ffa6787ac81a62e28e5e23b859cc9ed68a9.zip
Much more efficient and clean way to get the last n messages from history
Diffstat (limited to 'src')
-rw-r--r--src/logger.py44
1 files changed, 22 insertions, 22 deletions
diff --git a/src/logger.py b/src/logger.py
index f103bcd1..bee6fd79 100644
--- a/src/logger.py
+++ b/src/logger.py
@@ -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