github.com/anacrolix/torrent@v1.61.0/storage/sqlite-piece-completion.go (about) 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 sqlite "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 func (me *sqlitePieceCompletion) Persistent() bool { 32 return true 33 } 34 35 var _ PieceCompletion = (*sqlitePieceCompletion)(nil) 36 37 func NewSqlitePieceCompletion(dir string) (ret *sqlitePieceCompletion, err error) { 38 p := filepath.Join(dir, ".torrent.db") 39 db, err := sqlite.OpenConn(p, 0) 40 if err != nil { 41 return 42 } 43 err = sqlitex.ExecScript(db, `create table if not exists piece_completion(infohash, "index", complete, unique(infohash, "index"))`) 44 if err != nil { 45 db.Close() 46 return 47 } 48 ret = &sqlitePieceCompletion{db: db} 49 return 50 } 51 52 func (me *sqlitePieceCompletion) Get(pk metainfo.PieceKey) (c Completion, err error) { 53 me.mu.Lock() 54 defer me.mu.Unlock() 55 if me.closed { 56 err = errors.New("closed") 57 return 58 } 59 err = sqlitex.Exec( 60 me.db, `select complete from piece_completion where infohash=? and "index"=?`, 61 func(stmt *sqlite.Stmt) error { 62 c.Complete = stmt.ColumnInt(0) != 0 63 c.Ok = true 64 return nil 65 }, 66 pk.InfoHash.HexString(), pk.Index) 67 return 68 } 69 70 func (me *sqlitePieceCompletion) Set(pk metainfo.PieceKey, b bool) error { 71 me.mu.Lock() 72 defer me.mu.Unlock() 73 if me.closed { 74 return errors.New("closed") 75 } 76 return sqlitex.Exec( 77 me.db, 78 `insert or replace into piece_completion(infohash, "index", complete) values(?, ?, ?)`, 79 nil, 80 pk.InfoHash.HexString(), pk.Index, b) 81 } 82 83 func (me *sqlitePieceCompletion) Close() (err error) { 84 me.mu.Lock() 85 defer me.mu.Unlock() 86 if me.closed { 87 return 88 } 89 err = me.db.Close() 90 me.db = nil 91 me.closed = true 92 return 93 }