| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "net/http" |
| |
| "context" |
| |
| "google.golang.org/appengine" |
| "google.golang.org/appengine/datastore" |
| ) |
| |
| func updateBenchmark(w http.ResponseWriter, r *http.Request) { |
| if !appengine.IsDevAppServer() { |
| fmt.Fprint(w, "Update must not run on real server.") |
| return |
| } |
| |
| if r.Method != "POST" { |
| fmt.Fprintf(w, "bad request method") |
| return |
| } |
| |
| c := contextForRequest(r) |
| if !validKey(c, r.FormValue("key"), r.FormValue("builder")) { |
| fmt.Fprintf(w, "bad builder/key") |
| return |
| } |
| |
| defer r.Body.Close() |
| var hashes []string |
| if err := json.NewDecoder(r.Body).Decode(&hashes); err != nil { |
| fmt.Fprintf(w, "failed to decode request: %v", err) |
| return |
| } |
| |
| ncommit := 0 |
| nrun := 0 |
| tx := func(c context.Context) error { |
| var cr *CommitRun |
| for _, hash := range hashes { |
| // Update Commit. |
| com := &Commit{Hash: hash} |
| err := datastore.Get(c, com.Key(c), com) |
| if err != nil && err != datastore.ErrNoSuchEntity { |
| return fmt.Errorf("fetching Commit: %v", err) |
| } |
| if err == datastore.ErrNoSuchEntity { |
| continue |
| } |
| com.NeedsBenchmarking = true |
| com.PerfResults = nil |
| if err := putCommit(c, com); err != nil { |
| return err |
| } |
| ncommit++ |
| |
| // create PerfResult |
| res := &PerfResult{CommitHash: com.Hash, CommitNum: com.Num} |
| err = datastore.Get(c, res.Key(c), res) |
| if err != nil && err != datastore.ErrNoSuchEntity { |
| return fmt.Errorf("fetching PerfResult: %v", err) |
| } |
| if err == datastore.ErrNoSuchEntity { |
| if _, err := datastore.Put(c, res.Key(c), res); err != nil { |
| return fmt.Errorf("putting PerfResult: %v", err) |
| } |
| } |
| |
| // Update CommitRun. |
| if cr != nil && cr.StartCommitNum != com.Num/PerfRunLength*PerfRunLength { |
| if _, err := datastore.Put(c, cr.Key(c), cr); err != nil { |
| return fmt.Errorf("putting CommitRun: %v", err) |
| } |
| nrun++ |
| cr = nil |
| } |
| if cr == nil { |
| var err error |
| cr, err = GetCommitRun(c, com.Num) |
| if err != nil { |
| return fmt.Errorf("getting CommitRun: %v", err) |
| } |
| } |
| if com.Num < cr.StartCommitNum || com.Num >= cr.StartCommitNum+PerfRunLength { |
| return fmt.Errorf("commit num %v out of range [%v, %v)", com.Num, cr.StartCommitNum, cr.StartCommitNum+PerfRunLength) |
| } |
| idx := com.Num - cr.StartCommitNum |
| cr.Hash[idx] = com.Hash |
| cr.User[idx] = shortDesc(com.User) |
| cr.Desc[idx] = shortDesc(com.Desc) |
| cr.Time[idx] = com.Time |
| cr.NeedsBenchmarking[idx] = com.NeedsBenchmarking |
| } |
| if cr != nil { |
| if _, err := datastore.Put(c, cr.Key(c), cr); err != nil { |
| return fmt.Errorf("putting CommitRun: %v", err) |
| } |
| nrun++ |
| } |
| return nil |
| } |
| if err := datastore.RunInTransaction(c, tx, nil); err != nil { |
| fmt.Fprintf(w, "failed to execute tx: %v", err) |
| return |
| } |
| fmt.Fprintf(w, "OK (updated %v commits and %v commit runs)", ncommit, nrun) |
| } |