func TestTimedMutex(t *testing.T) { var msgs []string printf := func(ctx context.Context, innerMsg string, args ...interface{}) { formatted := fmt.Sprintf(innerMsg, args...) msgs = append(msgs, formatted) } var numMeasurements int record := func(time.Duration) { numMeasurements++ } { cb := syncutil.ThresholdLogger( context.Background(), time.Nanosecond, printf, record, ) // Should fire. tm := syncutil.MakeTimedMutex(cb) tm.Lock() time.Sleep(2 * time.Nanosecond) tm.Unlock() re := regexp.MustCompile(`mutex held by .*TestTimedMutex for .* \(\>1ns\):`) if len(msgs) != 1 || !re.MatchString(msgs[0]) { t.Fatalf("mutex did not warn as expected: %+v", msgs) } if numMeasurements != 1 { t.Fatalf("expected one measurement, not %d", numMeasurements) } } numMeasurements = 0 msgs = nil { cb := syncutil.ThresholdLogger( context.Background(), time.Duration(math.MaxInt64), printf, record, ) tm := syncutil.MakeTimedMutex(cb) const num = 10 for i := 0; i < num; i++ { tm.Lock() // Avoid staticcheck complaining about empty critical section. time.Sleep(time.Nanosecond) tm.Unlock() } if len(msgs) != 0 { t.Fatalf("mutex warned erroneously: %+v", msgs) } if numMeasurements != num { t.Fatalf("expected %d measurements not %d", num, numMeasurements) } } }
func newRaftScheduler( ambient log.AmbientContext, metrics *StoreMetrics, processor raftProcessor, numWorkers int, ) *raftScheduler { s := &raftScheduler{ processor: processor, numWorkers: numWorkers, } muLogger := syncutil.ThresholdLogger( ambient.AnnotateCtx(context.Background()), defaultReplicaMuWarnThreshold, func(ctx context.Context, msg string, args ...interface{}) { log.Warningf(ctx, "raftScheduler.mu: "+msg, args...) }, func(t time.Duration) { if metrics != nil { metrics.MuSchedulerNanos.RecordValue(t.Nanoseconds()) } }, ) s.mu.TimedMutex = syncutil.MakeTimedMutex(muLogger) s.mu.cond = sync.NewCond(&s.mu.TimedMutex) s.mu.state = make(map[roachpb.RangeID]raftScheduleState) return s }