You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
5.9 KiB
333 lines
5.9 KiB
package udptransfer
|
|
|
|
type qNode struct {
|
|
*packet
|
|
prev *qNode
|
|
next *qNode
|
|
sent int64 // last sent time
|
|
sent_1 int64 // prev sent time
|
|
miss int // sack miss count
|
|
}
|
|
|
|
type linkedMap struct {
|
|
head *qNode
|
|
tail *qNode
|
|
qmap map[uint32]*qNode
|
|
lastIns *qNode
|
|
maxCtnSeq uint32
|
|
mode int
|
|
}
|
|
|
|
const (
|
|
_QModeIn = 1
|
|
_QModeOut = 2
|
|
)
|
|
|
|
func newLinkedMap(qmode int) *linkedMap {
|
|
return &linkedMap{
|
|
qmap: make(map[uint32]*qNode),
|
|
mode: qmode,
|
|
}
|
|
}
|
|
|
|
func (l *linkedMap) get(seq uint32) (i *qNode) {
|
|
i = l.qmap[seq]
|
|
return
|
|
}
|
|
|
|
func (l *linkedMap) contains(seq uint32) bool {
|
|
_, y := l.qmap[seq]
|
|
return y
|
|
}
|
|
|
|
func (l *linkedMap) size() int32 {
|
|
return int32(len(l.qmap))
|
|
}
|
|
|
|
func (l *linkedMap) reset() {
|
|
l.head = nil
|
|
l.tail = nil
|
|
l.lastIns = nil
|
|
l.maxCtnSeq = 0
|
|
l.qmap = make(map[uint32]*qNode)
|
|
}
|
|
|
|
func (l *linkedMap) isEqualsHead(seq uint32) bool {
|
|
return l.head != nil && seq == l.head.seq
|
|
}
|
|
|
|
func (l *linkedMap) distanceOfHead(seq uint32) int32 {
|
|
if l.head != nil {
|
|
return int32(seq - l.head.seq)
|
|
} else {
|
|
return -1
|
|
}
|
|
}
|
|
|
|
func (l *linkedMap) appendTail(one *qNode) {
|
|
if l.tail != nil {
|
|
l.tail.next = one
|
|
one.prev = l.tail
|
|
l.tail = one
|
|
} else {
|
|
l.head = one
|
|
l.tail = one
|
|
}
|
|
l.qmap[one.seq] = one
|
|
}
|
|
|
|
// xxx - n - yyy
|
|
// xxx - yyy
|
|
func (l *linkedMap) deleteAt(n *qNode) {
|
|
x, y := n.prev, n.next
|
|
if x != nil {
|
|
x.next = y
|
|
} else {
|
|
l.head = y
|
|
}
|
|
if y != nil {
|
|
y.prev = x
|
|
} else {
|
|
l.tail = x
|
|
}
|
|
n.prev, n.next = nil, nil
|
|
delete(l.qmap, n.seq)
|
|
}
|
|
|
|
// delete with n <- ...n |
|
|
func (l *linkedMap) deleteBefore(n *qNode) (left *qNode, deleted int32) {
|
|
for i := n; i != nil; i = i.prev {
|
|
delete(l.qmap, i.seq)
|
|
if i.scnt != _SENT_OK {
|
|
deleted++
|
|
// only outQ could delete at here
|
|
if l.mode == _QModeOut {
|
|
bpool.Put(i.buffer)
|
|
i.buffer = nil
|
|
}
|
|
}
|
|
}
|
|
left = l.head
|
|
l.head = n.next
|
|
n.next = nil
|
|
if l.head != nil {
|
|
l.head.prev = nil
|
|
} else { // n.next is the tail and is nil
|
|
l.tail = nil
|
|
}
|
|
return
|
|
}
|
|
|
|
// xxx - ref
|
|
// xxx - one - ref
|
|
func (l *linkedMap) insertBefore(ref, one *qNode) {
|
|
x := ref.prev
|
|
if x != nil {
|
|
x.next = one
|
|
one.prev = x
|
|
} else {
|
|
l.head = one
|
|
}
|
|
ref.prev = one
|
|
one.next = ref
|
|
l.qmap[one.seq] = one
|
|
}
|
|
|
|
// ref - zzz
|
|
// ref - one - zzz
|
|
func (l *linkedMap) insertAfter(ref, one *qNode) {
|
|
z := ref.next
|
|
if z == nil { // append
|
|
ref.next = one
|
|
l.tail = one
|
|
} else { // insert mid
|
|
z.prev = one
|
|
ref.next = one
|
|
}
|
|
one.prev = ref
|
|
one.next = z
|
|
l.qmap[one.seq] = one
|
|
}
|
|
|
|
// baseHead: the left outside boundary
|
|
// if inserted, return the distance between newNode with baseHead
|
|
func (l *linkedMap) searchInsert(one *qNode, baseHead uint32) (dis int64) {
|
|
for i := l.tail; i != nil; i = i.prev {
|
|
dis = int64(one.seq) - int64(i.seq)
|
|
if dis > 0 {
|
|
l.insertAfter(i, one)
|
|
return
|
|
} else if dis == 0 {
|
|
// duplicated
|
|
return
|
|
}
|
|
}
|
|
if one.seq <= baseHead {
|
|
return 0
|
|
}
|
|
if l.head != nil {
|
|
l.insertBefore(l.head, one)
|
|
} else {
|
|
l.head = one
|
|
l.tail = one
|
|
l.qmap[one.seq] = one
|
|
}
|
|
dis = int64(one.seq) - int64(baseHead)
|
|
return
|
|
}
|
|
|
|
func (l *linkedMap) updateContinuous(i *qNode) bool {
|
|
var lastCtnSeq = l.maxCtnSeq
|
|
for ; i != nil; i = i.next {
|
|
if i.seq-lastCtnSeq == 1 {
|
|
lastCtnSeq = i.seq
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
if lastCtnSeq != l.maxCtnSeq {
|
|
l.maxCtnSeq = lastCtnSeq
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (l *linkedMap) isWholeContinuous() bool {
|
|
return l.tail != nil && l.maxCtnSeq == l.tail.seq
|
|
}
|
|
|
|
/*
|
|
func (l *linkedMap) searchMaxContinued(baseHead uint32) (*qNode, bool) {
|
|
var last *qNode
|
|
for i := l.head; i != nil; i = i.next {
|
|
if last != nil {
|
|
if i.seq-last.seq > 1 {
|
|
return last, true
|
|
}
|
|
} else {
|
|
if i.seq != baseHead {
|
|
return nil, false
|
|
}
|
|
}
|
|
last = i
|
|
}
|
|
if last != nil {
|
|
return last, true
|
|
} else {
|
|
return nil, false
|
|
}
|
|
}
|
|
*/
|
|
|
|
func (q *qNode) forward(n int) *qNode {
|
|
for ; n > 0 && q != nil; n-- {
|
|
q = q.next
|
|
}
|
|
return q
|
|
}
|
|
|
|
// prev of bitmap start point
|
|
func (l *linkedMap) makeHolesBitmap(prev uint32) ([]uint64, uint32) {
|
|
var start *qNode
|
|
var bits uint64
|
|
var j uint32
|
|
for i := l.head; i != nil; i = i.next {
|
|
if i.seq >= prev+1 {
|
|
start = i
|
|
break
|
|
}
|
|
}
|
|
var bitmap []uint64
|
|
// search start which is the recent successor of [prev]
|
|
Iterator:
|
|
for i := start; i != nil; i = i.next {
|
|
dis := i.seq - prev
|
|
prev = i.seq
|
|
j += dis // j is next bit index
|
|
for j >= 65 {
|
|
if len(bitmap) >= 20 { // bitmap too long
|
|
break Iterator
|
|
}
|
|
bitmap = append(bitmap, bits)
|
|
bits = 0
|
|
j -= 64
|
|
}
|
|
bits |= 1 << (j - 1)
|
|
}
|
|
if j > 0 {
|
|
// j -> (0, 64]
|
|
bitmap = append(bitmap, bits)
|
|
}
|
|
return bitmap, j
|
|
}
|
|
|
|
// from= the bitmap start point
|
|
func (l *linkedMap) deleteByBitmap(bmap []uint64, from uint32, tailBitsLen uint32) (deleted, missed int32, lastContinued bool) {
|
|
var start = l.qmap[from]
|
|
if start != nil {
|
|
// delete predecessors
|
|
if pred := start.prev; pred != nil {
|
|
_, n := l.deleteBefore(pred)
|
|
deleted += n
|
|
}
|
|
} else {
|
|
// [from] is out of bounds
|
|
return
|
|
}
|
|
var j, bitsLen uint32
|
|
var bits uint64
|
|
bits, bmap = bmap[0], bmap[1:]
|
|
if len(bmap) > 0 {
|
|
bitsLen = 64
|
|
} else {
|
|
// bmap.len==1, tail is here
|
|
bitsLen = tailBitsLen
|
|
}
|
|
// maxContinued will save the max continued node (from [start]) which could be deleted safely.
|
|
// keep the queue smallest
|
|
var maxContinued *qNode
|
|
lastContinued = true
|
|
|
|
for i := start; i != nil; j++ {
|
|
if j >= bitsLen {
|
|
if len(bmap) > 0 {
|
|
j = 0
|
|
bits, bmap = bmap[0], bmap[1:]
|
|
if len(bmap) > 0 {
|
|
bitsLen = 64
|
|
} else {
|
|
bitsLen = tailBitsLen
|
|
}
|
|
} else {
|
|
// no more pages
|
|
goto finished
|
|
}
|
|
}
|
|
if bits&1 == 1 {
|
|
if lastContinued {
|
|
maxContinued = i
|
|
}
|
|
if i.scnt != _SENT_OK {
|
|
// no mark means first deleting
|
|
deleted++
|
|
}
|
|
// don't delete, just mark it
|
|
i.scnt = _SENT_OK
|
|
} else {
|
|
// known it may be lost
|
|
if i.miss == 0 {
|
|
missed++
|
|
}
|
|
i.miss++
|
|
lastContinued = false
|
|
}
|
|
bits >>= 1
|
|
i = i.next
|
|
}
|
|
|
|
finished:
|
|
if maxContinued != nil {
|
|
l.deleteBefore(maxContinued)
|
|
}
|
|
return
|
|
}
|