124 lines
2.9 KiB
Go
124 lines
2.9 KiB
Go
package channeldb
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/lightningnetwork/lnd/kvdb"
|
|
"github.com/lightningnetwork/lnd/routing/route"
|
|
)
|
|
|
|
var (
|
|
// peersBucket is the name of a top level bucket in which we store
|
|
// information about our peers. Information for different peers is
|
|
// stored in buckets keyed by their public key.
|
|
//
|
|
//
|
|
// peers-bucket
|
|
// |
|
|
// |-- <peer-pubkey>
|
|
// | |--flap-count-key: <ts><flap count>
|
|
// |
|
|
// |-- <peer-pubkey>
|
|
// | |--flap-count-key: <ts><flap count>
|
|
peersBucket = []byte("peers-bucket")
|
|
|
|
// flapCountKey is a key used in the peer pubkey sub-bucket that stores
|
|
// the timestamp of a peer's last flap count and its all time flap
|
|
// count.
|
|
flapCountKey = []byte("flap-count")
|
|
)
|
|
|
|
var (
|
|
// ErrNoPeerBucket is returned when we try to read entries for a peer
|
|
// that is not tracked.
|
|
ErrNoPeerBucket = errors.New("peer bucket not found")
|
|
)
|
|
|
|
// FlapCount contains information about a peer's flap count.
|
|
type FlapCount struct {
|
|
// Count provides the total flap count for a peer.
|
|
Count uint32
|
|
|
|
// LastFlap is the timestamp of the last flap recorded for a peer.
|
|
LastFlap time.Time
|
|
}
|
|
|
|
// WriteFlapCounts writes the flap count for a set of peers to disk, creating a
|
|
// bucket for the peer's pubkey if necessary. Note that this function overwrites
|
|
// the current value.
|
|
func (d *DB) WriteFlapCounts(flapCounts map[route.Vertex]*FlapCount) error {
|
|
return kvdb.Update(d, func(tx kvdb.RwTx) error {
|
|
// Run through our set of flap counts and record them for
|
|
// each peer, creating a bucket for the peer pubkey if required.
|
|
for peer, flapCount := range flapCounts {
|
|
peers := tx.ReadWriteBucket(peersBucket)
|
|
|
|
peerBucket, err := peers.CreateBucketIfNotExists(
|
|
peer[:],
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
err = serializeTime(&b, flapCount.LastFlap)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = WriteElement(&b, flapCount.Count); err != nil {
|
|
return err
|
|
}
|
|
|
|
err = peerBucket.Put(flapCountKey, b.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}, func() {})
|
|
}
|
|
|
|
// ReadFlapCount attempts to read the flap count for a peer, failing if the
|
|
// peer is not found or we do not have flap count stored.
|
|
func (d *DB) ReadFlapCount(pubkey route.Vertex) (*FlapCount, error) {
|
|
var flapCount FlapCount
|
|
|
|
if err := kvdb.View(d, func(tx kvdb.RTx) error {
|
|
peers := tx.ReadBucket(peersBucket)
|
|
|
|
peerBucket := peers.NestedReadBucket(pubkey[:])
|
|
if peerBucket == nil {
|
|
return ErrNoPeerBucket
|
|
}
|
|
|
|
flapBytes := peerBucket.Get(flapCountKey)
|
|
if flapBytes == nil {
|
|
return fmt.Errorf("flap count not recorded for: %v",
|
|
pubkey)
|
|
}
|
|
|
|
var (
|
|
err error
|
|
r = bytes.NewReader(flapBytes)
|
|
)
|
|
|
|
flapCount.LastFlap, err = deserializeTime(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return ReadElements(r, &flapCount.Count)
|
|
}, func() {
|
|
flapCount = FlapCount{}
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &flapCount, nil
|
|
}
|