123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package main
- import (
- "bufio"
- "errors"
- "flag"
- "fmt"
- "io"
- "log"
- "os"
- "path"
- "path/filepath"
- "strings"
- "sync/atomic"
- "time"
- "github.com/google/gops/agent"
- "github.com/tal-tech/go-zero/core/mr"
- )
- var (
- dir = flag.String("d", "", "dir to enumerate")
- stopOnFile = flag.String("s", "", "stop when got file")
- maxFiles = flag.Int("m", 0, "at most files to process")
- mode = flag.String("mode", "", "simulate mode, can be return|panic")
- count uint32
- )
- func enumerateLines(filename string) chan string {
- output := make(chan string)
- go func() {
- file, err := os.Open(filename)
- if err != nil {
- return
- }
- defer file.Close()
- reader := bufio.NewReader(file)
- for {
- line, err := reader.ReadString('\n')
- if err == io.EOF {
- break
- }
- if !strings.HasPrefix(line, "#") {
- output <- line
- }
- }
- close(output)
- }()
- return output
- }
- func mapper(filename interface{}, writer mr.Writer, cancel func(error)) {
- if len(*stopOnFile) > 0 && path.Base(filename.(string)) == *stopOnFile {
- fmt.Printf("Stop on file: %s\n", *stopOnFile)
- cancel(errors.New("stop on file"))
- return
- }
- var result int
- for line := range enumerateLines(filename.(string)) {
- if strings.HasPrefix(strings.TrimSpace(line), "func") {
- result++
- }
- }
- switch *mode {
- case "return":
- if atomic.AddUint32(&count, 1)%10 == 0 {
- return
- }
- case "panic":
- if atomic.AddUint32(&count, 1)%10 == 0 {
- panic("wow")
- }
- }
- writer.Write(result)
- }
- func reducer(input <-chan interface{}, writer mr.Writer, cancel func(error)) {
- var result int
- for count := range input {
- v := count.(int)
- if *maxFiles > 0 && result >= *maxFiles {
- fmt.Printf("Reached max files: %d\n", *maxFiles)
- cancel(errors.New("max files reached"))
- return
- }
- result += v
- }
- writer.Write(result)
- }
- func main() {
- if err := agent.Listen(agent.Options{}); err != nil {
- log.Fatal(err)
- }
- flag.Parse()
- if len(*dir) == 0 {
- flag.Usage()
- }
- fmt.Println("Processing, please wait...")
- start := time.Now()
- result, err := mr.MapReduce(func(source chan<- interface{}) {
- filepath.Walk(*dir, func(fpath string, f os.FileInfo, err error) error {
- if !f.IsDir() && path.Ext(fpath) == ".go" {
- source <- fpath
- }
- return nil
- })
- }, mapper, reducer)
- if err != nil {
- fmt.Println(err)
- } else {
- fmt.Println(result)
- fmt.Println("Elapsed:", time.Since(start))
- fmt.Println("Done")
- }
- }
|