@cryptotaxi247 / kubo / commits / 1079acf69

bitswap: add `ledger` subcommand

License: MIT Signed-off-by: Thomas Gardner <tmg@fastmail.com>

Thomas Gardner committed Aug 5, 2016 at 19:35 UTC 1079acf695f5f248b894fe7b4843e2f34818b329
4 files changed +88 -2
core/commands/bitswap.go
+61 -2
@@ -5,11 +5,12 @@ import (
5 "fmt"
6 "io"
7
8 - "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
9 -
8 key "github.com/ipfs/go-ipfs/blocks/key"
9 cmds "github.com/ipfs/go-ipfs/commands"
10 bitswap "github.com/ipfs/go-ipfs/exchange/bitswap"
11 + decision "github.com/ipfs/go-ipfs/exchange/bitswap/decision"
12 +
13 + "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
14 peer "gx/ipfs/QmRBqJF7hb8ZSpRcMwUt8hNhydWcxGEhtk81HKq6oUwKvs/go-libp2p-peer"
15 u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
16 )
@@ -23,6 +24,7 @@ var BitswapCmd = &cmds.Command{
24 "wantlist": showWantlistCmd,
25 "stat": bitswapStatCmd,
26 "unwant": unwantCmd,
27 + "ledger": ledgerCmd,
28 },
29 }
30
@@ -171,3 +173,60 @@ var bitswapStatCmd = &cmds.Command{
173 },
174 },
175 }
176 +
177 +var ledgerCmd = &cmds.Command{
178 + Helptext: cmds.HelpText{
179 + Tagline: "Show the current ledger for a peer.",
180 + ShortDescription: `
181 +The Bitswap decision engine tracks the number of bytes exchanged between IPFS
182 +nodes, and stores this information as a collection of ledgers. This command
183 +prints the ledger associated with a given peer.
184 +`,
185 + },
186 + Arguments: []cmds.Argument{
187 + cmds.StringArg("peer", true, false, "The PeerID (B58) of the ledger to inspect."),
188 + },
189 + Type: decision.Receipt{},
190 + Run: func(req cmds.Request, res cmds.Response) {
191 + nd, err := req.InvocContext().GetNode()
192 + if err != nil {
193 + res.SetError(err, cmds.ErrNormal)
194 + return
195 + }
196 +
197 + if !nd.OnlineMode() {
198 + res.SetError(errNotOnline, cmds.ErrClient)
199 + return
200 + }
201 +
202 + bs, ok := nd.Exchange.(*bitswap.Bitswap)
203 + if !ok {
204 + res.SetError(u.ErrCast(), cmds.ErrNormal)
205 + return
206 + }
207 +
208 + partner, err := peer.IDB58Decode(req.Arguments()[0])
209 + if err != nil {
210 + res.SetError(err, cmds.ErrClient)
211 + return
212 + }
213 + res.SetOutput(bs.LedgerForPeer(partner))
214 + },
215 + Marshalers: cmds.MarshalerMap{
216 + cmds.Text: func(res cmds.Response) (io.Reader, error) {
217 + out, ok := res.Output().(*decision.Receipt)
218 + if !ok {
219 + return nil, u.ErrCast()
220 + }
221 + buf := new(bytes.Buffer)
222 + fmt.Fprintf(buf, "Ledger for %s\n"+
223 + "Debt ratio:\t%f\n"+
224 + "Exchanges:\t%d\n"+
225 + "Bytes sent:\t%d\n"+
226 + "Bytes received:\t%d\n\n",
227 + out.Peer, out.Value, out.Exchanged,
228 + out.Sent, out.Recv)
229 + return buf, nil
230 + },
231 + },
232 +}
exchange/bitswap/bitswap.go
+4
@@ -205,6 +205,10 @@ func (bs *Bitswap) WantlistForPeer(p peer.ID) []key.Key {
205 return out
206 }
207
208 +func (bs *Bitswap) LedgerForPeer(p peer.ID) *decision.Receipt {
209 + return bs.engine.LedgerForPeer(p)
210 +}
211 +
212 // GetBlocks returns a channel where the caller may receive blocks that
213 // correspond to the provided |keys|. Returns an error if BitSwap is unable to
214 // begin this request within the deadline enforced by the context.
exchange/bitswap/decision/engine.go
+15
@@ -114,6 +114,21 @@ func (e *Engine) WantlistForPeer(p peer.ID) (out []wl.Entry) {
114 return out
115 }
116
117 +func (e *Engine) LedgerForPeer(p peer.ID) *Receipt {
118 + ledger := e.findOrCreate(p)
119 +
120 + ledger.lk.Lock()
121 + defer ledger.lk.Unlock()
122 +
123 + return &Receipt{
124 + Peer: ledger.Partner.String(),
125 + Value: ledger.Accounting.Value(),
126 + Sent: ledger.Accounting.BytesSent,
127 + Recv: ledger.Accounting.BytesRecv,
128 + Exchanged: ledger.ExchangeCount(),
129 + }
130 +}
131 +
132 func (e *Engine) taskWorker(ctx context.Context) {
133 defer close(e.outbox) // because taskWorker uses the channel exclusively
134 for {
exchange/bitswap/decision/ledger.go
+8
@@ -49,6 +49,14 @@ type ledger struct {
49 lk sync.Mutex
50 }
51
52 +type Receipt struct {
53 + Peer string
54 + Value float64
55 + Sent uint64
56 + Recv uint64
57 + Exchanged uint64
58 +}
59 +
60 type debtRatio struct {
61 BytesSent uint64
62 BytesRecv uint64