var _ interface {
PieceImpl
//PieceReaderer
+ io.WriterTo
} = (*filePieceImpl)(nil)
func (me *filePieceImpl) logger() *slog.Logger {
}
}
-// If a piece is complete, check consituent files have the minimum required sizes.
+// If a piece is complete, check constituent files have the minimum required sizes.
func (me *filePieceImpl) checkCompleteFileSizes() (c Completion) {
c.Complete = true
c.Ok = true
return me.t.partFiles()
}
+func (me *filePieceImpl) WriteTo(w io.Writer) (n int64, err error) {
+ for fileIndex, extent := range me.iterFileSegments() {
+ file := me.t.file(fileIndex)
+ var f *os.File
+ f, err = me.t.openFile(file)
+ if err != nil {
+ return
+ }
+ f.Seek(extent.Start, io.SeekStart)
+ var n1 int64
+ n1, err = io.CopyN(w, f, extent.Length)
+ n += n1
+ f.Close()
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
//
//// TODO: Just implement StorageReader already.
//func (me *filePieceImpl) NewReader() (PieceReader, error) {
// Returns EOF on short or missing file.
func (fst fileTorrentImplIO) readFileAt(file file, b []byte, off int64) (n int, err error) {
fst.fts.logger().Debug("readFileAt", "file.safeOsPath", file.safeOsPath)
- var f sharedFileIf
- file.mu.RLock()
- // Fine to open once under each name on a unix system. We could make the shared file keys more
- // constrained but it shouldn't matter. TODO: Ensure at most one of the names exist.
- if fst.fts.partFiles() {
- f, err = sharedFiles.Open(file.partFilePath())
- }
- if err == nil && f == nil || errors.Is(err, fs.ErrNotExist) {
- f, err = sharedFiles.Open(file.safeOsPath)
- }
- file.mu.RUnlock()
+ f, err := fst.fts.openSharedFile(file)
if errors.Is(err, fs.ErrNotExist) {
// File missing is treated the same as a short file. Should we propagate this through the
// interface now that fs.ErrNotExist is a thing?
fileExtra: &fts.files[index],
}
}
+
+// Open file for reading.
+func (me *fileTorrentImpl) openSharedFile(file file) (f sharedFileIf, err error) {
+ file.mu.RLock()
+ // Fine to open once under each name on a unix system. We could make the shared file keys more
+ // constrained, but it shouldn't matter. TODO: Ensure at most one of the names exist.
+ if me.partFiles() {
+ f, err = sharedFiles.Open(file.partFilePath())
+ }
+ if err == nil && f == nil || errors.Is(err, fs.ErrNotExist) {
+ f, err = sharedFiles.Open(file.safeOsPath)
+ }
+ file.mu.RUnlock()
+ return
+}
+
+// Open file for reading.
+func (me *fileTorrentImpl) openFile(file file) (f *os.File, err error) {
+ file.mu.RLock()
+ // Fine to open once under each name on a unix system. We could make the shared file keys more
+ // constrained, but it shouldn't matter. TODO: Ensure at most one of the names exist.
+ if me.partFiles() {
+ f, err = os.Open(file.partFilePath())
+ }
+ if err == nil && f == nil || errors.Is(err, fs.ErrNotExist) {
+ f, err = os.Open(file.safeOsPath)
+ }
+ file.mu.RUnlock()
+ return
+}
package storage
-import (
- "iter"
-)
-
-func enumIter[T any](i iter.Seq[T]) iter.Seq2[int, T] {
- return func(yield func(int, T) bool) {
- j := 0
- for t := range i {
- if !yield(j, t) {
- return
- }
- j++
- }
- }
-}