github.com/lbryio/lbcd@v0.22.119/claimtrie/temporal/temporalrepo/pebble.go (about) 1 package temporalrepo 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 7 "github.com/pkg/errors" 8 9 "github.com/cockroachdb/pebble" 10 ) 11 12 type Pebble struct { 13 db *pebble.DB 14 } 15 16 func NewPebble(path string) (*Pebble, error) { 17 18 db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(16 << 20), MaxOpenFiles: 2000}) 19 repo := &Pebble{db: db} 20 21 return repo, errors.Wrapf(err, "unable to open %s", path) 22 } 23 24 func (repo *Pebble) SetNodesAt(name [][]byte, heights []int32) error { 25 26 // key format: height(4B) + 0(1B) + name(varable length) 27 key := bytes.NewBuffer(nil) 28 batch := repo.db.NewBatch() 29 defer batch.Close() 30 for i, name := range name { 31 key.Reset() 32 binary.Write(key, binary.BigEndian, heights[i]) 33 binary.Write(key, binary.BigEndian, byte(0)) 34 key.Write(name) 35 36 err := batch.Set(key.Bytes(), nil, pebble.NoSync) 37 if err != nil { 38 return errors.Wrap(err, "in set") 39 } 40 } 41 return errors.Wrap(batch.Commit(pebble.NoSync), "in commit") 42 } 43 44 func (repo *Pebble) NodesAt(height int32) ([][]byte, error) { 45 46 prefix := bytes.NewBuffer(nil) 47 binary.Write(prefix, binary.BigEndian, height) 48 binary.Write(prefix, binary.BigEndian, byte(0)) 49 50 end := bytes.NewBuffer(nil) 51 binary.Write(end, binary.BigEndian, height) 52 binary.Write(end, binary.BigEndian, byte(1)) 53 54 prefixIterOptions := &pebble.IterOptions{ 55 LowerBound: prefix.Bytes(), 56 UpperBound: end.Bytes(), 57 } 58 59 var names [][]byte 60 61 iter := repo.db.NewIter(prefixIterOptions) 62 for iter.First(); iter.Valid(); iter.Next() { 63 // Skipping the first 5 bytes (height and a null byte), we get the name. 64 name := make([]byte, len(iter.Key())-5) 65 copy(name, iter.Key()[5:]) // iter.Key() reuses its buffer 66 names = append(names, name) 67 } 68 69 return names, errors.Wrap(iter.Close(), "in close") 70 } 71 72 func (repo *Pebble) Close() error { 73 74 err := repo.db.Flush() 75 if err != nil { 76 // if we fail to close are we going to try again later? 77 return errors.Wrap(err, "on flush") 78 } 79 80 err = repo.db.Close() 81 return errors.Wrap(err, "on close") 82 } 83 84 func (repo *Pebble) Flush() error { 85 _, err := repo.db.AsyncFlush() 86 return err 87 }