package main
-// based on storage/bolt-piece-completion.go
-
import (
- "encoding/binary"
+ "io"
+ "os"
"sync"
- "time"
-
- "go.etcd.io/bbolt"
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/storage"
)
-const (
- boltDbCompleteValue = "c"
- boltDbIncompleteValue = "i"
-)
-
-var completionBucketKey = []byte("completion")
-
-type boltPieceCompletion struct {
- dbs map[metainfo.Hash]*bbolt.DB
- dbsLock sync.Mutex
+type BFPieceCompletion struct {
+ sync.Mutex
}
-var _ storage.PieceCompletion = (*boltPieceCompletion)(nil)
-
-func NewBoltPieceCompletion() *boltPieceCompletion {
- return &boltPieceCompletion{dbs: make(map[metainfo.Hash]*bbolt.DB)}
+func NewBFPieceCompletion() *BFPieceCompletion {
+ return &BFPieceCompletion{}
}
-func (me *boltPieceCompletion) Get(pk metainfo.PieceKey) (cn storage.Completion, err error) {
- me.dbsLock.Lock()
- db, ok := me.dbs[pk.InfoHash]
- if !ok {
- db, err = bbolt.Open(
- pk.InfoHash.HexString()+".bolt",
- 0o666,
- &bbolt.Options{Timeout: time.Second},
- )
- if err != nil {
- me.dbsLock.Unlock()
- return
- }
- db.NoSync = true
- me.dbs[pk.InfoHash] = db
+func (self *BFPieceCompletion) Get(pk metainfo.PieceKey) (c storage.Completion, rerr error) {
+ self.Lock()
+ defer self.Unlock()
+ fd, err := os.OpenFile(pk.InfoHash.HexString()+".bf", os.O_RDWR|os.O_CREATE, 0666)
+ if err != nil {
+ rerr = err
+ return
+ }
+ defer fd.Close()
+ _, err = fd.Seek(int64(pk.Index), io.SeekStart)
+ if err != nil {
+ return
+ }
+ b := []byte{0}
+ _, err = fd.Read(b)
+ if err != nil {
+ return
+ }
+ c.Ok = true
+ switch string(b) {
+ case "0":
+ c.Complete = false
+ case "1":
+ c.Complete = true
+ default:
+ c.Ok = false
}
- me.dbsLock.Unlock()
- err = 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 {
+func (self *BFPieceCompletion) Set(pk metainfo.PieceKey, complete bool) error {
+ if c, err := self.Get(pk); err == nil && c.Ok && c.Complete == complete {
return nil
}
- me.dbsLock.Lock()
- db := me.dbs[pk.InfoHash]
- me.dbsLock.Unlock()
- return 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
- }
- }()))
- })
+ self.Lock()
+ defer self.Unlock()
+ fd, err := os.OpenFile(pk.InfoHash.HexString()+".bf", os.O_RDWR|os.O_CREATE, 0666)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ if _, err = fd.Seek(int64(pk.Index), io.SeekStart); err != nil {
+ return err
+ }
+ b := []byte{'1'}
+ if !complete {
+ b[0] = '0'
+ }
+ if _, err = fd.Write(b); err != nil {
+ return err
+ }
+ return nil
}
-func (me *boltPieceCompletion) Close() error {
- me.dbsLock.Lock()
- for _, db := range me.dbs {
- db.Close()
- }
- me.dbsLock.Unlock()
+func (self *BFPieceCompletion) Close() error {
return nil
}