1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage main 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "errors" 19*333d2b36SAndroid Build Coastguard Worker "flag" 20*333d2b36SAndroid Build Coastguard Worker "fmt" 21*333d2b36SAndroid Build Coastguard Worker "io" 22*333d2b36SAndroid Build Coastguard Worker "io/ioutil" 23*333d2b36SAndroid Build Coastguard Worker "log" 24*333d2b36SAndroid Build Coastguard Worker "os" 25*333d2b36SAndroid Build Coastguard Worker "runtime/pprof" 26*333d2b36SAndroid Build Coastguard Worker "sort" 27*333d2b36SAndroid Build Coastguard Worker "strings" 28*333d2b36SAndroid Build Coastguard Worker "time" 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker "android/soong/finder" 31*333d2b36SAndroid Build Coastguard Worker "android/soong/finder/fs" 32*333d2b36SAndroid Build Coastguard Worker) 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Workervar ( 35*333d2b36SAndroid Build Coastguard Worker // configuration of what to find 36*333d2b36SAndroid Build Coastguard Worker excludeDirs string 37*333d2b36SAndroid Build Coastguard Worker filenamesToFind string 38*333d2b36SAndroid Build Coastguard Worker pruneFiles string 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Worker // other configuration 41*333d2b36SAndroid Build Coastguard Worker cpuprofile string 42*333d2b36SAndroid Build Coastguard Worker verbose bool 43*333d2b36SAndroid Build Coastguard Worker dbPath string 44*333d2b36SAndroid Build Coastguard Worker numIterations int 45*333d2b36SAndroid Build Coastguard Worker) 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Workerfunc init() { 48*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&cpuprofile, "cpuprofile", "", 49*333d2b36SAndroid Build Coastguard Worker "filepath of profile file to write (optional)") 50*333d2b36SAndroid Build Coastguard Worker flag.BoolVar(&verbose, "v", false, "log additional information") 51*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&dbPath, "db", "", "filepath of cache db") 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&excludeDirs, "exclude-dirs", "", 54*333d2b36SAndroid Build Coastguard Worker "comma-separated list of directory names to exclude from search") 55*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&filenamesToFind, "names", "", 56*333d2b36SAndroid Build Coastguard Worker "comma-separated list of filenames to find") 57*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&pruneFiles, "prune-files", "", 58*333d2b36SAndroid Build Coastguard Worker "filenames that if discovered will exclude their entire directory "+ 59*333d2b36SAndroid Build Coastguard Worker "(including sibling files and directories)") 60*333d2b36SAndroid Build Coastguard Worker flag.IntVar(&numIterations, "count", 1, 61*333d2b36SAndroid Build Coastguard Worker "number of times to run. This is intended for use with --cpuprofile"+ 62*333d2b36SAndroid Build Coastguard Worker " , to increase profile accuracy") 63*333d2b36SAndroid Build Coastguard Worker} 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Workervar usage = func() { 66*333d2b36SAndroid Build Coastguard Worker fmt.Printf("usage: finder -name <fileName> --db <dbPath> <searchDirectory> [<searchDirectory>...]\n") 67*333d2b36SAndroid Build Coastguard Worker flag.PrintDefaults() 68*333d2b36SAndroid Build Coastguard Worker} 69*333d2b36SAndroid Build Coastguard Worker 70*333d2b36SAndroid Build Coastguard Workerfunc main() { 71*333d2b36SAndroid Build Coastguard Worker err := run() 72*333d2b36SAndroid Build Coastguard Worker if err != nil { 73*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(os.Stderr, "%v\n", err.Error()) 74*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 75*333d2b36SAndroid Build Coastguard Worker } 76*333d2b36SAndroid Build Coastguard Worker} 77*333d2b36SAndroid Build Coastguard Worker 78*333d2b36SAndroid Build Coastguard Workerfunc stringToList(input string) []string { 79*333d2b36SAndroid Build Coastguard Worker return strings.Split(input, ",") 80*333d2b36SAndroid Build Coastguard Worker} 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Workerfunc run() error { 83*333d2b36SAndroid Build Coastguard Worker startTime := time.Now() 84*333d2b36SAndroid Build Coastguard Worker flag.Parse() 85*333d2b36SAndroid Build Coastguard Worker 86*333d2b36SAndroid Build Coastguard Worker if cpuprofile != "" { 87*333d2b36SAndroid Build Coastguard Worker f, err := os.Create(cpuprofile) 88*333d2b36SAndroid Build Coastguard Worker if err != nil { 89*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("Error opening cpuprofile: %s", err) 90*333d2b36SAndroid Build Coastguard Worker } 91*333d2b36SAndroid Build Coastguard Worker pprof.StartCPUProfile(f) 92*333d2b36SAndroid Build Coastguard Worker defer f.Close() 93*333d2b36SAndroid Build Coastguard Worker defer pprof.StopCPUProfile() 94*333d2b36SAndroid Build Coastguard Worker } 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker var writer io.Writer 97*333d2b36SAndroid Build Coastguard Worker if verbose { 98*333d2b36SAndroid Build Coastguard Worker writer = os.Stderr 99*333d2b36SAndroid Build Coastguard Worker } else { 100*333d2b36SAndroid Build Coastguard Worker writer = ioutil.Discard 101*333d2b36SAndroid Build Coastguard Worker } 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Worker // TODO: replace Lshortfile with Llongfile when bug 63821638 is done 104*333d2b36SAndroid Build Coastguard Worker logger := log.New(writer, "", log.Ldate|log.Lmicroseconds|log.Lshortfile) 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker logger.Printf("Finder starting at %v\n", startTime) 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker rootPaths := flag.Args() 109*333d2b36SAndroid Build Coastguard Worker if len(rootPaths) < 1 { 110*333d2b36SAndroid Build Coastguard Worker usage() 111*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf( 112*333d2b36SAndroid Build Coastguard Worker "Must give at least one <searchDirectory>") 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker workingDir, err := os.Getwd() 116*333d2b36SAndroid Build Coastguard Worker if err != nil { 117*333d2b36SAndroid Build Coastguard Worker return err 118*333d2b36SAndroid Build Coastguard Worker } 119*333d2b36SAndroid Build Coastguard Worker params := finder.CacheParams{ 120*333d2b36SAndroid Build Coastguard Worker WorkingDirectory: workingDir, 121*333d2b36SAndroid Build Coastguard Worker RootDirs: rootPaths, 122*333d2b36SAndroid Build Coastguard Worker ExcludeDirs: stringToList(excludeDirs), 123*333d2b36SAndroid Build Coastguard Worker PruneFiles: stringToList(pruneFiles), 124*333d2b36SAndroid Build Coastguard Worker IncludeFiles: stringToList(filenamesToFind), 125*333d2b36SAndroid Build Coastguard Worker } 126*333d2b36SAndroid Build Coastguard Worker if dbPath == "" { 127*333d2b36SAndroid Build Coastguard Worker usage() 128*333d2b36SAndroid Build Coastguard Worker return errors.New("Param 'db' must be nonempty") 129*333d2b36SAndroid Build Coastguard Worker } 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Worker matches := []string{} 132*333d2b36SAndroid Build Coastguard Worker for i := 0; i < numIterations; i++ { 133*333d2b36SAndroid Build Coastguard Worker matches, err = runFind(params, logger) 134*333d2b36SAndroid Build Coastguard Worker if err != nil { 135*333d2b36SAndroid Build Coastguard Worker return err 136*333d2b36SAndroid Build Coastguard Worker } 137*333d2b36SAndroid Build Coastguard Worker } 138*333d2b36SAndroid Build Coastguard Worker findDuration := time.Since(startTime) 139*333d2b36SAndroid Build Coastguard Worker logger.Printf("Found these %v inodes in %v :\n", len(matches), findDuration) 140*333d2b36SAndroid Build Coastguard Worker sort.Strings(matches) 141*333d2b36SAndroid Build Coastguard Worker for _, match := range matches { 142*333d2b36SAndroid Build Coastguard Worker fmt.Println(match) 143*333d2b36SAndroid Build Coastguard Worker } 144*333d2b36SAndroid Build Coastguard Worker logger.Printf("End of %v inodes\n", len(matches)) 145*333d2b36SAndroid Build Coastguard Worker logger.Printf("Finder completed in %v\n", time.Since(startTime)) 146*333d2b36SAndroid Build Coastguard Worker return nil 147*333d2b36SAndroid Build Coastguard Worker} 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Workerfunc runFind(params finder.CacheParams, logger *log.Logger) (paths []string, err error) { 150*333d2b36SAndroid Build Coastguard Worker service, err := finder.New(params, fs.OsFs, logger, dbPath) 151*333d2b36SAndroid Build Coastguard Worker if err != nil { 152*333d2b36SAndroid Build Coastguard Worker return []string{}, err 153*333d2b36SAndroid Build Coastguard Worker } 154*333d2b36SAndroid Build Coastguard Worker defer service.Shutdown() 155*333d2b36SAndroid Build Coastguard Worker return service.FindAll(), nil 156*333d2b36SAndroid Build Coastguard Worker} 157