diff --git a/server/torr/storage/torrstor/cache.go b/server/torr/storage/torrstor/cache.go index 62fc393..7db817b 100644 --- a/server/torr/storage/torrstor/cache.go +++ b/server/torr/storage/torrstor/cache.go @@ -1,6 +1,10 @@ package torrstor import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" "sort" "sync" "time" @@ -35,6 +39,9 @@ type Cache struct { isRemove bool muRemove sync.Mutex torrent *torrent.Torrent + + info *metainfo.Info + file *os.File } const FileRangeNotDelete = 5 * 1024 * 1024 @@ -53,6 +60,7 @@ 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 } @@ -61,12 +69,23 @@ func (c *Cache) Init(info *metainfo.Info, hash metainfo.Hash) { c.pieceCount = info.NumPieces() c.hash = hash - for i := 0; i < c.pieceCount; i++ { - c.pieces[i] = &Piece{ - Id: i, - cache: c, + if settings.BTsets.UseDisk { + name := filepath.Join(settings.BTsets.TorrentsSavePath, hash.HexString()) + ff, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + log.TLogln("Error open file:", err) + } else { + c.file = ff } } + + for i := 0; i < c.pieceCount; i++ { + c.pieces[i] = NewPiece(i, c) + } + + if settings.BTsets.UseDisk { + c.loadInfo() + } } func (c *Cache) SetTorrent(torr *torrent.Torrent) { @@ -91,6 +110,10 @@ func (c *Cache) Close() error { c.readers = nil c.muReaders.Unlock() + if c.file != nil { + c.file.Close() + } + utils.FreeOSMemGC() return nil } @@ -122,7 +145,7 @@ func (c *Cache) GetState() *state.CacheState { Id: p.Id, Size: p.Size, Length: c.pieceLength, - Completed: p.complete, + Completed: p.Complete, } } } @@ -214,7 +237,7 @@ func (c *Cache) getRemPieces() []*Piece { limit := 5 for pc <= end && limit > 0 { - if !c.pieces[pc].complete { + if !c.pieces[pc].Complete { if c.torrent.PieceState(pc).Priority == torrent.PiecePriorityNone { c.torrent.Piece(pc).SetPriority(torrent.PiecePriorityNormal) } @@ -225,7 +248,7 @@ func (c *Cache) getRemPieces() []*Piece { } sort.Slice(piecesRemove, func(i, j int) bool { - return piecesRemove[i].accessed < piecesRemove[j].accessed + return piecesRemove[i].Accessed < piecesRemove[j].Accessed }) c.filled = fill @@ -247,6 +270,55 @@ func (c *Cache) isIdInFileBE(ranges []Range, id int) bool { return false } +func (c *Cache) loadPieces() { + ranges := make([]Range, 0) + c.muReaders.Lock() + for r, _ := range c.readers { + ranges = append(ranges, r.getPiecesRange()) + } + c.muReaders.Unlock() + ranges = mergeRange(ranges) + + for r, _ := range c.readers { + pc := r.getReaderPiece() + limit := 5 + + for 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) 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 + } + } + } +} + +func (c *Cache) saveInfo() { + buf, err := json.Marshal(c.pieces) + if err == nil { + name := c.file.Name() + ".info" + ioutil.WriteFile(name, buf, 0666) + } +} + ////////////////// // Reader section ////////