This commit is contained in:
yourok
2019-05-17 10:53:59 +03:00
parent e9e231b809
commit 770fea51fb
4 changed files with 58 additions and 54 deletions

View File

@@ -14,53 +14,43 @@ type buffer struct {
} }
type BufferPool struct { type BufferPool struct {
buffs map[int]*buffer buffs map[int]*buffer
frees int bufferLength int64
size int64 bufferCount int
mu sync.Mutex mu sync.Mutex
} }
func NewBufferPool(bufferLength int64, capacity int64) *BufferPool { func NewBufferPool(bufferLength int64) *BufferPool {
bp := new(BufferPool) bp := new(BufferPool)
buffsSize := int(capacity/bufferLength) + 3 bp.bufferLength = bufferLength
bp.frees = buffsSize bp.buffs = make(map[int]*buffer)
bp.size = bufferLength
return bp return bp
} }
func (b *BufferPool) mkBuffs() {
if b.buffs != nil {
return
}
b.buffs = make(map[int]*buffer, b.frees)
fmt.Println("Create", b.frees, "buffers")
for i := 0; i < b.frees; i++ {
buf := buffer{
-1,
make([]byte, b.size),
false,
}
b.buffs[i] = &buf
}
}
func (b *BufferPool) GetBuffer(p *Piece) (buff []byte, index int) { func (b *BufferPool) GetBuffer(p *Piece) (buff []byte, index int) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
b.mkBuffs()
for id, buf := range b.buffs { for id, buf := range b.buffs {
if !buf.used { if !buf.used {
fmt.Println("Get buffer:", id)
buf.used = true buf.used = true
buf.pieceId = p.Id buf.pieceId = p.Id
buff = buf.buf buff = buf.buf
index = id index = id
b.frees--
//fmt.Printf("Get buffer: %v %v %v %p\n", id, p.Id, b.frees, buff)
return return
} }
} }
fmt.Println("Create slow buffer")
return make([]byte, b.size), -1 fmt.Println("Create buffer:", b.bufferCount)
buf := new(buffer)
buf.buf = make([]byte, b.bufferLength)
buf.used = true
buf.pieceId = p.Id
b.buffs[b.bufferCount] = buf
index = b.bufferCount
buff = buf.buf
b.bufferCount++
return
} }
func (b *BufferPool) ReleaseBuffer(index int) { func (b *BufferPool) ReleaseBuffer(index int) {
@@ -70,23 +60,18 @@ func (b *BufferPool) ReleaseBuffer(index int) {
} }
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
b.mkBuffs()
if buff, ok := b.buffs[index]; ok { if buff, ok := b.buffs[index]; ok {
fmt.Println("Release buffer:", index)
buff.used = false buff.used = false
buff.pieceId = -1 buff.pieceId = -1
b.frees++
//fmt.Println("Release buffer:", index, b.frees)
} else { } else {
utils.FreeOSMem() utils.FreeOSMem()
} }
} }
func (b *BufferPool) Used() map[int]struct{} { func (b *BufferPool) Used() map[int]struct{} {
if len(b.buffs) == 0 { b.mu.Lock()
b.mu.Lock() defer b.mu.Unlock()
b.mkBuffs()
b.mu.Unlock()
}
used := make(map[int]struct{}) used := make(map[int]struct{})
for _, b := range b.buffs { for _, b := range b.buffs {
if b.used { if b.used {
@@ -97,5 +82,13 @@ func (b *BufferPool) Used() map[int]struct{} {
} }
func (b *BufferPool) Len() int { func (b *BufferPool) Len() int {
return b.frees b.mu.Lock()
defer b.mu.Unlock()
count := 0
for _, b := range b.buffs {
if b.used {
count++
}
}
return count
} }

View File

@@ -15,8 +15,6 @@ import (
type Cache struct { type Cache struct {
storage.TorrentImpl storage.TorrentImpl
s *Storage
capacity int64 capacity int64
filled int64 filled int64
hash metainfo.Hash hash metainfo.Hash
@@ -33,14 +31,14 @@ type Cache struct {
bufferPull *BufferPool bufferPull *BufferPool
prcLoaded int prcLoaded int
position int
} }
func NewCache(capacity int64, storage *Storage) *Cache { func NewCache(capacity int64) *Cache {
ret := &Cache{ ret := &Cache{
capacity: capacity, capacity: capacity,
filled: 0, filled: 0,
pieces: make(map[int]*Piece), pieces: make(map[int]*Piece),
s: storage,
} }
return ret return ret
@@ -57,7 +55,7 @@ func (c *Cache) Init(info *metainfo.Info, hash metainfo.Hash) {
c.pieceCount = info.NumPieces() c.pieceCount = info.NumPieces()
c.piecesBuff = int(c.capacity / c.pieceLength) c.piecesBuff = int(c.capacity / c.pieceLength)
c.hash = hash c.hash = hash
c.bufferPull = NewBufferPool(c.pieceLength, c.capacity) c.bufferPull = NewBufferPool(c.pieceLength)
for i := 0; i < c.pieceCount; i++ { for i := 0; i < c.pieceCount; i++ {
c.pieces[i] = &Piece{ c.pieces[i] = &Piece{
@@ -81,9 +79,6 @@ func (c *Cache) Piece(m metainfo.Piece) storage.PieceImpl {
func (c *Cache) Close() error { func (c *Cache) Close() error {
c.isRemove = false c.isRemove = false
fmt.Println("Close cache for:", c.hash) fmt.Println("Close cache for:", c.hash)
if _, ok := c.s.caches[c.hash]; ok {
delete(c.s.caches, c.hash)
}
c.pieces = nil c.pieces = nil
c.bufferPull = nil c.bufferPull = nil
utils.FreeOSMemGC() utils.FreeOSMemGC()
@@ -114,6 +109,11 @@ func (c *Cache) GetState() state.CacheState {
return cState return cState
} }
func (c *Cache) setPos(pos int) {
c.position = (c.position + pos) / 2
//fmt.Println("Read:", c.position)
}
func (c *Cache) cleanPieces() { func (c *Cache) cleanPieces() {
if c.isRemove { if c.isRemove {
return return
@@ -150,10 +150,15 @@ func (c *Cache) getRemPieces() []*Piece {
fill := int64(0) fill := int64(0)
loading := 0 loading := 0
used := c.bufferPull.Used() used := c.bufferPull.Used()
fpices := c.piecesBuff - int(utils.GetReadahead()/c.pieceLength)
low := c.position - fpices + 1
high := c.position + c.piecesBuff - fpices + 3
for u := range used { for u := range used {
v := c.pieces[u] v := c.pieces[u]
if v.Size > 0 { if v.Size > 0 {
if v.Id > 0 { if v.Id > 0 && (v.Id < low || v.Id > high) {
pieces = append(pieces, v) pieces = append(pieces, v)
} }
fill += v.Size fill += v.Size
@@ -164,7 +169,7 @@ func (c *Cache) getRemPieces() []*Piece {
} }
c.filled = fill c.filled = fill
sort.Slice(pieces, func(i, j int) bool { sort.Slice(pieces, func(i, j int) bool {
return pieces[i].accessed.Before(pieces[j].accessed) return pieces[i].accessed < pieces[j].accessed
}) })
c.prcLoaded = prc(c.piecesBuff-loading, c.piecesBuff) c.prcLoaded = prc(c.piecesBuff-loading, c.piecesBuff)

View File

@@ -21,7 +21,7 @@ type Piece struct {
complete bool complete bool
readed bool readed bool
accessed time.Time accessed int64
buffer []byte buffer []byte
bufIndex int bufIndex int
@@ -42,14 +42,13 @@ func (p *Piece) WriteAt(b []byte, off int64) (n int, err error) {
} }
n = copy(p.buffer[off:], b[:]) n = copy(p.buffer[off:], b[:])
p.Size += int64(n) p.Size += int64(n)
p.accessed = time.Now() p.accessed = time.Now().Unix() + 2000
return return
} }
func (p *Piece) ReadAt(b []byte, off int64) (n int, err error) { func (p *Piece) ReadAt(b []byte, off int64) (n int, err error) {
p.mu.RLock() p.mu.RLock()
defer p.mu.RUnlock() defer p.mu.RUnlock()
size := len(b) size := len(b)
if size+int(off) > len(p.buffer) { if size+int(off) > len(p.buffer) {
size = len(p.buffer) - int(off) size = len(p.buffer) - int(off)
@@ -61,13 +60,19 @@ func (p *Piece) ReadAt(b []byte, off int64) (n int, err error) {
return 0, io.ErrUnexpectedEOF return 0, io.ErrUnexpectedEOF
} }
n = copy(b, p.buffer[int(off) : int(off)+size][:]) n = copy(b, p.buffer[int(off) : int(off)+size][:])
p.accessed = time.Now()
if int(off)+size >= len(p.buffer) { if int(off)+size >= len(p.buffer) {
p.readed = true p.readed = true
} }
if int64(len(b))+off >= p.Size { if int64(len(b))+off >= p.Size {
go p.cache.cleanPieces() go p.cache.cleanPieces()
} }
if p.complete {
p.accessed = time.Now().Unix()
p.cache.setPos(p.Id)
}
return n, nil return n, nil
} }
@@ -81,12 +86,13 @@ func (p *Piece) MarkComplete() error {
func (p *Piece) MarkNotComplete() error { func (p *Piece) MarkNotComplete() error {
p.complete = false p.complete = false
p.accessed = 0
return nil return nil
} }
func (p *Piece) Completion() storage.Completion { func (p *Piece) Completion() storage.Completion {
return storage.Completion{ return storage.Completion{
Complete: p.complete && len(p.buffer) > 0, Complete: p.complete,
Ok: true, Ok: true,
} }
} }

View File

@@ -28,7 +28,7 @@ func NewStorage(capacity int64) storage.Storage {
func (s *Storage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (storage2.TorrentImpl, error) { func (s *Storage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (storage2.TorrentImpl, error) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
ch := NewCache(s.capacity, s) ch := NewCache(s.capacity)
ch.Init(info, infoHash) ch.Init(info, infoHash)
s.caches[infoHash] = ch s.caches[infoHash] = ch
return ch, nil return ch, nil