mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
if this is wrong i blame suzubrah for playing entirely too hype music at 6am in the fkn morning
improve shares/session-db smoketests and error semantics
This commit is contained in:
parent
e3043004ba
commit
8e0364efad
|
@ -73,6 +73,9 @@ from .util import (
|
||||||
ub64enc,
|
ub64enc,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if HAVE_SQLITE3:
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
try:
|
try:
|
||||||
from .mdns import MDNS
|
from .mdns import MDNS
|
||||||
|
@ -84,6 +87,10 @@ if PY2:
|
||||||
range = xrange # type: ignore
|
range = xrange # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
VER_SESSION_DB = 1
|
||||||
|
VER_SHARES_DB = 2
|
||||||
|
|
||||||
|
|
||||||
class SvcHub(object):
|
class SvcHub(object):
|
||||||
"""
|
"""
|
||||||
Hosts all services which cannot be parallelized due to reliance on monolithic resources.
|
Hosts all services which cannot be parallelized due to reliance on monolithic resources.
|
||||||
|
@ -406,25 +413,44 @@ class SvcHub(object):
|
||||||
self.log("root", t, 3)
|
self.log("root", t, 3)
|
||||||
return
|
return
|
||||||
|
|
||||||
import sqlite3
|
assert sqlite3 # type: ignore # !rm
|
||||||
|
|
||||||
|
# policy:
|
||||||
|
# the sessions-db is whatever, if something looks broken then just nuke it
|
||||||
|
|
||||||
create = True
|
|
||||||
db_path = self.args.ses_db
|
db_path = self.args.ses_db
|
||||||
self.log("root", "opening sessions-db %s" % (db_path,))
|
try:
|
||||||
for n in range(2):
|
create = not os.path.getsize(db_path)
|
||||||
|
except:
|
||||||
|
create = True
|
||||||
|
zs = "creating new" if create else "opening"
|
||||||
|
self.log("root", "%s sessions-db %s" % (zs, db_path))
|
||||||
|
|
||||||
|
for tries in range(2):
|
||||||
|
sver = 0
|
||||||
try:
|
try:
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
try:
|
try:
|
||||||
|
zs = "select v from kv where k='sver'"
|
||||||
|
sver = cur.execute(zs).fetchall()[0][0]
|
||||||
|
if sver > VER_SESSION_DB:
|
||||||
|
zs = "this version of copyparty only understands session-db v%d and older; the db is v%d"
|
||||||
|
raise Exception(zs % (VER_SESSION_DB, sver))
|
||||||
|
|
||||||
cur.execute("select count(*) from us").fetchone()
|
cur.execute("select count(*) from us").fetchone()
|
||||||
create = False
|
|
||||||
break
|
|
||||||
except:
|
except:
|
||||||
pass
|
if sver:
|
||||||
|
raise
|
||||||
|
sver = 1
|
||||||
|
self._create_session_db(cur)
|
||||||
|
self._verify_session_db(cur, sver)
|
||||||
|
break
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
if n:
|
if tries or sver > VER_SESSION_DB:
|
||||||
raise
|
raise
|
||||||
t = "sessions-db corrupt; deleting and recreating: %r"
|
t = "sessions-db is unusable; deleting and recreating: %r"
|
||||||
self.log("root", t % (ex,), 3)
|
self.log("root", t % (ex,), 3)
|
||||||
try:
|
try:
|
||||||
cur.close() # type: ignore
|
cur.close() # type: ignore
|
||||||
|
@ -436,6 +462,7 @@ class SvcHub(object):
|
||||||
pass
|
pass
|
||||||
os.unlink(db_path)
|
os.unlink(db_path)
|
||||||
|
|
||||||
|
def _create_session_db(self, cur: "sqlite3.Cursor") -> None:
|
||||||
sch = [
|
sch = [
|
||||||
r"create table kv (k text, v int)",
|
r"create table kv (k text, v int)",
|
||||||
r"create table us (un text, si text, t0 int)",
|
r"create table us (un text, si text, t0 int)",
|
||||||
|
@ -445,15 +472,37 @@ class SvcHub(object):
|
||||||
r"create index us_t0 on us(t0)",
|
r"create index us_t0 on us(t0)",
|
||||||
r"insert into kv values ('sver', 1)",
|
r"insert into kv values ('sver', 1)",
|
||||||
]
|
]
|
||||||
|
for cmd in sch:
|
||||||
|
cur.execute(cmd)
|
||||||
|
self.log("root", "created new sessions-db")
|
||||||
|
|
||||||
assert db # type: ignore # !rm
|
def _verify_session_db(self, cur: "sqlite3.Cursor", sver: int) -> None:
|
||||||
assert cur # type: ignore # !rm
|
# ensure writable (maybe owned by other user)
|
||||||
if create:
|
db = cur.connection
|
||||||
for cmd in sch:
|
|
||||||
cur.execute(cmd)
|
|
||||||
self.log("root", "created new sessions-db")
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
zil = cur.execute("select v from kv where k='pid'").fetchall()
|
||||||
|
if len(zil) > 1:
|
||||||
|
raise Exception()
|
||||||
|
owner = zil[0][0]
|
||||||
|
except:
|
||||||
|
owner = 0
|
||||||
|
|
||||||
|
vars = (("pid", os.getpid()), ("ts", int(time.time() * 1000)))
|
||||||
|
if owner:
|
||||||
|
# wear-estimate: 2 cells; offsets 0x10, 0x50, 0x19720
|
||||||
|
for k, v in vars:
|
||||||
|
cur.execute("update kv set v=? where k=?", (v, k))
|
||||||
|
else:
|
||||||
|
# wear-estimate: 3~4 cells; offsets 0x10, 0x50, 0x19180, 0x19710, 0x36000, 0x360b0, 0x36b90
|
||||||
|
for k, v in vars:
|
||||||
|
cur.execute("insert into kv values(?, ?)", (k, v))
|
||||||
|
|
||||||
|
if sver < VER_SESSION_DB:
|
||||||
|
cur.execute("delete from kv where k='sver'")
|
||||||
|
cur.execute("insert into kv values('sver',?)", (VER_SESSION_DB,))
|
||||||
|
|
||||||
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
@ -475,34 +524,41 @@ class SvcHub(object):
|
||||||
al.shr = "/%s/" % (al.shr,)
|
al.shr = "/%s/" % (al.shr,)
|
||||||
al.shr1 = al.shr[1:]
|
al.shr1 = al.shr[1:]
|
||||||
|
|
||||||
create = True
|
# policy:
|
||||||
modified = False
|
# the shares-db is important, so panic if something is wrong
|
||||||
|
|
||||||
db_path = self.args.shr_db
|
db_path = self.args.shr_db
|
||||||
self.log("root", "opening shares-db %s" % (db_path,))
|
try:
|
||||||
for n in range(2):
|
create = not os.path.getsize(db_path)
|
||||||
try:
|
except:
|
||||||
db = sqlite3.connect(db_path)
|
create = True
|
||||||
cur = db.cursor()
|
zs = "creating new" if create else "opening"
|
||||||
try:
|
self.log("root", "%s shares-db %s" % (zs, db_path))
|
||||||
cur.execute("select count(*) from sh").fetchone()
|
|
||||||
create = False
|
sver = 0
|
||||||
break
|
try:
|
||||||
except:
|
db = sqlite3.connect(db_path)
|
||||||
pass
|
cur = db.cursor()
|
||||||
except Exception as ex:
|
if not create:
|
||||||
if n:
|
zs = "select v from kv where k='sver'"
|
||||||
raise
|
sver = cur.execute(zs).fetchall()[0][0]
|
||||||
t = "shares-db corrupt; deleting and recreating: %r"
|
if sver > VER_SHARES_DB:
|
||||||
self.log("root", t % (ex,), 3)
|
zs = "this version of copyparty only understands shares-db v%d and older; the db is v%d"
|
||||||
try:
|
raise Exception(zs % (VER_SHARES_DB, sver))
|
||||||
cur.close() # type: ignore
|
|
||||||
except:
|
cur.execute("select count(*) from sh").fetchone()
|
||||||
pass
|
except Exception as ex:
|
||||||
try:
|
t = "could not open shares-db; will now panic...\nthe following database must be repaired or deleted before you can launch copyparty:\n%s\n\nERROR: %s\n\nadditional details:\n%s\n"
|
||||||
db.close() # type: ignore
|
self.log("root", t % (db_path, ex, min_ex()), 1)
|
||||||
except:
|
raise
|
||||||
pass
|
|
||||||
os.unlink(db_path)
|
try:
|
||||||
|
zil = cur.execute("select v from kv where k='pid'").fetchall()
|
||||||
|
if len(zil) > 1:
|
||||||
|
raise Exception()
|
||||||
|
owner = zil[0][0]
|
||||||
|
except:
|
||||||
|
owner = 0
|
||||||
|
|
||||||
sch1 = [
|
sch1 = [
|
||||||
r"create table kv (k text, v int)",
|
r"create table kv (k text, v int)",
|
||||||
|
@ -514,34 +570,37 @@ class SvcHub(object):
|
||||||
r"create index sf_k on sf(k)",
|
r"create index sf_k on sf(k)",
|
||||||
r"create index sh_k on sh(k)",
|
r"create index sh_k on sh(k)",
|
||||||
r"create index sh_t1 on sh(t1)",
|
r"create index sh_t1 on sh(t1)",
|
||||||
|
r"insert into kv values ('sver', 2)",
|
||||||
]
|
]
|
||||||
|
|
||||||
assert db # type: ignore # !rm
|
assert db # type: ignore # !rm
|
||||||
assert cur # type: ignore # !rm
|
assert cur # type: ignore # !rm
|
||||||
if create:
|
if not sver:
|
||||||
dver = 2
|
sver = VER_SHARES_DB
|
||||||
modified = True
|
|
||||||
for cmd in sch1 + sch2:
|
for cmd in sch1 + sch2:
|
||||||
cur.execute(cmd)
|
cur.execute(cmd)
|
||||||
self.log("root", "created new shares-db")
|
self.log("root", "created new shares-db")
|
||||||
else:
|
|
||||||
(dver,) = cur.execute("select v from kv where k = 'sver'").fetchall()[0]
|
|
||||||
|
|
||||||
if dver == 1:
|
if sver == 1:
|
||||||
modified = True
|
|
||||||
for cmd in sch2:
|
for cmd in sch2:
|
||||||
cur.execute(cmd)
|
cur.execute(cmd)
|
||||||
cur.execute("update sh set st = 0")
|
cur.execute("update sh set st = 0")
|
||||||
self.log("root", "shares-db schema upgrade ok")
|
self.log("root", "shares-db schema upgrade ok")
|
||||||
|
|
||||||
if modified:
|
if sver < VER_SHARES_DB:
|
||||||
for cmd in [
|
cur.execute("delete from kv where k='sver'")
|
||||||
r"delete from kv where k = 'sver'",
|
cur.execute("insert into kv values('sver',?)", (VER_SHARES_DB,))
|
||||||
r"insert into kv values ('sver', %d)" % (2,),
|
|
||||||
]:
|
|
||||||
cur.execute(cmd)
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
|
vars = (("pid", os.getpid()), ("ts", int(time.time() * 1000)))
|
||||||
|
if owner:
|
||||||
|
# wear-estimate: same as sessions-db
|
||||||
|
for k, v in vars:
|
||||||
|
cur.execute("update kv set v=? where k=?", (v, k))
|
||||||
|
else:
|
||||||
|
for k, v in vars:
|
||||||
|
cur.execute("insert into kv values(?, ?)", (k, v))
|
||||||
|
|
||||||
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue