bitswap.go 5.54 KB
Newer Older
1 2 3
package commands

import (
Jeromy's avatar
Jeromy committed
4
	"fmt"
5 6
	"io"

7
	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
Jan Winkelmann's avatar
Jan Winkelmann committed
8
	e "github.com/ipfs/go-ipfs/core/commands/e"
Overbool's avatar
Overbool committed
9 10

	humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
Steven Allen's avatar
Steven Allen committed
11 12 13 14
	bitswap "gx/ipfs/QmXRphxBT4BH2GqGHUSbqULm7wNsxnpA2NrbNaY3DU1Y5K/go-bitswap"
	decision "gx/ipfs/QmXRphxBT4BH2GqGHUSbqULm7wNsxnpA2NrbNaY3DU1Y5K/go-bitswap/decision"
	cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds"
	peer "gx/ipfs/QmcqU6QUDSXprb1518vYDGczrTJTyGwLG9eUa5iNX4xUtS/go-libp2p-peer"
15
	cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
16 17 18
)

var BitswapCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
19
	Helptext: cmdkit.HelpText{
20
		Tagline:          "Interact with the bitswap agent.",
21 22
		ShortDescription: ``,
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
23

24
	Subcommands: map[string]*cmds.Command{
25
		"stat":      bitswapStatCmd,
Overbool's avatar
Overbool committed
26 27 28
		"wantlist":  showWantlistCmd,
		"ledger":    ledgerCmd,
		"reprovide": reprovideCmd,
29 30 31
	},
}

Kejie Zhang's avatar
Kejie Zhang committed
32 33 34 35
const (
	peerOptionName = "peer"
)

Overbool's avatar
Overbool committed
36
var showWantlistCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
37
	Helptext: cmdkit.HelpText{
Richard Littauer's avatar
Richard Littauer committed
38
		Tagline: "Show blocks currently on the wantlist.",
39
		ShortDescription: `
Richard Littauer's avatar
Richard Littauer committed
40
Print out all blocks currently on the bitswap wantlist for the local peer.`,
41
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
42
	Options: []cmdkit.Option{
Kejie Zhang's avatar
Kejie Zhang committed
43
		cmdkit.StringOption(peerOptionName, "p", "Specify which peer to show wantlist for. Default: self."),
44
	},
45
	Type: KeyList{},
Overbool's avatar
Overbool committed
46 47
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
		nd, err := cmdenv.GetNode(env)
48
		if err != nil {
Overbool's avatar
Overbool committed
49
			return err
50
		}
51 52

		if !nd.OnlineMode() {
Overbool's avatar
Overbool committed
53
			return ErrNotOnline
54 55
		}

56 57
		bs, ok := nd.Exchange.(*bitswap.Bitswap)
		if !ok {
Overbool's avatar
Overbool committed
58
			return e.TypeErr(bs, nd.Exchange)
59
		}
60

Overbool's avatar
Overbool committed
61
		pstr, found := req.Options[peerOptionName].(string)
62 63 64
		if found {
			pid, err := peer.IDB58Decode(pstr)
			if err != nil {
Overbool's avatar
Overbool committed
65
				return err
66
			}
Jeromy's avatar
Jeromy committed
67
			if pid == nd.Identity {
68
				return cmds.EmitOnce(res, &KeyList{bs.GetWantlist()})
Jeromy's avatar
Jeromy committed
69 70
			}

71
			return cmds.EmitOnce(res, &KeyList{bs.WantlistForPeer(pid)})
72
		}
73
		return cmds.EmitOnce(res, &KeyList{bs.GetWantlist()})
74
	},
Overbool's avatar
Overbool committed
75 76 77 78 79 80 81 82
	Encoders: cmds.EncoderMap{
		cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *KeyList) error {
			for _, key := range out.Keys {
				fmt.Fprintln(w, key.String())
			}

			return nil
		}),
83 84 85 86
	},
}

var bitswapStatCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
87
	Helptext: cmdkit.HelpText{
Richard Littauer's avatar
Richard Littauer committed
88
		Tagline:          "Show some diagnostic information on the bitswap agent.",
89 90 91
		ShortDescription: ``,
	},
	Type: bitswap.Stat{},
keks's avatar
keks committed
92
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
93
		nd, err := cmdenv.GetNode(env)
94
		if err != nil {
keks's avatar
keks committed
95
			return err
96 97
		}

98
		if !nd.OnlineMode() {
keks's avatar
keks committed
99
			return cmdkit.Errorf(cmdkit.ErrClient, ErrNotOnline.Error())
100 101
		}

102 103
		bs, ok := nd.Exchange.(*bitswap.Bitswap)
		if !ok {
keks's avatar
keks committed
104
			return e.TypeErr(bs, nd.Exchange)
105 106 107 108
		}

		st, err := bs.Stat()
		if err != nil {
keks's avatar
keks committed
109
			return err
110 111
		}

keks's avatar
keks committed
112
		return cmds.EmitOnce(res, st)
