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