github.com/decred/dcrlnd@v0.7.6/channeldb/peers.go (about) 1 package channeldb 2 3 import ( 4 "bytes" 5 "errors" 6 "time" 7 8 "github.com/decred/dcrlnd/kvdb" 9 "github.com/decred/dcrlnd/routing/route" 10 ) 11 12 var ( 13 // peersBucket is the name of a top level bucket in which we store 14 // information about our peers. Information for different peers is 15 // stored in buckets keyed by their public key. 16 // 17 // 18 // peers-bucket 19 // | 20 // |-- <peer-pubkey> 21 // | |--flap-count-key: <ts><flap count> 22 // | 23 // |-- <peer-pubkey> 24 // | |--flap-count-key: <ts><flap count> 25 // 26 // Note(decred): each peer has an additional value set: 27 // |--last-gossip-msg-ts: <ts> 28 peersBucket = []byte("peers-bucket") 29 30 // flapCountKey is a key used in the peer pubkey sub-bucket that stores 31 // the timestamp of a peer's last flap count and its all time flap 32 // count. 33 flapCountKey = []byte("flap-count") 34 ) 35 36 var ( 37 // ErrNoPeerBucket is returned when we try to read entries for a peer 38 // that is not tracked. 39 ErrNoPeerBucket = errors.New("peer bucket not found") 40 ) 41 42 // FlapCount contains information about a peer's flap count. 43 type FlapCount struct { 44 // Count provides the total flap count for a peer. 45 Count uint32 46 47 // LastFlap is the timestamp of the last flap recorded for a peer. 48 LastFlap time.Time 49 } 50 51 // WriteFlapCounts writes the flap count for a set of peers to disk, creating a 52 // bucket for the peer's pubkey if necessary. Note that this function overwrites 53 // the current value. 54 func (d *DB) WriteFlapCounts(flapCounts map[route.Vertex]*FlapCount) error { 55 return kvdb.Update(d, func(tx kvdb.RwTx) error { 56 // Run through our set of flap counts and record them for 57 // each peer, creating a bucket for the peer pubkey if required. 58 for peer, flapCount := range flapCounts { 59 peers := tx.ReadWriteBucket(peersBucket) 60 61 peerBucket, err := peers.CreateBucketIfNotExists( 62 peer[:], 63 ) 64 if err != nil { 65 return err 66 } 67 68 var b bytes.Buffer 69 err = serializeTime(&b, flapCount.LastFlap) 70 if err != nil { 71 return err 72 } 73 74 if err = WriteElement(&b, flapCount.Count); err != nil { 75 return err 76 } 77 78 err = peerBucket.Put(flapCountKey, b.Bytes()) 79 if err != nil { 80 return err 81 } 82 } 83 84 return nil 85 }, func() {}) 86 } 87 88 // ReadFlapCount attempts to read the flap count for a peer, failing if the 89 // peer is not found or we do not have flap count stored. 90 func (d *DB) ReadFlapCount(pubkey route.Vertex) (*FlapCount, error) { 91 var flapCount FlapCount 92 93 if err := kvdb.View(d, func(tx kvdb.RTx) error { 94 peers := tx.ReadBucket(peersBucket) 95 96 peerBucket := peers.NestedReadBucket(pubkey[:]) 97 if peerBucket == nil { 98 return ErrNoPeerBucket 99 } 100 101 flapBytes := peerBucket.Get(flapCountKey) 102 if flapBytes == nil { 103 // Note(decred): in lnd this returns an opaque error, 104 // but we may have entries in the peersBucket that 105 // may not have a set flapCountKey, so return the same 106 // error that flags that the info does not exist for 107 // this peer. 108 return ErrNoPeerBucket 109 } 110 111 var ( 112 err error 113 r = bytes.NewReader(flapBytes) 114 ) 115 116 flapCount.LastFlap, err = deserializeTime(r) 117 if err != nil { 118 return err 119 } 120 121 return ReadElements(r, &flapCount.Count) 122 }, func() { 123 flapCount = FlapCount{} 124 }); err != nil { 125 return nil, err 126 } 127 128 return &flapCount, nil 129 }