From 70b71dc279cc28a2365ddf769bcd5c8f8f907491 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Mon, 17 May 2021 11:54:56 +0300 Subject: [PATCH] change disk cache --- server/torr/apihelper.go | 15 ++++ server/torr/storage/torrstor/cache.go | 86 +++++++++++++---------- server/torr/storage/torrstor/diskpiece.go | 44 +++++------- server/torr/torrent.go | 1 + 4 files changed, 85 insertions(+), 61 deletions(-) diff --git a/server/torr/apihelper.go b/server/torr/apihelper.go index 7cc8786..cadff77 100644 --- a/server/torr/apihelper.go +++ b/server/torr/apihelper.go @@ -3,6 +3,7 @@ package torr import ( "io" "os" + "path/filepath" "sort" "time" @@ -126,6 +127,20 @@ func RemTorrent(hashHex string) { hash := metainfo.NewHashFromHex(hashHex) bts.RemoveTorrent(hash) RemTorrentDB(hash) + if sets.BTsets.UseDisk && + hashHex != "" && + hashHex != "/" && + sets.BTsets.TorrentsSavePath != "" && + sets.BTsets.TorrentsSavePath != "/" { + + name := filepath.Join(sets.BTsets.TorrentsSavePath, hashHex) + err := os.RemoveAll(name) + if err != nil { + log.TLogln("Error remove cache:", err) + } else { + log.TLogln("Remove cache from disk:", hashHex) + } + } } func ListTorrent() []*Torrent { diff --git a/server/torr/storage/torrstor/cache.go b/server/torr/storage/torrstor/cache.go index 2b3bff7..3266aa3 100644 --- a/server/torr/storage/torrstor/cache.go +++ b/server/torr/storage/torrstor/cache.go @@ -1,11 +1,11 @@ package torrstor import ( - "encoding/json" "io/ioutil" "os" "path/filepath" "sort" + "strconv" "sync" "time" @@ -39,9 +39,6 @@ type Cache struct { isRemove bool muRemove sync.Mutex torrent *torrent.Torrent - - info *metainfo.Info - file *os.File } const FileRangeNotDelete = 5 * 1024 * 1024 @@ -60,7 +57,6 @@ func NewCache(capacity int64, storage *Storage) *Cache { func (c *Cache) Init(info *metainfo.Info, hash metainfo.Hash) { log.TLogln("Create cache for:", info.Name, hash.HexString()) - c.info = info if c.capacity == 0 { c.capacity = info.PieceLength * 4 } @@ -71,11 +67,9 @@ func (c *Cache) Init(info *metainfo.Info, hash metainfo.Hash) { if settings.BTsets.UseDisk { name := filepath.Join(settings.BTsets.TorrentsSavePath, hash.HexString()) - ff, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + err := os.MkdirAll(name, 0777) if err != nil { - log.TLogln("Error open file:", err) - } else { - c.file = ff + log.TLogln("Error create dir:", err) } } @@ -84,7 +78,18 @@ func (c *Cache) Init(info *metainfo.Info, hash metainfo.Hash) { } if settings.BTsets.UseDisk { - c.loadInfo() + name := filepath.Join(settings.BTsets.TorrentsSavePath, hash.HexString()) + fs, err := ioutil.ReadDir(name) + if err == nil { + for _, f := range fs { + id, err := strconv.Atoi(f.Name()) + if err == nil { + c.pieces[id].Size = f.Size() + c.pieces[id].Complete = f.Size() == c.pieceLength + c.pieces[id].Accessed = f.ModTime().Unix() + } + } + } } } @@ -108,10 +113,6 @@ func (c *Cache) Close() error { c.readers = nil c.muReaders.Unlock() - if c.file != nil { - c.file.Close() - } - utils.FreeOSMemGC() return nil } @@ -268,7 +269,24 @@ func (c *Cache) isIdInFileBE(ranges []Range, id int) bool { return false } -func (c *Cache) loadPieces() { +// run only in cache on disk +func (c *Cache) LoadPiecesOnDisk() { + if c.torrent == nil { + return + } + + if c.isRemove { + return + } + c.muRemove.Lock() + if c.isRemove { + c.muRemove.Unlock() + return + } + c.isRemove = true + defer func() { c.isRemove = false }() + c.muRemove.Unlock() + ranges := make([]Range, 0) c.muReaders.Lock() for r, _ := range c.readers { @@ -291,29 +309,25 @@ func (c *Cache) loadPieces() { pc++ } } -} - -func (c *Cache) loadInfo() { - name := c.file.Name() + ".info" - buf, err := ioutil.ReadFile(name) - if err == nil { - var pieces map[int]*Piece - err := json.Unmarshal(buf, &pieces) - if err == nil { - for id, p := range pieces { - c.pieces[id].Size = p.Size - c.pieces[id].Complete = p.Complete - c.pieces[id].Accessed = p.Accessed + if len(c.readers) == 0 { + limit := 5 + pc := 0 + end := c.pieceCount + for pc <= end { + if !c.pieces[pc].Complete { + break } + pc++ + } + for pc <= end && limit > 0 { + if !c.pieces[pc].Complete { + if c.torrent.PieceState(pc).Priority == torrent.PiecePriorityNone { + c.torrent.Piece(pc).SetPriority(torrent.PiecePriorityNormal) + } + limit-- + } + pc++ } - } -} - -func (c *Cache) saveInfo() { - buf, err := json.Marshal(c.pieces) - if err == nil { - name := c.file.Name() + ".info" - ioutil.WriteFile(name, buf, 0666) } } diff --git a/server/torr/storage/torrstor/diskpiece.go b/server/torr/storage/torrstor/diskpiece.go index 2a4cf44..71bc569 100644 --- a/server/torr/storage/torrstor/diskpiece.go +++ b/server/torr/storage/torrstor/diskpiece.go @@ -1,38 +1,41 @@ package torrstor import ( - "io" + "os" + "path/filepath" + "strconv" "sync" "time" + + "server/log" + "server/settings" ) type DiskPiece struct { piece *Piece + file *os.File + mu sync.RWMutex } func NewDiskPiece(p *Piece) *DiskPiece { - return &DiskPiece{piece: p} + name := filepath.Join(settings.BTsets.TorrentsSavePath, p.cache.hash.HexString(), strconv.Itoa(p.Id)) + ff, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + log.TLogln("Error open file:", err) + return nil + } + return &DiskPiece{piece: p, file: ff} } func (p *DiskPiece) WriteAt(b []byte, off int64) (n int, err error) { p.mu.Lock() defer p.mu.Unlock() - id := int64(p.piece.Id) - pl := p.piece.cache.pieceLength - poff := id * pl - off += poff + n, err = p.file.WriteAt(b, off) - n = 0 - off, err = p.piece.cache.file.Seek(off, io.SeekStart) - if err == nil { - n, err = p.piece.cache.file.Write(b) - } - - go p.piece.cache.loadPieces() - p.piece.cache.saveInfo() + go p.piece.cache.LoadPiecesOnDisk() p.piece.Size += int64(n) p.piece.Accessed = time.Now().Unix() @@ -43,21 +46,12 @@ func (p *DiskPiece) ReadAt(b []byte, off int64) (n int, err error) { p.mu.Lock() defer p.mu.Unlock() - id := int64(p.piece.Id) - pl := p.piece.cache.pieceLength - poff := id * pl - off += poff - - n = 0 - off, err = p.piece.cache.file.Seek(off, io.SeekStart) - if err == nil { - n, err = p.piece.cache.file.Read(b) - } + n, err = p.file.ReadAt(b, off) p.piece.Accessed = time.Now().Unix() return n, nil } func (p *DiskPiece) Release() { - + p.file.Close() } diff --git a/server/torr/torrent.go b/server/torr/torrent.go index 27f8eeb..59494fd 100644 --- a/server/torr/torrent.go +++ b/server/torr/torrent.go @@ -109,6 +109,7 @@ func (t *Torrent) WaitInfo() bool { case <-t.Torrent.GotInfo(): t.cache = t.bt.storage.GetCache(t.Hash()) t.cache.SetTorrent(t.Torrent) + go t.cache.LoadPiecesOnDisk() return true case <-t.closed: return false