copyparty 1.15.1__py3-none-any.whl → 1.15.2__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/__init__.py +1 -0
- copyparty/__main__.py +16 -12
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +11 -6
- copyparty/broker_mp.py +2 -2
- copyparty/broker_mpw.py +2 -2
- copyparty/broker_thr.py +4 -9
- copyparty/broker_util.py +13 -1
- copyparty/cfg.py +1 -0
- copyparty/fsutil.py +0 -3
- copyparty/httpcli.py +105 -60
- copyparty/httpconn.py +0 -1
- copyparty/httpsrv.py +3 -5
- copyparty/svchub.py +2 -6
- copyparty/th_srv.py +15 -7
- copyparty/u2idx.py +0 -3
- copyparty/up2k.py +206 -98
- copyparty/util.py +116 -63
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +12 -0
- copyparty/web/splash.js.gz +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/METADATA +15 -3
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/RECORD +28 -28
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/WHEEL +1 -1
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/LICENSE +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.2.dist-info}/top_level.txt +0 -0
copyparty/up2k.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
|
-
import base64
|
5
4
|
import errno
|
6
5
|
import gzip
|
7
6
|
import hashlib
|
@@ -61,6 +60,7 @@ from .util import (
|
|
61
60
|
sfsenc,
|
62
61
|
spack,
|
63
62
|
statdir,
|
63
|
+
ub64enc,
|
64
64
|
unhumanize,
|
65
65
|
vjoin,
|
66
66
|
vsplit,
|
@@ -265,19 +265,29 @@ class Up2k(object):
|
|
265
265
|
if not self.stop:
|
266
266
|
self.log("uploads are now possible", 2)
|
267
267
|
|
268
|
-
def get_state(self) :
|
268
|
+
def get_state(self, get_q , uname ) :
|
269
269
|
mtpq = 0
|
270
|
+
ups = []
|
271
|
+
up_en = not self.args.no_up_list
|
270
272
|
q = "select count(w) from mt where k = 't:mtp'"
|
271
273
|
got_lock = False if PY2 else self.mutex.acquire(timeout=0.5)
|
272
274
|
if got_lock:
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
275
|
+
try:
|
276
|
+
for cur in self.cur.values() if get_q else []:
|
277
|
+
try:
|
278
|
+
mtpq += cur.execute(q).fetchone()[0]
|
279
|
+
except:
|
280
|
+
pass
|
281
|
+
if uname and up_en:
|
282
|
+
ups = self._active_uploads(uname)
|
283
|
+
finally:
|
284
|
+
self.mutex.release()
|
279
285
|
else:
|
280
286
|
mtpq = "(?)"
|
287
|
+
if up_en:
|
288
|
+
ups = [(0, 0, time.time(), "cannot show list (server too busy)")]
|
289
|
+
|
290
|
+
ups.sort(reverse=True)
|
281
291
|
|
282
292
|
ret = {
|
283
293
|
"volstate": self.volstate,
|
@@ -285,6 +295,7 @@ class Up2k(object):
|
|
285
295
|
"hashq": self.n_hashq,
|
286
296
|
"tagq": self.n_tagq,
|
287
297
|
"mtpq": mtpq,
|
298
|
+
"ups": ups,
|
288
299
|
"dbwu": "{:.2f}".format(self.db_act),
|
289
300
|
"dbwt": "{:.2f}".format(
|
290
301
|
min(1000 * 24 * 60 * 60 - 1, time.time() - self.db_act)
|
@@ -292,6 +303,32 @@ class Up2k(object):
|
|
292
303
|
}
|
293
304
|
return json.dumps(ret, separators=(",\n", ": "))
|
294
305
|
|
306
|
+
def _active_uploads(self, uname ) :
|
307
|
+
ret = []
|
308
|
+
for vtop in self.asrv.vfs.aread[uname]:
|
309
|
+
vfs = self.asrv.vfs.all_vols.get(vtop)
|
310
|
+
if not vfs: # dbv only
|
311
|
+
continue
|
312
|
+
ptop = vfs.realpath
|
313
|
+
tab = self.registry.get(ptop)
|
314
|
+
if not tab:
|
315
|
+
continue
|
316
|
+
for job in tab.values():
|
317
|
+
ineed = len(job["need"])
|
318
|
+
ihash = len(job["hash"])
|
319
|
+
if ineed == ihash or not ineed:
|
320
|
+
continue
|
321
|
+
|
322
|
+
zt = (
|
323
|
+
ineed / ihash,
|
324
|
+
job["size"],
|
325
|
+
int(job["t0"]),
|
326
|
+
int(job["poke"]),
|
327
|
+
djoin(vtop, job["prel"], job["name"]),
|
328
|
+
)
|
329
|
+
ret.append(zt)
|
330
|
+
return ret
|
331
|
+
|
295
332
|
def find_job_by_ap(self, ptop , ap ) :
|
296
333
|
try:
|
297
334
|
if ANYWIN:
|
@@ -572,7 +609,6 @@ class Up2k(object):
|
|
572
609
|
return timeout
|
573
610
|
|
574
611
|
def _check_shares(self) :
|
575
|
-
assert sqlite3 # type: ignore
|
576
612
|
|
577
613
|
now = time.time()
|
578
614
|
timeout = now + 9001
|
@@ -893,7 +929,6 @@ class Up2k(object):
|
|
893
929
|
with self.mutex, self.reg_mutex:
|
894
930
|
reg = self.register_vpath(vol.realpath, vol.flags)
|
895
931
|
|
896
|
-
assert reg
|
897
932
|
cur, _ = reg
|
898
933
|
with self.mutex:
|
899
934
|
cur.connection.commit()
|
@@ -910,7 +945,6 @@ class Up2k(object):
|
|
910
945
|
reg = self.register_vpath(vol.realpath, vol.flags)
|
911
946
|
|
912
947
|
try:
|
913
|
-
assert reg
|
914
948
|
cur, db_path = reg
|
915
949
|
if bos.path.getsize(db_path + "-wal") < 1024 * 1024 * 5:
|
916
950
|
continue
|
@@ -1116,7 +1150,7 @@ class Up2k(object):
|
|
1116
1150
|
zsl = [x[len(prefix) :] for x in zsl]
|
1117
1151
|
zsl.sort()
|
1118
1152
|
zb = hashlib.sha1("\n".join(zsl).encode("utf-8", "replace")).digest()
|
1119
|
-
vcfg =
|
1153
|
+
vcfg = ub64enc(zb[:18]).decode("ascii")
|
1120
1154
|
|
1121
1155
|
c = cur.execute("select v from kv where k = 'volcfg'")
|
1122
1156
|
try:
|
@@ -1145,7 +1179,6 @@ class Up2k(object):
|
|
1145
1179
|
with self.reg_mutex:
|
1146
1180
|
reg = self.register_vpath(top, vol.flags)
|
1147
1181
|
|
1148
|
-
assert reg and self.pp
|
1149
1182
|
cur, db_path = reg
|
1150
1183
|
|
1151
1184
|
db = Dbw(cur, 0, time.time())
|
@@ -1164,6 +1197,10 @@ class Up2k(object):
|
|
1164
1197
|
# ~/.wine/dosdevices/z:/ and such
|
1165
1198
|
excl.extend(("/dev", "/proc", "/run", "/sys"))
|
1166
1199
|
|
1200
|
+
if self.args.re_dirsz:
|
1201
|
+
db.c.execute("delete from ds")
|
1202
|
+
db.n += 1
|
1203
|
+
|
1167
1204
|
rtop = absreal(top)
|
1168
1205
|
n_add = n_rm = 0
|
1169
1206
|
try:
|
@@ -1172,7 +1209,7 @@ class Up2k(object):
|
|
1172
1209
|
self.log(t % (vol.vpath, rtop), 6)
|
1173
1210
|
return True, False
|
1174
1211
|
|
1175
|
-
n_add = self._build_dir(
|
1212
|
+
n_add, _, _ = self._build_dir(
|
1176
1213
|
db,
|
1177
1214
|
top,
|
1178
1215
|
set(excl),
|
@@ -1246,17 +1283,18 @@ class Up2k(object):
|
|
1246
1283
|
cst ,
|
1247
1284
|
dev ,
|
1248
1285
|
xvol ,
|
1249
|
-
)
|
1286
|
+
) :
|
1250
1287
|
if xvol and not rcdir.startswith(top):
|
1251
1288
|
self.log("skip xvol: [{}] -> [{}]".format(cdir, rcdir), 6)
|
1252
|
-
return 0
|
1289
|
+
return 0, 0, 0
|
1253
1290
|
|
1254
1291
|
if rcdir in seen:
|
1255
1292
|
t = "bailing from symlink loop,\n prev: {}\n curr: {}\n from: {}"
|
1256
1293
|
self.log(t.format(seen[-1], rcdir, cdir), 3)
|
1257
|
-
return 0
|
1294
|
+
return 0, 0, 0
|
1258
1295
|
|
1259
|
-
|
1296
|
+
# total-files-added, total-num-files, recursive-size
|
1297
|
+
tfa = tnf = rsz = 0
|
1260
1298
|
seen = seen + [rcdir]
|
1261
1299
|
unreg = []
|
1262
1300
|
files = []
|
@@ -1266,22 +1304,24 @@ class Up2k(object):
|
|
1266
1304
|
th_cvd = self.args.th_coversd
|
1267
1305
|
th_cvds = self.args.th_coversd_set
|
1268
1306
|
|
1269
|
-
assert self.pp and self.mem_cur
|
1270
1307
|
self.pp.msg = "a%d %s" % (self.pp.n, cdir)
|
1271
1308
|
|
1272
1309
|
rd = cdir[len(top) :].strip("/")
|
1273
1310
|
if WINDOWS:
|
1274
1311
|
rd = rd.replace("\\", "/").strip("/")
|
1275
1312
|
|
1313
|
+
rds = rd + "/" if rd else ""
|
1314
|
+
cdirs = cdir + os.sep
|
1315
|
+
|
1276
1316
|
g = statdir(self.log_func, not self.args.no_scandir, True, cdir)
|
1277
1317
|
gl = sorted(g)
|
1278
1318
|
partials = set([x[0] for x in gl if "PARTIAL" in x[0]])
|
1279
1319
|
for iname, inf in gl:
|
1280
1320
|
if self.stop:
|
1281
|
-
return -1
|
1321
|
+
return -1, 0, 0
|
1282
1322
|
|
1283
|
-
rp =
|
1284
|
-
abspath =
|
1323
|
+
rp = rds + iname
|
1324
|
+
abspath = cdirs + iname
|
1285
1325
|
|
1286
1326
|
if rei and rei.search(abspath):
|
1287
1327
|
unreg.append(rp)
|
@@ -1315,7 +1355,7 @@ class Up2k(object):
|
|
1315
1355
|
continue
|
1316
1356
|
# self.log(" dir: {}".format(abspath))
|
1317
1357
|
try:
|
1318
|
-
|
1358
|
+
i1, i2, i3 = self._build_dir(
|
1319
1359
|
db,
|
1320
1360
|
top,
|
1321
1361
|
excl,
|
@@ -1330,6 +1370,9 @@ class Up2k(object):
|
|
1330
1370
|
dev,
|
1331
1371
|
xvol,
|
1332
1372
|
)
|
1373
|
+
tfa += i1
|
1374
|
+
tnf += i2
|
1375
|
+
rsz += i3
|
1333
1376
|
except:
|
1334
1377
|
t = "failed to index subdir [{}]:\n{}"
|
1335
1378
|
self.log(t.format(abspath, min_ex()), c=1)
|
@@ -1348,6 +1391,7 @@ class Up2k(object):
|
|
1348
1391
|
# placeholder for unfinished upload
|
1349
1392
|
continue
|
1350
1393
|
|
1394
|
+
rsz += sz
|
1351
1395
|
files.append((sz, lmod, iname))
|
1352
1396
|
liname = iname.lower()
|
1353
1397
|
if (
|
@@ -1369,6 +1413,18 @@ class Up2k(object):
|
|
1369
1413
|
):
|
1370
1414
|
cv = iname
|
1371
1415
|
|
1416
|
+
if not self.args.no_dirsz:
|
1417
|
+
tnf += len(files)
|
1418
|
+
q = "select sz, nf from ds where rd=? limit 1"
|
1419
|
+
try:
|
1420
|
+
db_sz, db_nf = db.c.execute(q, (rd,)).fetchone() or (-1, -1)
|
1421
|
+
if rsz != db_sz or tnf != db_nf:
|
1422
|
+
db.c.execute("delete from ds where rd=?", (rd,))
|
1423
|
+
db.c.execute("insert into ds values (?,?,?)", (rd, rsz, tnf))
|
1424
|
+
db.n += 1
|
1425
|
+
except:
|
1426
|
+
pass # mojibake rd
|
1427
|
+
|
1372
1428
|
# folder of 1000 files = ~1 MiB RAM best-case (tiny filenames);
|
1373
1429
|
# free up stuff we're done with before dhashing
|
1374
1430
|
gl = []
|
@@ -1382,7 +1438,7 @@ class Up2k(object):
|
|
1382
1438
|
|
1383
1439
|
zh.update(cv.encode("utf-8", "replace"))
|
1384
1440
|
zh.update(spack(b"<d", cst.st_mtime))
|
1385
|
-
dhash =
|
1441
|
+
dhash = ub64enc(zh.digest()[:12]).decode("ascii")
|
1386
1442
|
sql = "select d from dh where d=? and +h=?"
|
1387
1443
|
try:
|
1388
1444
|
c = db.c.execute(sql, (rd, dhash))
|
@@ -1392,7 +1448,7 @@ class Up2k(object):
|
|
1392
1448
|
c = db.c.execute(sql, (drd, dhash))
|
1393
1449
|
|
1394
1450
|
if c.fetchone():
|
1395
|
-
return
|
1451
|
+
return tfa, tnf, rsz
|
1396
1452
|
|
1397
1453
|
if cv and rd:
|
1398
1454
|
# mojibake not supported (for performance / simplicity):
|
@@ -1409,10 +1465,10 @@ class Up2k(object):
|
|
1409
1465
|
seen_files = set([x[2] for x in files]) # for dropcheck
|
1410
1466
|
for sz, lmod, fn in files:
|
1411
1467
|
if self.stop:
|
1412
|
-
return -1
|
1468
|
+
return -1, 0, 0
|
1413
1469
|
|
1414
|
-
rp =
|
1415
|
-
abspath =
|
1470
|
+
rp = rds + fn
|
1471
|
+
abspath = cdirs + fn
|
1416
1472
|
nohash = reh.search(abspath) if reh else False
|
1417
1473
|
|
1418
1474
|
sql = "select w, mt, sz, ip, at from up where rd = ? and fn = ?"
|
@@ -1442,7 +1498,7 @@ class Up2k(object):
|
|
1442
1498
|
)
|
1443
1499
|
self.log(t)
|
1444
1500
|
self.db_rm(db.c, rd, fn, 0)
|
1445
|
-
|
1501
|
+
tfa += 1
|
1446
1502
|
db.n += 1
|
1447
1503
|
in_db = []
|
1448
1504
|
else:
|
@@ -1467,7 +1523,7 @@ class Up2k(object):
|
|
1467
1523
|
continue
|
1468
1524
|
|
1469
1525
|
if not hashes:
|
1470
|
-
return -1
|
1526
|
+
return -1, 0, 0
|
1471
1527
|
|
1472
1528
|
wark = up2k_wark_from_hashlist(self.salt, sz, hashes)
|
1473
1529
|
|
@@ -1478,7 +1534,7 @@ class Up2k(object):
|
|
1478
1534
|
# skip upload hooks by not providing vflags
|
1479
1535
|
self.db_add(db.c, {}, rd, fn, lmod, sz, "", "", wark, "", "", ip, at)
|
1480
1536
|
db.n += 1
|
1481
|
-
|
1537
|
+
tfa += 1
|
1482
1538
|
td = time.time() - db.t
|
1483
1539
|
if db.n >= 4096 or td >= 60:
|
1484
1540
|
self.log("commit {} new files".format(db.n))
|
@@ -1491,33 +1547,37 @@ class Up2k(object):
|
|
1491
1547
|
db.c.execute("insert into dh values (?,?)", (drd, dhash)) # type: ignore
|
1492
1548
|
|
1493
1549
|
if self.stop:
|
1494
|
-
return -1
|
1550
|
+
return -1, 0, 0
|
1495
1551
|
|
1496
1552
|
# drop shadowed folders
|
1497
1553
|
for sh_rd in unreg:
|
1498
1554
|
n = 0
|
1499
|
-
q = "select count(w) from up where (rd
|
1555
|
+
q = "select count(w) from up where (rd=? or rd like ?||'/%') and +at == 0"
|
1500
1556
|
for sh_erd in [sh_rd, "//" + w8b64enc(sh_rd)]:
|
1501
1557
|
try:
|
1502
|
-
|
1558
|
+
erd_erd = (sh_erd, sh_erd)
|
1559
|
+
n = db.c.execute(q, erd_erd).fetchone()[0]
|
1503
1560
|
break
|
1504
1561
|
except:
|
1505
1562
|
pass
|
1506
1563
|
|
1564
|
+
|
1507
1565
|
if n:
|
1508
1566
|
t = "forgetting {} shadowed autoindexed files in [{}] > [{}]"
|
1509
1567
|
self.log(t.format(n, top, sh_rd))
|
1510
|
-
assert sh_erd # type: ignore
|
1511
1568
|
|
1512
|
-
q = "delete from dh where (d = ? or d like ?||'
|
1513
|
-
db.c.execute(q,
|
1569
|
+
q = "delete from dh where (d = ? or d like ?||'/%')"
|
1570
|
+
db.c.execute(q, erd_erd)
|
1514
1571
|
|
1515
|
-
q = "delete from up where (rd
|
1516
|
-
db.c.execute(q,
|
1517
|
-
|
1572
|
+
q = "delete from up where (rd=? or rd like ?||'/%') and +at == 0"
|
1573
|
+
db.c.execute(q, erd_erd)
|
1574
|
+
tfa += n
|
1575
|
+
|
1576
|
+
q = "delete from ds where (rd=? or rd like ?||'/%')"
|
1577
|
+
db.c.execute(q, erd_erd)
|
1518
1578
|
|
1519
1579
|
if n4g:
|
1520
|
-
return
|
1580
|
+
return tfa, tnf, rsz
|
1521
1581
|
|
1522
1582
|
# drop missing files
|
1523
1583
|
q = "select fn from up where rd = ?"
|
@@ -1535,7 +1595,7 @@ class Up2k(object):
|
|
1535
1595
|
if n_rm:
|
1536
1596
|
self.log("forgot {} deleted files".format(n_rm))
|
1537
1597
|
|
1538
|
-
return
|
1598
|
+
return tfa, tnf, rsz
|
1539
1599
|
|
1540
1600
|
def _drop_lost(self, cur , top , excl ) :
|
1541
1601
|
rm = []
|
@@ -1610,7 +1670,7 @@ class Up2k(object):
|
|
1610
1670
|
|
1611
1671
|
# then covers
|
1612
1672
|
n_rm3 = 0
|
1613
|
-
qu = "select 1 from up where rd=? and
|
1673
|
+
qu = "select 1 from up where rd=? and fn=? limit 1"
|
1614
1674
|
q = "delete from cv where rd=? and dn=? and +fn=?"
|
1615
1675
|
for crd, cdn, fn in cur.execute("select * from cv"):
|
1616
1676
|
urd = vjoin(crd, cdn)
|
@@ -1753,13 +1813,13 @@ class Up2k(object):
|
|
1753
1813
|
return 0
|
1754
1814
|
|
1755
1815
|
with self.mutex:
|
1816
|
+
q = "update up set w=?, sz=?, mt=? where rd=? and fn=?"
|
1756
1817
|
for rd, fn, w, sz, mt in rewark:
|
1757
|
-
q = "update up set w = ?, sz = ?, mt = ? where rd = ? and fn = ? limit 1"
|
1758
1818
|
cur.execute(q, (w, sz, int(mt), rd, fn))
|
1759
1819
|
|
1760
|
-
|
1761
|
-
q = "delete from up where
|
1762
|
-
cur.
|
1820
|
+
if f404:
|
1821
|
+
q = "delete from up where rd=? and fn=? and +w=?"
|
1822
|
+
cur.executemany(q, f404)
|
1763
1823
|
|
1764
1824
|
cur.connection.commit()
|
1765
1825
|
|
@@ -2226,7 +2286,6 @@ class Up2k(object):
|
|
2226
2286
|
# mp.pool.ThreadPool and concurrent.futures.ThreadPoolExecutor
|
2227
2287
|
# both do crazy runahead so lets reinvent another wheel
|
2228
2288
|
nw = max(1, self.args.mtag_mt)
|
2229
|
-
assert self.mtag
|
2230
2289
|
if not self.mpool_used:
|
2231
2290
|
self.mpool_used = True
|
2232
2291
|
self.log("using {}x {}".format(nw, self.mtag.backend))
|
@@ -2300,7 +2359,6 @@ class Up2k(object):
|
|
2300
2359
|
at ,
|
2301
2360
|
) :
|
2302
2361
|
"""will mutex(main)"""
|
2303
|
-
assert self.mtag
|
2304
2362
|
|
2305
2363
|
try:
|
2306
2364
|
st = bos.stat(abspath)
|
@@ -2332,7 +2390,6 @@ class Up2k(object):
|
|
2332
2390
|
tags ,
|
2333
2391
|
) :
|
2334
2392
|
"""mutex(main) me"""
|
2335
|
-
assert self.mtag
|
2336
2393
|
|
2337
2394
|
if not bos.path.isfile(abspath):
|
2338
2395
|
return 0
|
@@ -2388,7 +2445,7 @@ class Up2k(object):
|
|
2388
2445
|
def _log_sqlite_incompat(self, db_path, t0) :
|
2389
2446
|
txt = t0 or ""
|
2390
2447
|
digest = hashlib.sha512(db_path.encode("utf-8", "replace")).digest()
|
2391
|
-
stackname =
|
2448
|
+
stackname = ub64enc(digest[:9]).decode("ascii")
|
2392
2449
|
stackpath = os.path.join(E.cfg, "stack-%s.txt" % (stackname,))
|
2393
2450
|
|
2394
2451
|
t = " the filesystem at %s may not support locking, or is otherwise incompatible with sqlite\n\n %s\n\n"
|
@@ -2431,12 +2488,11 @@ class Up2k(object):
|
|
2431
2488
|
self.log("WARN: failed to upgrade from v4", 3)
|
2432
2489
|
|
2433
2490
|
if ver == DB_VER:
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
pass
|
2491
|
+
self._add_dhash_tab(cur)
|
2492
|
+
self._add_xiu_tab(cur)
|
2493
|
+
self._add_cv_tab(cur)
|
2494
|
+
self._add_idx_up_vp(cur, db_path)
|
2495
|
+
self._add_ds_tab(cur)
|
2440
2496
|
|
2441
2497
|
try:
|
2442
2498
|
nfiles = next(cur.execute("select count(w) from up"))[0]
|
@@ -2533,9 +2589,10 @@ class Up2k(object):
|
|
2533
2589
|
|
2534
2590
|
for cmd in [
|
2535
2591
|
r"create table up (w text, mt int, sz int, rd text, fn text, ip text, at int)",
|
2536
|
-
r"create index
|
2592
|
+
r"create index up_vp on up(rd, fn)",
|
2537
2593
|
r"create index up_fn on up(fn)",
|
2538
2594
|
r"create index up_ip on up(ip)",
|
2595
|
+
r"create index up_at on up(at)",
|
2539
2596
|
idx,
|
2540
2597
|
r"create table mt (w text, k text, v int)",
|
2541
2598
|
r"create index mt_w on mt(w)",
|
@@ -2549,6 +2606,7 @@ class Up2k(object):
|
|
2549
2606
|
self._add_dhash_tab(cur)
|
2550
2607
|
self._add_xiu_tab(cur)
|
2551
2608
|
self._add_cv_tab(cur)
|
2609
|
+
self._add_ds_tab(cur)
|
2552
2610
|
self.log("created DB at {}".format(db_path))
|
2553
2611
|
return cur
|
2554
2612
|
|
@@ -2565,6 +2623,12 @@ class Up2k(object):
|
|
2565
2623
|
|
2566
2624
|
def _add_dhash_tab(self, cur ) :
|
2567
2625
|
# v5 -> v5a
|
2626
|
+
try:
|
2627
|
+
cur.execute("select d, h from dh limit 1").fetchone()
|
2628
|
+
return
|
2629
|
+
except:
|
2630
|
+
pass
|
2631
|
+
|
2568
2632
|
for cmd in [
|
2569
2633
|
r"create table dh (d text, h text)",
|
2570
2634
|
r"create index dh_d on dh(d)",
|
@@ -2618,6 +2682,40 @@ class Up2k(object):
|
|
2618
2682
|
|
2619
2683
|
cur.connection.commit()
|
2620
2684
|
|
2685
|
+
def _add_idx_up_vp(self, cur , db_path ) :
|
2686
|
+
# v5c -> v5d
|
2687
|
+
try:
|
2688
|
+
cur.execute("drop index up_rd")
|
2689
|
+
except:
|
2690
|
+
return
|
2691
|
+
|
2692
|
+
for cmd in [
|
2693
|
+
r"create index up_vp on up(rd, fn)",
|
2694
|
+
r"create index up_at on up(at)",
|
2695
|
+
]:
|
2696
|
+
self.log("upgrading db [%s]: %s" % (db_path, cmd[:18]))
|
2697
|
+
cur.execute(cmd)
|
2698
|
+
|
2699
|
+
self.log("upgrading db [%s]: writing to disk..." % (db_path,))
|
2700
|
+
cur.connection.commit()
|
2701
|
+
cur.execute("vacuum")
|
2702
|
+
|
2703
|
+
def _add_ds_tab(self, cur ) :
|
2704
|
+
# v5d -> v5e
|
2705
|
+
try:
|
2706
|
+
cur.execute("select rd, sz from ds limit 1").fetchone()
|
2707
|
+
return
|
2708
|
+
except:
|
2709
|
+
pass
|
2710
|
+
|
2711
|
+
for cmd in [
|
2712
|
+
r"create table ds (rd text, sz int, nf int)",
|
2713
|
+
r"create index ds_rd on ds(rd)",
|
2714
|
+
]:
|
2715
|
+
cur.execute(cmd)
|
2716
|
+
|
2717
|
+
cur.connection.commit()
|
2718
|
+
|
2621
2719
|
def wake_rescanner(self):
|
2622
2720
|
with self.rescan_cond:
|
2623
2721
|
self.rescan_cond.notify_all()
|
@@ -2802,7 +2900,6 @@ class Up2k(object):
|
|
2802
2900
|
|
2803
2901
|
c2 = cur
|
2804
2902
|
|
2805
|
-
assert c2
|
2806
2903
|
c2.connection.commit()
|
2807
2904
|
|
2808
2905
|
cur = jcur
|
@@ -2907,9 +3004,12 @@ class Up2k(object):
|
|
2907
3004
|
job = deepcopy(job)
|
2908
3005
|
job["wark"] = wark
|
2909
3006
|
job["at"] = cj.get("at") or time.time()
|
2910
|
-
zs = "
|
3007
|
+
zs = "vtop ptop prel name lmod host user addr poke"
|
2911
3008
|
for k in zs.split():
|
2912
3009
|
job[k] = cj.get(k) or ""
|
3010
|
+
for k in ("life", "replace"):
|
3011
|
+
if k in cj:
|
3012
|
+
job[k] = cj[k]
|
2913
3013
|
|
2914
3014
|
pdir = djoin(cj["ptop"], cj["prel"])
|
2915
3015
|
if rand:
|
@@ -3010,18 +3110,8 @@ class Up2k(object):
|
|
3010
3110
|
"busy": {},
|
3011
3111
|
}
|
3012
3112
|
# client-provided, sanitized by _get_wark: name, size, lmod
|
3013
|
-
|
3014
|
-
|
3015
|
-
"user",
|
3016
|
-
"addr",
|
3017
|
-
"vtop",
|
3018
|
-
"ptop",
|
3019
|
-
"prel",
|
3020
|
-
"name",
|
3021
|
-
"size",
|
3022
|
-
"lmod",
|
3023
|
-
"poke",
|
3024
|
-
]:
|
3113
|
+
zs = "vtop ptop prel name size lmod host user addr poke"
|
3114
|
+
for k in zs.split():
|
3025
3115
|
job[k] = cj[k]
|
3026
3116
|
|
3027
3117
|
for k in ["life", "replace"]:
|
@@ -3127,8 +3217,9 @@ class Up2k(object):
|
|
3127
3217
|
dip = self.hub.iphash.s(ip)
|
3128
3218
|
|
3129
3219
|
suffix = "-%.6f-%s" % (ts, dip)
|
3130
|
-
|
3131
|
-
|
3220
|
+
f, ret = ren_open(fname, "wb", fdir=fdir, suffix=suffix)
|
3221
|
+
f.close()
|
3222
|
+
return ret
|
3132
3223
|
|
3133
3224
|
def _symlink(
|
3134
3225
|
self,
|
@@ -3275,7 +3366,6 @@ class Up2k(object):
|
|
3275
3366
|
t = "that chunk is already being written to:\n {}\n {} {}/{}\n {}"
|
3276
3367
|
raise Pebkac(400, t.format(wark, chash, idx, nh, job["name"]))
|
3277
3368
|
|
3278
|
-
assert chash # type: ignore
|
3279
3369
|
chunksize = up2k_chunksize(job["size"])
|
3280
3370
|
|
3281
3371
|
coffsets = []
|
@@ -3310,19 +3400,30 @@ class Up2k(object):
|
|
3310
3400
|
|
3311
3401
|
return chashes, chunksize, coffsets, path, job["lmod"], job["sprs"]
|
3312
3402
|
|
3313
|
-
def
|
3314
|
-
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
3403
|
+
def fast_confirm_chunks(
|
3404
|
+
self, ptop , wark , chashes
|
3405
|
+
) :
|
3406
|
+
if not self.mutex.acquire(False):
|
3407
|
+
return -1, ""
|
3408
|
+
if not self.reg_mutex.acquire(False):
|
3409
|
+
self.mutex.release()
|
3410
|
+
return -1, ""
|
3411
|
+
try:
|
3412
|
+
return self._confirm_chunks(ptop, wark, chashes)
|
3413
|
+
finally:
|
3414
|
+
self.reg_mutex.release()
|
3415
|
+
self.mutex.release()
|
3321
3416
|
|
3322
3417
|
def confirm_chunks(
|
3323
3418
|
self, ptop , wark , chashes
|
3324
3419
|
) :
|
3325
3420
|
with self.mutex, self.reg_mutex:
|
3421
|
+
return self._confirm_chunks(ptop, wark, chashes)
|
3422
|
+
|
3423
|
+
def _confirm_chunks(
|
3424
|
+
self, ptop , wark , chashes
|
3425
|
+
) :
|
3426
|
+
if True:
|
3326
3427
|
self.db_act = self.vol_act[ptop] = time.time()
|
3327
3428
|
try:
|
3328
3429
|
job = self.registry[ptop][wark]
|
@@ -3330,7 +3431,7 @@ class Up2k(object):
|
|
3330
3431
|
src = djoin(pdir, job["tnam"])
|
3331
3432
|
dst = djoin(pdir, job["name"])
|
3332
3433
|
except Exception as ex:
|
3333
|
-
return "confirm_chunk, wark(%r)" % (ex,) # type: ignore
|
3434
|
+
return -2, "confirm_chunk, wark(%r)" % (ex,) # type: ignore
|
3334
3435
|
|
3335
3436
|
for chash in chashes:
|
3336
3437
|
job["busy"].pop(chash, None)
|
@@ -3339,7 +3440,7 @@ class Up2k(object):
|
|
3339
3440
|
for chash in chashes:
|
3340
3441
|
job["need"].remove(chash)
|
3341
3442
|
except Exception as ex:
|
3342
|
-
return "confirm_chunk, chash(%s) %r" % (chash, ex) # type: ignore
|
3443
|
+
return -2, "confirm_chunk, chash(%s) %r" % (chash, ex) # type: ignore
|
3343
3444
|
|
3344
3445
|
ret = len(job["need"])
|
3345
3446
|
if ret > 0:
|
@@ -3488,7 +3589,6 @@ class Up2k(object):
|
|
3488
3589
|
cur.connection.commit()
|
3489
3590
|
except Exception as ex:
|
3490
3591
|
x = self.register_vpath(ptop, {})
|
3491
|
-
assert x
|
3492
3592
|
db_ex_chk(self.log, ex, x[1])
|
3493
3593
|
raise
|
3494
3594
|
|
@@ -3503,7 +3603,6 @@ class Up2k(object):
|
|
3503
3603
|
try:
|
3504
3604
|
r = db.execute(sql, (rd, fn))
|
3505
3605
|
except:
|
3506
|
-
assert self.mem_cur
|
3507
3606
|
r = db.execute(sql, s3enc(self.mem_cur, rd, fn))
|
3508
3607
|
|
3509
3608
|
if r.rowcount:
|
@@ -3541,7 +3640,6 @@ class Up2k(object):
|
|
3541
3640
|
try:
|
3542
3641
|
db.execute(sql, v)
|
3543
3642
|
except:
|
3544
|
-
assert self.mem_cur
|
3545
3643
|
rd, fn = s3enc(self.mem_cur, rd, fn)
|
3546
3644
|
v = (wark, int(ts), sz, rd, fn, db_ip, int(at or 0))
|
3547
3645
|
db.execute(sql, v)
|
@@ -3589,7 +3687,6 @@ class Up2k(object):
|
|
3589
3687
|
try:
|
3590
3688
|
db.execute(q, (cd, wark[:16], rd, fn))
|
3591
3689
|
except:
|
3592
|
-
assert self.mem_cur
|
3593
3690
|
rd, fn = s3enc(self.mem_cur, rd, fn)
|
3594
3691
|
db.execute(q, (cd, wark[:16], rd, fn))
|
3595
3692
|
|
@@ -3622,6 +3719,19 @@ class Up2k(object):
|
|
3622
3719
|
except:
|
3623
3720
|
pass
|
3624
3721
|
|
3722
|
+
if "nodirsz" not in vflags:
|
3723
|
+
try:
|
3724
|
+
q = "update ds set nf=nf+1, sz=sz+? where rd=?"
|
3725
|
+
q2 = "insert into ds values(?,?,1)"
|
3726
|
+
while True:
|
3727
|
+
if not db.execute(q, (sz, rd)).rowcount:
|
3728
|
+
db.execute(q2, (rd, sz))
|
3729
|
+
if not rd:
|
3730
|
+
break
|
3731
|
+
rd = rd.rsplit("/", 1)[0] if "/" in rd else ""
|
3732
|
+
except:
|
3733
|
+
pass
|
3734
|
+
|
3625
3735
|
def handle_rm(
|
3626
3736
|
self,
|
3627
3737
|
uname ,
|
@@ -4006,7 +4116,6 @@ class Up2k(object):
|
|
4006
4116
|
|
4007
4117
|
has_dupes = False
|
4008
4118
|
if w:
|
4009
|
-
assert c1
|
4010
4119
|
if c2 and c2 != c1:
|
4011
4120
|
self._copy_tags(c1, c2, w)
|
4012
4121
|
|
@@ -4144,7 +4253,6 @@ class Up2k(object):
|
|
4144
4253
|
try:
|
4145
4254
|
c = cur.execute(q, (rd, fn))
|
4146
4255
|
except:
|
4147
|
-
assert self.mem_cur
|
4148
4256
|
c = cur.execute(q, s3enc(self.mem_cur, rd, fn))
|
4149
4257
|
|
4150
4258
|
hit = c.fetchone()
|
@@ -4387,8 +4495,7 @@ class Up2k(object):
|
|
4387
4495
|
rem -= len(buf)
|
4388
4496
|
|
4389
4497
|
digest = hashobj.digest()[:33]
|
4390
|
-
|
4391
|
-
ret.append(digest.decode("utf-8"))
|
4498
|
+
ret.append(ub64enc(digest).decode("ascii"))
|
4392
4499
|
|
4393
4500
|
return ret, st
|
4394
4501
|
|
@@ -4460,8 +4567,8 @@ class Up2k(object):
|
|
4460
4567
|
dip = self.hub.iphash.s(job["addr"])
|
4461
4568
|
|
4462
4569
|
suffix = "-%.6f-%s" % (job["t0"], dip)
|
4463
|
-
|
4464
|
-
|
4570
|
+
f, job["tnam"] = ren_open(tnam, "wb", fdir=pdir, suffix=suffix)
|
4571
|
+
try:
|
4465
4572
|
abspath = djoin(pdir, job["tnam"])
|
4466
4573
|
sprs = job["sprs"]
|
4467
4574
|
sz = job["size"]
|
@@ -4508,6 +4615,8 @@ class Up2k(object):
|
|
4508
4615
|
if job["hash"] and sprs:
|
4509
4616
|
f.seek(sz - 1)
|
4510
4617
|
f.write(b"e")
|
4618
|
+
finally:
|
4619
|
+
f.close()
|
4511
4620
|
|
4512
4621
|
if not job["hash"]:
|
4513
4622
|
self._finish_upload(job["ptop"], job["wark"])
|
@@ -4850,11 +4959,10 @@ def up2k_wark_from_hashlist(salt , filesize , hashes ) :
|
|
4850
4959
|
vstr = "\n".join(values)
|
4851
4960
|
|
4852
4961
|
wark = hashlib.sha512(vstr.encode("utf-8")).digest()[:33]
|
4853
|
-
|
4854
|
-
return wark.decode("ascii")
|
4962
|
+
return ub64enc(wark).decode("ascii")
|
4855
4963
|
|
4856
4964
|
|
4857
4965
|
def up2k_wark_from_metadata(salt , sz , lastmod , rd , fn ) :
|
4858
4966
|
ret = sfsenc("%s\n%d\n%d\n%s\n%s" % (salt, lastmod, sz, rd, fn))
|
4859
|
-
ret =
|
4967
|
+
ret = ub64enc(hashlib.sha512(ret).digest())
|
4860
4968
|
return ("#%s" % (ret.decode("ascii"),))[:44]
|