Change a bunch of Stringer and status stuff

Cumulative interest time, download rate per connection, request low and high waters, peer extension bytes
This commit is contained in:
Matt Joiner 2018-02-05 17:47:47 +11:00
parent f57437201e
commit d5682e9cd0
4 changed files with 63 additions and 46 deletions

View File

@ -59,7 +59,10 @@ type connection struct {
lastChunkSent time.Time lastChunkSent time.Time
// Stuff controlled by the local peer. // Stuff controlled by the local peer.
Interested bool Interested bool
lastBecameInterested time.Time
priorInterest time.Duration
Choked bool Choked bool
requests map[request]struct{} requests map[request]struct{}
requestsLowWater int requestsLowWater int
@ -99,6 +102,14 @@ type connection struct {
writerCond sync.Cond writerCond sync.Cond
} }
func (cn *connection) cumInterest() time.Duration {
ret := cn.priorInterest
if cn.Interested {
ret += time.Since(cn.lastBecameInterested)
}
return ret
}
func (cn *connection) peerHasAllPieces() (all bool, known bool) { func (cn *connection) peerHasAllPieces() (all bool, known bool) {
if cn.peerSentHaveAll { if cn.peerSentHaveAll {
return true, true return true, true
@ -197,30 +208,38 @@ func (cn *connection) statusFlags() (ret string) {
return return
} }
func (cn *connection) String() string { // func (cn *connection) String() string {
var buf bytes.Buffer // var buf bytes.Buffer
cn.WriteStatus(&buf, nil) // cn.WriteStatus(&buf, nil)
return buf.String() // return buf.String()
// }
func (cn *connection) downloadRate() float64 {
return float64(cn.stats.BytesReadUsefulData) / cn.cumInterest().Seconds()
} }
func (cn *connection) WriteStatus(w io.Writer, t *Torrent) { func (cn *connection) WriteStatus(w io.Writer, t *Torrent) {
// \t isn't preserved in <pre> blocks? // \t isn't preserved in <pre> blocks?
fmt.Fprintf(w, "%-40s: %s-%s\n", cn.PeerID, cn.localAddr(), cn.remoteAddr()) fmt.Fprintf(w, "%+-55q %s %s-%s\n", cn.PeerID, cn.PeerExtensionBytes, cn.localAddr(), cn.remoteAddr())
fmt.Fprintf(w, " last msg: %s, connected: %s, last helpful: %s\n", fmt.Fprintf(w, " last msg: %s, connected: %s, last helpful: %s, itime: %s\n",
eventAgeString(cn.lastMessageReceived), eventAgeString(cn.lastMessageReceived),
eventAgeString(cn.completedHandshake), eventAgeString(cn.completedHandshake),
eventAgeString(cn.lastHelpful())) eventAgeString(cn.lastHelpful()),
cn.cumInterest(),
)
fmt.Fprintf(w, fmt.Fprintf(w,
" %s completed, %d pieces touched, good chunks: %d/%d-%d reqq: %d-%d, flags: %s\n", " %s completed, %d pieces touched, good chunks: %d/%d-%d reqq: (%d,%d,%d]-%d, flags: %s, dr: %.1f KiB/s\n",
cn.completedString(), cn.completedString(),
len(cn.peerTouchedPieces), len(cn.peerTouchedPieces),
cn.stats.ChunksReadUseful, cn.stats.ChunksReadUseful,
// TODO: Use ChunksRead? Verify that value is the same as this sum? cn.stats.ChunksRead,
cn.stats.ChunksReadUnwanted+cn.stats.ChunksReadUseful,
cn.stats.ChunksWritten, cn.stats.ChunksWritten,
cn.requestsLowWater,
cn.numLocalRequests(), cn.numLocalRequests(),
cn.nominalMaxRequests(),
len(cn.PeerRequests), len(cn.PeerRequests),
cn.statusFlags(), cn.statusFlags(),
cn.downloadRate()/(1<<10),
) )
roi := cn.pieceRequestOrderIter() roi := cn.pieceRequestOrderIter()
fmt.Fprintf(w, " next pieces: %v%s\n", fmt.Fprintf(w, " next pieces: %v%s\n",
@ -350,6 +369,11 @@ func (cn *connection) SetInterested(interested bool, msg func(pp.Message) bool)
return true return true
} }
cn.Interested = interested cn.Interested = interested
if interested {
cn.lastBecameInterested = time.Now()
} else if !cn.lastBecameInterested.IsZero() {
cn.priorInterest += time.Since(cn.lastBecameInterested)
}
// log.Printf("%p: setting interest: %v", cn, interested) // log.Printf("%p: setting interest: %v", cn, interested)
return msg(pp.Message{ return msg(pp.Message{
Type: func() pp.MessageType { Type: func() pp.MessageType {

View File

@ -38,6 +38,10 @@ type (
peerExtensionBytes [8]byte peerExtensionBytes [8]byte
) )
func (me peerExtensionBytes) String() string {
return hex.EncodeToString(me[:])
}
func newPeerExtensionBytes(bits ...ExtensionBit) (ret peerExtensionBytes) { func newPeerExtensionBytes(bits ...ExtensionBit) (ret peerExtensionBytes) {
for _, b := range bits { for _, b := range bits {
ret.SetBit(b) ret.SetBit(b)
@ -124,7 +128,7 @@ func handshake(sock io.ReadWriter, ih *metainfo.Hash, peerID [20]byte, extension
missinggo.CopyExact(&res.peerExtensionBytes, b[20:28]) missinggo.CopyExact(&res.peerExtensionBytes, b[20:28])
missinggo.CopyExact(&res.Hash, b[28:48]) missinggo.CopyExact(&res.Hash, b[28:48])
missinggo.CopyExact(&res.PeerID, b[48:68]) missinggo.CopyExact(&res.PeerID, b[48:68])
peerExtensions.Add(hex.EncodeToString(res.peerExtensionBytes[:]), 1) peerExtensions.Add(res.peerExtensionBytes.String(), 1)
// TODO: Maybe we can just drop peers here if we're not interested. This // TODO: Maybe we can just drop peers here if we're not interested. This
// could prevent them trying to reconnect, falsely believing there was // could prevent them trying to reconnect, falsely believing there was

View File

@ -1,17 +1,14 @@
package torrent package torrent
import (
"encoding/hex"
)
// Peer client ID. // Peer client ID.
type PeerID [20]byte type PeerID [20]byte
// Pretty prints the ID as hex, except parts that adher to the Peer ID // // Pretty prints the ID as hex, except parts that adher to the Peer ID
// Conventions of BEP 20. // // Conventions of BEP 20.
func (me PeerID) String() string { // func (me PeerID) String() string {
if me[0] == '-' && me[7] == '-' { // // if me[0] == '-' && me[7] == '-' {
return string(me[:8]) + hex.EncodeToString(me[8:]) // // return string(me[:8]) + hex.EncodeToString(me[8:])
} // // }
return hex.EncodeToString(me[:]) // // return hex.EncodeToString(me[:])
} // return fmt.Sprintf("%+q", me[:])
// }

View File

@ -1,24 +1,16 @@
package torrent package torrent
import ( // func TestPeerIdString(t *testing.T) {
"fmt" // for _, _case := range []struct {
"testing" // id string
// s string
"github.com/anacrolix/missinggo" // }{
"github.com/stretchr/testify/assert" // {"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n", "\"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n\""},
) // {"-FD51W\xe4-LaZMk0N8ZLA7", "-FD51W\xe4-LaZMk0N8ZLA7"},
// } {
func TestPeerIdString(t *testing.T) { // var pi PeerID
for _, _case := range []struct { // missinggo.CopyExact(&pi, _case.id)
id string // assert.EqualValues(t, _case.s, pi.String())
s string // assert.EqualValues(t, fmt.Sprintf("%q", _case.s), fmt.Sprintf("%q", pi))
}{ // }
{"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n", "1c4e4a7d9cc7c46f943c9b8cc221491c07ec986e"}, // }
{"-FD51W\xe4-LaZMk0N8ZLA7", "-FD51W\xe4-4c615a4d6b304e385a4c4137"},
} {
var pi PeerID
missinggo.CopyExact(&pi, _case.id)
assert.EqualValues(t, _case.s, pi.String())
assert.EqualValues(t, fmt.Sprintf("%q", _case.s), fmt.Sprintf("%q", pi))
}
}