OLD | NEW |
1 package gsloader | 1 package gsloader |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "sort" | 5 "sort" |
6 "sync" | 6 "sync" |
7 "sync/atomic" | 7 "sync/atomic" |
8 | 8 |
9 "github.com/skia-dev/glog" | 9 "github.com/skia-dev/glog" |
10 "go.skia.org/infra/fuzzer/go/common" | 10 "go.skia.org/infra/fuzzer/go/common" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 // The "fresh" in the name refers to the fact that all other loaded fuzzes (if a
ny) | 54 // The "fresh" in the name refers to the fact that all other loaded fuzzes (if a
ny) |
55 // are written over, including in the cache. | 55 // are written over, including in the cache. |
56 // Upon completion, the full results are cached to a boltDB instance and moved f
rom staging | 56 // Upon completion, the full results are cached to a boltDB instance and moved f
rom staging |
57 // to the current copy. | 57 // to the current copy. |
58 func (g *GSLoader) LoadFreshFromGoogleStorage() error { | 58 func (g *GSLoader) LoadFreshFromGoogleStorage() error { |
59 revision := config.FrontEnd.SkiaVersion.Hash | 59 revision := config.FrontEnd.SkiaVersion.Hash |
60 data.ClearStaging() | 60 data.ClearStaging() |
61 fuzzNames := make([]string, 0, 100) | 61 fuzzNames := make([]string, 0, 100) |
62 for _, cat := range common.FUZZ_CATEGORIES { | 62 for _, cat := range common.FUZZ_CATEGORIES { |
63 badPath := fmt.Sprintf("%s/%s/bad", cat, revision) | 63 badPath := fmt.Sprintf("%s/%s/bad", cat, revision) |
64 » » reports, err := g.getBinaryReportsFromGS(badPath, nil) | 64 » » reports, err := g.getBinaryReportsFromGS(badPath, cat, nil) |
65 if err != nil { | 65 if err != nil { |
66 return err | 66 return err |
67 } | 67 } |
68 n := 0 | 68 n := 0 |
69 for report := range reports { | 69 for report := range reports { |
70 data.NewFuzzFound(cat, report) | 70 data.NewFuzzFound(cat, report) |
71 fuzzNames = append(fuzzNames, report.FuzzName) | 71 fuzzNames = append(fuzzNames, report.FuzzName) |
72 n++ | 72 n++ |
73 } | 73 } |
74 glog.Infof("%d bad fuzzes freshly loaded from gs://%s/%s", n, co
nfig.GS.Bucket, badPath) | 74 glog.Infof("%d bad fuzzes freshly loaded from gs://%s/%s", n, co
nfig.GS.Bucket, badPath) |
(...skipping 12 matching lines...) Expand all Loading... |
87 // and loads them into memory (as staging). After loading them, it updates the
cache | 87 // and loads them into memory (as staging). After loading them, it updates the
cache |
88 // and moves them from staging to the current copy. | 88 // and moves them from staging to the current copy. |
89 func (g *GSLoader) LoadBinaryFuzzesFromGoogleStorage(whitelist []string) error { | 89 func (g *GSLoader) LoadBinaryFuzzesFromGoogleStorage(whitelist []string) error { |
90 revision := config.FrontEnd.SkiaVersion.Hash | 90 revision := config.FrontEnd.SkiaVersion.Hash |
91 data.StagingFromCurrent() | 91 data.StagingFromCurrent() |
92 sort.Strings(whitelist) | 92 sort.Strings(whitelist) |
93 | 93 |
94 fuzzNames := make([]string, 0, 100) | 94 fuzzNames := make([]string, 0, 100) |
95 for _, cat := range common.FUZZ_CATEGORIES { | 95 for _, cat := range common.FUZZ_CATEGORIES { |
96 badPath := fmt.Sprintf("%s/%s/bad", cat, revision) | 96 badPath := fmt.Sprintf("%s/%s/bad", cat, revision) |
97 » » reports, err := g.getBinaryReportsFromGS(badPath, whitelist) | 97 » » reports, err := g.getBinaryReportsFromGS(badPath, cat, whitelist
) |
98 if err != nil { | 98 if err != nil { |
99 return err | 99 return err |
100 } | 100 } |
101 n := 0 | 101 n := 0 |
102 for report := range reports { | 102 for report := range reports { |
103 data.NewFuzzFound(cat, report) | 103 data.NewFuzzFound(cat, report) |
104 fuzzNames = append(fuzzNames, report.FuzzName) | 104 fuzzNames = append(fuzzNames, report.FuzzName) |
105 n++ | 105 n++ |
106 } | 106 } |
107 glog.Infof("%d bad fuzzes freshly loaded from gs://%s/%s", n, co
nfig.GS.Bucket, badPath) | 107 glog.Infof("%d bad fuzzes freshly loaded from gs://%s/%s", n, co
nfig.GS.Bucket, badPath) |
(...skipping 10 matching lines...) Expand all Loading... |
118 glog.Errorf("Problem storing category %s to boltDB: %s",
category, err) | 118 glog.Errorf("Problem storing category %s to boltDB: %s",
category, err) |
119 } | 119 } |
120 } | 120 } |
121 return g.Cache.StoreFuzzNames(append(oldBinaryFuzzNames, whitelist...),
revision) | 121 return g.Cache.StoreFuzzNames(append(oldBinaryFuzzNames, whitelist...),
revision) |
122 } | 122 } |
123 | 123 |
124 // A fuzzPackage contains all the information about a fuzz, mostly the paths to
the files that | 124 // A fuzzPackage contains all the information about a fuzz, mostly the paths to
the files that |
125 // need to be downloaded. | 125 // need to be downloaded. |
126 type fuzzPackage struct { | 126 type fuzzPackage struct { |
127 FuzzName string | 127 FuzzName string |
| 128 FuzzCategory string |
| 129 DebugASANName string |
128 DebugDumpName string | 130 DebugDumpName string |
129 DebugErrName string | 131 DebugErrName string |
| 132 ReleaseASANName string |
130 ReleaseDumpName string | 133 ReleaseDumpName string |
131 ReleaseErrName string | 134 ReleaseErrName string |
132 } | 135 } |
133 | 136 |
134 // getBinaryReportsFromGS pulls all files in baseFolder from the skia-fuzzer buc
ket and | 137 // getBinaryReportsFromGS pulls all files in baseFolder from the skia-fuzzer buc
ket and |
135 // groups them by fuzz. It parses these groups of files into a BinaryFuzzReport
and returns | 138 // groups them by fuzz. It parses these groups of files into a BinaryFuzzReport
and returns |
136 // a channel through whcih all reports generated in this way will be streamed. | 139 // a channel through whcih all reports generated in this way will be streamed. |
137 // The channel will be closed when all reports are done being sent. | 140 // The channel will be closed when all reports are done being sent. |
138 func (g *GSLoader) getBinaryReportsFromGS(baseFolder string, whitelist []string)
(<-chan data.FuzzReport, error) { | 141 func (g *GSLoader) getBinaryReportsFromGS(baseFolder, category string, whitelist
[]string) (<-chan data.FuzzReport, error) { |
139 reports := make(chan data.FuzzReport, 10000) | 142 reports := make(chan data.FuzzReport, 10000) |
140 | 143 |
141 » fuzzPackages, err := g.fetchFuzzPackages(baseFolder) | 144 » fuzzPackages, err := g.fetchFuzzPackages(baseFolder, category) |
142 if err != nil { | 145 if err != nil { |
143 close(reports) | 146 close(reports) |
144 return reports, err | 147 return reports, err |
145 } | 148 } |
146 | 149 |
147 toDownload := make(chan fuzzPackage, len(fuzzPackages)) | 150 toDownload := make(chan fuzzPackage, len(fuzzPackages)) |
148 g.completedCounter = 0 | 151 g.completedCounter = 0 |
149 | 152 |
150 var wg sync.WaitGroup | 153 var wg sync.WaitGroup |
151 for i := 0; i < config.FrontEnd.NumDownloadProcesses; i++ { | 154 for i := 0; i < config.FrontEnd.NumDownloadProcesses; i++ { |
(...skipping 19 matching lines...) Expand all Loading... |
171 wg.Wait() | 174 wg.Wait() |
172 close(reports) | 175 close(reports) |
173 }() | 176 }() |
174 | 177 |
175 return reports, nil | 178 return reports, nil |
176 } | 179 } |
177 | 180 |
178 // fetchFuzzPackages scans for all fuzzes in the given folder and returns a | 181 // fetchFuzzPackages scans for all fuzzes in the given folder and returns a |
179 // slice of all of the metadata for each fuzz, as a fuzz package. It returns | 182 // slice of all of the metadata for each fuzz, as a fuzz package. It returns |
180 // error if it cannot access Google Storage. | 183 // error if it cannot access Google Storage. |
181 func (g *GSLoader) fetchFuzzPackages(baseFolder string) (fuzzPackages []fuzzPack
age, err error) { | 184 func (g *GSLoader) fetchFuzzPackages(baseFolder, category string) (fuzzPackages
[]fuzzPackage, err error) { |
182 | 185 |
183 fuzzNames, err := common.GetAllFuzzNamesInFolder(g.storageClient, baseFo
lder) | 186 fuzzNames, err := common.GetAllFuzzNamesInFolder(g.storageClient, baseFo
lder) |
184 if err != nil { | 187 if err != nil { |
185 return nil, fmt.Errorf("Problem getting fuzz packages from %s: %
s", baseFolder, err) | 188 return nil, fmt.Errorf("Problem getting fuzz packages from %s: %
s", baseFolder, err) |
186 } | 189 } |
187 for _, fuzzName := range fuzzNames { | 190 for _, fuzzName := range fuzzNames { |
188 prefix := fmt.Sprintf("%s/%s/%s", baseFolder, fuzzName, fuzzName
) | 191 prefix := fmt.Sprintf("%s/%s/%s", baseFolder, fuzzName, fuzzName
) |
189 fuzzPackages = append(fuzzPackages, fuzzPackage{ | 192 fuzzPackages = append(fuzzPackages, fuzzPackage{ |
190 FuzzName: fuzzName, | 193 FuzzName: fuzzName, |
| 194 FuzzCategory: category, |
| 195 DebugASANName: fmt.Sprintf("%s_debug.asan", prefix), |
191 DebugDumpName: fmt.Sprintf("%s_debug.dump", prefix), | 196 DebugDumpName: fmt.Sprintf("%s_debug.dump", prefix), |
192 DebugErrName: fmt.Sprintf("%s_debug.err", prefix), | 197 DebugErrName: fmt.Sprintf("%s_debug.err", prefix), |
| 198 ReleaseASANName: fmt.Sprintf("%s_release.asan", prefix), |
193 ReleaseDumpName: fmt.Sprintf("%s_release.dump", prefix), | 199 ReleaseDumpName: fmt.Sprintf("%s_release.dump", prefix), |
194 ReleaseErrName: fmt.Sprintf("%s_release.err", prefix), | 200 ReleaseErrName: fmt.Sprintf("%s_release.err", prefix), |
195 }) | 201 }) |
196 } | 202 } |
197 return fuzzPackages, nil | 203 return fuzzPackages, nil |
198 } | 204 } |
199 | 205 |
200 // emptyStringOnError returns a string of the passed in bytes or empty string if
err is nil. | 206 // emptyStringOnError returns a string of the passed in bytes or empty string if
err is nil. |
201 func emptyStringOnError(b []byte, err error) string { | 207 func emptyStringOnError(b []byte, err error) string { |
202 if err != nil { | 208 if err != nil { |
203 glog.Warningf("Ignoring error when fetching file contents: %v",
err) | 209 glog.Warningf("Ignoring error when fetching file contents: %v",
err) |
204 return "" | 210 return "" |
205 } | 211 } |
206 return string(b) | 212 return string(b) |
207 } | 213 } |
208 | 214 |
209 // download waits for fuzzPackages to appear on the toDownload channel and then
downloads | 215 // download waits for fuzzPackages to appear on the toDownload channel and then
downloads |
210 // the four pieces of the package. It then parses them into a BinaryFuzzReport
and sends | 216 // the four pieces of the package. It then parses them into a BinaryFuzzReport
and sends |
211 // the binary to the passed in channel. When there is no more work to be done,
this function. | 217 // the binary to the passed in channel. When there is no more work to be done,
this function. |
212 // returns and writes out true to the done channel. | 218 // returns and writes out true to the done channel. |
213 func (g *GSLoader) download(toDownload <-chan fuzzPackage, reports chan<- data.F
uzzReport, wg *sync.WaitGroup) { | 219 func (g *GSLoader) download(toDownload <-chan fuzzPackage, reports chan<- data.F
uzzReport, wg *sync.WaitGroup) { |
214 defer wg.Done() | 220 defer wg.Done() |
215 for job := range toDownload { | 221 for job := range toDownload { |
216 » » debugDump := emptyStringOnError(gs.FileContentsFromGS(g.storageC
lient, config.GS.Bucket, job.DebugDumpName)) | 222 » » p := data.GCSPackage{ |
217 » » debugErr := emptyStringOnError(gs.FileContentsFromGS(g.storageCl
ient, config.GS.Bucket, job.DebugErrName)) | 223 » » » Name: job.FuzzName, |
218 » » releaseDump := emptyStringOnError(gs.FileContentsFromGS(g.storag
eClient, config.GS.Bucket, job.ReleaseDumpName)) | 224 » » » FuzzCategory: job.FuzzCategory, |
219 » » releaseErr := emptyStringOnError(gs.FileContentsFromGS(g.storage
Client, config.GS.Bucket, job.ReleaseErrName)) | 225 » » » Debug: data.OutputFiles{ |
220 » » reports <- data.ParseReport(job.FuzzName, debugDump, debugErr, r
eleaseDump, releaseErr) | 226 » » » » Asan: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.DebugASANName)), |
| 227 » » » » Dump: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.DebugDumpName)), |
| 228 » » » » StdErr: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.DebugErrName)), |
| 229 » » » }, |
| 230 » » » Release: data.OutputFiles{ |
| 231 » » » » Asan: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.ReleaseASANName)), |
| 232 » » » » Dump: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.ReleaseDumpName)), |
| 233 » » » » StdErr: emptyStringOnError(gs.FileContentsFromGS
(g.storageClient, config.GS.Bucket, job.ReleaseErrName)), |
| 234 » » » }, |
| 235 » » } |
| 236 |
| 237 » » reports <- data.ParseReport(p) |
221 atomic.AddInt32(&g.completedCounter, 1) | 238 atomic.AddInt32(&g.completedCounter, 1) |
222 if g.completedCounter%100 == 0 { | 239 if g.completedCounter%100 == 0 { |
223 glog.Infof("%d fuzzes downloaded", g.completedCounter) | 240 glog.Infof("%d fuzzes downloaded", g.completedCounter) |
224 } | 241 } |
225 } | 242 } |
226 } | 243 } |
OLD | NEW |