Example #1
0
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)
	}
}
Example #2
0
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))
}