Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Unified Diff: fuzzer/go/storage/download_reports.go

Issue 1691893002: Fuzzer now deduplicates on the analysis side instead of the download side (Closed) Base URL: https://skia.googlesource.com/buildbot@metrics
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « fuzzer/go/generator/afl_generation.go ('k') | fuzzer/res/imp/fuzzer-collapse-file-sk.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: fuzzer/go/storage/download_reports.go
diff --git a/fuzzer/go/storage/download_reports.go b/fuzzer/go/storage/download_reports.go
new file mode 100644
index 0000000000000000000000000000000000000000..98070194228ed6b64685320160b43f1c19027fc2
--- /dev/null
+++ b/fuzzer/go/storage/download_reports.go
@@ -0,0 +1,137 @@
+package storage
+
+import (
+ "fmt"
+ "sort"
+ "sync"
+ "sync/atomic"
+
+ "github.com/skia-dev/glog"
+ "go.skia.org/infra/fuzzer/go/common"
+ "go.skia.org/infra/fuzzer/go/config"
+ "go.skia.org/infra/fuzzer/go/data"
+ "go.skia.org/infra/go/gs"
+ "google.golang.org/cloud/storage"
+)
+
+// GetReportsFromGS fetches all fuzz reports in the baseFolder from Google Storage. It returns a
+// channel through which all reports will be sent. The channel will be closed when finished. An
+// optional whitelist can be included, in which case only the fuzzes whose names are on the list
+// will be downloaded. The category is needed to properly parse the downloaded files to make
+// the FuzzReports. The downloading will use as many processes as specified, to speed things up.
+func GetReportsFromGS(s *storage.Client, baseFolder, category string, whitelist []string, processes int) (<-chan data.FuzzReport, error) {
+ reports := make(chan data.FuzzReport, 10000)
+
+ fuzzPackages, err := fetchFuzzPackages(s, baseFolder, category)
+ if err != nil {
+ close(reports)
+ return reports, err
+ }
+
+ toDownload := make(chan fuzzPackage, len(fuzzPackages))
+ completedCounter := int32(0)
+
+ var wg sync.WaitGroup
+ for i := 0; i < processes; i++ {
+ wg.Add(1)
+ go download(s, toDownload, reports, &completedCounter, &wg)
+ }
+
+ for _, d := range fuzzPackages {
+ if whitelist != nil {
+ name := d.FuzzName
+ if i := sort.SearchStrings(whitelist, name); i < len(whitelist) && whitelist[i] == name {
+ // is on the whitelist
+ toDownload <- d
+ }
+ } else {
+ // no white list
+ toDownload <- d
+ }
+ }
+ close(toDownload)
+
+ // Wait until all are done downloading to close the reports channel, but don't block
+ go func() {
+ wg.Wait()
+ close(reports)
+ }()
+
+ return reports, nil
+}
+
+// A fuzzPackage contains all the information about a fuzz, mostly the paths to the files that
+// need to be downloaded. The use of this struct decouples the names of the files that need to be
+// downloaded with the download logic.
+type fuzzPackage struct {
+ FuzzName string
+ FuzzCategory string
+ DebugASANName string
+ DebugDumpName string
+ DebugErrName string
+ ReleaseASANName string
+ ReleaseDumpName string
+ ReleaseErrName string
+}
+
+// fetchFuzzPackages scans for all fuzzes in the given folder and returns a slice of all of the
+// metadata for each fuzz, as a fuzz package. It returns error if it cannot access Google Storage.
+func fetchFuzzPackages(s *storage.Client, baseFolder, category string) (fuzzPackages []fuzzPackage, err error) {
+ fuzzNames, err := common.GetAllFuzzNamesInFolder(s, baseFolder)
+ if err != nil {
+ return nil, fmt.Errorf("Problem getting fuzz packages from %s: %s", baseFolder, err)
+ }
+ for _, fuzzName := range fuzzNames {
+ prefix := fmt.Sprintf("%s/%s/%s", baseFolder, fuzzName, fuzzName)
+ fuzzPackages = append(fuzzPackages, fuzzPackage{
+ FuzzName: fuzzName,
+ FuzzCategory: category,
+ DebugASANName: fmt.Sprintf("%s_debug.asan", prefix),
+ DebugDumpName: fmt.Sprintf("%s_debug.dump", prefix),
+ DebugErrName: fmt.Sprintf("%s_debug.err", prefix),
+ ReleaseASANName: fmt.Sprintf("%s_release.asan", prefix),
+ ReleaseDumpName: fmt.Sprintf("%s_release.dump", prefix),
+ ReleaseErrName: fmt.Sprintf("%s_release.err", prefix),
+ })
+ }
+ return fuzzPackages, nil
+}
+
+// emptyStringOnError returns a string of the passed in bytes or empty string if err is nil.
+func emptyStringOnError(b []byte, err error) string {
+ if err != nil {
+ glog.Warningf("Ignoring error when fetching file contents: %v", err)
+ return ""
+ }
+ return string(b)
+}
+
+// download waits for fuzzPackages to appear on the toDownload channel and then downloads
+// the four pieces of the package. It then parses them into a BinaryFuzzReport and sends
+// the binary to the passed in channel. When there is no more work to be done, this function.
+// returns and writes out true to the done channel.
+func download(s *storage.Client, toDownload <-chan fuzzPackage, reports chan<- data.FuzzReport, completedCounter *int32, wg *sync.WaitGroup) {
+ defer wg.Done()
+ for job := range toDownload {
+ p := data.GCSPackage{
+ Name: job.FuzzName,
+ FuzzCategory: job.FuzzCategory,
+ Debug: data.OutputFiles{
+ Asan: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.DebugASANName)),
+ Dump: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.DebugDumpName)),
+ StdErr: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.DebugErrName)),
+ },
+ Release: data.OutputFiles{
+ Asan: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.ReleaseASANName)),
+ Dump: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.ReleaseDumpName)),
+ StdErr: emptyStringOnError(gs.FileContentsFromGS(s, config.GS.Bucket, job.ReleaseErrName)),
+ },
+ }
+
+ reports <- data.ParseReport(p)
+ atomic.AddInt32(completedCounter, 1)
+ if *completedCounter%100 == 0 {
+ glog.Infof("%d fuzzes downloaded", *completedCounter)
+ }
+ }
+}
« no previous file with comments | « fuzzer/go/generator/afl_generation.go ('k') | fuzzer/res/imp/fuzzer-collapse-file-sk.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698