113
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
114
	Encoders: cmds.EncoderMap{
115
		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
Jan Winkelmann's avatar
Jan Winkelmann committed
116
			out, ok := v.(*bitswap.Stat)
117
			if !ok {
Jan Winkelmann's avatar
Jan Winkelmann committed
118
				return e.TypeErr(out, v)
119
			}
Jan Winkelmann's avatar
Jan Winkelmann committed
120 121 122 123 124 125 126 127 128 129

			fmt.Fprintln(w, "bitswap status")
			fmt.Fprintf(w, "\tprovides buffer: %d / %d\n", out.ProvideBufLen, bitswap.HasBlockBufferSize)
			fmt.Fprintf(w, "\tblocks received: %d\n", out.BlocksReceived)
			fmt.Fprintf(w, "\tblocks sent: %d\n", out.BlocksSent)
			fmt.Fprintf(w, "\tdata received: %d\n", out.DataReceived)
			fmt.Fprintf(w, "\tdata sent: %d\n", out.DataSent)
			fmt.Fprintf(w, "\tdup blocks received: %d\n", out.DupBlksReceived)
			fmt.Fprintf(w, "\tdup data received: %s\n", humanize.Bytes(out.DupDataReceived))
			fmt.Fprintf(w, "\twantlist [%d keys]\n", len(out.Wantlist))
Jeromy's avatar
Jeromy committed
130
			for _, k := range out.Wantlist {
Jan Winkelmann's avatar
Jan Winkelmann committed
131
				fmt.Fprintf(w, "\t\t%s\n", k.String())
Jeromy's avatar
Jeromy committed
132
			}
Jan Winkelmann's avatar
Jan Winkelmann committed
133
			fmt.Fprintf(w, "\tpartners [%d]\n", len(out.Peers))
Jeromy's avatar
Jeromy committed
134
			for _, p := range out.Peers {
Jan Winkelmann's avatar
Jan Winkelmann committed
135
				fmt.Fprintf(w, "\t\t%s\n", p)
136
			}
Jan Winkelmann's avatar
Jan Winkelmann committed
137 138 139

			return nil
		}),
140 141
	},
}
142

Overbool's avatar
Overbool committed
143
var ledgerCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
144
	Helptext: cmdkit.HelpText{
145 146 147 148 149 150 151
		Tagline: "Show the current ledger for a peer.",
		ShortDescription: `
The Bitswap decision engine tracks the number of bytes exchanged between IPFS
nodes, and stores this information as a collection of ledgers. This command
prints the ledger associated with a given peer.
`,
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
152 153
	Arguments: []cmdkit.Argument{
		cmdkit.StringArg("peer", true, false, "The PeerID (B58) of the ledger to inspect."),
154 155
	},
	Type: decision.Receipt{},
Overbool's avatar
Overbool committed
156 157
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
		nd, err := cmdenv.GetNode(env)
158
		if err != nil {
Overbool's avatar
Overbool committed
159
			return err
160 161 162
		}

		if !nd.OnlineMode() {
Overbool's avatar
Overbool committed
163
			return ErrNotOnline
164 165 166 167
		}

		bs, ok := nd.Exchange.(*bitswap.Bitswap)
		if !ok {
Overbool's avatar
Overbool committed
168
			return e.TypeErr(bs, nd.Exchange)
169 170
		}

Overbool's avatar
Overbool committed
171
		partner, err := peer.IDB58Decode(req.Arguments[0])
172
		if err != nil {
Overbool's avatar
Overbool committed
173
			return err
174
		}
175
		return cmds.EmitOnce(res, bs.LedgerForPeer(partner))
176
	},
Overbool's avatar
Overbool committed
177 178 179
	Encoders: cmds.EncoderMap{
		cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *decision.Receipt) error {
			fmt.Fprintf(w, "Ledger for %s\n"+
180 181 182 183 184 185
				"Debt ratio:\t%f\n"+
				"Exchanges:\t%d\n"+
				"Bytes sent:\t%d\n"+
				"Bytes received:\t%d\n\n",
				out.Peer, out.Value, out.Exchanged,
				out.Sent, out.Recv)
Overbool's avatar
Overbool committed
186 187
			return nil
		}),
188 189
	},
}
190

Overbool's avatar
Overbool committed
191
var reprovideCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
192
	Helptext: cmdkit.HelpText{
193 194 195 196 197
		Tagline: "Trigger reprovider.",
		ShortDescription: `
Trigger reprovider to announce our data to network.
`,
	},
Overbool's avatar
Overbool committed
198 199
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
		nd, err := cmdenv.GetNode(env)
200
		if err != nil {
Overbool's avatar
Overbool committed
201
			return err
202 203 204
		}

		if !nd.OnlineMode() {
Overbool's avatar
Overbool committed
205
			return ErrNotOnline
206 207
		}

Overbool's avatar
Overbool committed
208
		err = nd.Reprovider.Trigger(req.Context)
209
		if err != nil {
Overbool's avatar
Overbool committed
210
			return err
211
		}
Jan Winkelmann's avatar
Jan Winkelmann committed
212

Overbool's avatar
Overbool committed
213
		return nil
214 215
	},
}