copyparty 1.12.1__py3-none-any.whl → 1.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__main__.py +7 -2
- copyparty/__version__.py +3 -3
- copyparty/authsrv.py +8 -7
- copyparty/cert.py +17 -6
- copyparty/cfg.py +3 -0
- copyparty/httpcli.py +188 -10
- copyparty/httpconn.py +1 -0
- copyparty/httpsrv.py +2 -0
- copyparty/svchub.py +13 -0
- copyparty/th_srv.py +2 -1
- copyparty/up2k.py +124 -60
- copyparty/util.py +101 -29
- copyparty/web/a/u2c.py +8 -4
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +1 -1
- copyparty/web/up2k.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/METADATA +29 -4
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/RECORD +25 -25
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/LICENSE +0 -0
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/WHEEL +0 -0
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/entry_points.txt +0 -0
- {copyparty-1.12.1.dist-info → copyparty-1.13.0.dist-info}/top_level.txt +0 -0
copyparty/up2k.py
CHANGED
@@ -88,6 +88,9 @@ CV_EXTS = set(zsg.split(","))
|
|
88
88
|
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)"
|
89
89
|
|
90
90
|
|
91
|
+
VF_CAREFUL = {"mv_re_t": 5, "rm_re_t": 5, "mv_re_r": 0.1, "rm_re_r": 0.1}
|
92
|
+
|
93
|
+
|
91
94
|
class Dbw(object):
|
92
95
|
def __init__(self, c , n , t ) :
|
93
96
|
self.c = c
|
@@ -133,6 +136,7 @@ class Up2k(object):
|
|
133
136
|
self.need_rescan = set()
|
134
137
|
self.db_act = 0.0
|
135
138
|
|
139
|
+
self.reg_mutex = threading.Lock()
|
136
140
|
self.registry = {}
|
137
141
|
self.flags = {}
|
138
142
|
self.droppable = {}
|
@@ -140,7 +144,7 @@ class Up2k(object):
|
|
140
144
|
self.volsize = {}
|
141
145
|
self.volstate = {}
|
142
146
|
self.vol_act = {}
|
143
|
-
self.busy_aps
|
147
|
+
self.busy_aps = {}
|
144
148
|
self.dupesched = {}
|
145
149
|
self.snap_prev = {}
|
146
150
|
|
@@ -197,11 +201,15 @@ class Up2k(object):
|
|
197
201
|
Daemon(self.deferred_init, "up2k-deferred-init")
|
198
202
|
|
199
203
|
def reload(self, rescan_all_vols ) :
|
200
|
-
"""mutex me"""
|
204
|
+
"""mutex(main) me"""
|
201
205
|
self.log("reload #{} scheduled".format(self.gid + 1))
|
202
206
|
all_vols = self.asrv.vfs.all_vols
|
203
207
|
|
204
|
-
|
208
|
+
with self.reg_mutex:
|
209
|
+
scan_vols = [
|
210
|
+
k for k, v in all_vols.items() if v.realpath not in self.registry
|
211
|
+
]
|
212
|
+
|
205
213
|
if rescan_all_vols:
|
206
214
|
scan_vols = list(all_vols.keys())
|
207
215
|
|
@@ -214,7 +222,7 @@ class Up2k(object):
|
|
214
222
|
if self.stop:
|
215
223
|
# up-mt consistency not guaranteed if init is interrupted;
|
216
224
|
# drop caches for a full scan on next boot
|
217
|
-
with self.mutex:
|
225
|
+
with self.mutex, self.reg_mutex:
|
218
226
|
self._drop_caches()
|
219
227
|
|
220
228
|
if self.pp:
|
@@ -280,10 +288,27 @@ class Up2k(object):
|
|
280
288
|
min(1000 * 24 * 60 * 60 - 1, time.time() - self.db_act)
|
281
289
|
),
|
282
290
|
}
|
283
|
-
return json.dumps(ret,
|
291
|
+
return json.dumps(ret, separators=(",\n", ": "))
|
292
|
+
|
293
|
+
def find_job_by_ap(self, ptop , ap ) :
|
294
|
+
try:
|
295
|
+
if ANYWIN:
|
296
|
+
ap = ap.replace("\\", "/")
|
297
|
+
|
298
|
+
vp = ap[len(ptop) :].strip("/")
|
299
|
+
dn, fn = vsplit(vp)
|
300
|
+
with self.reg_mutex:
|
301
|
+
tab2 = self.registry[ptop]
|
302
|
+
for job in tab2.values():
|
303
|
+
if job["prel"] == dn and job["name"] == fn:
|
304
|
+
return json.dumps(job, separators=(",\n", ": "))
|
305
|
+
except:
|
306
|
+
pass
|
307
|
+
|
308
|
+
return "{}"
|
284
309
|
|
285
310
|
def get_unfinished_by_user(self, uname, ip) :
|
286
|
-
if PY2 or not self.
|
311
|
+
if PY2 or not self.reg_mutex.acquire(timeout=2):
|
287
312
|
return '[{"timeout":1}]'
|
288
313
|
|
289
314
|
ret = []
|
@@ -312,17 +337,25 @@ class Up2k(object):
|
|
312
337
|
)
|
313
338
|
ret.append(zt5)
|
314
339
|
finally:
|
315
|
-
self.
|
340
|
+
self.reg_mutex.release()
|
341
|
+
|
342
|
+
if ANYWIN:
|
343
|
+
ret = [(x[0], x[1].replace("\\", "/"), x[2], x[3], x[4]) for x in ret]
|
316
344
|
|
317
345
|
ret.sort(reverse=True)
|
318
346
|
ret2 = [
|
319
|
-
{
|
347
|
+
{
|
348
|
+
"at": at,
|
349
|
+
"vp": "/" + quotep(vp),
|
350
|
+
"pd": 100 - ((nn * 100) // (nh or 1)),
|
351
|
+
"sz": sz,
|
352
|
+
}
|
320
353
|
for (at, vp, sz, nn, nh) in ret
|
321
354
|
]
|
322
|
-
return json.dumps(ret2,
|
355
|
+
return json.dumps(ret2, separators=(",\n", ": "))
|
323
356
|
|
324
357
|
def get_unfinished(self) :
|
325
|
-
if PY2 or not self.
|
358
|
+
if PY2 or not self.reg_mutex.acquire(timeout=0.5):
|
326
359
|
return ""
|
327
360
|
|
328
361
|
ret = {}
|
@@ -344,17 +377,17 @@ class Up2k(object):
|
|
344
377
|
|
345
378
|
ret[ptop] = (nbytes, nfiles)
|
346
379
|
finally:
|
347
|
-
self.
|
380
|
+
self.reg_mutex.release()
|
348
381
|
|
349
|
-
return json.dumps(ret,
|
382
|
+
return json.dumps(ret, separators=(",\n", ": "))
|
350
383
|
|
351
384
|
def get_volsize(self, ptop ) :
|
352
|
-
with self.
|
385
|
+
with self.reg_mutex:
|
353
386
|
return self._get_volsize(ptop)
|
354
387
|
|
355
388
|
def get_volsizes(self, ptops ) :
|
356
389
|
ret = []
|
357
|
-
with self.
|
390
|
+
with self.reg_mutex:
|
358
391
|
for ptop in ptops:
|
359
392
|
ret.append(self._get_volsize(ptop))
|
360
393
|
|
@@ -382,7 +415,7 @@ class Up2k(object):
|
|
382
415
|
def _rescan(
|
383
416
|
self, all_vols , scan_vols , wait , fscan
|
384
417
|
) :
|
385
|
-
"""mutex me"""
|
418
|
+
"""mutex(main) me"""
|
386
419
|
if not wait and self.pp:
|
387
420
|
return "cannot initiate; scan is already in progress"
|
388
421
|
|
@@ -664,7 +697,7 @@ class Up2k(object):
|
|
664
697
|
self.log(msg, c=3)
|
665
698
|
|
666
699
|
live_vols = []
|
667
|
-
with self.mutex:
|
700
|
+
with self.mutex, self.reg_mutex:
|
668
701
|
# only need to protect register_vpath but all in one go feels right
|
669
702
|
for vol in vols:
|
670
703
|
try:
|
@@ -706,7 +739,7 @@ class Up2k(object):
|
|
706
739
|
|
707
740
|
if self.args.re_dhash or [zv for zv in vols if "e2tsr" in zv.flags]:
|
708
741
|
self.args.re_dhash = False
|
709
|
-
with self.mutex:
|
742
|
+
with self.mutex, self.reg_mutex:
|
710
743
|
self._drop_caches()
|
711
744
|
|
712
745
|
for vol in vols:
|
@@ -783,7 +816,9 @@ class Up2k(object):
|
|
783
816
|
self.volstate[vol.vpath] = "online (mtp soon)"
|
784
817
|
|
785
818
|
for vol in need_vac:
|
786
|
-
|
819
|
+
with self.mutex, self.reg_mutex:
|
820
|
+
reg = self.register_vpath(vol.realpath, vol.flags)
|
821
|
+
|
787
822
|
assert reg
|
788
823
|
cur, _ = reg
|
789
824
|
with self.mutex:
|
@@ -797,7 +832,9 @@ class Up2k(object):
|
|
797
832
|
if vol.flags["dbd"] == "acid":
|
798
833
|
continue
|
799
834
|
|
800
|
-
|
835
|
+
with self.mutex, self.reg_mutex:
|
836
|
+
reg = self.register_vpath(vol.realpath, vol.flags)
|
837
|
+
|
801
838
|
try:
|
802
839
|
assert reg
|
803
840
|
cur, db_path = reg
|
@@ -844,6 +881,7 @@ class Up2k(object):
|
|
844
881
|
def register_vpath(
|
845
882
|
self, ptop , flags
|
846
883
|
) :
|
884
|
+
"""mutex(main,reg) me"""
|
847
885
|
histpath = self.asrv.vfs.histtab.get(ptop)
|
848
886
|
if not histpath:
|
849
887
|
self.log("no histpath for [{}]".format(ptop))
|
@@ -866,7 +904,7 @@ class Up2k(object):
|
|
866
904
|
ft = "\033[0;32m{}{:.0}"
|
867
905
|
ff = "\033[0;35m{}{:.0}"
|
868
906
|
fv = "\033[0;36m{}:\033[90m{}"
|
869
|
-
fx = set(("html_head", "rm_re_t", "rm_re_r"))
|
907
|
+
fx = set(("html_head", "rm_re_t", "rm_re_r", "mv_re_t", "mv_re_r"))
|
870
908
|
fd = vf_bmap()
|
871
909
|
fd.update(vf_cmap())
|
872
910
|
fd.update(vf_vmap())
|
@@ -1027,7 +1065,9 @@ class Up2k(object):
|
|
1027
1065
|
dev = cst.st_dev if vol.flags.get("xdev") else 0
|
1028
1066
|
|
1029
1067
|
with self.mutex:
|
1030
|
-
|
1068
|
+
with self.reg_mutex:
|
1069
|
+
reg = self.register_vpath(top, vol.flags)
|
1070
|
+
|
1031
1071
|
assert reg and self.pp
|
1032
1072
|
cur, db_path = reg
|
1033
1073
|
|
@@ -1624,7 +1664,7 @@ class Up2k(object):
|
|
1624
1664
|
|
1625
1665
|
def _build_tags_index(self, vol ) :
|
1626
1666
|
ptop = vol.realpath
|
1627
|
-
with self.mutex:
|
1667
|
+
with self.mutex, self.reg_mutex:
|
1628
1668
|
reg = self.register_vpath(ptop, vol.flags)
|
1629
1669
|
|
1630
1670
|
assert reg and self.pp
|
@@ -1645,6 +1685,7 @@ class Up2k(object):
|
|
1645
1685
|
return ret
|
1646
1686
|
|
1647
1687
|
def _drop_caches(self) :
|
1688
|
+
"""mutex(main,reg) me"""
|
1648
1689
|
self.log("dropping caches for a full filesystem scan")
|
1649
1690
|
for vol in self.asrv.vfs.all_vols.values():
|
1650
1691
|
reg = self.register_vpath(vol.realpath, vol.flags)
|
@@ -1820,7 +1861,7 @@ class Up2k(object):
|
|
1820
1861
|
params ,
|
1821
1862
|
flt ,
|
1822
1863
|
) :
|
1823
|
-
"""mutex me"""
|
1864
|
+
"""mutex(main) me"""
|
1824
1865
|
n = 0
|
1825
1866
|
c2 = cur.connection.cursor()
|
1826
1867
|
tf = tempfile.SpooledTemporaryFile(1024 * 1024 * 8, "w+b", prefix="cpp-tq-")
|
@@ -2154,7 +2195,7 @@ class Up2k(object):
|
|
2154
2195
|
ip ,
|
2155
2196
|
at ,
|
2156
2197
|
) :
|
2157
|
-
"""will mutex"""
|
2198
|
+
"""will mutex(main)"""
|
2158
2199
|
assert self.mtag
|
2159
2200
|
|
2160
2201
|
try:
|
@@ -2186,7 +2227,7 @@ class Up2k(object):
|
|
2186
2227
|
abspath ,
|
2187
2228
|
tags ,
|
2188
2229
|
) :
|
2189
|
-
"""mutex me"""
|
2230
|
+
"""mutex(main) me"""
|
2190
2231
|
assert self.mtag
|
2191
2232
|
|
2192
2233
|
if not bos.path.isfile(abspath):
|
@@ -2471,28 +2512,36 @@ class Up2k(object):
|
|
2471
2512
|
|
2472
2513
|
cur.connection.commit()
|
2473
2514
|
|
2474
|
-
def
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
def handle_json(self, cj , busy_aps ) :
|
2515
|
+
def handle_json(
|
2516
|
+
self, cj , busy_aps
|
2517
|
+
) :
|
2518
|
+
# busy_aps is u2fh (always undefined if -j0) so this is safe
|
2480
2519
|
self.busy_aps = busy_aps
|
2520
|
+
got_lock = False
|
2481
2521
|
try:
|
2482
2522
|
# bit expensive; 3.9=10x 3.11=2x
|
2483
2523
|
if self.mutex.acquire(timeout=10):
|
2484
|
-
|
2485
|
-
self.
|
2524
|
+
got_lock = True
|
2525
|
+
with self.reg_mutex:
|
2526
|
+
return self._handle_json(cj)
|
2486
2527
|
else:
|
2487
2528
|
t = "cannot receive uploads right now;\nserver busy with {}.\nPlease wait; the client will retry..."
|
2488
2529
|
raise Pebkac(503, t.format(self.blocked or "[unknown]"))
|
2489
2530
|
except TypeError:
|
2490
2531
|
if not PY2:
|
2491
2532
|
raise
|
2492
|
-
with self.mutex:
|
2493
|
-
self.
|
2533
|
+
with self.mutex, self.reg_mutex:
|
2534
|
+
return self._handle_json(cj)
|
2535
|
+
finally:
|
2536
|
+
if got_lock:
|
2537
|
+
self.mutex.release()
|
2494
2538
|
|
2539
|
+
def _handle_json(self, cj ) :
|
2495
2540
|
ptop = cj["ptop"]
|
2541
|
+
if not self.register_vpath(ptop, cj["vcfg"]):
|
2542
|
+
if ptop not in self.registry:
|
2543
|
+
raise Pebkac(410, "location unavailable")
|
2544
|
+
|
2496
2545
|
cj["name"] = sanitize_fn(cj["name"], "", [".prologue.html", ".epilogue.html"])
|
2497
2546
|
cj["poke"] = now = self.db_act = self.vol_act[ptop] = time.time()
|
2498
2547
|
wark = self._get_wark(cj)
|
@@ -2507,7 +2556,7 @@ class Up2k(object):
|
|
2507
2556
|
# refuse out-of-order / multithreaded uploading if sprs False
|
2508
2557
|
sprs = self.fstab.get(pdir) != "ng"
|
2509
2558
|
|
2510
|
-
|
2559
|
+
if True:
|
2511
2560
|
jcur = self.cur.get(ptop)
|
2512
2561
|
reg = self.registry[ptop]
|
2513
2562
|
vfs = self.asrv.vfs.all_vols[cj["vtop"]]
|
@@ -2945,7 +2994,7 @@ class Up2k(object):
|
|
2945
2994
|
def handle_chunk(
|
2946
2995
|
self, ptop , wark , chash
|
2947
2996
|
) :
|
2948
|
-
with self.mutex:
|
2997
|
+
with self.mutex, self.reg_mutex:
|
2949
2998
|
self.db_act = self.vol_act[ptop] = time.time()
|
2950
2999
|
job = self.registry[ptop].get(wark)
|
2951
3000
|
if not job:
|
@@ -2988,7 +3037,7 @@ class Up2k(object):
|
|
2988
3037
|
return chunksize, ofs, path, job["lmod"], job["sprs"]
|
2989
3038
|
|
2990
3039
|
def release_chunk(self, ptop , wark , chash ) :
|
2991
|
-
with self.
|
3040
|
+
with self.reg_mutex:
|
2992
3041
|
job = self.registry[ptop].get(wark)
|
2993
3042
|
if job:
|
2994
3043
|
job["busy"].pop(chash, None)
|
@@ -2996,7 +3045,7 @@ class Up2k(object):
|
|
2996
3045
|
return True
|
2997
3046
|
|
2998
3047
|
def confirm_chunk(self, ptop , wark , chash ) :
|
2999
|
-
with self.mutex:
|
3048
|
+
with self.mutex, self.reg_mutex:
|
3000
3049
|
self.db_act = self.vol_act[ptop] = time.time()
|
3001
3050
|
try:
|
3002
3051
|
job = self.registry[ptop][wark]
|
@@ -3019,16 +3068,16 @@ class Up2k(object):
|
|
3019
3068
|
|
3020
3069
|
if self.args.nw:
|
3021
3070
|
self.regdrop(ptop, wark)
|
3022
|
-
return ret, dst
|
3023
3071
|
|
3024
3072
|
return ret, dst
|
3025
3073
|
|
3026
3074
|
def finish_upload(self, ptop , wark , busy_aps ) :
|
3027
3075
|
self.busy_aps = busy_aps
|
3028
|
-
with self.mutex:
|
3076
|
+
with self.mutex, self.reg_mutex:
|
3029
3077
|
self._finish_upload(ptop, wark)
|
3030
3078
|
|
3031
3079
|
def _finish_upload(self, ptop , wark ) :
|
3080
|
+
"""mutex(main,reg) me"""
|
3032
3081
|
try:
|
3033
3082
|
job = self.registry[ptop][wark]
|
3034
3083
|
pdir = djoin(job["ptop"], job["prel"])
|
@@ -3041,12 +3090,11 @@ class Up2k(object):
|
|
3041
3090
|
t = "finish_upload {} with remaining chunks {}"
|
3042
3091
|
raise Pebkac(500, t.format(wark, job["need"]))
|
3043
3092
|
|
3044
|
-
# self.log("--- " + wark + " " + dst + " finish_upload atomic " + dst, 4)
|
3045
|
-
atomic_move(src, dst)
|
3046
|
-
|
3047
3093
|
upt = job.get("at") or time.time()
|
3048
3094
|
vflags = self.flags[ptop]
|
3049
3095
|
|
3096
|
+
atomic_move(self.log, src, dst, vflags)
|
3097
|
+
|
3050
3098
|
times = (int(time.time()), int(job["lmod"]))
|
3051
3099
|
self.log(
|
3052
3100
|
"no more chunks, setting times {} ({}) on {}".format(
|
@@ -3102,6 +3150,7 @@ class Up2k(object):
|
|
3102
3150
|
cur.connection.commit()
|
3103
3151
|
|
3104
3152
|
def regdrop(self, ptop , wark ) :
|
3153
|
+
"""mutex(main,reg) me"""
|
3105
3154
|
olds = self.droppable[ptop]
|
3106
3155
|
if wark:
|
3107
3156
|
olds.append(wark)
|
@@ -3196,16 +3245,23 @@ class Up2k(object):
|
|
3196
3245
|
at ,
|
3197
3246
|
skip_xau = False,
|
3198
3247
|
) :
|
3248
|
+
"""mutex(main) me"""
|
3199
3249
|
self.db_rm(db, rd, fn, sz)
|
3200
3250
|
|
3251
|
+
if not ip:
|
3252
|
+
db_ip = ""
|
3253
|
+
else:
|
3254
|
+
# plugins may expect this to look like an actual IP
|
3255
|
+
db_ip = "1.1.1.1" if self.args.no_db_ip else ip
|
3256
|
+
|
3201
3257
|
sql = "insert into up values (?,?,?,?,?,?,?)"
|
3202
|
-
v = (wark, int(ts), sz, rd, fn,
|
3258
|
+
v = (wark, int(ts), sz, rd, fn, db_ip, int(at or 0))
|
3203
3259
|
try:
|
3204
3260
|
db.execute(sql, v)
|
3205
3261
|
except:
|
3206
3262
|
assert self.mem_cur
|
3207
3263
|
rd, fn = s3enc(self.mem_cur, rd, fn)
|
3208
|
-
v = (wark, int(ts), sz, rd, fn,
|
3264
|
+
v = (wark, int(ts), sz, rd, fn, db_ip, int(at or 0))
|
3209
3265
|
db.execute(sql, v)
|
3210
3266
|
|
3211
3267
|
self.volsize[db] += sz
|
@@ -3309,7 +3365,7 @@ class Up2k(object):
|
|
3309
3365
|
vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0])
|
3310
3366
|
vn, rem = vn.get_dbv(rem)
|
3311
3367
|
ptop = vn.realpath
|
3312
|
-
with self.mutex:
|
3368
|
+
with self.mutex, self.reg_mutex:
|
3313
3369
|
abrt_cfg = self.flags.get(ptop, {}).get("u2abort", 1)
|
3314
3370
|
addr = (ip or "\n") if abrt_cfg in (1, 2) else ""
|
3315
3371
|
user = (uname or "\n") if abrt_cfg in (1, 3) else ""
|
@@ -3317,7 +3373,10 @@ class Up2k(object):
|
|
3317
3373
|
for wark, job in reg.items():
|
3318
3374
|
if (user and user != job["user"]) or (addr and addr != job["addr"]):
|
3319
3375
|
continue
|
3320
|
-
|
3376
|
+
jrem = djoin(job["prel"], job["name"])
|
3377
|
+
if ANYWIN:
|
3378
|
+
jrem = jrem.replace("\\", "/")
|
3379
|
+
if jrem == rem:
|
3321
3380
|
if job["ptop"] != ptop:
|
3322
3381
|
t = "job.ptop [%s] != vol.ptop [%s] ??"
|
3323
3382
|
raise Exception(t % (job["ptop"] != ptop))
|
@@ -3413,7 +3472,7 @@ class Up2k(object):
|
|
3413
3472
|
continue
|
3414
3473
|
|
3415
3474
|
n_files += 1
|
3416
|
-
with self.mutex:
|
3475
|
+
with self.mutex, self.reg_mutex:
|
3417
3476
|
cur = None
|
3418
3477
|
try:
|
3419
3478
|
ptop = dbv.realpath
|
@@ -3531,6 +3590,7 @@ class Up2k(object):
|
|
3531
3590
|
def _mv_file(
|
3532
3591
|
self, uname , svp , dvp , curs
|
3533
3592
|
) :
|
3593
|
+
"""mutex(main) me; will mutex(reg)"""
|
3534
3594
|
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
|
3535
3595
|
svn, srem = svn.get_dbv(srem)
|
3536
3596
|
|
@@ -3611,7 +3671,9 @@ class Up2k(object):
|
|
3611
3671
|
if c2 and c2 != c1:
|
3612
3672
|
self._copy_tags(c1, c2, w)
|
3613
3673
|
|
3614
|
-
|
3674
|
+
with self.reg_mutex:
|
3675
|
+
has_dupes = self._forget_file(svn.realpath, srem, c1, w, is_xvol, fsize)
|
3676
|
+
|
3615
3677
|
if not is_xvol:
|
3616
3678
|
has_dupes = self._relink(w, svn.realpath, srem, dabs)
|
3617
3679
|
|
@@ -3650,7 +3712,7 @@ class Up2k(object):
|
|
3650
3712
|
self._symlink(dlink, dabs, dvn.flags, lmod=ftime)
|
3651
3713
|
wunlink(self.log, sabs, svn.flags)
|
3652
3714
|
else:
|
3653
|
-
atomic_move(sabs, dabs)
|
3715
|
+
atomic_move(self.log, sabs, dabs, svn.flags)
|
3654
3716
|
|
3655
3717
|
except OSError as ex:
|
3656
3718
|
if ex.errno != errno.EXDEV:
|
@@ -3741,7 +3803,10 @@ class Up2k(object):
|
|
3741
3803
|
drop_tags ,
|
3742
3804
|
sz ,
|
3743
3805
|
) :
|
3744
|
-
"""
|
3806
|
+
"""
|
3807
|
+
mutex(main,reg) me
|
3808
|
+
forgets file in db, fixes symlinks, does not delete
|
3809
|
+
"""
|
3745
3810
|
srd, sfn = vsplit(vrem)
|
3746
3811
|
has_dupes = False
|
3747
3812
|
self.log("forgetting {}".format(vrem))
|
@@ -3827,8 +3892,7 @@ class Up2k(object):
|
|
3827
3892
|
self.log("linkswap [{}] and [{}]".format(sabs, slabs))
|
3828
3893
|
mt = bos.path.getmtime(slabs, False)
|
3829
3894
|
flags = self.flags.get(ptop) or {}
|
3830
|
-
|
3831
|
-
bos.rename(sabs, slabs)
|
3895
|
+
atomic_move(self.log, sabs, slabs, flags)
|
3832
3896
|
bos.utime(slabs, (int(time.time()), int(mt)), False)
|
3833
3897
|
self._symlink(slabs, sabs, flags, False)
|
3834
3898
|
full[slabs] = (ptop, rem)
|
@@ -4067,7 +4131,7 @@ class Up2k(object):
|
|
4067
4131
|
self.do_snapshot()
|
4068
4132
|
|
4069
4133
|
def do_snapshot(self) :
|
4070
|
-
with self.mutex:
|
4134
|
+
with self.mutex, self.reg_mutex:
|
4071
4135
|
for k, reg in self.registry.items():
|
4072
4136
|
self._snap_reg(k, reg)
|
4073
4137
|
|
@@ -4135,11 +4199,11 @@ class Up2k(object):
|
|
4135
4199
|
|
4136
4200
|
path2 = "{}.{}".format(path, os.getpid())
|
4137
4201
|
body = {"droppable": self.droppable[ptop], "registry": reg}
|
4138
|
-
j = json.dumps(body,
|
4202
|
+
j = json.dumps(body, sort_keys=True, separators=(",\n", ": ")).encode("utf-8")
|
4139
4203
|
with gzip.GzipFile(path2, "wb") as f:
|
4140
4204
|
f.write(j)
|
4141
4205
|
|
4142
|
-
atomic_move(path2, path)
|
4206
|
+
atomic_move(self.log, path2, path, VF_CAREFUL)
|
4143
4207
|
|
4144
4208
|
self.log("snap: {} |{}|".format(path, len(reg.keys())))
|
4145
4209
|
self.snap_prev[ptop] = etag
|
@@ -4208,7 +4272,7 @@ class Up2k(object):
|
|
4208
4272
|
raise Exception("invalid hash task")
|
4209
4273
|
|
4210
4274
|
try:
|
4211
|
-
if not self._hash_t(task):
|
4275
|
+
if not self._hash_t(task) and self.stop:
|
4212
4276
|
return
|
4213
4277
|
except Exception as ex:
|
4214
4278
|
self.log("failed to hash %s: %s" % (task, ex), 1)
|
@@ -4218,7 +4282,7 @@ class Up2k(object):
|
|
4218
4282
|
) :
|
4219
4283
|
ptop, vtop, flags, rd, fn, ip, at, usr, skip_xau = task
|
4220
4284
|
# self.log("hashq {} pop {}/{}/{}".format(self.n_hashq, ptop, rd, fn))
|
4221
|
-
with self.mutex:
|
4285
|
+
with self.mutex, self.reg_mutex:
|
4222
4286
|
if not self.register_vpath(ptop, flags):
|
4223
4287
|
return True
|
4224
4288
|
|
@@ -4236,7 +4300,7 @@ class Up2k(object):
|
|
4236
4300
|
|
4237
4301
|
wark = up2k_wark_from_hashlist(self.salt, inf.st_size, hashes)
|
4238
4302
|
|
4239
|
-
with self.mutex:
|
4303
|
+
with self.mutex, self.reg_mutex:
|
4240
4304
|
self.idx_wark(
|
4241
4305
|
self.flags[ptop],
|
4242
4306
|
rd,
|