4 "github.com/anacrolix/missinggo/v2/bitmap"
6 "github.com/anacrolix/torrent/metainfo"
9 // Provides access to regions of torrent data that correspond to its files.
20 func (f *File) Torrent() *Torrent {
24 // Data for this file begins this many bytes into the Torrent.
25 func (f *File) Offset() int64 {
29 // The FileInfo from the metainfo.Info to which this file corresponds.
30 func (f File) FileInfo() metainfo.FileInfo {
34 // The file's path components joined by '/'.
35 func (f File) Path() string {
39 // The file's length in bytes.
40 func (f *File) Length() int64 {
44 // Number of bytes of the entire file we have completed. This is the sum of
45 // completed pieces, and dirtied chunks of incomplete pieces.
46 func (f *File) BytesCompleted() int64 {
48 defer f.t.cl.rUnlock()
49 return f.bytesCompleted()
52 func (f *File) bytesCompleted() int64 {
53 return f.length - f.bytesLeft()
57 torrentUsualPieceSize int64,
58 fileFirstPieceIndex int,
59 fileEndPieceIndex int,
60 fileTorrentOffset int64,
62 torrentCompletedPieces bitmap.Bitmap,
64 numPiecesSpanned := fileEndPieceIndex - fileFirstPieceIndex
65 switch numPiecesSpanned {
68 if !torrentCompletedPieces.Get(bitmap.BitIndex(fileFirstPieceIndex)) {
72 if !torrentCompletedPieces.Get(bitmap.BitIndex(fileFirstPieceIndex)) {
73 left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize)
75 if !torrentCompletedPieces.Get(bitmap.BitIndex(fileEndPieceIndex - 1)) {
76 left += fileTorrentOffset + fileLength - int64(fileEndPieceIndex-1)*torrentUsualPieceSize
78 completedMiddlePieces := torrentCompletedPieces.Copy()
79 completedMiddlePieces.RemoveRange(0, bitmap.BitRange(fileFirstPieceIndex+1))
80 completedMiddlePieces.RemoveRange(bitmap.BitRange(fileEndPieceIndex-1), bitmap.ToEnd)
81 left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.Len())) * torrentUsualPieceSize
86 func (f *File) bytesLeft() (left int64) {
87 return fileBytesLeft(int64(f.t.usualPieceSize()), f.firstPieceIndex(), f.endPieceIndex(), f.offset, f.length, f.t._completedPieces)
90 // The relative file path for a multi-file torrent, and the torrent name for a
91 // single-file torrent. Dir separators are '/'.
92 func (f *File) DisplayPath() string {
96 // The download status of a piece that comprises part of a File.
97 type FilePieceState struct {
98 Bytes int64 // Bytes within the piece that are part of this File.
102 // Returns the state of pieces in this file.
103 func (f *File) State() (ret []FilePieceState) {
105 defer f.t.cl.rUnlock()
106 pieceSize := int64(f.t.usualPieceSize())
107 off := f.offset % pieceSize
108 remaining := f.length
109 for i := pieceIndex(f.offset / pieceSize); ; i++ {
113 len1 := pieceSize - off
114 if len1 > remaining {
117 ps := f.t.pieceState(i)
118 ret = append(ret, FilePieceState{len1, ps})
125 // Requests that all pieces containing data in the file be downloaded.
126 func (f *File) Download() {
127 f.SetPriority(PiecePriorityNormal)
130 func byteRegionExclusivePieces(off, size, pieceSize int64) (begin, end int) {
131 begin = int((off + pieceSize - 1) / pieceSize)
132 end = int((off + size) / pieceSize)
136 // Deprecated: Use File.SetPriority.
137 func (f *File) Cancel() {
138 f.SetPriority(PiecePriorityNone)
141 func (f *File) NewReader() Reader {
145 readahead: 5 * 1024 * 1024,
153 // Sets the minimum priority for pieces in the File.
154 func (f *File) SetPriority(prio piecePriority) {
156 defer f.t.cl.unlock()
161 f.t.updatePiecePriorities(f.firstPieceIndex(), f.endPieceIndex())
164 // Returns the priority per File.SetPriority.
165 func (f *File) Priority() piecePriority {
167 defer f.t.cl.unlock()
171 // Returns the index of the first piece containing data for the file.
172 func (f *File) firstPieceIndex() pieceIndex {
173 if f.t.usualPieceSize() == 0 {
176 return pieceIndex(f.offset / int64(f.t.usualPieceSize()))
179 // Returns the index of the piece after the last one containing data for the file.
180 func (f *File) endPieceIndex() pieceIndex {
181 if f.t.usualPieceSize() == 0 {
184 return pieceIndex((f.offset + f.length + int64(f.t.usualPieceSize()) - 1) / int64(f.t.usualPieceSize()))