// Start initalizes all scoreboard subsystems and starts up a webserver on port func Start(port uint16) { l := openLog() if l != nil { defer l.Close() } mux := http.NewServeMux() var savers []*statemanager.Saver // Initialize statemanager and load Settings.* statemanager.Initialize() savers = append(savers, initSettings("config/settings")) // Initialize leagues and load Leagues.* leagues.Initialize() savers = append(savers, statemanager.NewSaver("config/leagues", "Leagues", time.Duration(5)*time.Second, true, true)) // Initialize scoreboard and load Scoreboard.* statemanager.Lock() scoreboard.New() statemanager.Unlock() savers = append(savers, statemanager.NewSaver("config/scoreboard", "Scoreboard", time.Duration(5)*time.Second, true, true)) // Initialize websocket interface websocket.Initialize(mux) addFileWatcher("TeamLogos", "html", "/images/teamlogo") addFileWatcher("Sponsors", "html", "/images/sponsor_banner") addFileWatcher("Image", "html", "/images/fullscreen") addFileWatcher("Video", "html", "/videos") addFileWatcher("CustomHtml", "html", "/customhtml") printStartup(port) mux.Handle("/", http.FileServer(http.Dir(filepath.Join(statemanager.BaseFilePath(), "html")))) c := make(chan os.Signal, 1) go func() { err := http.ListenAndServe(fmt.Sprintf(":%d", port), setDefaultHeaders(mux)) if err != nil { log.Print(err) } c <- os.Kill }() mux.Handle("/version", http.HandlerFunc(versionHandler)) mux.Handle("/urls", http.HandlerFunc(urlsHandler)) signal.Notify(c, os.Interrupt, os.Kill) s := <-c log.Printf("Server received signal: %v. Shutting down", s) for _, saver := range savers { saver.Close() } }
func openLog() *os.File { path := filepath.Join(statemanager.BaseFilePath(), "logs", fmt.Sprintf("scoreboard-%v.log", time.Now().Format(time.RFC3339))) os.MkdirAll(filepath.Dir(path), 0775) f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664) if err != nil { log.Printf("Error opening file %v: %v", path, err) return nil } log.SetOutput(io.MultiWriter(f, os.Stdout)) return f }
func addFileWatcher(mediaType, prefix, path string) (*fsnotify.Watcher, error) { fullpath := filepath.Join(statemanager.BaseFilePath(), prefix, path) os.MkdirAll(fullpath, 0775) watcher, err := fsnotify.NewWatcher() if err != nil { return nil, err } err = watcher.Add(fullpath) if err != nil { watcher.Close() return nil, err } f, err := os.Open(fullpath) if err != nil { return nil, err } names, err := f.Readdirnames(-1) f.Close() for _, name := range names { short := filepath.Base(name) full := filepath.Join(path, short) statemanager.StateUpdateString(fmt.Sprintf("Media.Type(%v).File(%v)", mediaType, full), short) } go func() { for { select { case event := <-watcher.Events: short := filepath.Base(event.Name) full := filepath.Join(path, short) if event.Op&fsnotify.Create == fsnotify.Create { statemanager.StateUpdateString(fmt.Sprintf("Media.Type(%v).File(%v)", mediaType, full), short) } else if event.Op&fsnotify.Rename == fsnotify.Rename { statemanager.StateDelete(fmt.Sprintf("Media.Type(%v).File(%v)", mediaType, full)) } else if event.Op&fsnotify.Remove == fsnotify.Remove { statemanager.StateDelete(fmt.Sprintf("Media.Type(%v).File(%v)", mediaType, full)) } case err := <-watcher.Errors: log.Println("error:", err) } } }() return watcher, nil }
func main() { path, err := osext.ExecutableFolder() if err == nil { if exists(true, path, "html") && exists(false, path, "html/index.html") { statemanager.SetBaseFilePath(path) } else if exists(true, path, "..", "html") && exists(false, path, "..", "html/index.html") { statemanager.SetBaseFilePath(path, "..") } } flag.Parse() if cpuProf { f, err := os.Create(filepath.Join(statemanager.BaseFilePath(), "profile.cpu")) if err != nil { log.Print(err) } else { pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } } server.Start(uint16(port)) }