fix: 修复 dedicated bulk attach 竞态并优化 short write 补写路径
- 客户端 dedicated attach 回复改为精确读取单帧,避免 attach reply 与后续 NBR1 数据粘连后被误解析 - 服务端 accepted attach 改为先 detach transport,再直接回 attach reply,随后立即切入 dedicated bulk read loop - transport 读循环在 stop 或 transport ownership 失效后不再继续上推已读数据,避免 handoff 后首包被旧 reader 吃掉 - dedicated bulk record 写路径改为 full-write,消除 short write 导致的 invalid bulk fast payload - 优化 vectored write 补写策略:先尝试一次 writev,未写完时直接顺序补完剩余 buffers,减少重复 WriteTo 开销 - 放宽 vectored write 能力识别,支持通过 UnwrapConn/WriteBuffers 命中 fast path - 修复 dedicated batch 排队路径 payload 复用问题,改为深拷贝 queued items - 补齐 dedicated attach、short write、payload clone、transport stop/handoff 等回归测试
This commit is contained in:
@@ -69,6 +69,12 @@ func (c *LogicalConn) readFromTUTransportConnWithBuffer(conn net.Conn, data []by
|
||||
}
|
||||
|
||||
func (c *LogicalConn) handleTUTransportReadResultWithSession(stopCtx context.Context, conn net.Conn, generation uint64, num int, data []byte, err error) bool {
|
||||
if transportReadShouldStop(stopCtx) || !c.ownsTransportRead(conn, generation) {
|
||||
if c.shouldCloseTransportOnStop(conn) {
|
||||
_ = conn.Close()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if err == os.ErrDeadlineExceeded {
|
||||
if num != 0 {
|
||||
c.pushServerOwnedTransportMessage(data[:num], conn, generation)
|
||||
@@ -95,6 +101,30 @@ func (c *LogicalConn) handleTUTransportReadResultWithSession(stopCtx context.Con
|
||||
return true
|
||||
}
|
||||
|
||||
func transportReadShouldStop(stopCtx context.Context) bool {
|
||||
select {
|
||||
case <-sessionStopChan(stopCtx):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *LogicalConn) ownsTransportRead(conn net.Conn, generation uint64) bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
rt := c.clientConnSessionRuntimeSnapshot()
|
||||
if rt == nil || !rt.transportAttached || rt.transportGeneration != generation {
|
||||
return false
|
||||
}
|
||||
current := rt.tuConn
|
||||
if rt.transport != nil && rt.transport.connSnapshot() != nil {
|
||||
current = rt.transport.connSnapshot()
|
||||
}
|
||||
return current == conn
|
||||
}
|
||||
|
||||
func (c *LogicalConn) pushServerOwnedTransportMessage(data []byte, conn net.Conn, generation uint64) {
|
||||
if c == nil || len(data) == 0 {
|
||||
return
|
||||
@@ -163,6 +193,12 @@ func (c *ClientConn) handleTUTransportReadResultWithSession(stopCtx context.Cont
|
||||
if logical := c.LogicalConn(); logical != nil {
|
||||
return logical.handleTUTransportReadResultWithSession(stopCtx, conn, generation, num, data, err)
|
||||
}
|
||||
if transportReadShouldStop(stopCtx) || !c.ownsTransportRead(conn, generation) {
|
||||
if c.shouldCloseClientConnTransportOnStop(conn) {
|
||||
_ = conn.Close()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if err == os.ErrDeadlineExceeded {
|
||||
if num != 0 {
|
||||
c.pushServerOwnedTransportMessage(data[:num], conn, generation)
|
||||
@@ -189,6 +225,21 @@ func (c *ClientConn) handleTUTransportReadResultWithSession(stopCtx context.Cont
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *ClientConn) ownsTransportRead(conn net.Conn, generation uint64) bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
rt := c.clientConnSessionRuntimeSnapshot()
|
||||
if rt == nil || !rt.transportAttached || rt.transportGeneration != generation {
|
||||
return false
|
||||
}
|
||||
current := rt.tuConn
|
||||
if rt.transport != nil && rt.transport.connSnapshot() != nil {
|
||||
current = rt.transport.connSnapshot()
|
||||
}
|
||||
return current == conn
|
||||
}
|
||||
|
||||
func (c *ClientConn) pushServerOwnedTransportMessage(data []byte, conn net.Conn, generation uint64) {
|
||||
if logical := c.LogicalConn(); logical != nil {
|
||||
logical.pushServerOwnedTransportMessage(data, conn, generation)
|
||||
|
||||
Reference in New Issue
Block a user