func runWebUI(addr string, p *coordinator, cache gopnik.CachePluginInterface) { m := staticbin.Classic(gopnikwebstatic.Asset) var logger webUILogger m.Map(stdlog.New(&logger, "[martini] ", stdlog.LstdFlags)) m.Use(rendergold.Renderer(rendergold.Options{Asset: Asset})) m.Get("/", func(r rendergold.Render) { done, total := p.DoneTasks() progress := float64(done) / float64(total) * 100.0 r.HTML( http.StatusOK, "status", map[string]interface{}{ "Page": "Status", "Total": total, "Done": done, "Progress": fmt.Sprintf("%.02f", progress), }, ) }) m.Get("/nodes", func(r rendergold.Render) { type node struct { Addr string Status bool } addrs := p.Nodes() nodes := make([]node, len(addrs)) for i, addr := range addrs { nodes[i].Addr = addr nodes[i].Status = p.NodeStatus(addr) } r.HTML( http.StatusOK, "nodes", map[string]interface{}{ "Page": "Nodes", "Nodes": nodes, }, ) }) m.Get("/charts/:addr", func(params martini.Params, r rendergold.Render) { addr := params["addr"] mon := p.NodeMonitor(addr) if mon == nil { r.Redirect("/nodes") } r.HTML( http.StatusOK, "charts", map[string]interface{}{ "Page": "Charts", "Addr": addr, "Metrics": mon.Metrics(), }, ) }) m.Get("/chart/:addr", func(params martini.Params, res http.ResponseWriter, req *http.Request) { addr := params["addr"] mon := p.NodeMonitor(addr) if mon == nil { res.WriteHeader(400) return } metricArgs := req.URL.Query()["metric"] if len(metricArgs) != 1 { res.WriteHeader(400) return } metric := metricArgs[0] points := mon.Points(metric) enc := json.NewEncoder(res) err := enc.Encode(points) if err != nil { log.Error("%v", err) } }) m.Get("/map", func(r rendergold.Render) { r.HTML( http.StatusOK, "map", map[string]interface{}{ "Page": "Map", }, ) }) m.Get("/tiles/:z/:x/:y.png", func(params martini.Params) []byte { z, _ := strconv.ParseUint(params["z"], 10, 64) x, _ := strconv.ParseUint(params["x"], 10, 64) y, _ := strconv.ParseUint(params["y"], 10, 64) coord := gopnik.TileCoord{x, y, z, 1, nil} res, err := cache.Get(coord) if err != nil { log.Error("%v", err) return nil } return res }) log.Info("Starting WebUI on %v", addr) log.Fatal(http.ListenAndServe(addr, m)) }
func copyMetaTile(metaCoord gopnik.TileCoord, cfg *Config, from, to gopnik.CachePluginInterface) { var metaTile []gopnik.Tile for y := uint(0); y < cfg.MetaSize; y++ { for x := uint(0); x < cfg.MetaSize; x++ { coord := gopnik.TileCoord{ X: metaCoord.X + uint64(x), Y: metaCoord.Y + uint64(y), Zoom: metaCoord.Zoom, Size: 1, Tags: metaCoord.Tags, } attempt := 0 TRYLOOP: for { if cfg.Copy.Retries > 0 { attempt++ } var err error var rawTile []byte rawTile, err = from.Get(coord) if err != nil { if attempt <= cfg.Copy.Retries { log.Error("Get error: %v", err) continue } else { if cfg.Copy.SkipErrors { log.Error("Get error: %v", err) return } log.Fatalf("Get error: %v", err) } } tile, err := gopnik.NewTile(rawTile) if err != nil { if attempt <= cfg.Copy.Retries { log.Error("NewTile error: %v", err) continue } else { if cfg.Copy.SkipErrors { log.Error("NewTile error: %v", err) return } log.Fatalf("NewTile error: %v", err) } } metaTile = append(metaTile, *tile) break TRYLOOP } } } attempt := 0 TRYLOOP2: for { if cfg.Copy.Retries > 0 { attempt++ } err := to.Set(metaCoord, metaTile) if err != nil { if attempt <= cfg.Copy.Retries { log.Error("Set error: %v", err) continue } else { if cfg.Copy.SkipErrors { log.Error("Set error: %v", err) return } log.Fatalf("Set error: %v", err) } } break TRYLOOP2 } }