Better error handling
This commit is contained in:
parent
a559e92d3e
commit
c15681a51c
|
@ -5,6 +5,7 @@ import time
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
SECOND = 1
|
SECOND = 1
|
||||||
MINUTE = 60 * SECOND
|
MINUTE = 60 * SECOND
|
||||||
|
@ -154,7 +155,7 @@ def encode(state, directory):
|
||||||
|
|
||||||
|
|
||||||
def clean(state, directory):
|
def clean(state, directory):
|
||||||
os.removedirs(directory)
|
shutil.rmtree(directory)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import pprint
|
import pprint
|
||||||
|
|
|
@ -12,30 +12,22 @@ import re
|
||||||
import logging
|
import logging
|
||||||
import dvd
|
import dvd
|
||||||
import cd
|
import cd
|
||||||
import traceback
|
|
||||||
import worker
|
import worker
|
||||||
|
|
||||||
class Encoder(worker.Worker):
|
class Encoder(worker.Worker):
|
||||||
def __init__(self, directory=None):
|
def __init__(self, directory=None):
|
||||||
self.status = {}
|
self.status = {}
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
|
self.loop_delay = 12
|
||||||
return super().__init__(directory)
|
return super().__init__(directory)
|
||||||
|
|
||||||
def run(self):
|
def once(self):
|
||||||
while True:
|
wait = True
|
||||||
wait = True
|
self.status["type"] = "encoder"
|
||||||
self.status = {"type": "encoder", "state": "idle"}
|
for fn in glob.glob(self.workdir("*", "sucker.json")):
|
||||||
for fn in glob.glob(self.workdir("*", "sucker.json")):
|
directory = os.path.dirname(fn)
|
||||||
directory = os.path.dirname(fn)
|
state = self.read_state(directory)
|
||||||
state = self.read_state(directory)
|
self.encode(directory, state)
|
||||||
try:
|
|
||||||
self.encode(directory, state)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error("Error encoding %s: %s" % (directory, e))
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
wait = False
|
|
||||||
if wait:
|
|
||||||
time.sleep(12)
|
|
||||||
|
|
||||||
def encode(self, directory, state):
|
def encode(self, directory, state):
|
||||||
self.status["state"] = "encoding"
|
self.status["state"] = "encoding"
|
||||||
|
|
|
@ -5,7 +5,6 @@ import subprocess
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import fcntl
|
import fcntl
|
||||||
import traceback
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import slugify
|
import slugify
|
||||||
|
@ -29,58 +28,55 @@ CDS_DATA_2 = 102
|
||||||
CDROM_LOCKDOOR = 0x5329
|
CDROM_LOCKDOOR = 0x5329
|
||||||
CDROM_EJECT = 0x5309
|
CDROM_EJECT = 0x5309
|
||||||
|
|
||||||
|
SECOND = 1
|
||||||
|
MINUTE = 60 * SECOND
|
||||||
|
HOUR = 60 * MINUTE
|
||||||
|
|
||||||
class Reader(worker.Worker):
|
class Reader(worker.Worker):
|
||||||
def __init__(self, device, directory):
|
def __init__(self, device, directory):
|
||||||
super().__init__(directory)
|
super().__init__(directory)
|
||||||
self.device = device
|
self.device = device
|
||||||
self.status["type"] = "reader"
|
|
||||||
self.status["device"] = device
|
|
||||||
self.complete = 0
|
|
||||||
self.staleness = 0
|
self.staleness = 0
|
||||||
self.drive = None
|
self.drive = None
|
||||||
logging.info("Starting reader on %s" % self.device)
|
logging.info("Starting reader on %s" % self.device)
|
||||||
|
|
||||||
def reopen(self):
|
def reopen(self):
|
||||||
if (self.staleness > 15) or not self.drive:
|
if self.drive and (self.staleness < 15):
|
||||||
if self.drive:
|
|
||||||
os.close(self.drive)
|
|
||||||
self.drive = None
|
|
||||||
try:
|
|
||||||
self.drive = os.open(self.device, os.O_RDONLY | os.O_NONBLOCK)
|
|
||||||
logging.debug("Reopened %s" % self.device)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
self.staleness = 0
|
|
||||||
else:
|
|
||||||
self.staleness += 1
|
self.staleness += 1
|
||||||
|
return True
|
||||||
|
self.staleness = 0
|
||||||
|
if self.drive:
|
||||||
|
os.close(self.drive)
|
||||||
|
self.drive = None
|
||||||
|
try:
|
||||||
|
self.drive = os.open(self.device, os.O_RDONLY | os.O_NONBLOCK)
|
||||||
|
logging.debug("Reopened %s" % self.device)
|
||||||
|
return True
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False
|
||||||
|
|
||||||
def run(self):
|
def once(self):
|
||||||
while True:
|
self.status["type"] = "reader"
|
||||||
self.status["state"] = "idle"
|
self.status["device"] = self.device
|
||||||
self.reopen()
|
if not self.reopen():
|
||||||
if not self.drive:
|
time.sleep(10 * SECOND)
|
||||||
time.sleep(30)
|
return
|
||||||
continue
|
rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS)
|
||||||
rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS)
|
if rv == CDS_DISC_OK:
|
||||||
if rv == CDS_DISC_OK:
|
rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS)
|
||||||
rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS)
|
if rv == CDS_AUDIO:
|
||||||
try:
|
self.handle(False)
|
||||||
if rv == CDS_AUDIO:
|
elif rv in [CDS_DATA_1, CDS_DATA_2]:
|
||||||
self.handle(False)
|
self.handle(True)
|
||||||
elif rv in [CDS_DATA_1, CDS_DATA_2]:
|
|
||||||
self.handle(True)
|
|
||||||
else:
|
|
||||||
logging.info("Can't handle disc type %d" % rv)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error("Error in disc handler: %s" % e)
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
self.eject()
|
|
||||||
elif rv in (CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READ):
|
|
||||||
time.sleep(3)
|
|
||||||
else:
|
else:
|
||||||
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv]))
|
logging.info("Can't handle disc type %d" % rv)
|
||||||
time.sleep(3)
|
self.eject()
|
||||||
|
elif rv in (CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READ):
|
||||||
|
time.sleep(3 * SECOND)
|
||||||
|
else:
|
||||||
|
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv]))
|
||||||
|
time.sleep(3 * SECOND)
|
||||||
|
|
||||||
def eject(self):
|
def eject(self):
|
||||||
for i in range(20):
|
for i in range(20):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -10,14 +10,20 @@ import reader, encoder, statuser
|
||||||
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||||
def __init__(self, r, a, s, directory, statuser):
|
def __init__(self, r, a, s, directory, statuser):
|
||||||
self.statuser = statuser
|
self.statuser = statuser
|
||||||
|
self.quiet = False
|
||||||
super().__init__(r, a, s, directory=directory)
|
super().__init__(r, a, s, directory=directory)
|
||||||
|
|
||||||
|
def log_request(self, code="-", size="-"):
|
||||||
|
if not self.quiet:
|
||||||
|
super().log_request(code, size)
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
if self.path == "/status.json":
|
if self.path == "/status.json":
|
||||||
return self.get_status()
|
return self.get_status()
|
||||||
return super().do_GET()
|
return super().do_GET()
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
|
self.quiet = True
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
buf = self.statuser.json().encode("utf-8")
|
buf = self.statuser.json().encode("utf-8")
|
||||||
|
|
|
@ -2,17 +2,34 @@ import threading
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
SECOND = 1
|
||||||
|
MINUTE = 60 * SECOND
|
||||||
|
HOUR = 60 * MINUTE
|
||||||
|
|
||||||
class Worker(threading.Thread):
|
class Worker(threading.Thread):
|
||||||
def __init__(self, directory, **kwargs):
|
def __init__(self, directory, **kwargs):
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
self.status = {
|
self.loop_delay = 2 * SECOND
|
||||||
"state": "idle",
|
self.status = {}
|
||||||
}
|
|
||||||
|
|
||||||
kwargs["daemon"] = True
|
kwargs["daemon"] = True
|
||||||
return super().__init__(**kwargs)
|
return super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
self.status = {"state": "idle"}
|
||||||
|
try:
|
||||||
|
self.once()
|
||||||
|
except Exception as exc:
|
||||||
|
self.status["state"] = "error"
|
||||||
|
for line in traceback.format_exception(exc):
|
||||||
|
logging.error(line)
|
||||||
|
time.sleep(30 * SECOND)
|
||||||
|
time.sleep(self.loop_delay)
|
||||||
|
|
||||||
def workdir(self, *path):
|
def workdir(self, *path):
|
||||||
return os.path.join(self.directory, *path)
|
return os.path.join(self.directory, *path)
|
||||||
|
|
||||||
|
@ -25,8 +42,14 @@ class Worker(threading.Thread):
|
||||||
os.rename(newstatefn, statefn)
|
os.rename(newstatefn, statefn)
|
||||||
|
|
||||||
def read_state(self, subdir):
|
def read_state(self, subdir):
|
||||||
with open(self.workdir(subdir, "sucker.json")) as f:
|
try:
|
||||||
return json.load(f)
|
with open(self.workdir(subdir, "sucker.json")) as f:
|
||||||
|
return json.load(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {}
|
||||||
|
|
||||||
def clear_state(self, subdir):
|
def clear_state(self, subdir):
|
||||||
os.unlink(self.workdir(subdir, "sucker.json"))
|
try:
|
||||||
|
os.unlink(self.workdir(subdir, "sucker.json"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
Loading…
Reference in New Issue