func run(ruleset *internal.RuleSet, scanner *bufio.Scanner, apiInstance api.API, unmatched *os.File) Statistics { stat := Statistics{ perMetric: make(map[api.MetricKey]PerMetricStatistics), } for scanner.Scan() { input := scanner.Text() converted, matched := ruleset.MatchRule(input) if matched { stat.matched++ perMetric := stat.perMetric[converted.MetricKey] perMetric.matched++ reversed, err := ruleset.ToGraphiteName(converted) if *insertToDatabase { apiInstance.AddMetric(converted) } if err != nil { perMetric.reverseError++ } else if string(reversed) != input { perMetric.reverseIncorrect++ } else { perMetric.reverseSuccess++ } stat.perMetric[converted.MetricKey] = perMetric } else { stat.unmatched++ if unmatched != nil { unmatched.WriteString(input) unmatched.WriteString("\n") } } } return stat }
func run(ruleset internal.RuleSet, scanner *bufio.Scanner, apiInstance api.API, unmatched *os.File) Statistics { var wg sync.WaitGroup stat := Statistics{ perMetric: make(map[api.MetricKey]PerMetricStatistics), } type result struct { input string result api.TaggedMetric success bool } inputBuffer := make(chan string, 10) outputBuffer := make(chan result, 10) done := make(chan struct{}) for id := 0; id < runtime.NumCPU(); id++ { go func() { for { select { case <-done: return case input := <-inputBuffer: metric, matched := ruleset.MatchRule(input) outputBuffer <- result{ input, metric, matched, } } } }() } go func() { // aggregate function. for { select { case <-done: return case output := <-outputBuffer: converted, matched := output.result, output.success if matched { stat.matched++ perMetric := stat.perMetric[converted.MetricKey] perMetric.matched++ if *insertToDatabase { apiInstance.AddMetric(converted) } if *reverse { reversed, err := ruleset.ToGraphiteName(converted) if err != nil { perMetric.reverseError++ } else if string(reversed) != output.input { perMetric.reverseIncorrect++ } else { perMetric.reverseSuccess++ } } stat.perMetric[converted.MetricKey] = perMetric } else { stat.unmatched++ if unmatched != nil { unmatched.WriteString(output.input) unmatched.WriteString("\n") } } wg.Done() } } }() for scanner.Scan() { wg.Add(1) input := scanner.Text() inputBuffer <- input } wg.Wait() close(done) // broadcast to shutdown all goroutines. return stat }