From 99ddad31c9a2f3c631e451a134500beb8db32a18 Mon Sep 17 00:00:00 2001
From: Matt Joiner <anacrolix@gmail.com>
Date: Sat, 21 Nov 2020 13:40:09 +1100
Subject: [PATCH] Track piece marking state separately

---
 piece.go      |  1 +
 piecestate.go |  8 +++++++-
 torrent.go    | 22 ++++++++++++++++++----
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/piece.go b/piece.go
index 08fc9bab..c1410d0a 100644
--- a/piece.go
+++ b/piece.go
@@ -50,6 +50,7 @@ type Piece struct {
 
 	numVerifies         int64
 	hashing             bool
+	marking             bool
 	storageCompletionOk bool
 
 	publicPieceState PieceState
diff --git a/piecestate.go b/piecestate.go
index 7a2e7164..089adca4 100644
--- a/piecestate.go
+++ b/piecestate.go
@@ -8,8 +8,14 @@ import (
 type PieceState struct {
 	Priority piecePriority
 	storage.Completion
-	// The piece is being hashed, or is queued for hash.
+	// The piece is being hashed, or is queued for hash. Deprecated: Use those fields instead.
 	Checking bool
+
+	Hashing       bool
+	QueuedForHash bool
+	// The piece state is being marked in the storage.
+	Marking bool
+
 	// Some of the piece has been obtained.
 	Partial bool
 }
diff --git a/torrent.go b/torrent.go
index 9e980abe..af8a2b00 100644
--- a/torrent.go
+++ b/torrent.go
@@ -500,9 +500,10 @@ func (t *Torrent) pieceState(index pieceIndex) (ret PieceState) {
 	p := &t.pieces[index]
 	ret.Priority = t.piecePriority(index)
 	ret.Completion = p.completion()
-	if p.queuedForHash() || p.hashing {
-		ret.Checking = true
-	}
+	ret.QueuedForHash = p.queuedForHash()
+	ret.Hashing = p.hashing
+	ret.Checking = ret.QueuedForHash || ret.Hashing
+	ret.Marking = p.marking
 	if !ret.Complete && t.piecePartiallyDownloaded(index) {
 		ret.Partial = true
 	}
@@ -562,9 +563,15 @@ func (psr PieceStateRun) String() (ret string) {
 			return ""
 		}
 	}()
-	if psr.Checking {
+	if psr.Hashing {
 		ret += "H"
 	}
+	if psr.QueuedForHash {
+		ret += "Q"
+	}
+	if psr.Marking {
+		ret += "M"
+	}
 	if psr.Partial {
 		ret += "P"
 	}
@@ -1739,6 +1746,13 @@ func (t *Torrent) pieceHashed(piece pieceIndex, passed bool, hashIoErr error) {
 		}
 	}
 
+	p.marking = true
+	t.publishPieceChange(piece)
+	defer func() {
+		p.marking = false
+		t.publishPieceChange(piece)
+	}()
+
 	if passed {
 		if len(p.dirtiers) != 0 {
 			// Don't increment stats above connection-level for every involved connection.
-- 
2.51.0