github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/reporter_simple.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "runtime" 9 "sync" 10 11 "golang.org/x/net/context" 12 13 "github.com/keybase/client/go/kbfs/tlf" 14 "github.com/keybase/client/go/protocol/keybase1" 15 ) 16 17 // ReporterSimple remembers the last maxErrors errors, or all errors 18 // if maxErrors < 1. 19 type ReporterSimple struct { 20 clock Clock 21 maxErrors int 22 currErrorIndex int 23 filledOnce bool 24 // errors is a circular buffer when maxErrors >= 1 25 errors []ReportedError 26 lock sync.RWMutex // protects everything 27 } 28 29 // NewReporterSimple creates a new ReporterSimple. 30 func NewReporterSimple(clock Clock, maxErrors int) *ReporterSimple { 31 rs := &ReporterSimple{ 32 clock: clock, 33 maxErrors: maxErrors, 34 currErrorIndex: -1, 35 } 36 37 if maxErrors >= 1 { 38 rs.errors = make([]ReportedError, maxErrors) 39 } 40 41 return rs 42 } 43 44 // ReportErr implements the Reporter interface for ReporterSimple. 45 func (r *ReporterSimple) ReportErr(ctx context.Context, 46 _ tlf.CanonicalName, _ tlf.Type, _ ErrorModeType, err error) { 47 r.lock.Lock() 48 defer r.lock.Unlock() 49 50 stack := make([]uintptr, 20) 51 n := runtime.Callers(2, stack) 52 re := ReportedError{ 53 Time: r.clock.Now(), 54 Error: err, 55 Stack: stack[:n], 56 } 57 r.currErrorIndex++ 58 if r.maxErrors < 1 { 59 r.errors = append(r.errors, re) 60 } else { 61 if r.currErrorIndex == r.maxErrors { 62 r.currErrorIndex = 0 63 r.filledOnce = true 64 } 65 r.errors[r.currErrorIndex] = re 66 } 67 68 } 69 70 // AllKnownErrors implements the Reporter interface for ReporterSimple. 71 func (r *ReporterSimple) AllKnownErrors() []ReportedError { 72 r.lock.RLock() 73 defer r.lock.RUnlock() 74 75 if !r.filledOnce { 76 // deep copy since r.errors shouldn't be read without the lock. 77 errors := make([]ReportedError, r.currErrorIndex+1) 78 copy(errors, r.errors[:r.currErrorIndex+1]) 79 return errors 80 } 81 82 errors := make([]ReportedError, r.maxErrors) 83 s := r.currErrorIndex + 1 84 t := r.maxErrors - s 85 copy(errors[:t], r.errors[s:]) 86 copy(errors[t:], r.errors[:s]) 87 return errors 88 } 89 90 // OnlineStatusChanged implements the Reporter interface for ReporterSimple. 91 func (r *ReporterSimple) OnlineStatusChanged(_ context.Context, online bool) { 92 // ignore notifications 93 } 94 95 // Notify implements the Reporter interface for ReporterSimple. 96 func (r *ReporterSimple) Notify(_ context.Context, _ *keybase1.FSNotification) { 97 // ignore notifications 98 } 99 100 // NotifyPathUpdated implements the Reporter interface for ReporterSimple. 101 func (r *ReporterSimple) NotifyPathUpdated(_ context.Context, _ string) { 102 // ignore notifications 103 } 104 105 // NotifySyncStatus implements the Reporter interface for ReporterSimple. 106 func (r *ReporterSimple) NotifySyncStatus(_ context.Context, 107 _ *keybase1.FSPathSyncStatus) { 108 // ignore notifications 109 } 110 111 // NotifyFavoritesChanged implements the Reporter interface for 112 // ReporterSimple. 113 func (r *ReporterSimple) NotifyFavoritesChanged(_ context.Context) { 114 // ignore notifications 115 } 116 117 // NotifyOverallSyncStatus implements the Reporter interface for 118 // ReporterSimple. 119 func (r *ReporterSimple) NotifyOverallSyncStatus( 120 _ context.Context, _ keybase1.FolderSyncStatus) { 121 // ignore notifications 122 } 123 124 // Shutdown implements the Reporter interface for ReporterSimple. 125 func (r *ReporterSimple) Shutdown() { 126 127 }