Index: fuzzer/go/common/storage.go |
diff --git a/fuzzer/go/common/storage.go b/fuzzer/go/common/storage.go |
index 010c32eae2deff61fc0d58dddf7cfea7b36443b4..ca1a7c76dcee433fef664c7bf98896c3db22a91f 100644 |
--- a/fuzzer/go/common/storage.go |
+++ b/fuzzer/go/common/storage.go |
@@ -2,20 +2,43 @@ package common |
import ( |
"fmt" |
+ "io/ioutil" |
+ "os" |
+ "path/filepath" |
"strings" |
+ "sync" |
+ "sync/atomic" |
+ "github.com/skia-dev/glog" |
"go.skia.org/infra/fuzzer/go/config" |
+ "go.skia.org/infra/go/fileutil" |
"go.skia.org/infra/go/gs" |
"google.golang.org/cloud/storage" |
) |
+// ExtractFuzzNameFromPath turns a path name into a fuzz name by stripping off all but the |
+// last piece from the path. |
+func ExtractFuzzNameFromPath(path string) (name string) { |
+ return path[strings.LastIndex(path, "/")+1:] |
+} |
+ |
+// ExtractFuzzNamesFromPaths turns all path names into just fuzz names, by extracting the |
+// last piece of the path. |
+func ExtractFuzzNamesFromPaths(paths []string) (names []string) { |
+ names = make([]string, 0, len(paths)) |
+ for _, path := range paths { |
+ names = append(names, ExtractFuzzNameFromPath(path)) |
+ } |
+ return names |
+} |
+ |
// GetAllFuzzNamesInFolder returns all the fuzz names in a given GCS folder. It basically |
// returns a list of all files that don't end with a .dump or .err, or error |
// if there was a problem. |
func GetAllFuzzNamesInFolder(s *storage.Client, name string) (hashes []string, err error) { |
filter := func(item *storage.ObjectAttrs) { |
name := item.Name |
- if strings.Contains(name, ".") { |
+ if !IsNameOfFuzz(name) { |
return |
} |
fuzzHash := name[strings.LastIndex(name, "/")+1:] |
@@ -27,3 +50,64 @@ func GetAllFuzzNamesInFolder(s *storage.Client, name string) (hashes []string, e |
} |
return hashes, nil |
} |
+ |
+// IsNameOfFuzz returns true if the GCS file name given is a fuzz, which is basically if it doesn't |
+// have a . in it. |
+func IsNameOfFuzz(name string) bool { |
+ return !strings.Contains(name, ".") |
+} |
+ |
+// DownloadAllFuzzes downloads all fuzzes of a given type "bad", "grey" at the specified revision |
+// and returns a slice of all the paths on disk where they are. |
+func DownloadAllFuzzes(s *storage.Client, downloadPath, category, revision, fuzzType string, processes int) ([]string, error) { |
+ completedCount := int32(0) |
+ var wg sync.WaitGroup |
+ toDownload := make(chan string, 1000) |
+ for i := 0; i < processes; i++ { |
+ go download(s, toDownload, downloadPath, &wg, &completedCount) |
+ } |
+ fuzzPaths := []string{} |
+ |
+ download := func(item *storage.ObjectAttrs) { |
+ name := item.Name |
+ if !IsNameOfFuzz(name) { |
+ return |
+ } |
+ fuzzHash := name[strings.LastIndex(name, "/")+1:] |
+ fuzzPaths = append(fuzzPaths, filepath.Join(downloadPath, fuzzHash)) |
+ toDownload <- item.Name |
+ } |
+ if err := gs.AllFilesInDir(s, config.GS.Bucket, fmt.Sprintf("%s/%s/%s", category, revision, fuzzType), download); err != nil { |
+ return nil, fmt.Errorf("Problem iterating through all files: %s", err) |
+ } |
+ close(toDownload) |
+ wg.Wait() |
+ |
+ return fuzzPaths, nil |
+} |
+ |
+// download starts a go routine that waits for files to download from Google Storage and downloads |
+// them to downloadPath. When it is done (on error or when the channel is closed), it signals to |
+// the WaitGroup that it is done. It also logs the progress on downloading the fuzzes. |
+func download(storageClient *storage.Client, toDownload <-chan string, downloadPath string, wg *sync.WaitGroup, completedCounter *int32) { |
+ wg.Add(1) |
+ defer wg.Done() |
+ for file := range toDownload { |
+ hash := file[strings.LastIndex(file, "/")+1:] |
+ onDisk := filepath.Join(downloadPath, hash) |
+ if !fileutil.FileExists(onDisk) { |
+ contents, err := gs.FileContentsFromGS(storageClient, config.GS.Bucket, file) |
+ if err != nil { |
+ glog.Warningf("Problem downloading fuzz %s, continuing anyway: %s", file, err) |
+ continue |
+ } |
+ if err = ioutil.WriteFile(onDisk, contents, 0644); err != nil && !os.IsExist(err) { |
+ glog.Warningf("Problem writing fuzz to %s, continuing anyway: %s", onDisk, err) |
+ } |
+ } |
+ atomic.AddInt32(completedCounter, 1) |
+ if *completedCounter%100 == 0 { |
+ glog.Infof("%d fuzzes downloaded", *completedCounter) |
+ } |
+ } |
+} |