Use flip buffering for connection writing
This commit is contained in:
parent
86aabb081c
commit
efecf88d3c
|
@ -2,6 +2,7 @@ package torrent
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
|
@ -1233,10 +1234,10 @@ func (cl *Client) banPeerIP(ip net.IP) {
|
|||
func (cl *Client) newConnection(nc net.Conn) (c *connection) {
|
||||
c = &connection{
|
||||
conn: nc,
|
||||
|
||||
Choked: true,
|
||||
PeerChoked: true,
|
||||
PeerMaxRequests: 250,
|
||||
writeBuffer: new(bytes.Buffer),
|
||||
}
|
||||
c.writerCond.L = &cl.mu
|
||||
c.setRW(connStatsReadWriter{nc, &cl.mu, c})
|
||||
|
|
|
@ -93,7 +93,7 @@ type connection struct {
|
|||
pieceInclination []int
|
||||
pieceRequestOrder prioritybitmap.PriorityBitmap
|
||||
|
||||
writeBuffer bytes.Buffer
|
||||
writeBuffer *bytes.Buffer
|
||||
uploadTimer *time.Timer
|
||||
writerCond sync.Cond
|
||||
}
|
||||
|
@ -404,10 +404,9 @@ func (cn *connection) fillWriteBuffer(msg func(pp.Message) bool) {
|
|||
// connection is writable.
|
||||
func (cn *connection) writer(keepAliveTimeout time.Duration) {
|
||||
var (
|
||||
// buf bytes.Buffer
|
||||
lastWrite time.Time = time.Now()
|
||||
keepAliveTimer *time.Timer
|
||||
)
|
||||
var keepAliveTimer *time.Timer
|
||||
keepAliveTimer = time.AfterFunc(keepAliveTimeout, func() {
|
||||
cn.mu().Lock()
|
||||
defer cn.mu().Unlock()
|
||||
|
@ -420,6 +419,7 @@ func (cn *connection) writer(keepAliveTimeout time.Duration) {
|
|||
defer cn.mu().Unlock()
|
||||
defer cn.Close()
|
||||
defer keepAliveTimer.Stop()
|
||||
frontBuf := new(bytes.Buffer)
|
||||
for {
|
||||
if cn.closed.IsSet() {
|
||||
return
|
||||
|
@ -440,12 +440,10 @@ func (cn *connection) writer(keepAliveTimeout time.Duration) {
|
|||
cn.writerCond.Wait()
|
||||
continue
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.Write(cn.writeBuffer.Bytes())
|
||||
cn.writeBuffer.Reset()
|
||||
// Flip the buffers.
|
||||
frontBuf, cn.writeBuffer = cn.writeBuffer, frontBuf
|
||||
cn.mu().Unlock()
|
||||
// log.Printf("writing %d bytes", buf.Len())
|
||||
n, err := cn.w.Write(buf.Bytes())
|
||||
n, err := cn.w.Write(frontBuf.Bytes())
|
||||
cn.mu().Lock()
|
||||
if n != 0 {
|
||||
lastWrite = time.Now()
|
||||
|
@ -454,10 +452,10 @@ func (cn *connection) writer(keepAliveTimeout time.Duration) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n != buf.Len() {
|
||||
if n != frontBuf.Len() {
|
||||
panic("short write")
|
||||
}
|
||||
buf.Reset()
|
||||
frontBuf.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,12 @@ import (
|
|||
// Have that would potentially alter it.
|
||||
func TestSendBitfieldThenHave(t *testing.T) {
|
||||
r, w := io.Pipe()
|
||||
c := &connection{
|
||||
t: &Torrent{
|
||||
cl: &Client{},
|
||||
},
|
||||
r: r,
|
||||
w: w,
|
||||
}
|
||||
c.writerCond.L = &c.t.cl.mu
|
||||
var cl Client
|
||||
cl.initLogger()
|
||||
c := cl.newConnection(nil)
|
||||
c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
|
||||
c.r = r
|
||||
c.w = w
|
||||
go c.writer(time.Minute)
|
||||
c.mu().Lock()
|
||||
c.Bitfield([]bool{false, true, false})
|
||||
|
|
Loading…
Reference in New Issue