OLD | NEW |
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
| 4 "encoding/json" |
4 "flag" | 5 "flag" |
5 "net/http" | 6 "net/http" |
| 7 "time" |
6 | 8 |
7 "github.com/golang/glog" | 9 "github.com/golang/glog" |
| 10 "github.com/gorilla/mux" |
| 11 |
| 12 "skia.googlesource.com/buildbot.git/go/database" |
| 13 "skia.googlesource.com/buildbot.git/golden/go/analysis" |
| 14 "skia.googlesource.com/buildbot.git/golden/go/db" |
| 15 "skia.googlesource.com/buildbot.git/golden/go/expstorage" |
| 16 "skia.googlesource.com/buildbot.git/golden/go/filediffstore" |
| 17 "skia.googlesource.com/buildbot.git/perf/go/filetilestore" |
8 ) | 18 ) |
9 | 19 |
10 // Command line flags. | 20 // Command line flags. |
11 var ( | 21 var ( |
12 » port = flag.String("port", ":9000", "HTTP service address (e.g., ':
9000')") | 22 » port = flag.String("port", ":9000", "HTTP service address (e.g.,
':9000')") |
13 » staticDir = flag.String("static", "./app", "Directory with static conten
t to serve") | 23 » local = flag.Bool("local", false, "Running locally if true. As op
posed to in production.") |
| 24 » staticDir = flag.String("static_dir", "./app", "Directory with static
content to serve") |
| 25 » tileStoreDir = flag.String("tile_store_dir", "/tmp/tileStore", "What dir
ectory to look for tiles in.") |
| 26 » imageDiffDir = flag.String("image_diff_dir", "/tmp/imagediffdir", "What
directory to store diff images in.") |
| 27 » gsBucketName = flag.String("gs_bucket", "chromium-skia-gm", "Name of the
google storage bucket that holds uploaded images.") |
| 28 » mysqlConnStr = flag.String("mysql_conn", "", "MySQL connection string fo
r backend database. If 'local' is false the password in this string will be subs
tituted via the metadata server.") |
| 29 » sqlitePath = flag.String("sqlite_path", "./golden.db", "Filepath of th
e embedded SQLite database. Requires 'local' to be set to true and 'mysql_conn'
to be empty to take effect.") |
| 30 ) |
14 | 31 |
15 // TODO (stephana): Just ideas to be sorted out later | 32 // ResponseEnvelope wraps all responses. Some fields might be empty depending |
16 // tempDir = flag.String("temp", "./.cache", | 33 // on context or whether there was an error or not. |
17 // "Directory to store temporary file and application cache") | 34 type ResponseEnvelope struct { |
18 ) | 35 » Data *interface{} `json:"data"` |
| 36 » Err *string `json:"err"` |
| 37 » Status int `json:"status"` |
| 38 } |
| 39 |
| 40 var analyzer *analysis.Analyzer = nil |
| 41 |
| 42 // tileCountsHandler handles GET requests for the classification counts over |
| 43 // all tests and digests of a tile. |
| 44 func tileCountsHandler(w http.ResponseWriter, r *http.Request) { |
| 45 » result, err := analyzer.GetTileCounts() |
| 46 » if err != nil { |
| 47 » » sendErrorResponse(w, err.Error(), http.StatusInternalServerError
) |
| 48 » » return |
| 49 » } |
| 50 |
| 51 » sendResponse(w, result, http.StatusOK) |
| 52 } |
| 53 |
| 54 // testCountsHandler handles GET requests for the aggregrated classification |
| 55 // counts for a specific tests. |
| 56 func testCountsHandler(w http.ResponseWriter, r *http.Request) { |
| 57 » testName := mux.Vars(r)["testname"] |
| 58 » result, err := analyzer.GetTestCounts(testName) |
| 59 » if err != nil { |
| 60 » » sendErrorResponse(w, err.Error(), http.StatusInternalServerError
) |
| 61 » » return |
| 62 » } |
| 63 |
| 64 » sendResponse(w, result, http.StatusOK) |
| 65 } |
| 66 |
| 67 // sendErrorResponse wraps an error in a response envelope and sends it to |
| 68 // the client. |
| 69 func sendErrorResponse(w http.ResponseWriter, errorMsg string, status int) { |
| 70 » resp := ResponseEnvelope{nil, &errorMsg, status} |
| 71 » sendJson(w, &resp) |
| 72 } |
| 73 |
| 74 // sendResponse wraps the data of a succesful response in a response envelope |
| 75 // and sends it to the client. |
| 76 func sendResponse(w http.ResponseWriter, data interface{}, status int) { |
| 77 » resp := ResponseEnvelope{&data, nil, status} |
| 78 » sendJson(w, &resp) |
| 79 } |
| 80 |
| 81 // sendJson serializes the response envelope and sends ito the client. |
| 82 func sendJson(w http.ResponseWriter, resp *ResponseEnvelope) { |
| 83 » jsonBytes, err := json.Marshal(resp) |
| 84 » if err != nil { |
| 85 » » http.Error(w, err.Error(), http.StatusInternalServerError) |
| 86 » » return |
| 87 » } |
| 88 |
| 89 » w.Header().Set("Content-Type", "application/json") |
| 90 » w.Write(jsonBytes) |
| 91 } |
19 | 92 |
20 func main() { | 93 func main() { |
21 flag.Parse() | 94 flag.Parse() |
22 defer glog.Flush() | 95 defer glog.Flush() |
23 | 96 |
24 » http.Handle("/", http.FileServer(http.Dir(*staticDir))) | 97 » // Get the expecations storage, the filediff storage and the tilestore. |
| 98 » diffStore := filediffstore.NewFileDiffStore(nil, *imageDiffDir, *gsBucke
tName) |
| 99 » vdb := database.NewVersionedDB(db.GetDatabaseConfig(*mysqlConnStr, *sqli
tePath, *local)) |
| 100 » expStore := expstorage.NewSQLExpectationStore(vdb) |
| 101 » tileStore := filetilestore.NewFileTileStore(*tileStoreDir, "golden", -1) |
25 | 102 |
| 103 // Initialize the Analyzer |
| 104 analyzer = analysis.NewAnalyzer(expStore, tileStore, diffStore, 5*time.M
inute) |
| 105 |
| 106 router := mux.NewRouter() |
| 107 |
| 108 // Wire up the resources. We use the 'rest' prefix to avoid any name |
| 109 // clashes witht the static files being served. |
| 110 // TODO (stephana): Wrap the handlers in autogzip unless we defer that t
o |
| 111 // the front-end proxy. |
| 112 router.HandleFunc("/rest/tilecounts", tileCountsHandler) |
| 113 router.HandleFunc("/rest/tilecounts/{testname}", testCountsHandler) |
| 114 |
| 115 // Everything else is served out of the static directory. |
| 116 router.PathPrefix("/").Handler(http.FileServer(http.Dir(*staticDir))) |
| 117 |
| 118 // Send all requests to the router |
| 119 http.Handle("/", router) |
| 120 |
| 121 // Start the server |
26 glog.Infoln("Serving on http://127.0.0.1" + *port) | 122 glog.Infoln("Serving on http://127.0.0.1" + *port) |
27 glog.Fatal(http.ListenAndServe(*port, nil)) | 123 glog.Fatal(http.ListenAndServe(*port, nil)) |
28 } | 124 } |
OLD | NEW |