--- /dev/null
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strconv"
+ "sync"
+ "time"
+
+ "github.com/anacrolix/torrent"
+ "github.com/anacrolix/torrent/metainfo"
+)
+
+const TxExt = ".tx"
+
+var (
+ TxStats = map[metainfo.Hash]int64{}
+ TxStatsM sync.Mutex
+)
+
+func txStatsLoad(h metainfo.Hash) {
+ pth := h.HexString() + TxExt
+ data, err := os.ReadFile(pth)
+ if err != nil {
+ return
+ }
+ v, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64)
+ if err != nil {
+ log.Println("ParseInt:", pth, err)
+ return
+ }
+ TxStatsM.Lock()
+ TxStats[h] = v
+ TxStatsM.Unlock()
+}
+
+func txStatsDel(h metainfo.Hash) {
+ TxStatsM.Lock()
+ delete(TxStats, h)
+ TxStatsM.Unlock()
+}
+
+func txStatsDump(t *torrent.Torrent) {
+ stats := t.Stats()
+ TxStatsM.Lock()
+ s := stats.BytesWrittenData.Int64() + TxStats[t.InfoHash()]
+ pth := t.InfoHash().HexString() + TxExt
+ if err := os.WriteFile(pth, []byte(fmt.Sprintf("%d\n", s)), 0666); err != nil {
+ log.Println("WriteFile:", pth, err)
+ }
+ TxStatsM.Unlock()
+}
+
+func txStatsDumpAll(c *torrent.Client) {
+ for _, t := range c.Torrents() {
+ if t.Info() != nil {
+ txStatsDump(t)
+ }
+ }
+}
+
+func txStatsDumper(c *torrent.Client) {
+ tick := time.Tick(10 * time.Second)
+ for {
+ txStatsDumpAll(c)
+ select {
+ case <-Cancel:
+ Jobs.Done()
+ return
+ case <-tick:
+ }
+ }
+}