github.com/anacrolix/torrent@v1.61.0/client-unlock-handlers.go (about) 1 package torrent 2 3 import ( 4 "log/slog" 5 "time" 6 7 g "github.com/anacrolix/generics" 8 "github.com/anacrolix/missinggo/v2/panicif" 9 ) 10 11 type torrentUnlockActions struct { 12 updateRegularTrackerAnnouncing bool 13 updateComplete bool 14 } 15 16 // A non-dynamic way to register handlers to run just once when the client is unlocked. 17 type clientUnlockHandlers struct { 18 torrentActions map[*Torrent]torrentUnlockActions 19 changedPieceStates map[*Piece]struct{} 20 } 21 22 func (me *clientUnlockHandlers) init() { 23 g.MakeMap(&me.torrentActions) 24 g.MakeMap(&me.changedPieceStates) 25 } 26 27 func (me *clientUnlockHandlers) deferUpdateTorrentRegularTrackerAnnouncing(t *Torrent) { 28 g.MakeMapIfNil(&me.torrentActions) 29 value := me.torrentActions[t] 30 value.updateRegularTrackerAnnouncing = true 31 me.torrentActions[t] = value 32 } 33 34 func (me *clientUnlockHandlers) addUpdateComplete(t *Torrent) { 35 v := me.torrentActions[t] 36 v.updateComplete = true 37 me.torrentActions[t] = v 38 } 39 40 func (me *clientUnlockHandlers) run(logger *slog.Logger) { 41 trackers := 0 42 started := time.Now() 43 for t, v := range me.torrentActions { 44 if v.updateRegularTrackerAnnouncing { 45 trackers++ 46 t.updateRegularTrackerAnnouncing() 47 } 48 if v.updateComplete { 49 t.updateComplete() 50 } 51 delete(me.torrentActions, t) 52 } 53 since := time.Since(started) 54 // Around here the Go scheduler starts to do crazy stuff. 55 if since > 20*time.Millisecond { 56 logger.Warn("client unlock handlers took a long time", "duration", since, "trackers", trackers) 57 } 58 for p := range me.changedPieceStates { 59 p.publishStateChange() 60 delete(me.changedPieceStates, p) 61 } 62 panicif.NotEq(len(me.torrentActions), 0) 63 }