]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Fix broken file benchmark
authorMatt Joiner <anacrolix@gmail.com>
Mon, 12 May 2025 07:03:29 +0000 (17:03 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 12 May 2025 07:03:29 +0000 (17:03 +1000)
storage/file-piece.go
storage/file.go
storage/mark-complete_test.go
storage/test/bench-piece-mark-complete.go
torrent-piece-request-order.go
torrent.go
torrent_test.go

index c3968c5bb8eac12f9c72d50fa9d6fb1fd5c9787f..c8d2dce5cd416d5f1fd8cd0d3e86aed09c90fdc2 100644 (file)
@@ -115,6 +115,10 @@ nextFile:
                        _ = i
                        //fmt.Printf("%v %#v %v\n", i, f, p)
                        cmpl := me.t.getCompletion(p)
+                       if cmpl.Err != nil {
+                               err = fmt.Errorf("error getting completion for piece %d: %w", p, cmpl.Err)
+                               return
+                       }
                        if !cmpl.Ok || !cmpl.Complete {
                                continue nextFile
                        }
@@ -168,12 +172,26 @@ func (me *filePieceImpl) promotePartFile(f file) (err error) {
        return
 }
 
+// Rename from if exists, and if so, to must not exist.
+func (me *filePieceImpl) exclRenameIfExists(from, to string) (err error) {
+       _, err = os.Stat(from)
+       if errors.Is(err, fs.ErrNotExist) {
+               return nil
+       }
+       // We don't want anyone reading or writing to this until the rename completes.
+       f, err := os.OpenFile(to, os.O_CREATE|os.O_EXCL, 0)
+       if err != nil {
+               return fmt.Errorf("error creating destination file: %w", err)
+       }
+       f.Close()
+       return os.Rename(from, to)
+}
+
 func (me *filePieceImpl) onFileNotComplete(f file) (err error) {
        if me.partFiles() {
-               err = os.Rename(f.safeOsPath, f.partFilePath())
-               // If we get ENOENT, the file may already be in the final location.
-               if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                       err = fmt.Errorf("renaming incomplete file: %w", err)
+               err = me.exclRenameIfExists(f.safeOsPath, f.partFilePath())
+               if err != nil {
+                       err = fmt.Errorf("restoring part file: %w", err)
                        return
                }
        }
index 3cf5f62b14a01cea390f760a42e3f478638d6b7f..c905be1298b154858b63c549df29245c5b3d8927 100644 (file)
@@ -226,7 +226,7 @@ func (fst fileTorrentImplIO) readFileAt(file file, b []byte, off int64) (n int,
        if fst.fts.partFiles() {
                f, err = os.Open(file.partFilePath())
        }
-       if errors.Is(err, fs.ErrNotExist) {
+       if err == nil && f == nil || errors.Is(err, fs.ErrNotExist) {
                f, err = os.Open(file.safeOsPath)
        }
        if errors.Is(err, fs.ErrNotExist) {
index 7e50832d2714dd51fdf2644a09c85ad6dfd3d861..482e9e0b22e31ee0a3a5aa09f1b3b8420c0300db 100644 (file)
@@ -13,7 +13,12 @@ func BenchmarkMarkComplete(b *testing.B) {
                        b, ci, test_storage.DefaultPieceSize, test_storage.DefaultNumPieces, 0)
        }
        b.Run("File", func(b *testing.B) {
-               ci := storage.NewFile(b.TempDir())
+               ci := storage.NewFileOpts(storage.NewFileClientOpts{
+                       ClientBaseDir: b.TempDir(),
+                       // TODO: Is the benchmark finding a bug?
+                       //UsePartFiles: g.Some(false),
+               })
+               //ci := storage.NewFile(b.TempDir())
                b.Cleanup(func() { ci.Close() })
                bench(b, ci)
        })
index dee46a88b2508a889335e2b88f08633b0838b713..8b3482fe895f68b5ae74f6ff89a507f58003983d 100644 (file)
@@ -71,8 +71,8 @@ func BenchmarkPieceMarkComplete(
                        qt.Assert(b, qt.Equals(pi.Completion(), storage.Completion{Complete: true, Ok: true}))
                        n, err := pi.WriteTo(bytes.NewBuffer(readData[:0]))
                        b.StopTimer()
+                       qt.Check(b, qt.Equals(n, int64(len(data))))
                        qt.Assert(b, qt.IsNil(err))
-                       qt.Assert(b, qt.Equals(n, int64(len(data))))
                        qt.Assert(b, qt.IsTrue(bytes.Equal(readData[:n], data)))
                }
        }
index eb4e00d70fead290850ed93d67ee4ad600947eb5..7a9cf221d7b4d97384a623582a147d15cf230359 100644 (file)
@@ -77,5 +77,8 @@ func (t *Torrent) addRequestOrderPiece(i int) {
 }
 
 func (t *Torrent) getPieceRequestOrder() *request_strategy.PieceRequestOrder {
+       if t.storage == nil {
+               return nil
+       }
        return t.cl.pieceRequestOrder[t.clientPieceRequestOrderKey()]
 }
index e780c80f83be9f5b1fd8d2c0f74d5368840fb835..c8775d7ac3cf4c13ff1a0c2668a19d2cc4c7c7bd 100644 (file)
@@ -1535,13 +1535,16 @@ func (t *Torrent) logPieceRequestOrder() {
                return
        }
        pro := t.getPieceRequestOrder()
-       if pro != nil {
-               for item := range pro.Iter() {
-                       t.slogger().Debug(
-                               "piece request order item", "infohash",
-                               item.Key.InfoHash, "piece",
-                               item.Key.Index, "state",
-                               item.State)
+       // This might require some optimization around Record to avoid performance issues when
+       // benchmarking.
+       if false {
+               if pro != nil {
+                       for item := range pro.Iter() {
+                               t.slogger().Debug("piece request order item",
+                                       "infohash", item.Key.InfoHash,
+                                       "piece", item.Key.Index,
+                                       "state", item.State)
+                       }
                }
        }
 }
index 7940fe2c98c22e4bac4b335b2318a419178f5669..75df58fde6770dff927b30dba080da8902df78a6 100644 (file)
@@ -107,7 +107,7 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) {
                t._completedPieces.Add(bitmap.BitIndex(i))
        }
        t.DownloadPieces(0, t.numPieces())
-       for i := 0; i < b.N; i += 1 {
+       for b.Loop() {
                t.updateAllPiecePriorities("")
        }
 }