From 6ac38a6ac336c02b7ee5f895659dcc50c17dc122 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sun, 27 Nov 2022 14:40:00 +0300 Subject: [PATCH] Simple bitfield file piece completion database But it uses whole characters instead of bits. --- cmd/btrtrc/main.go | 2 +- cmd/btrtrc/pc.go | 141 +++++++++++++++++---------------------------- 2 files changed, 54 insertions(+), 89 deletions(-) diff --git a/cmd/btrtrc/main.go b/cmd/btrtrc/main.go index cf932b6d..3b8c86b7 100644 --- a/cmd/btrtrc/main.go +++ b/cmd/btrtrc/main.go @@ -51,7 +51,7 @@ func main() { cc.NoDefaultPortForwarding = true cc.DisableWebtorrent = true cc.Logger = analog.Default.WithNames("main", "client") - cc.DefaultStorage = storage.NewFileWithCompletion(".", NewBoltPieceCompletion()) + cc.DefaultStorage = storage.NewFileWithCompletion(".", NewBFPieceCompletion()) if *verify { doVerify(cc, flag.Args()) return diff --git a/cmd/btrtrc/pc.go b/cmd/btrtrc/pc.go index 12911fa1..6f81923b 100644 --- a/cmd/btrtrc/pc.go +++ b/cmd/btrtrc/pc.go @@ -1,111 +1,76 @@ 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 } -- 2.48.1