| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- //go:build !noboltdb && !wasm
- // +build !noboltdb,!wasm
- package storage
- import (
- "encoding/binary"
- "os"
- "path/filepath"
- "time"
- "go.etcd.io/bbolt"
- "github.com/anacrolix/torrent/metainfo"
- )
- const (
- boltDbCompleteValue = "c"
- boltDbIncompleteValue = "i"
- )
- var completionBucketKey = []byte("completion")
- type boltPieceCompletion struct {
- db *bbolt.DB
- }
- var _ PieceCompletion = (*boltPieceCompletion)(nil)
- func NewBoltPieceCompletion(dir string) (ret PieceCompletion, err error) {
- os.MkdirAll(dir, 0o750)
- p := filepath.Join(dir, ".torrent.bolt.db")
- db, err := bbolt.Open(p, 0o660, &bbolt.Options{
- Timeout: time.Second,
- })
- if err != nil {
- return
- }
- db.NoSync = true
- ret = &boltPieceCompletion{db}
- return
- }
- func (me boltPieceCompletion) Get(pk metainfo.PieceKey) (cn Completion, err error) {
- err = me.db.View(func(tx *bbolt.Tx) error {
- cb := tx.Bucket(completionBucketKey)
- if cb == nil {
- return nil
- }
- ih := cb.Bucket(pk.InfoHash[:])
- if ih == nil {
- return nil
- }
- var key [4]byte
- binary.BigEndian.PutUint32(key[:], uint32(pk.Index))
- cn.Ok = true
- switch string(ih.Get(key[:])) {
- case boltDbCompleteValue:
- cn.Complete = true
- case boltDbIncompleteValue:
- cn.Complete = false
- default:
- cn.Ok = false
- }
- return nil
- })
- return
- }
- func (me boltPieceCompletion) Set(pk metainfo.PieceKey, b bool) error {
- if c, err := me.Get(pk); err == nil && c.Ok && c.Complete == b {
- return nil
- }
- return me.db.Update(func(tx *bbolt.Tx) error {
- c, err := tx.CreateBucketIfNotExists(completionBucketKey)
- if err != nil {
- return err
- }
- ih, err := c.CreateBucketIfNotExists(pk.InfoHash[:])
- if err != nil {
- return err
- }
- var key [4]byte
- binary.BigEndian.PutUint32(key[:], uint32(pk.Index))
- return ih.Put(key[:], []byte(func() string {
- if b {
- return boltDbCompleteValue
- } else {
- return boltDbIncompleteValue
- }
- }()))
- })
- }
- func (me *boltPieceCompletion) Close() error {
- return me.db.Close()
- }
|