|
@@ -3,6 +3,7 @@ package mux
|
|
|
import (
|
|
|
"errors"
|
|
|
"github.com/astaxie/beego/logs"
|
|
|
+ "github.com/cnlh/nps/lib/common"
|
|
|
"io"
|
|
|
"math"
|
|
|
"net"
|
|
@@ -10,8 +11,6 @@ import (
|
|
|
"sync"
|
|
|
"sync/atomic"
|
|
|
"time"
|
|
|
-
|
|
|
- "github.com/cnlh/nps/lib/common"
|
|
|
)
|
|
|
|
|
|
type conn struct {
|
|
@@ -146,25 +145,44 @@ func (s *conn) SetWriteDeadline(t time.Time) error {
|
|
|
}
|
|
|
|
|
|
type window struct {
|
|
|
- remainingWait uint64
|
|
|
- off uint32
|
|
|
- maxSize uint32
|
|
|
- closeOp bool
|
|
|
- closeOpCh chan struct{}
|
|
|
- mux *Mux
|
|
|
-}
|
|
|
-
|
|
|
-func (Self *window) unpack(ptrs uint64) (remaining, wait uint32) {
|
|
|
- const mask = 1<<dequeueBits - 1
|
|
|
- remaining = uint32((ptrs >> dequeueBits) & mask)
|
|
|
- wait = uint32(ptrs & mask)
|
|
|
+ maxSizeDone uint64
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ off uint32
|
|
|
+ closeOp bool
|
|
|
+ closeOpCh chan struct{}
|
|
|
+ mux *Mux
|
|
|
+}
|
|
|
+
|
|
|
+const windowBits = 31
|
|
|
+const waitBits = dequeueBits + windowBits
|
|
|
+const mask1 = 1
|
|
|
+const mask31 = 1<<windowBits - 1
|
|
|
+
|
|
|
+func (Self *window) unpack(ptrs uint64) (maxSize, done uint32, wait bool) {
|
|
|
+ maxSize = uint32((ptrs >> dequeueBits) & mask31)
|
|
|
+ done = uint32(ptrs & mask31)
|
|
|
+
|
|
|
+ if ((ptrs >> waitBits) & mask1) == 1 {
|
|
|
+ wait = true
|
|
|
+ return
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func (Self *window) pack(remaining, wait uint32) uint64 {
|
|
|
- const mask = 1<<dequeueBits - 1
|
|
|
- return (uint64(remaining) << dequeueBits) |
|
|
|
- uint64(wait&mask)
|
|
|
+func (Self *window) pack(maxSize, done uint32, wait bool) uint64 {
|
|
|
+
|
|
|
+ if wait {
|
|
|
+ return (uint64(1)<<waitBits |
|
|
|
+ uint64(maxSize&mask31)<<dequeueBits) |
|
|
|
+ uint64(done&mask31)
|
|
|
+ }
|
|
|
+ return (uint64(0)<<waitBits |
|
|
|
+ uint64(maxSize&mask31)<<dequeueBits) |
|
|
|
+ uint64(done&mask31)
|
|
|
}
|
|
|
|
|
|
func (Self *window) New() {
|
|
@@ -185,20 +203,22 @@ type ReceiveWindow struct {
|
|
|
element *common.ListElement
|
|
|
count int8
|
|
|
once sync.Once
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
func (Self *ReceiveWindow) New(mux *Mux) {
|
|
|
|
|
|
Self.bufQueue.New()
|
|
|
Self.element = common.ListElementPool.Get()
|
|
|
- Self.maxSize = common.MAXIMUM_SEGMENT_SIZE * 10
|
|
|
+ Self.maxSizeDone = Self.pack(common.MAXIMUM_SEGMENT_SIZE*10, 0, false)
|
|
|
Self.mux = mux
|
|
|
Self.window.New()
|
|
|
}
|
|
|
|
|
|
-func (Self *ReceiveWindow) remainingSize(delta uint16) (n uint32) {
|
|
|
+func (Self *ReceiveWindow) remainingSize(maxSize uint32, delta uint16) (n uint32) {
|
|
|
|
|
|
- l := int64(atomic.LoadUint32(&Self.maxSize)) - int64(Self.bufQueue.Len())
|
|
|
+ l := int64(maxSize) - int64(Self.bufQueue.Len())
|
|
|
l -= int64(delta)
|
|
|
if l > 0 {
|
|
|
n = uint32(l)
|
|
@@ -213,27 +233,33 @@ func (Self *ReceiveWindow) calcSize() {
|
|
|
conns := Self.mux.connMap.Size()
|
|
|
n := uint32(math.Float64frombits(atomic.LoadUint64(&Self.mux.latency)) *
|
|
|
Self.mux.bw.Get() / float64(conns))
|
|
|
+
|
|
|
if n < common.MAXIMUM_SEGMENT_SIZE*10 {
|
|
|
n = common.MAXIMUM_SEGMENT_SIZE * 10
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if n < Self.maxSize/2 {
|
|
|
- n = Self.maxSize / 2
|
|
|
- }
|
|
|
-
|
|
|
- if n > 2*Self.maxSize {
|
|
|
- n = 2 * Self.maxSize
|
|
|
- }
|
|
|
- if n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) {
|
|
|
- logs.Warn("window too large", n)
|
|
|
- n = common.MAXIMUM_WINDOW_SIZE / uint32(conns)
|
|
|
+ for {
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ size, read, wait := Self.unpack(ptrs)
|
|
|
+ if n < size/2 {
|
|
|
+ n = size / 2
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if n > 2*size {
|
|
|
+ n = 2 * size
|
|
|
+
|
|
|
+ }
|
|
|
+ if n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) {
|
|
|
+
|
|
|
+ n = common.MAXIMUM_WINDOW_SIZE / uint32(conns)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(n, read, wait)) {
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- atomic.StoreUint32(&Self.maxSize, n)
|
|
|
Self.count = -10
|
|
|
}
|
|
|
Self.count += 1
|
|
@@ -245,30 +271,40 @@ func (Self *ReceiveWindow) Write(buf []byte, l uint16, part bool, id int32) (err
|
|
|
return errors.New("conn.receiveWindow: write on closed window")
|
|
|
}
|
|
|
element, err := NewListElement(buf, l, part)
|
|
|
-
|
|
|
+
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
Self.calcSize()
|
|
|
- var wait uint32
|
|
|
+ var wait bool
|
|
|
+ var maxSize, read uint32
|
|
|
start:
|
|
|
- ptrs := atomic.LoadUint64(&Self.remainingWait)
|
|
|
- _, wait = Self.unpack(ptrs)
|
|
|
- newRemaining := Self.remainingSize(l)
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ maxSize, read, wait = Self.unpack(ptrs)
|
|
|
+ remain := Self.remainingSize(maxSize, l)
|
|
|
|
|
|
- if newRemaining == 0 {
|
|
|
+ if remain == 0 && !wait {
|
|
|
|
|
|
- wait = 1
|
|
|
- }
|
|
|
- if !atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, wait)) {
|
|
|
- goto start
|
|
|
-
|
|
|
- }
|
|
|
+ wait = true
|
|
|
+ if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, read, wait)) {
|
|
|
+
|
|
|
+ goto start
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if !wait {
|
|
|
+ if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, 0, wait)) {
|
|
|
+
|
|
|
+ goto start
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
Self.bufQueue.Push(element)
|
|
|
|
|
|
- if wait == 0 {
|
|
|
- Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.maxSize, newRemaining)
|
|
|
-
|
|
|
+ if !wait {
|
|
|
+ Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false))
|
|
|
+
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
@@ -279,7 +315,7 @@ func (Self *ReceiveWindow) Read(p []byte, id int32) (n int, err error) {
|
|
|
}
|
|
|
pOff := 0
|
|
|
l := 0
|
|
|
-
|
|
|
+
|
|
|
copyData:
|
|
|
if Self.off == uint32(Self.element.L) {
|
|
|
|
|
@@ -291,14 +327,13 @@ copyData:
|
|
|
Self.element, err = Self.bufQueue.Pop()
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
Self.off = 0
|
|
|
if err != nil {
|
|
|
Self.CloseWindow()
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
l = copy(p[pOff:], Self.element.Buf[Self.off:Self.element.L])
|
|
|
pOff += l
|
|
@@ -320,22 +355,41 @@ copyData:
|
|
|
}
|
|
|
|
|
|
func (Self *ReceiveWindow) sendStatus(id int32, l uint16) {
|
|
|
- var remaining, wait uint32
|
|
|
+ var maxSize, read uint32
|
|
|
+ var wait bool
|
|
|
for {
|
|
|
- ptrs := atomic.LoadUint64(&Self.remainingWait)
|
|
|
- remaining, wait = Self.unpack(ptrs)
|
|
|
- remaining += uint32(l)
|
|
|
- if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(remaining, 0)) {
|
|
|
- break
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ maxSize, read, wait = Self.unpack(ptrs)
|
|
|
+ if read <= (read+uint32(l))&mask31 {
|
|
|
+ read += uint32(l)
|
|
|
+ remain := Self.remainingSize(maxSize, 0)
|
|
|
+ if wait && remain > 0 || remain == maxSize {
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, 0, false)) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false))
|
|
|
+ break
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, read, wait)) {
|
|
|
+
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, uint32(l), wait)) {
|
|
|
+
|
|
|
+ Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false))
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
runtime.Gosched()
|
|
|
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if wait == 1 {
|
|
|
-
|
|
|
- Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, atomic.LoadUint32(&Self.maxSize), remaining)
|
|
|
}
|
|
|
return
|
|
|
}
|
|
@@ -380,12 +434,14 @@ type SendWindow struct {
|
|
|
buf []byte
|
|
|
setSizeCh chan struct{}
|
|
|
timeout time.Time
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
func (Self *SendWindow) New(mux *Mux) {
|
|
|
Self.setSizeCh = make(chan struct{})
|
|
|
- Self.maxSize = common.MAXIMUM_SEGMENT_SIZE * 10
|
|
|
- atomic.AddUint64(&Self.remainingWait, uint64(common.MAXIMUM_SEGMENT_SIZE*10)<<dequeueBits)
|
|
|
+ Self.maxSizeDone = Self.pack(common.MAXIMUM_SEGMENT_SIZE*10, 0, false)
|
|
|
Self.mux = mux
|
|
|
Self.window.New()
|
|
|
}
|
|
@@ -396,7 +452,15 @@ func (Self *SendWindow) SetSendBuf(buf []byte) {
|
|
|
Self.off = 0
|
|
|
}
|
|
|
|
|
|
-func (Self *SendWindow) SetSize(windowSize, newRemaining uint32) (closed bool) {
|
|
|
+func (Self *SendWindow) remainingSize(maxSize, send uint32) uint32 {
|
|
|
+ l := int64(maxSize&mask31) - int64(send&mask31)
|
|
|
+ if l > 0 {
|
|
|
+ return uint32(l)
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+func (Self *SendWindow) SetSize(currentMaxSizeDone uint64) (closed bool) {
|
|
|
|
|
|
defer func() {
|
|
|
if recover() != nil {
|
|
@@ -408,26 +472,34 @@ func (Self *SendWindow) SetSize(windowSize, newRemaining uint32) (closed bool) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
- var remaining, wait, newWait uint32
|
|
|
+ var maxsize, send uint32
|
|
|
+ var wait, newWait bool
|
|
|
+ currentMaxSize, read, _ := Self.unpack(currentMaxSizeDone)
|
|
|
for {
|
|
|
- ptrs := atomic.LoadUint64(&Self.remainingWait)
|
|
|
- remaining, wait = Self.unpack(ptrs)
|
|
|
- if remaining == newRemaining {
|
|
|
-
|
|
|
- return false
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ maxsize, send, wait = Self.unpack(ptrs)
|
|
|
+ if read > send {
|
|
|
+ logs.Error("read > send")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if read == 0 && currentMaxSize == maxsize {
|
|
|
+ return
|
|
|
}
|
|
|
- if newRemaining == 0 && wait == 1 {
|
|
|
- newWait = 1
|
|
|
-
|
|
|
+ send -= read
|
|
|
+ remain := Self.remainingSize(currentMaxSize, send)
|
|
|
+ if remain == 0 && wait {
|
|
|
+
|
|
|
+ newWait = true
|
|
|
}
|
|
|
- if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(newRemaining, newWait)) {
|
|
|
+
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(currentMaxSize, send, newWait)) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
}
|
|
|
- if wait == 1 {
|
|
|
+ if wait && !newWait {
|
|
|
|
|
|
-
|
|
|
+
|
|
|
Self.allow()
|
|
|
}
|
|
|
|
|
@@ -446,18 +518,20 @@ func (Self *SendWindow) allow() {
|
|
|
}
|
|
|
|
|
|
func (Self *SendWindow) sent(sentSize uint32) {
|
|
|
- var remaining, wait uint32
|
|
|
+ var maxSie, send uint32
|
|
|
+ var wait bool
|
|
|
for {
|
|
|
- ptrs := atomic.LoadUint64(&Self.remainingWait)
|
|
|
- remaining, wait = Self.unpack(ptrs)
|
|
|
- if remaining >= sentSize {
|
|
|
- atomic.AddUint64(&Self.remainingWait, ^(uint64(sentSize)<<dequeueBits - 1))
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ maxSie, send, wait = Self.unpack(ptrs)
|
|
|
+ if (send+sentSize)&mask31 < send {
|
|
|
+
|
|
|
+ runtime.Gosched()
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSie, send+sentSize, wait)) {
|
|
|
+
|
|
|
+
|
|
|
break
|
|
|
- } else {
|
|
|
- if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, wait)) {
|
|
|
-
|
|
|
- break
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -472,12 +546,14 @@ func (Self *SendWindow) WriteTo() (p []byte, sendSize uint32, part bool, err err
|
|
|
return nil, 0, false, io.EOF
|
|
|
|
|
|
}
|
|
|
- var remaining uint32
|
|
|
+ var maxSize, send uint32
|
|
|
start:
|
|
|
- ptrs := atomic.LoadUint64(&Self.remainingWait)
|
|
|
- remaining, _ = Self.unpack(ptrs)
|
|
|
- if remaining == 0 {
|
|
|
- if !atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, 1)) {
|
|
|
+ ptrs := atomic.LoadUint64(&Self.maxSizeDone)
|
|
|
+ maxSize, send, _ = Self.unpack(ptrs)
|
|
|
+ remain := Self.remainingSize(maxSize, send)
|
|
|
+ if remain == 0 {
|
|
|
+ if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, send, true)) {
|
|
|
+
|
|
|
goto start
|
|
|
}
|
|
|
|
|
@@ -490,17 +566,17 @@ start:
|
|
|
goto start
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
if len(Self.buf[Self.off:]) > common.MAXIMUM_SEGMENT_SIZE {
|
|
|
sendSize = common.MAXIMUM_SEGMENT_SIZE
|
|
|
|
|
|
} else {
|
|
|
sendSize = uint32(len(Self.buf[Self.off:]))
|
|
|
}
|
|
|
- if remaining < sendSize {
|
|
|
+ if remain < sendSize {
|
|
|
|
|
|
|
|
|
- sendSize = remaining
|
|
|
+ sendSize = remain
|
|
|
|
|
|
}
|
|
|
|