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/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
- for cur in self.cur.values():
274
- try:
275
- mtpq += cur.execute(q).fetchone()[0]
276
- except:
277
- pass
278
- self.mutex.release()
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 = base64.urlsafe_b64encode(zb[:18]).decode("ascii")
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
- ret = 0
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 = vjoin(rd, iname)
1284
- abspath = os.path.join(cdir, iname)
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
- ret += self._build_dir(
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 = base64.urlsafe_b64encode(zh.digest()[:12]).decode("ascii")
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 ret
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 = vjoin(rd, fn)
1415
- abspath = os.path.join(cdir, fn)
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
- ret += 1
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
- ret += 1
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 = ? or rd like ?||'%') and at == 0"
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
- n = db.c.execute(q, (sh_erd, sh_erd + "/")).fetchone()[0]
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, (sh_erd, sh_erd + "/"))
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 = ? or rd like ?||'%') and at == 0"
1516
- db.c.execute(q, (sh_erd, sh_erd + "/"))
1517
- ret += n
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 ret
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 ret
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 +fn=? limit 1"
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
- for _, _, w in f404:
1761
- q = "delete from up where w = ? limit 1"
1762
- cur.execute(q, (w,))
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 = base64.urlsafe_b64encode(digest[:9]).decode("utf-8")
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
- try:
2435
- self._add_cv_tab(cur)
2436
- self._add_xiu_tab(cur)
2437
- self._add_dhash_tab(cur)
2438
- except:
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 up_rd on up(rd)",
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 = "lmod ptop vtop prel name host user addr poke"
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
- for k in [
3014
- "host",
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
- with ren_open(fname, "wb", fdir=fdir, suffix=suffix) as zfw:
3131
- return zfw["orz"][1]
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 release_chunks(self, ptop , wark , chashes ) :
3314
- with self.reg_mutex:
3315
- job = self.registry[ptop].get(wark)
3316
- if job:
3317
- for chash in chashes:
3318
- job["busy"].pop(chash, None)
3319
-
3320
- return True
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
- digest = base64.urlsafe_b64encode(digest)
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
- with ren_open(tnam, "wb", fdir=pdir, suffix=suffix) as zfw:
4464
- f, job["tnam"] = zfw["orz"]
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
- wark = base64.urlsafe_b64encode(wark)
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 = base64.urlsafe_b64encode(hashlib.sha512(ret).digest())
4967
+ ret = ub64enc(hashlib.sha512(ret).digest())
4860
4968
  return ("#%s" % (ret.decode("ascii"),))[:44]