]> Sergey Matveev's repositories - btrtrc.git/blob - storage/sqlite-piece-completion.go
Merge branch 'master' into crawshaw
[btrtrc.git] / storage / sqlite-piece-completion.go
1 // modernc.org/sqlite depends on modernc.org/libc which doesn't work for JS (and probably wasm but I
2 // think JS is the stronger signal).
3 //go:build cgo && !nosqlite
4 // +build cgo,!nosqlite
5
6 package storage
7
8 import (
9         "errors"
10         "path/filepath"
11         "sync"
12
13         "crawshaw.io/sqlite"
14         "crawshaw.io/sqlite/sqlitex"
15         "github.com/anacrolix/torrent/metainfo"
16 )
17
18 // sqlite is always the default when available.
19 func NewDefaultPieceCompletionForDir(dir string) (PieceCompletion, error) {
20         return NewSqlitePieceCompletion(dir)
21 }
22
23 type sqlitePieceCompletion struct {
24         mu     sync.Mutex
25         closed bool
26         db     *sqlite.Conn
27 }
28
29 var _ PieceCompletion = (*sqlitePieceCompletion)(nil)
30
31 func NewSqlitePieceCompletion(dir string) (ret *sqlitePieceCompletion, err error) {
32         p := filepath.Join(dir, ".torrent.db")
33         db, err := sqlite.OpenConn(p, 0)
34         if err != nil {
35                 return
36         }
37         err = sqlitex.ExecScript(db, `create table if not exists piece_completion(infohash, "index", complete, unique(infohash, "index"))`)
38         if err != nil {
39                 db.Close()
40                 return
41         }
42         ret = &sqlitePieceCompletion{db: db}
43         return
44 }
45
46 func (me *sqlitePieceCompletion) Get(pk metainfo.PieceKey) (c Completion, err error) {
47         me.mu.Lock()
48         defer me.mu.Unlock()
49         err = sqlitex.Exec(
50                 me.db, `select complete from piece_completion where infohash=? and "index"=?`,
51                 func(stmt *sqlite.Stmt) error {
52                         c.Complete = stmt.ColumnInt(0) != 0
53                         c.Ok = true
54                         return nil
55                 },
56                 pk.InfoHash.HexString(), pk.Index)
57         return
58 }
59
60 func (me *sqlitePieceCompletion) Set(pk metainfo.PieceKey, b bool) error {
61         me.mu.Lock()
62         defer me.mu.Unlock()
63         if me.closed {
64                 return errors.New("closed")
65         }
66         return sqlitex.Exec(
67                 me.db,
68                 `insert or replace into piece_completion(infohash, "index", complete) values(?, ?, ?)`,
69                 nil,
70                 pk.InfoHash.HexString(), pk.Index, b)
71 }
72
73 func (me *sqlitePieceCompletion) Close() (err error) {
74         me.mu.Lock()
75         defer me.mu.Unlock()
76         if me.closed {
77                 return
78         }
79         err = me.db.Close()
80         me.db = nil
81         me.closed = true
82         return
83 }