func main() { InitMagick() /* here we ensure that go's signal handlers don't interfere. We have to shut down graphicsmagick correctly or crash */ signal_chan := make(chan os.Signal, 1) // Blow away go's handlers signal.Reset(syscall.SIGTERM, syscall.SIGINT) signal.Notify(signal_chan, syscall.SIGTERM, syscall.SIGINT) go func() { <-signal_chan // clean up graphicsmagick's memory / event loops CloseMagick() os.Exit(1) }() r := mux.NewRouter() readSettings() var factory *ImageFactory if Conf.S3 { factory = NewS3ImageFactory(Conf.BucketName) } else { factory = NewDiskImageFactory() } imageCollections, err := ParseImageCollections(Conf.CollectionsPath) if err != nil { log.Fatal(err) return } log.Print("Found collections: ") for k, _ := range imageCollections { log.Print(k) } handler := Handler{ Confs: Conf, imageCollections: imageCollections, ImageFactory: factory, } capHandler := CapHandler{ Handler: handler, dimension: C.CAP, } r.Handle("/img/{collection}/cap{dimension}/{name}", capHandler) r.Handle("/img/{collection}/cap{dimension}/blur{blur}/{name}", capHandler) r.Handle("/img/{collection}/cap/{dimension}/{name}", capHandler) r.Handle("/img/{collection}/cap/{dimension}/blur{blur}/{name}", capHandler) widthHandler := CapHandler{ Handler: handler, dimension: C.WIDTH, } r.Handle("/img/{collection}/width{dimension}/{name}", widthHandler) r.Handle("/img/{collection}/width{dimension}/blur{blur}/{name}", widthHandler) r.Handle("/img/{collection}/width/{dimension}/{name}", widthHandler) r.Handle("/img/{collection}/width/{dimension}/blur{blur}/{name}", widthHandler) heightHandler := CapHandler{ Handler: handler, dimension: C.HEIGHT, } r.Handle("/img/{collection}/height{dimension}/{name}", heightHandler) r.Handle("/img/{collection}/height{dimension}/blur{blur}/{name}", heightHandler) r.Handle("/img/{collection}/height/{dimension}/{name}", heightHandler) r.Handle("/img/{collection}/height/{dimension}/blur{blur}/{name}", heightHandler) resizeHandler := ResizeHandler{ Handler: handler, } r.Handle("/img/{collection}/{width}x{height}/{name}", resizeHandler) r.Handle("/img/{collection}/{width}x{height}/blur{blur}/{name}", resizeHandler) originalHandler := OriginalHandler{ Handler: handler, } r.Handle("/img/{collection}/original/{name}", originalHandler) http.Handle("/", r) log.Print("Starting imageservice") if port, err := strconv.Atoi(Conf.Port); err == nil { adminzEndpoints = adminz.New() adminzEndpoints.KillfilePaths(adminz.Killfiles(port)) adminzEndpoints.Start() log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", Conf.Port), nil)) } else { log.Fatalf("Unable to parse port %s %s", Conf.Port, err) } }
func main() { log.Printf("Quiver version %s (built %s, %s).\n\n", version, buildTime, runtime.Version()) t := time.Now() graphite := report.Flag() args := readSettings() stats := report.NewRecorder(). EnableGCInfoCollection(). MaybeReportTo(graphite). RegisterHttp(). SetAsDefault() hostname, err := os.Hostname() if err != nil { hostname = "localhost" } registrations := new(Registrations) if Settings.discoveryPath != "" && !Settings.downloadOnly { registrations.Connect() defer registrations.Close() } configs := getCollectionConfig(args) log.Println("Loading collections...") cs, err := hfile.LoadCollections(configs, Settings.cachePath, Settings.downloadOnly, stats) if err != nil { log.Fatal(err) } if Settings.downloadOnly { stats.FlushNow() return } if Settings.bloom > 0 { beforeBloom := time.Now() for _, c := range cs.Collections { log.Println("Calculating bloom filter for", c.Name) c.CalculateBloom(float64(Settings.bloom) / 100) } stats.TimeSince("startup.bloom", beforeBloom) } log.Printf("Serving on http://%s:%d/ \n", hostname, Settings.port) http.Handle("/rpc/HFileService", WrapHttpRpcHandler(cs, stats)) admin := adminz.New() admin.KillfilePaths(adminz.Killfiles(Settings.port)) admin.Servicez(func() interface{} { return struct { Collections map[string]*hfile.Reader `json:"collections"` Impl string `json:"implementation"` QuiverVersion string `json:"quiver_version"` PackageVersion string `json:"package_version"` }{ cs.Collections, "quiver", version, Settings.packageVersion, } }) admin.OnPause(registrations.Leave) admin.OnResume(func() { if Settings.discoveryPath != "" { registrations.Join(hostname, Settings.discoveryPath, configs, 0) } }) http.HandleFunc("/hfilez", admin.ServicezHandler) http.HandleFunc("/", admin.ServicezHandler) http.HandleFunc("/debug/bloom/enable", func(w http.ResponseWriter, r *http.Request) { for _, c := range cs.Collections { c.EnableBloom() } }) http.HandleFunc("/debug/bloom/disable", func(w http.ResponseWriter, r *http.Request) { for _, c := range cs.Collections { c.DisableBloom() } }) http.HandleFunc("/debug/bloom/calc", func(w http.ResponseWriter, r *http.Request) { if falsePos, err := strconv.Atoi(r.URL.Query().Get("err")); err != nil { http.Error(w, err.Error(), 400) } else if falsePos > 99 || falsePos < 1 { http.Error(w, "`err` param must be a false pos rate between 0 and 100", 400) } else { admin.Pause() defer admin.Resume() for _, c := range cs.Collections { fmt.Fprintln(w, "Recalculating bloom for", c.Name) c.CalculateBloom(float64(falsePos) / 100) } } }) runtime.GC() stats.FlushNow() admin.Start() stats.TimeSince("startup.total", t) if Settings.rpcPort > 0 { s, err := NewTRpcServer(fmt.Sprintf(":%d", Settings.rpcPort), WrapProcessor(cs, stats), thrift.NewTBinaryProtocolFactory(true, true)) if err != nil { log.Fatalln("Could not open RPC port", Settings.rpcPort, err) } else { if err := s.Listen(); err != nil { log.Fatalln("Failed to listen on RPC port", err) } go func() { log.Fatalln(s.Serve()) }() log.Println("Listening for raw RPC on", Settings.rpcPort) } } log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", Settings.port), nil)) }