1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-18 09:57:40 +03:00

Use watchdog module instead of polling for new log files.

Notify user at startup if client restart required.
This commit is contained in:
Jonathan Harris 2015-11-24 17:42:18 +00:00
parent 393ade32af
commit a94cf4cfd9
6 changed files with 63 additions and 27 deletions

View File

@ -155,12 +155,6 @@ class AppWindow:
if platform != 'linux2': # update_idletasks() doesn't allow for the menubar on Linux if platform != 'linux2': # update_idletasks() doesn't allow for the menubar on Linux
self.w.maxsize(-1, h) # Maximum height = initial height self.w.maxsize(-1, h) # Maximum height = initial height
# First run
if not config.get('username') or not config.get('password'):
prefs.PreferencesDialog(self.w, self.login)
else:
self.login()
# Load updater after UI creation (for WinSparkle) # Load updater after UI creation (for WinSparkle)
import update import update
self.updater = update.Updater(self.w) self.updater = update.Updater(self.w)
@ -176,6 +170,12 @@ class AppWindow:
monitor.enable_logging() monitor.enable_logging()
monitor.start(self.w) monitor.start(self.w)
# First run
if not config.get('username') or not config.get('password'):
prefs.PreferencesDialog(self.w, self.login)
else:
self.login()
# call after credentials have changed # call after credentials have changed
def login(self): def login(self):
self.status['text'] = _('Logging in...') self.status['text'] = _('Logging in...')
@ -201,6 +201,9 @@ class AppWindow:
except Exception as e: except Exception as e:
if __debug__: print_exc() if __debug__: print_exc()
self.status['text'] = unicode(e) self.status['text'] = unicode(e)
if not self.status['text'] and monitor.restart_required():
self.status['text'] = _('Re-start Elite: Dangerous for automatic log entries') # Status bar message on launch
self.cooldown() self.cooldown()
# callback after verification code # callback after verification code

View File

@ -139,6 +139,9 @@
/* Privacy setting. [prefs.py] */ /* Privacy setting. [prefs.py] */
"Pseudo-anonymized ID" = "Pseudo-anonymized ID"; "Pseudo-anonymized ID" = "Pseudo-anonymized ID";
/* Status bar message on launch. [EDMarketConnector.py] */
"Re-start Elite: Dangerous for automatic log entries" = "Re-start Elite: Dangerous for automatic log entries";
/* Output settings prompt. [prefs.py] */ /* Output settings prompt. [prefs.py] */
"Re-start Elite: Dangerous to use this feature" = "Re-start Elite: Dangerous to use this feature"; "Re-start Elite: Dangerous to use this feature" = "Re-start Elite: Dangerous to use this feature";

View File

@ -201,3 +201,6 @@
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Error: Can't get market data!" = "Erreur: Impossible d'obtenir les données du marché!"; "Error: Can't get market data!" = "Erreur: Impossible d'obtenir les données du marché!";
/* Status bar message on launch. [EDMarketConnector.py] */
"Re-start Elite: Dangerous for automatic log entries" = "Re-démarrer Elite: Dangereux pour les entrées de journal automatique";

View File

@ -197,7 +197,10 @@
"Automatically make a log entry on entering a system" = "Inserire automaticamente una log entry entrando in un sistema"; "Automatically make a log entry on entering a system" = "Inserire automaticamente una log entry entrando in un sistema";
/* Output settings prompt. [prefs.py] */ /* Output settings prompt. [prefs.py] */
"Re-start Elite: Dangerous to use this feature" = "Riavviare Elite:Dangerous per usare questa funzione"; "Re-start Elite: Dangerous to use this feature" = "Riavviare Elite: Dangerous per usare questa funzione";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Error: Can't get market data!" = "Errore: Non riesco a ottenere il market data!"; "Error: Can't get market data!" = "Errore: Non riesco a ottenere il market data!";
/* Status bar message on launch. [EDMarketConnector.py] */
"Re-start Elite: Dangerous for automatic log entries" = "Riavviare Elite: Dangerous per una log entry automatica";

View File

@ -192,3 +192,6 @@
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Sending data to EDSM..." = "Wysłanie danych do EDSM..."; "Sending data to EDSM..." = "Wysłanie danych do EDSM...";
/* Output settings prompt. [prefs.py] */
"Re-start Elite: Dangerous to use this feature" = "";

View File

