]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Implement io.WriterTo for file storage pieces
authorMatt Joiner <anacrolix@gmail.com>
Sat, 19 Jul 2025 11:41:18 +0000 (21:41 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Sat, 19 Jul 2025 11:41:18 +0000 (21:41 +1000)
storage/file-piece.go
storage/file-torrent-io.go
storage/file-torrent.go
storage/iter.go

index f6c9de969efb506916227af8e0bdfa9f6fdae16f..654ea155c9060c1de3cfadbd899991345d924e70 100644 (file)
@@ -27,6 +27,7 @@ type filePieceImpl struct {
 var _ interface {
        PieceImpl
        //PieceReaderer
+       io.WriterTo
 } = (*filePieceImpl)(nil)
 
 func (me *filePieceImpl) logger() *slog.Logger {
@@ -85,7 +86,7 @@ func (me *filePieceImpl) iterFileSegments() iter.Seq2[int, segments.Extent] {
        }
 }
 
-// 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
@@ -315,6 +316,26 @@ func (me *filePieceImpl) partFiles() bool {
        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) {
index 107f28e9789468429994e02c712839255597b501..c2080b05f83635af79dfe4c6344db48f77ae6f98 100644 (file)
@@ -18,17 +18,7 @@ type fileTorrentImplIO struct {
 // 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?
index d3e458ab7cced767bb19b99991685a42ce952347..55200d4f2a2c0aaabbf97fc7947441f7d8520083 100644 (file)
@@ -125,3 +125,33 @@ func (fts *fileTorrentImpl) file(index int) file {
                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
+}
index 9fe49c5e64de181d4eb65feac7e75a2ba3896202..b889dec1f9b77830fe9a6d3e78bdc913632245f8 100644 (file)
@@ -1,17 +1,2 @@
 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++
-               }
-       }
-}