func main() { flag.Parse() runtime.GOMAXPROCS(runtime.NumCPU()) if profile { log.Println("Running with profiling enabled") f, err := os.Create("chihaya.cpu") if err != nil { log.Fatalf("Failed to create profile file: %s\n", err) } defer f.Close() pprof.StartCPUProfile(f) } if configPath == "" { log.Fatalf("Must specify a configuration file") } conf, err := config.Open(configPath) if err != nil { log.Fatalf("Failed to parse configuration file: %s\n", err) } s, err := server.New(conf) if err != nil { log.Fatalf("Failed to create server: %s\n", err) } go func() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) <-c if profile { pprof.StopCPUProfile() } log.Println("Caught interrupt, shutting down..") err := s.Stop() if err != nil { panic("Failed to shutdown cleanly") } log.Println("Shutdown successfully") <-c os.Exit(0) }() err = s.ListenAndServe() if err != nil { log.Fatalf("Failed to start server: %s\n", err) } }
// Boot starts Chihaya. By exporting this function, anyone can import their own // custom drivers into their own package main and then call chihaya.Boot. func Boot() { defer glog.Flush() flag.Parse() runtime.GOMAXPROCS(maxProcs) glog.V(1).Info("Set max threads to ", maxProcs) debugBoot() defer debugShutdown() cfg, err := config.Open(configPath) if err != nil { glog.Fatalf("Failed to parse configuration file: %s\n", err) } if cfg == &config.DefaultConfig { glog.V(1).Info("Using default config") } else { glog.V(1).Infof("Loaded config file: %s", configPath) } stats.DefaultStats = stats.New(cfg.StatsConfig) tkr, err := tracker.New(cfg) if err != nil { glog.Fatal("New: ", err) } var servers []server if cfg.APIConfig.ListenAddr != "" { servers = append(servers, api.NewServer(cfg, tkr)) } if cfg.HTTPConfig.ListenAddr != "" { servers = append(servers, http.NewServer(cfg, tkr)) } if cfg.UDPConfig.ListenAddr != "" { servers = append(servers, udp.NewServer(cfg, tkr)) } var wg sync.WaitGroup for _, srv := range servers { wg.Add(1) // If you don't explicitly pass the server, every goroutine captures the // last server in the list. go func(srv server) { defer wg.Done() srv.Serve() }(srv) } shutdown := make(chan os.Signal) signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM) go func() { wg.Wait() signal.Stop(shutdown) close(shutdown) }() <-shutdown glog.Info("Shutting down...") for _, srv := range servers { srv.Stop() } <-shutdown if err := tkr.Close(); err != nil { glog.Errorf("Failed to shut down tracker cleanly: %s", err.Error()) } }