2021-12-01 11:38:47 +08:00
|
|
|
package request_strategy
|
|
|
|
|
|
|
|
import (
|
2021-12-03 18:31:40 +08:00
|
|
|
"fmt"
|
|
|
|
|
2021-12-01 11:38:47 +08:00
|
|
|
"github.com/anacrolix/torrent/metainfo"
|
2021-12-15 11:37:52 +08:00
|
|
|
"github.com/tidwall/btree"
|
2021-12-01 11:38:47 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func NewPieceOrder() *PieceRequestOrder {
|
|
|
|
return &PieceRequestOrder{
|
2021-12-15 11:37:52 +08:00
|
|
|
tree: btree.NewOptions(
|
|
|
|
func(a, b pieceRequestOrderItem) bool {
|
|
|
|
return a.Less(&b)
|
|
|
|
},
|
|
|
|
btree.Options{NoLocks: true}),
|
2021-12-01 11:38:47 +08:00
|
|
|
keys: make(map[PieceRequestOrderKey]PieceRequestOrderState),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type PieceRequestOrder struct {
|
2021-12-15 11:37:52 +08:00
|
|
|
tree *btree.BTree[pieceRequestOrderItem]
|
|
|
|
keys map[PieceRequestOrderKey]PieceRequestOrderState
|
|
|
|
pathHint btree.PathHint
|
2021-12-01 11:38:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type PieceRequestOrderKey struct {
|
|
|
|
InfoHash metainfo.Hash
|
|
|
|
Index int
|
|
|
|
}
|
|
|
|
|
|
|
|
type PieceRequestOrderState struct {
|
|
|
|
Priority piecePriority
|
|
|
|
Partial bool
|
2021-12-17 19:06:21 +08:00
|
|
|
Availability int
|
2021-12-01 11:38:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type pieceRequestOrderItem struct {
|
|
|
|
key PieceRequestOrderKey
|
|
|
|
state PieceRequestOrderState
|
|
|
|
}
|
|
|
|
|
2021-12-15 11:37:52 +08:00
|
|
|
func (me *pieceRequestOrderItem) Less(otherConcrete *pieceRequestOrderItem) bool {
|
2021-12-15 15:07:17 +08:00
|
|
|
return pieceOrderLess(me, otherConcrete).Less()
|
2021-12-01 11:38:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *PieceRequestOrder) Add(key PieceRequestOrderKey, state PieceRequestOrderState) {
|
|
|
|
if _, ok := me.keys[key]; ok {
|
|
|
|
panic(key)
|
|
|
|
}
|
2021-12-15 11:37:52 +08:00
|
|
|
if _, ok := me.tree.SetHint(pieceRequestOrderItem{
|
2021-12-01 11:38:47 +08:00
|
|
|
key: key,
|
|
|
|
state: state,
|
2021-12-15 11:37:52 +08:00
|
|
|
}, &me.pathHint); ok {
|
2021-12-01 11:38:47 +08:00
|
|
|
panic("shouldn't already have this")
|
|
|
|
}
|
|
|
|
me.keys[key] = state
|
|
|
|
}
|
|
|
|
|
2021-12-15 11:37:52 +08:00
|
|
|
type PieceRequestOrderPathHint = btree.PathHint
|
|
|
|
|
2021-12-01 11:38:47 +08:00
|
|
|
func (me *PieceRequestOrder) Update(key PieceRequestOrderKey, state PieceRequestOrderState) {
|
2021-12-15 15:07:17 +08:00
|
|
|
oldState, ok := me.keys[key]
|
|
|
|
if !ok {
|
|
|
|
panic("key should have been added already")
|
|
|
|
}
|
|
|
|
if state == oldState {
|
2021-12-09 18:49:29 +08:00
|
|
|
return
|
|
|
|
}
|
2021-12-15 15:07:17 +08:00
|
|
|
item := pieceRequestOrderItem{
|
|
|
|
key: key,
|
|
|
|
state: oldState,
|
|
|
|
}
|
2021-12-15 11:37:52 +08:00
|
|
|
if _, ok := me.tree.DeleteHint(item, &me.pathHint); !ok {
|
2021-12-03 18:31:40 +08:00
|
|
|
panic(fmt.Sprintf("%#v", key))
|
2021-12-01 11:38:47 +08:00
|
|
|
}
|
2021-12-09 18:49:29 +08:00
|
|
|
item.state = state
|
2021-12-15 11:37:52 +08:00
|
|
|
if _, ok := me.tree.SetHint(item, &me.pathHint); ok {
|
2021-12-01 11:38:47 +08:00
|
|
|
panic(key)
|
|
|
|
}
|
|
|
|
me.keys[key] = state
|
|
|
|
}
|
|
|
|
|
|
|
|
func (me *PieceRequestOrder) existingItemForKey(key PieceRequestOrderKey) pieceRequestOrderItem {
|
|
|
|
return pieceRequestOrderItem{
|
|
|
|
key: key,
|
|
|
|
state: me.keys[key],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (me *PieceRequestOrder) Delete(key PieceRequestOrderKey) {
|
2021-12-09 18:49:29 +08:00
|
|
|
item := me.existingItemForKey(key)
|
2021-12-15 11:37:52 +08:00
|
|
|
if _, ok := me.tree.DeleteHint(item, &me.pathHint); !ok {
|
2021-12-01 11:38:47 +08:00
|
|
|
panic(key)
|
|
|
|
}
|
|
|
|
delete(me.keys, key)
|
|
|
|
}
|
2021-12-11 10:46:29 +08:00
|
|
|
|
|
|
|
func (me *PieceRequestOrder) Len() int {
|
|
|
|
return len(me.keys)
|
|
|
|
}
|