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