]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Simple bitfield file piece completion database
authorSergey Matveev <stargrave@stargrave.org>
Sun, 27 Nov 2022 11:40:00 +0000 (14:40 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Fri, 13 Jan 2023 08:32:42 +0000 (11:32 +0300)
But it uses whole characters instead of bits.

cmd/btrtrc/main.go
cmd/btrtrc/pc.go

index cf932b6dd819c15fea2d92db6525188fc2e775e1..3b8c86b78fb3e37d959f6f8ab0f7d717441db4de 100644 (file)
@@ -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
index 12911fa136fa2bac8ba671bbd3e1fb0cde4f3f6a..6f81923b87e699218ef8e132c6de8fb8b977fc06 100644 (file)
 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
 }