@ -1,12 +1,16 @@
import atexit
import re import re
import threading import threading
from os import listdir, pardir, rename, unlink from os import listdir, pardir, rename, unlink
from os.path import exists, isdir, isfile, join from os.path import basename, exists, isdir, isfile, join
from platform import machine from platform import machine
from sys import platform from sys import platform
from time import strptime, localtime, mktime, sleep, time from time import strptime, localtime, mktime, sleep, time
from datetime import datetime from datetime import datetime
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
if __debug__: if __debug__:
from traceback import print_exc from traceback import print_exc
@ -60,15 +64,29 @@ elif platform=='win32':
return True return True
class EDLogs: class EDLogs(FileSystemEventHandler):
def __init__(self): def __init__(self):
FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog
self.root = None self.root = None
self.logdir = self._logdir() self.logdir = self._logdir()
self.logfile = None
self.logging_enabled = self._logging_enabled self.logging_enabled = self._logging_enabled
self._restart_required = False self._restart_required = False
self.observer = None self.thread = None
self.last_event = None self.last_event = None # for communicating the Jump event
if self.logdir:
# Set up a watchog observer. This is low overhead so is left running irrespective of whether monitoring is desired.
observer = Observer()
observer.daemon = True
observer.schedule(self, self.logdir)
observer.start()
atexit.register(observer.stop)
# Latest pre-existing logfile - e.g. if E:D is already running. Assumes logs sort alphabetically.
logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')])
self.logfile = logfiles and join(self.logdir, logfiles[-1]) or None
def enable_logging(self): def enable_logging(self):
if self.logging_enabled(): if self.logging_enabled():
@ -137,17 +155,22 @@ class EDLogs:
return False return False
if self.running(): if self.running():
return True return True
self.observer = threading.Thread(target = self.worker, name = 'netLog worker') self.thread = threading.Thread(target = self.worker, name = 'netLog worker')
self.observer.daemon = True self.thread.daemon = True
self.observer.start() self.thread.start()
return True return True
def stop(self): def stop(self):
self.observer = None # Orphan the worker thread self.thread = None # Orphan the worker thread
self.last_event = None self.last_event = None
def running(self): def running(self):
return self.observer and self.observer.is_alive() return self.thread and self.thread.is_alive()
def on_created(self, event):
# watchdog callback, e.g. client (re)started.
if not event.is_directory and basename(event.src_path).startswith('netLog.'):
self.logfile = event.src_path
def worker(self): def worker(self):
# e.g. "{18:11:44} System:22(Gamma Doradus) Body:3 Pos:(3.69928e+07,1.13173e+09,-1.75892e+08) \r\n". # e.g. "{18:11:44} System:22(Gamma Doradus) Body:3 Pos:(3.69928e+07,1.13173e+09,-1.75892e+08) \r\n".
@ -155,27 +178,21 @@ class EDLogs:
regexp = re.compile(r'\{(.+)\} System:\d+\((.+)\) Body:') regexp = re.compile(r'\{(.+)\} System:\d+\((.+)\) Body:')
# Seek to the end of the latest log file # Seek to the end of the latest log file
logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')]) logfile = self.logfile
logfile = logfiles and logfiles[-1] or None
if logfile: if logfile:
loghandle = open(join(self.logdir, logfile), 'rt') loghandle = open(logfile, 'rt')
loghandle.seek(0, 2) # seek to EOF loghandle.seek(0, 2) # seek to EOF
else: else:
loghandle = None loghandle = None
while True: while True:
# Check whether we're still supposed to be running # Check whether new log file started, e.g. client (re)started.
if threading.current_thread() != self.observer: newlogfile = self.logfile
return # Terminate
# Check whether new log file started, e.g. client restarted. Assumes logs sort alphabetically.
logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')])
newlogfile = logfiles and logfiles[-1] or None
if logfile != newlogfile: if logfile != newlogfile:
logfile = newlogfile logfile = newlogfile
if loghandle: if loghandle:
loghandle.close() loghandle.close()
loghandle = open(join(self.logdir, logfile), 'rt') loghandle = open(logfile, 'rt')
if logfile: if logfile:
system = visited = None system = visited = None
@ -201,6 +218,10 @@ class EDLogs:
sleep(10) # New system gets posted to log file before hyperspace ends, so don't need to poll too often sleep(10) # New system gets posted to log file before hyperspace ends, so don't need to poll too often
# Check whether we're still supposed to be running
if threading.current_thread() != self.thread:
return # Terminate
if platform=='darwin': if platform=='darwin':