mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
IdP: async reload; closes #114
whenever a new idp user is registered, up2k will continuously reload in the background until all users have been processed just like before, this blocks up2k uploads from each user until said user makes it into a reload, but as of now, reloads will batch and execute without interrupting read-access needs further testing before next release, probably some rough edges to sand down
This commit is contained in:
parent
6a8d5e1731
commit
44ee07f0b2
|
@ -913,7 +913,7 @@ class AuthSrv(object):
|
||||||
self._reload()
|
self._reload()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
broker.ask("_reload_blocking", False).get()
|
broker.ask("reload", False, True).get()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _map_volume_idp(
|
def _map_volume_idp(
|
||||||
|
@ -2389,7 +2389,7 @@ class AuthSrv(object):
|
||||||
self._reload()
|
self._reload()
|
||||||
return True, "new password OK"
|
return True, "new password OK"
|
||||||
|
|
||||||
broker.ask("_reload_blocking", False, False).get()
|
broker.ask("reload", False, False).get()
|
||||||
return True, "new password OK"
|
return True, "new password OK"
|
||||||
|
|
||||||
def setup_chpw(self, acct: dict[str, str]) -> None:
|
def setup_chpw(self, acct: dict[str, str]) -> None:
|
||||||
|
|
|
@ -4591,7 +4591,7 @@ class HttpCli(object):
|
||||||
if self.args.no_reload:
|
if self.args.no_reload:
|
||||||
raise Pebkac(403, "the reload feature is disabled in server config")
|
raise Pebkac(403, "the reload feature is disabled in server config")
|
||||||
|
|
||||||
x = self.conn.hsrv.broker.ask("reload")
|
x = self.conn.hsrv.broker.ask("reload", True, True)
|
||||||
return self.redirect("", "?h", x.get(), "return to", False)
|
return self.redirect("", "?h", x.get(), "return to", False)
|
||||||
|
|
||||||
def tx_stack(self) -> bool:
|
def tx_stack(self) -> bool:
|
||||||
|
@ -4879,7 +4879,7 @@ class HttpCli(object):
|
||||||
|
|
||||||
cur.connection.commit()
|
cur.connection.commit()
|
||||||
if reload:
|
if reload:
|
||||||
self.conn.hsrv.broker.ask("_reload_blocking", False, False).get()
|
self.conn.hsrv.broker.ask("reload", False, False).get()
|
||||||
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
||||||
|
|
||||||
self.redirect(self.args.SRS + "?shares")
|
self.redirect(self.args.SRS + "?shares")
|
||||||
|
@ -4970,7 +4970,7 @@ class HttpCli(object):
|
||||||
cur.execute(q, (skey, fn))
|
cur.execute(q, (skey, fn))
|
||||||
|
|
||||||
cur.connection.commit()
|
cur.connection.commit()
|
||||||
self.conn.hsrv.broker.ask("_reload_blocking", False, False).get()
|
self.conn.hsrv.broker.ask("reload", False, False).get()
|
||||||
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
||||||
|
|
||||||
fn = quotep(fns[0]) if len(fns) == 1 else ""
|
fn = quotep(fns[0]) if len(fns) == 1 else ""
|
||||||
|
|
|
@ -112,7 +112,7 @@ class SvcHub(object):
|
||||||
self.stopping = False
|
self.stopping = False
|
||||||
self.stopped = False
|
self.stopped = False
|
||||||
self.reload_req = False
|
self.reload_req = False
|
||||||
self.reloading = 0
|
self.reload_mutex = threading.Lock()
|
||||||
self.stop_cond = threading.Condition()
|
self.stop_cond = threading.Condition()
|
||||||
self.nsigs = 3
|
self.nsigs = 3
|
||||||
self.retcode = 0
|
self.retcode = 0
|
||||||
|
@ -1004,20 +1004,8 @@ class SvcHub(object):
|
||||||
except:
|
except:
|
||||||
self.log("root", "ssdp startup failed;\n" + min_ex(), 3)
|
self.log("root", "ssdp startup failed;\n" + min_ex(), 3)
|
||||||
|
|
||||||
def reload(self) -> str:
|
def reload(self, rescan_all_vols: bool, up2k: bool) -> None:
|
||||||
with self.up2k.mutex:
|
with self.reload_mutex:
|
||||||
if self.reloading:
|
|
||||||
return "cannot reload; already in progress"
|
|
||||||
self.reloading = 1
|
|
||||||
|
|
||||||
Daemon(self._reload, "reloading")
|
|
||||||
return "reload initiated"
|
|
||||||
|
|
||||||
def _reload(self, rescan_all_vols: bool = True, up2k: bool = True) -> None:
|
|
||||||
with self.up2k.mutex:
|
|
||||||
if self.reloading != 1:
|
|
||||||
return
|
|
||||||
self.reloading = 2
|
|
||||||
self.log("root", "reloading config")
|
self.log("root", "reloading config")
|
||||||
self.asrv.reload(9 if up2k else 4)
|
self.asrv.reload(9 if up2k else 4)
|
||||||
if up2k:
|
if up2k:
|
||||||
|
@ -1025,20 +1013,6 @@ class SvcHub(object):
|
||||||
else:
|
else:
|
||||||
self.log("root", "reload done")
|
self.log("root", "reload done")
|
||||||
self.broker.reload()
|
self.broker.reload()
|
||||||
self.reloading = 0
|
|
||||||
|
|
||||||
def _reload_blocking(self, rescan_all_vols: bool = True, up2k: bool = True) -> None:
|
|
||||||
while True:
|
|
||||||
with self.up2k.mutex:
|
|
||||||
if self.reloading < 2:
|
|
||||||
self.reloading = 1
|
|
||||||
break
|
|
||||||
time.sleep(0.05)
|
|
||||||
|
|
||||||
# try to handle multiple pending IdP reloads at once:
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
self._reload(rescan_all_vols=rescan_all_vols, up2k=up2k)
|
|
||||||
|
|
||||||
def _reload_sessions(self) -> None:
|
def _reload_sessions(self) -> None:
|
||||||
with self.asrv.mutex:
|
with self.asrv.mutex:
|
||||||
|
@ -1052,7 +1026,7 @@ class SvcHub(object):
|
||||||
|
|
||||||
if self.reload_req:
|
if self.reload_req:
|
||||||
self.reload_req = False
|
self.reload_req = False
|
||||||
self.reload()
|
self.reload(True, True)
|
||||||
|
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,8 @@ zsg = "avif,avifs,bmp,gif,heic,heics,heif,heifs,ico,j2p,j2k,jp2,jpeg,jpg,jpx,png
|
||||||
CV_EXTS = set(zsg.split(","))
|
CV_EXTS = set(zsg.split(","))
|
||||||
|
|
||||||
|
|
||||||
|
SBUSY = "cannot receive uploads right now;\nserver busy with %s.\nPlease wait; the client will retry..."
|
||||||
|
|
||||||
HINT_HISTPATH = "you could try moving the database to another location (preferably an SSD or NVME drive) using either the --hist argument (global option for all volumes), or the hist volflag (just for this volume)"
|
HINT_HISTPATH = "you could try moving the database to another location (preferably an SSD or NVME drive) using either the --hist argument (global option for all volumes), or the hist volflag (just for this volume)"
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,12 +127,22 @@ class Up2k(object):
|
||||||
self.args = hub.args
|
self.args = hub.args
|
||||||
self.log_func = hub.log
|
self.log_func = hub.log
|
||||||
|
|
||||||
|
self.vfs = self.asrv.vfs
|
||||||
|
self.acct = self.asrv.acct
|
||||||
|
self.iacct = self.asrv.iacct
|
||||||
|
self.grps = self.asrv.grps
|
||||||
|
|
||||||
self.salt = self.args.warksalt
|
self.salt = self.args.warksalt
|
||||||
self.r_hash = re.compile("^[0-9a-zA-Z_-]{44}$")
|
self.r_hash = re.compile("^[0-9a-zA-Z_-]{44}$")
|
||||||
|
|
||||||
self.gid = 0
|
self.gid = 0
|
||||||
|
self.gt0 = 0
|
||||||
|
self.gt1 = 0
|
||||||
self.stop = False
|
self.stop = False
|
||||||
self.mutex = threading.Lock()
|
self.mutex = threading.Lock()
|
||||||
|
self.reload_mutex = threading.Lock()
|
||||||
|
self.reload_flag = 0
|
||||||
|
self.reloading = False
|
||||||
self.blocked: Optional[str] = None
|
self.blocked: Optional[str] = None
|
||||||
self.pp: Optional[ProgressPrinter] = None
|
self.pp: Optional[ProgressPrinter] = None
|
||||||
self.rescan_cond = threading.Condition()
|
self.rescan_cond = threading.Condition()
|
||||||
|
@ -203,7 +215,38 @@ class Up2k(object):
|
||||||
|
|
||||||
Daemon(self.deferred_init, "up2k-deferred-init")
|
Daemon(self.deferred_init, "up2k-deferred-init")
|
||||||
|
|
||||||
|
def unpp(self) -> None:
|
||||||
|
self.gt1 = time.time()
|
||||||
|
if self.pp:
|
||||||
|
self.pp.end = True
|
||||||
|
self.pp = None
|
||||||
|
|
||||||
def reload(self, rescan_all_vols: bool) -> None:
|
def reload(self, rescan_all_vols: bool) -> None:
|
||||||
|
n = 2 if rescan_all_vols else 1
|
||||||
|
with self.reload_mutex:
|
||||||
|
if self.reload_flag < n:
|
||||||
|
self.reload_flag = n
|
||||||
|
with self.rescan_cond:
|
||||||
|
self.rescan_cond.notify_all()
|
||||||
|
|
||||||
|
def _reload_thr(self) -> None:
|
||||||
|
while self.pp:
|
||||||
|
time.sleep(0.1)
|
||||||
|
while True:
|
||||||
|
with self.reload_mutex:
|
||||||
|
if not self.reload_flag:
|
||||||
|
break
|
||||||
|
rav = self.reload_flag == 2
|
||||||
|
self.reload_flag = 0
|
||||||
|
gt1 = self.gt1
|
||||||
|
with self.mutex:
|
||||||
|
self._reload(rav)
|
||||||
|
while gt1 == self.gt1 or self.pp:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
self.reloading = False
|
||||||
|
|
||||||
|
def _reload(self, rescan_all_vols: bool) -> None:
|
||||||
"""mutex(main) me"""
|
"""mutex(main) me"""
|
||||||
self.log("reload #{} scheduled".format(self.gid + 1))
|
self.log("reload #{} scheduled".format(self.gid + 1))
|
||||||
all_vols = self.asrv.vfs.all_vols
|
all_vols = self.asrv.vfs.all_vols
|
||||||
|
@ -228,10 +271,7 @@ class Up2k(object):
|
||||||
with self.mutex, self.reg_mutex:
|
with self.mutex, self.reg_mutex:
|
||||||
self._drop_caches()
|
self._drop_caches()
|
||||||
|
|
||||||
if self.pp:
|
self.unpp()
|
||||||
self.pp.end = True
|
|
||||||
self.pp = None
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.pp and self.args.exit == "idx":
|
if not self.pp and self.args.exit == "idx":
|
||||||
|
@ -311,8 +351,8 @@ class Up2k(object):
|
||||||
|
|
||||||
def _active_uploads(self, uname: str) -> list[tuple[float, int, int, str]]:
|
def _active_uploads(self, uname: str) -> list[tuple[float, int, int, str]]:
|
||||||
ret = []
|
ret = []
|
||||||
for vtop in self.asrv.vfs.aread[uname]:
|
for vtop in self.vfs.aread.get(uname) or []:
|
||||||
vfs = self.asrv.vfs.all_vols.get(vtop)
|
vfs = self.vfs.all_vols.get(vtop)
|
||||||
if not vfs: # dbv only
|
if not vfs: # dbv only
|
||||||
continue
|
continue
|
||||||
ptop = vfs.realpath
|
ptop = vfs.realpath
|
||||||
|
@ -485,6 +525,12 @@ class Up2k(object):
|
||||||
if self.stop:
|
if self.stop:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
with self.reload_mutex:
|
||||||
|
if self.reload_flag and not self.reloading:
|
||||||
|
self.reloading = True
|
||||||
|
zs = "up2k-reload-%d" % (self.gid,)
|
||||||
|
Daemon(self._reload_thr, zs)
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < cooldown:
|
if now < cooldown:
|
||||||
# self.log("SR: cd - now = {:.2f}".format(cooldown - now), 5)
|
# self.log("SR: cd - now = {:.2f}".format(cooldown - now), 5)
|
||||||
|
@ -521,7 +567,7 @@ class Up2k(object):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
with self.mutex:
|
with self.mutex:
|
||||||
for vp, vol in sorted(self.asrv.vfs.all_vols.items()):
|
for vp, vol in sorted(self.vfs.all_vols.items()):
|
||||||
maxage = vol.flags.get("scan")
|
maxage = vol.flags.get("scan")
|
||||||
if not maxage:
|
if not maxage:
|
||||||
continue
|
continue
|
||||||
|
@ -554,7 +600,7 @@ class Up2k(object):
|
||||||
|
|
||||||
if vols:
|
if vols:
|
||||||
cooldown = now + 10
|
cooldown = now + 10
|
||||||
err = self.rescan(self.asrv.vfs.all_vols, vols, False, False)
|
err = self.rescan(self.vfs.all_vols, vols, False, False)
|
||||||
if err:
|
if err:
|
||||||
for v in vols:
|
for v in vols:
|
||||||
self.need_rescan.add(v)
|
self.need_rescan.add(v)
|
||||||
|
@ -567,7 +613,7 @@ class Up2k(object):
|
||||||
def _check_lifetimes(self) -> float:
|
def _check_lifetimes(self) -> float:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
timeout = now + 9001
|
timeout = now + 9001
|
||||||
for vp, vol in sorted(self.asrv.vfs.all_vols.items()):
|
for vp, vol in sorted(self.vfs.all_vols.items()):
|
||||||
lifetime = vol.flags.get("lifetime")
|
lifetime = vol.flags.get("lifetime")
|
||||||
if not lifetime:
|
if not lifetime:
|
||||||
continue
|
continue
|
||||||
|
@ -621,7 +667,7 @@ class Up2k(object):
|
||||||
maxage = self.args.shr_rt * 60
|
maxage = self.args.shr_rt * 60
|
||||||
low = now - maxage
|
low = now - maxage
|
||||||
|
|
||||||
vn = self.asrv.vfs.nodes.get(self.args.shr.strip("/"))
|
vn = self.vfs.nodes.get(self.args.shr.strip("/"))
|
||||||
active = vn and vn.nodes
|
active = vn and vn.nodes
|
||||||
|
|
||||||
db = sqlite3.connect(self.args.shr_db, timeout=2)
|
db = sqlite3.connect(self.args.shr_db, timeout=2)
|
||||||
|
@ -646,7 +692,7 @@ class Up2k(object):
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
if reload:
|
if reload:
|
||||||
Daemon(self.hub._reload_blocking, "sharedrop", (False, False))
|
Daemon(self.hub.reload, "sharedrop", (False, False))
|
||||||
|
|
||||||
q = "select min(t1) from sh where t1 > ?"
|
q = "select min(t1) from sh where t1 > ?"
|
||||||
(earliest,) = cur.execute(q, (1,)).fetchone()
|
(earliest,) = cur.execute(q, (1,)).fetchone()
|
||||||
|
@ -672,7 +718,7 @@ class Up2k(object):
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
ret = 9001
|
ret = 9001
|
||||||
for _, vol in sorted(self.asrv.vfs.all_vols.items()):
|
for _, vol in sorted(self.vfs.all_vols.items()):
|
||||||
rp = vol.realpath
|
rp = vol.realpath
|
||||||
cur = self.cur.get(rp)
|
cur = self.cur.get(rp)
|
||||||
if not cur:
|
if not cur:
|
||||||
|
@ -774,6 +820,8 @@ class Up2k(object):
|
||||||
with self.mutex:
|
with self.mutex:
|
||||||
gid = self.gid
|
gid = self.gid
|
||||||
|
|
||||||
|
self.gt0 = time.time()
|
||||||
|
|
||||||
nspin = 0
|
nspin = 0
|
||||||
while True:
|
while True:
|
||||||
nspin += 1
|
nspin += 1
|
||||||
|
@ -796,6 +844,11 @@ class Up2k(object):
|
||||||
if gid:
|
if gid:
|
||||||
self.log("reload #%d running" % (gid,))
|
self.log("reload #%d running" % (gid,))
|
||||||
|
|
||||||
|
self.vfs = self.asrv.vfs
|
||||||
|
self.acct = self.asrv.acct
|
||||||
|
self.iacct = self.asrv.iacct
|
||||||
|
self.grps = self.asrv.grps
|
||||||
|
|
||||||
vols = list(all_vols.values())
|
vols = list(all_vols.values())
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
have_e2d = False
|
have_e2d = False
|
||||||
|
@ -859,7 +912,7 @@ class Up2k(object):
|
||||||
self._drop_caches()
|
self._drop_caches()
|
||||||
|
|
||||||
for vol in vols:
|
for vol in vols:
|
||||||
if self.stop:
|
if self.stop or gid != self.gid:
|
||||||
break
|
break
|
||||||
|
|
||||||
en = set(vol.flags.get("mte", {}))
|
en = set(vol.flags.get("mte", {}))
|
||||||
|
@ -990,7 +1043,7 @@ class Up2k(object):
|
||||||
if self.mtag:
|
if self.mtag:
|
||||||
Daemon(self._run_all_mtp, "up2k-mtp-scan", (gid,))
|
Daemon(self._run_all_mtp, "up2k-mtp-scan", (gid,))
|
||||||
else:
|
else:
|
||||||
self.pp = None
|
self.unpp()
|
||||||
|
|
||||||
return have_e2d
|
return have_e2d
|
||||||
|
|
||||||
|
@ -998,7 +1051,7 @@ class Up2k(object):
|
||||||
self, ptop: str, flags: dict[str, Any]
|
self, ptop: str, flags: dict[str, Any]
|
||||||
) -> Optional[tuple["sqlite3.Cursor", str]]:
|
) -> Optional[tuple["sqlite3.Cursor", str]]:
|
||||||
"""mutex(main,reg) me"""
|
"""mutex(main,reg) me"""
|
||||||
histpath = self.asrv.vfs.histtab.get(ptop)
|
histpath = self.vfs.histtab.get(ptop)
|
||||||
if not histpath:
|
if not histpath:
|
||||||
self.log("no histpath for [{}]".format(ptop))
|
self.log("no histpath for [{}]".format(ptop))
|
||||||
return None
|
return None
|
||||||
|
@ -1011,7 +1064,7 @@ class Up2k(object):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
vpath = "?"
|
vpath = "?"
|
||||||
for k, v in self.asrv.vfs.all_vols.items():
|
for k, v in self.vfs.all_vols.items():
|
||||||
if v.realpath == ptop:
|
if v.realpath == ptop:
|
||||||
vpath = k
|
vpath = k
|
||||||
|
|
||||||
|
@ -1178,7 +1231,7 @@ class Up2k(object):
|
||||||
def _verify_db_cache(self, cur: "sqlite3.Cursor", vpath: str) -> None:
|
def _verify_db_cache(self, cur: "sqlite3.Cursor", vpath: str) -> None:
|
||||||
# check if list of intersecting volumes changed since last use; drop caches if so
|
# check if list of intersecting volumes changed since last use; drop caches if so
|
||||||
prefix = (vpath + "/").lstrip("/")
|
prefix = (vpath + "/").lstrip("/")
|
||||||
zsl = [x for x in self.asrv.vfs.all_vols if x.startswith(prefix)]
|
zsl = [x for x in self.vfs.all_vols if x.startswith(prefix)]
|
||||||
zsl = [x[len(prefix) :] for x in zsl]
|
zsl = [x[len(prefix) :] for x in zsl]
|
||||||
zsl.sort()
|
zsl.sort()
|
||||||
zb = hashlib.sha1("\n".join(zsl).encode("utf-8", "replace")).digest()
|
zb = hashlib.sha1("\n".join(zsl).encode("utf-8", "replace")).digest()
|
||||||
|
@ -1223,7 +1276,7 @@ class Up2k(object):
|
||||||
if d != vol and (d.vpath.startswith(vol.vpath + "/") or not vol.vpath)
|
if d != vol and (d.vpath.startswith(vol.vpath + "/") or not vol.vpath)
|
||||||
]
|
]
|
||||||
excl += [absreal(x) for x in excl]
|
excl += [absreal(x) for x in excl]
|
||||||
excl += list(self.asrv.vfs.histtab.values())
|
excl += list(self.vfs.histtab.values())
|
||||||
if WINDOWS:
|
if WINDOWS:
|
||||||
excl = [x.replace("/", "\\") for x in excl]
|
excl = [x.replace("/", "\\") for x in excl]
|
||||||
else:
|
else:
|
||||||
|
@ -1733,7 +1786,7 @@ class Up2k(object):
|
||||||
|
|
||||||
excl = [
|
excl = [
|
||||||
d[len(vol.vpath) :].lstrip("/")
|
d[len(vol.vpath) :].lstrip("/")
|
||||||
for d in self.asrv.vfs.all_vols
|
for d in self.vfs.all_vols
|
||||||
if d != vol.vpath and (d.startswith(vol.vpath + "/") or not vol.vpath)
|
if d != vol.vpath and (d.startswith(vol.vpath + "/") or not vol.vpath)
|
||||||
]
|
]
|
||||||
qexa: list[str] = []
|
qexa: list[str] = []
|
||||||
|
@ -1885,7 +1938,7 @@ class Up2k(object):
|
||||||
def _drop_caches(self) -> None:
|
def _drop_caches(self) -> None:
|
||||||
"""mutex(main,reg) me"""
|
"""mutex(main,reg) me"""
|
||||||
self.log("dropping caches for a full filesystem scan")
|
self.log("dropping caches for a full filesystem scan")
|
||||||
for vol in self.asrv.vfs.all_vols.values():
|
for vol in self.vfs.all_vols.values():
|
||||||
reg = self.register_vpath(vol.realpath, vol.flags)
|
reg = self.register_vpath(vol.realpath, vol.flags)
|
||||||
if not reg:
|
if not reg:
|
||||||
continue
|
continue
|
||||||
|
@ -2113,7 +2166,7 @@ class Up2k(object):
|
||||||
self._run_one_mtp(ptop, gid)
|
self._run_one_mtp(ptop, gid)
|
||||||
|
|
||||||
vtop = "\n"
|
vtop = "\n"
|
||||||
for vol in self.asrv.vfs.all_vols.values():
|
for vol in self.vfs.all_vols.values():
|
||||||
if vol.realpath == ptop:
|
if vol.realpath == ptop:
|
||||||
vtop = vol.vpath
|
vtop = vol.vpath
|
||||||
if "running mtp" in self.volstate.get(vtop, ""):
|
if "running mtp" in self.volstate.get(vtop, ""):
|
||||||
|
@ -2123,7 +2176,7 @@ class Up2k(object):
|
||||||
msg = "mtp finished in {:.2f} sec ({})"
|
msg = "mtp finished in {:.2f} sec ({})"
|
||||||
self.log(msg.format(td, s2hms(td, True)))
|
self.log(msg.format(td, s2hms(td, True)))
|
||||||
|
|
||||||
self.pp = None
|
self.unpp()
|
||||||
if self.args.exit == "idx":
|
if self.args.exit == "idx":
|
||||||
self.hub.sigterm()
|
self.hub.sigterm()
|
||||||
|
|
||||||
|
@ -2765,6 +2818,9 @@ class Up2k(object):
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
# busy_aps is u2fh (always undefined if -j0) so this is safe
|
# busy_aps is u2fh (always undefined if -j0) so this is safe
|
||||||
self.busy_aps = busy_aps
|
self.busy_aps = busy_aps
|
||||||
|
if self.reload_flag or self.reloading:
|
||||||
|
raise Pebkac(503, SBUSY % ("fs-reload",))
|
||||||
|
|
||||||
got_lock = False
|
got_lock = False
|
||||||
try:
|
try:
|
||||||
# bit expensive; 3.9=10x 3.11=2x
|
# bit expensive; 3.9=10x 3.11=2x
|
||||||
|
@ -2773,8 +2829,7 @@ class Up2k(object):
|
||||||
with self.reg_mutex:
|
with self.reg_mutex:
|
||||||
ret = self._handle_json(cj)
|
ret = self._handle_json(cj)
|
||||||
else:
|
else:
|
||||||
t = "cannot receive uploads right now;\nserver busy with {}.\nPlease wait; the client will retry..."
|
raise Pebkac(503, SBUSY % (self.blocked or "[unknown]",))
|
||||||
raise Pebkac(503, t.format(self.blocked or "[unknown]"))
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
if not PY2:
|
if not PY2:
|
||||||
raise
|
raise
|
||||||
|
@ -2816,7 +2871,7 @@ class Up2k(object):
|
||||||
if True:
|
if True:
|
||||||
jcur = self.cur.get(ptop)
|
jcur = self.cur.get(ptop)
|
||||||
reg = self.registry[ptop]
|
reg = self.registry[ptop]
|
||||||
vfs = self.asrv.vfs.all_vols[cj["vtop"]]
|
vfs = self.vfs.all_vols[cj["vtop"]]
|
||||||
n4g = bool(vfs.flags.get("noforget"))
|
n4g = bool(vfs.flags.get("noforget"))
|
||||||
noclone = bool(vfs.flags.get("noclone"))
|
noclone = bool(vfs.flags.get("noclone"))
|
||||||
rand = vfs.flags.get("rand") or cj.get("rand")
|
rand = vfs.flags.get("rand") or cj.get("rand")
|
||||||
|
@ -2840,7 +2895,7 @@ class Up2k(object):
|
||||||
|
|
||||||
alts: list[tuple[int, int, dict[str, Any], "sqlite3.Cursor", str, str]] = []
|
alts: list[tuple[int, int, dict[str, Any], "sqlite3.Cursor", str, str]] = []
|
||||||
for ptop, cur in vols:
|
for ptop, cur in vols:
|
||||||
allv = self.asrv.vfs.all_vols
|
allv = self.vfs.all_vols
|
||||||
cvfs = next((v for v in allv.values() if v.realpath == ptop), vfs)
|
cvfs = next((v for v in allv.values() if v.realpath == ptop), vfs)
|
||||||
vtop = cj["vtop"] if cur == jcur else cvfs.vpath
|
vtop = cj["vtop"] if cur == jcur else cvfs.vpath
|
||||||
|
|
||||||
|
@ -3083,7 +3138,7 @@ class Up2k(object):
|
||||||
vp,
|
vp,
|
||||||
job["host"],
|
job["host"],
|
||||||
job["user"],
|
job["user"],
|
||||||
self.asrv.vfs.get_perms(job["vtop"], job["user"]),
|
self.vfs.get_perms(job["vtop"], job["user"]),
|
||||||
job["lmod"],
|
job["lmod"],
|
||||||
job["size"],
|
job["size"],
|
||||||
job["addr"],
|
job["addr"],
|
||||||
|
@ -3095,7 +3150,7 @@ class Up2k(object):
|
||||||
self.log(t, 1)
|
self.log(t, 1)
|
||||||
raise Pebkac(403, t)
|
raise Pebkac(403, t)
|
||||||
if hr.get("reloc"):
|
if hr.get("reloc"):
|
||||||
x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"])
|
x = pathmod(self.vfs, dst, vp, hr["reloc"])
|
||||||
if x:
|
if x:
|
||||||
zvfs = vfs
|
zvfs = vfs
|
||||||
pdir, _, job["name"], (vfs, rem) = x
|
pdir, _, job["name"], (vfs, rem) = x
|
||||||
|
@ -3555,7 +3610,7 @@ class Up2k(object):
|
||||||
wake_sr = False
|
wake_sr = False
|
||||||
try:
|
try:
|
||||||
flt = job["life"]
|
flt = job["life"]
|
||||||
vfs = self.asrv.vfs.all_vols[job["vtop"]]
|
vfs = self.vfs.all_vols[job["vtop"]]
|
||||||
vlt = vfs.flags["lifetime"]
|
vlt = vfs.flags["lifetime"]
|
||||||
if vlt and flt > 1 and flt < vlt:
|
if vlt and flt > 1 and flt < vlt:
|
||||||
upt -= vlt - flt
|
upt -= vlt - flt
|
||||||
|
@ -3731,7 +3786,7 @@ class Up2k(object):
|
||||||
djoin(vtop, rd, fn),
|
djoin(vtop, rd, fn),
|
||||||
host,
|
host,
|
||||||
usr,
|
usr,
|
||||||
self.asrv.vfs.get_perms(djoin(vtop, rd, fn), usr),
|
self.vfs.get_perms(djoin(vtop, rd, fn), usr),
|
||||||
ts,
|
ts,
|
||||||
sz,
|
sz,
|
||||||
ip,
|
ip,
|
||||||
|
@ -3841,12 +3896,12 @@ class Up2k(object):
|
||||||
partial = ""
|
partial = ""
|
||||||
if not unpost:
|
if not unpost:
|
||||||
permsets = [[True, False, False, True]]
|
permsets = [[True, False, False, True]]
|
||||||
vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0])
|
vn, rem = self.vfs.get(vpath, uname, *permsets[0])
|
||||||
vn, rem = vn.get_dbv(rem)
|
vn, rem = vn.get_dbv(rem)
|
||||||
else:
|
else:
|
||||||
# unpost with missing permissions? verify with db
|
# unpost with missing permissions? verify with db
|
||||||
permsets = [[False, True]]
|
permsets = [[False, True]]
|
||||||
vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0])
|
vn, rem = self.vfs.get(vpath, uname, *permsets[0])
|
||||||
vn, rem = vn.get_dbv(rem)
|
vn, rem = vn.get_dbv(rem)
|
||||||
ptop = vn.realpath
|
ptop = vn.realpath
|
||||||
with self.mutex, self.reg_mutex:
|
with self.mutex, self.reg_mutex:
|
||||||
|
@ -3951,7 +4006,7 @@ class Up2k(object):
|
||||||
vpath,
|
vpath,
|
||||||
"",
|
"",
|
||||||
uname,
|
uname,
|
||||||
self.asrv.vfs.get_perms(vpath, uname),
|
self.vfs.get_perms(vpath, uname),
|
||||||
stl.st_mtime,
|
stl.st_mtime,
|
||||||
st.st_size,
|
st.st_size,
|
||||||
ip,
|
ip,
|
||||||
|
@ -3991,7 +4046,7 @@ class Up2k(object):
|
||||||
vpath,
|
vpath,
|
||||||
"",
|
"",
|
||||||
uname,
|
uname,
|
||||||
self.asrv.vfs.get_perms(vpath, uname),
|
self.vfs.get_perms(vpath, uname),
|
||||||
stl.st_mtime,
|
stl.st_mtime,
|
||||||
st.st_size,
|
st.st_size,
|
||||||
ip,
|
ip,
|
||||||
|
@ -4015,7 +4070,7 @@ class Up2k(object):
|
||||||
if svp == dvp or dvp.startswith(svp + "/"):
|
if svp == dvp or dvp.startswith(svp + "/"):
|
||||||
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
||||||
|
|
||||||
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
|
svn, srem = self.vfs.get(svp, uname, True, False, True)
|
||||||
svn, srem = svn.get_dbv(srem)
|
svn, srem = svn.get_dbv(srem)
|
||||||
sabs = svn.canonical(srem, False)
|
sabs = svn.canonical(srem, False)
|
||||||
curs: set["sqlite3.Cursor"] = set()
|
curs: set["sqlite3.Cursor"] = set()
|
||||||
|
@ -4082,7 +4137,7 @@ class Up2k(object):
|
||||||
rem = ap[len(sabs) :].replace(os.sep, "/").lstrip("/")
|
rem = ap[len(sabs) :].replace(os.sep, "/").lstrip("/")
|
||||||
vp = vjoin(dvp, rem)
|
vp = vjoin(dvp, rem)
|
||||||
try:
|
try:
|
||||||
dvn, drem = self.asrv.vfs.get(vp, uname, False, True)
|
dvn, drem = self.vfs.get(vp, uname, False, True)
|
||||||
bos.mkdir(dvn.canonical(drem))
|
bos.mkdir(dvn.canonical(drem))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -4093,10 +4148,10 @@ class Up2k(object):
|
||||||
self, uname: str, ip: str, svp: str, dvp: str, curs: set["sqlite3.Cursor"]
|
self, uname: str, ip: str, svp: str, dvp: str, curs: set["sqlite3.Cursor"]
|
||||||
) -> str:
|
) -> str:
|
||||||
"""mutex(main) me; will mutex(reg)"""
|
"""mutex(main) me; will mutex(reg)"""
|
||||||
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
|
svn, srem = self.vfs.get(svp, uname, True, False, True)
|
||||||
svn, srem = svn.get_dbv(srem)
|
svn, srem = svn.get_dbv(srem)
|
||||||
|
|
||||||
dvn, drem = self.asrv.vfs.get(dvp, uname, False, True)
|
dvn, drem = self.vfs.get(dvp, uname, False, True)
|
||||||
dvn, drem = dvn.get_dbv(drem)
|
dvn, drem = dvn.get_dbv(drem)
|
||||||
|
|
||||||
sabs = svn.canonical(srem, False)
|
sabs = svn.canonical(srem, False)
|
||||||
|
@ -4140,7 +4195,7 @@ class Up2k(object):
|
||||||
svp,
|
svp,
|
||||||
"",
|
"",
|
||||||
uname,
|
uname,
|
||||||
self.asrv.vfs.get_perms(svp, uname),
|
self.vfs.get_perms(svp, uname),
|
||||||
ftime,
|
ftime,
|
||||||
fsize,
|
fsize,
|
||||||
ip,
|
ip,
|
||||||
|
@ -4180,7 +4235,7 @@ class Up2k(object):
|
||||||
dvp,
|
dvp,
|
||||||
"",
|
"",
|
||||||
uname,
|
uname,
|
||||||
self.asrv.vfs.get_perms(dvp, uname),
|
self.vfs.get_perms(dvp, uname),
|
||||||
ftime,
|
ftime,
|
||||||
fsize,
|
fsize,
|
||||||
ip,
|
ip,
|
||||||
|
@ -4293,7 +4348,7 @@ class Up2k(object):
|
||||||
dvp,
|
dvp,
|
||||||
"",
|
"",
|
||||||
uname,
|
uname,
|
||||||
self.asrv.vfs.get_perms(dvp, uname),
|
self.vfs.get_perms(dvp, uname),
|
||||||
ftime,
|
ftime,
|
||||||
fsize,
|
fsize,
|
||||||
ip,
|
ip,
|
||||||
|
@ -4606,7 +4661,7 @@ class Up2k(object):
|
||||||
vp_chk,
|
vp_chk,
|
||||||
job["host"],
|
job["host"],
|
||||||
job["user"],
|
job["user"],
|
||||||
self.asrv.vfs.get_perms(vp_chk, job["user"]),
|
self.vfs.get_perms(vp_chk, job["user"]),
|
||||||
job["lmod"],
|
job["lmod"],
|
||||||
job["size"],
|
job["size"],
|
||||||
job["addr"],
|
job["addr"],
|
||||||
|
@ -4618,7 +4673,7 @@ class Up2k(object):
|
||||||
self.log(t, 1)
|
self.log(t, 1)
|
||||||
raise Pebkac(403, t)
|
raise Pebkac(403, t)
|
||||||
if hr.get("reloc"):
|
if hr.get("reloc"):
|
||||||
x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"])
|
x = pathmod(self.vfs, ap_chk, vp_chk, hr["reloc"])
|
||||||
if x:
|
if x:
|
||||||
zvfs = vfs
|
zvfs = vfs
|
||||||
pdir, _, job["name"], (vfs, rem) = x
|
pdir, _, job["name"], (vfs, rem) = x
|
||||||
|
@ -4725,7 +4780,7 @@ class Up2k(object):
|
||||||
|
|
||||||
def _snap_reg(self, ptop: str, reg: dict[str, dict[str, Any]]) -> None:
|
def _snap_reg(self, ptop: str, reg: dict[str, dict[str, Any]]) -> None:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
histpath = self.asrv.vfs.histtab.get(ptop)
|
histpath = self.vfs.histtab.get(ptop)
|
||||||
if not histpath:
|
if not histpath:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -4973,7 +5028,7 @@ class Up2k(object):
|
||||||
else:
|
else:
|
||||||
fvp, fn = vsplit(fvp)
|
fvp, fn = vsplit(fvp)
|
||||||
|
|
||||||
x = pathmod(self.asrv.vfs, "", req_vp, {"vp": fvp, "fn": fn})
|
x = pathmod(self.vfs, "", req_vp, {"vp": fvp, "fn": fn})
|
||||||
if not x:
|
if not x:
|
||||||
t = "hook_fx(%s): failed to resolve %s based on %s"
|
t = "hook_fx(%s): failed to resolve %s based on %s"
|
||||||
self.log(t % (act, fvp, req_vp))
|
self.log(t % (act, fvp, req_vp))
|
||||||
|
|
Loading…
Reference in a new issue