]> Sergey Matveev's repositories - btrtrc.git/blob - storage/boltPieceCompletion.go
Use default bbolt package alias
[btrtrc.git] / storage / boltPieceCompletion.go
1 package storage
2
3 import (
4         "encoding/binary"
5         "os"
6         "path/filepath"
7         "time"
8
9         "go.etcd.io/bbolt"
10
11         "github.com/anacrolix/torrent/metainfo"
12 )
13
14 const (
15         boltDbCompleteValue   = "c"
16         boltDbIncompleteValue = "i"
17 )
18
19 var (
20         completionBucketKey = []byte("completion")
21 )
22
23 type boltPieceCompletion struct {
24         db *bbolt.DB
25 }
26
27 var _ PieceCompletion = (*boltPieceCompletion)(nil)
28
29 func NewBoltPieceCompletion(dir string) (ret PieceCompletion, err error) {
30         os.MkdirAll(dir, 0770)
31         p := filepath.Join(dir, ".torrent.bolt.db")
32         db, err := bbolt.Open(p, 0660, &bbolt.Options{
33                 Timeout: time.Second,
34         })
35         if err != nil {
36                 return
37         }
38         db.NoSync = true
39         ret = &boltPieceCompletion{db}
40         return
41 }
42
43 func (me boltPieceCompletion) Get(pk metainfo.PieceKey) (cn Completion, err error) {
44         err = me.db.View(func(tx *bbolt.Tx) error {
45                 cb := tx.Bucket(completionBucketKey)
46                 if cb == nil {
47                         return nil
48                 }
49                 ih := cb.Bucket(pk.InfoHash[:])
50                 if ih == nil {
51                         return nil
52                 }
53                 var key [4]byte
54                 binary.BigEndian.PutUint32(key[:], uint32(pk.Index))
55                 cn.Ok = true
56                 switch string(ih.Get(key[:])) {
57                 case boltDbCompleteValue:
58                         cn.Complete = true
59                 case boltDbIncompleteValue:
60                         cn.Complete = false
61                 default:
62                         cn.Ok = false
63                 }
64                 return nil
65         })
66         return
67 }
68
69 func (me boltPieceCompletion) Set(pk metainfo.PieceKey, b bool) error {
70         return me.db.Update(func(tx *bbolt.Tx) error {
71                 c, err := tx.CreateBucketIfNotExists(completionBucketKey)
72                 if err != nil {
73                         return err
74                 }
75                 ih, err := c.CreateBucketIfNotExists(pk.InfoHash[:])
76                 if err != nil {
77                         return err
78                 }
79                 var key [4]byte
80                 binary.BigEndian.PutUint32(key[:], uint32(pk.Index))
81                 return ih.Put(key[:], []byte(func() string {
82                         if b {
83                                 return boltDbCompleteValue
84                         } else {
85                                 return boltDbIncompleteValue
86                         }
87                 }()))
88         })
89 }
90
91 func (me *boltPieceCompletion) Close() error {
92         return me.db.Close()
93 }