// 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. // +build appengine package build import ( "encoding/json" "fmt" "net/http" "appengine" "appengine/datastore" ) func init() { http.HandleFunc("/updatebenchmark", updateBenchmark) } 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 appengine.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 if _, err := datastore.Put(c, com.Key(c), com); err != nil { return fmt.Errorf("putting Commit: %v", 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) }