2022-05-30 15:25:07 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"os"
|
2024-03-16 13:47:20 +00:00
|
|
|
"os/signal"
|
2022-05-30 15:25:07 +00:00
|
|
|
"path"
|
|
|
|
"strings"
|
2024-03-16 13:47:20 +00:00
|
|
|
"syscall"
|
2022-05-30 15:25:07 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"srs.epita.fr/fic-server/settings"
|
|
|
|
|
|
|
|
"gopkg.in/fsnotify.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
var SettingsDistDir = "./SETTINGSDIST/"
|
|
|
|
var TmpSettingsDirectory string
|
|
|
|
var TmpSettingsDistDirectory string
|
2024-03-17 15:49:15 +00:00
|
|
|
var watchedNotify = fsnotify.Create
|
2022-05-30 15:25:07 +00:00
|
|
|
|
2024-03-14 16:43:51 +00:00
|
|
|
func watchsubdir(l *distList, watcher *fsnotify.Watcher, pathname string, treat func(l *distList, pathname string)) error {
|
2022-05-30 15:25:07 +00:00
|
|
|
log.Println("Watch new directory:", pathname)
|
|
|
|
if err := watcher.Add(pathname); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if ds, err := ioutil.ReadDir(pathname); err != nil {
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
for _, d := range ds {
|
|
|
|
p := path.Join(pathname, d.Name())
|
|
|
|
if d.Mode().IsRegular() && d.Name() != ".tmp" {
|
2024-03-14 16:43:51 +00:00
|
|
|
treat(l, p)
|
2022-05-30 15:25:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2024-03-14 16:43:51 +00:00
|
|
|
flag.StringVar(&DashboardDir, "dashboard", DashboardDir, "Base directory where read dashboard files")
|
2022-05-30 15:25:07 +00:00
|
|
|
flag.StringVar(&settings.SettingsDir, "settings", settings.SettingsDir, "Base directory where read settings")
|
|
|
|
flag.StringVar(&SettingsDistDir, "settingsDist", SettingsDistDir, "Directory where place settings to distribute")
|
|
|
|
var debugINotify = flag.Bool("debuginotify", false, "Show skipped inotofy events")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
log.SetPrefix("[evdist] ")
|
|
|
|
|
2024-03-14 16:43:51 +00:00
|
|
|
DashboardDir = path.Clean(DashboardDir)
|
2022-05-30 15:25:07 +00:00
|
|
|
settings.SettingsDir = path.Clean(settings.SettingsDir)
|
|
|
|
|
|
|
|
log.Println("Creating settingsDist directory...")
|
|
|
|
TmpSettingsDistDirectory = path.Join(SettingsDistDir, ".tmp")
|
|
|
|
if _, err := os.Stat(TmpSettingsDistDirectory); os.IsNotExist(err) {
|
2023-07-14 14:49:57 +00:00
|
|
|
if err = os.MkdirAll(TmpSettingsDistDirectory, 0751); err != nil {
|
2022-05-30 15:25:07 +00:00
|
|
|
log.Fatal("Unable to create settingsdist directory:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TmpSettingsDirectory = path.Join(settings.SettingsDir, ".tmp")
|
|
|
|
if _, err := os.Stat(TmpSettingsDirectory); os.IsNotExist(err) {
|
2023-07-14 14:49:57 +00:00
|
|
|
if err = os.MkdirAll(TmpSettingsDirectory, 0751); err != nil {
|
2022-05-30 15:25:07 +00:00
|
|
|
log.Fatal("Unable to create settings directory:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Println("Registering directory events...")
|
|
|
|
watcher, err := fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer watcher.Close()
|
|
|
|
|
2024-03-14 16:43:51 +00:00
|
|
|
lDashboard := &distList{}
|
|
|
|
lDashboard.Timer = time.NewTimer(time.Minute)
|
2022-05-30 15:25:07 +00:00
|
|
|
|
2024-03-14 16:43:51 +00:00
|
|
|
if err := watchsubdir(lDashboard, watcher, DashboardDir, newDashboardFile); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lSettings := &distList{}
|
|
|
|
lSettings.Timer = time.NewTimer(time.Minute)
|
|
|
|
|
|
|
|
if err := watchsubdir(lSettings, watcher, settings.SettingsDir, newSettingsFile); err != nil {
|
2022-05-30 15:25:07 +00:00
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2024-03-16 13:47:20 +00:00
|
|
|
// Register SIGUSR1 and SIGTERM
|
|
|
|
interrupt1 := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(interrupt1, syscall.SIGUSR1)
|
|
|
|
interrupt := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(interrupt, syscall.SIGTERM)
|
|
|
|
|
2024-03-14 16:43:51 +00:00
|
|
|
treatNewFile := func(name string) {
|
|
|
|
if strings.HasPrefix(name, DashboardDir) {
|
|
|
|
newDashboardFile(lDashboard, name)
|
|
|
|
} else {
|
|
|
|
newSettingsFile(lSettings, name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-16 13:47:20 +00:00
|
|
|
loop:
|
2022-05-30 15:25:07 +00:00
|
|
|
for {
|
|
|
|
select {
|
2024-03-16 13:47:20 +00:00
|
|
|
case <-interrupt:
|
|
|
|
break loop
|
|
|
|
case <-interrupt1:
|
|
|
|
log.Println("SIGUSR1 received, displaying queues")
|
|
|
|
log.Println("Seeing settings distlist")
|
|
|
|
lSettings.Print()
|
|
|
|
log.Println("Seeing dashboard distlist")
|
|
|
|
lDashboard.Print()
|
2024-03-14 16:43:51 +00:00
|
|
|
case <-lSettings.Timer.C:
|
|
|
|
if v := lSettings.Pop(); v != nil {
|
|
|
|
log.Printf("TREATING SETTINGS DIFF: %v", v)
|
|
|
|
treatSettingsFile(v)
|
|
|
|
}
|
|
|
|
lSettings.ResetTimer()
|
|
|
|
case <-lDashboard.Timer.C:
|
|
|
|
if v := lDashboard.Pop(); v != nil {
|
|
|
|
log.Printf("TREATING DASHBOARD DIFF: %v", v)
|
|
|
|
if ndf, ok := v.(*NextDashboardFile); ok {
|
|
|
|
treatDashboardFile(ndf)
|
2022-05-30 15:25:07 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-14 16:43:51 +00:00
|
|
|
lDashboard.ResetTimer()
|
2022-05-30 15:25:07 +00:00
|
|
|
case ev := <-watcher.Events:
|
|
|
|
if d, err := os.Lstat(ev.Name); err == nil && ev.Op&watchedNotify == watchedNotify && d.Name() != ".tmp" && d.Mode().IsRegular() {
|
|
|
|
if *debugINotify {
|
|
|
|
log.Println("Treating event:", ev, "for", ev.Name)
|
|
|
|
}
|
2024-03-14 16:43:51 +00:00
|
|
|
treatNewFile(ev.Name)
|
|
|
|
} else if ev.Op&fsnotify.Remove == fsnotify.Remove {
|
2022-06-08 10:31:08 +00:00
|
|
|
if *debugINotify {
|
|
|
|
log.Println("Treating deletion event:", ev, "for", ev.Name)
|
|
|
|
}
|
2024-03-14 16:43:51 +00:00
|
|
|
if strings.HasPrefix(ev.Name, DashboardDir) {
|
2024-03-17 15:49:15 +00:00
|
|
|
if ts, err := parseDashboardFilename(path.Base(ev.Name)); err != nil {
|
2024-03-14 16:43:51 +00:00
|
|
|
log.Println("Unable to parseint", ev.Name, err.Error())
|
|
|
|
} else {
|
2024-03-17 15:49:15 +00:00
|
|
|
lDashboard.DelEvent(ts, nil)
|
2024-03-14 16:43:51 +00:00
|
|
|
}
|
2022-06-08 10:31:08 +00:00
|
|
|
} else {
|
2024-03-17 15:49:15 +00:00
|
|
|
if ts, err := parseSettingsFilename(path.Base(ev.Name)); err != nil {
|
2024-03-14 16:43:51 +00:00
|
|
|
log.Println("Unable to parseint", ev.Name, err.Error())
|
|
|
|
} else {
|
2024-03-17 15:49:15 +00:00
|
|
|
lSettings.DelEvent(ts, updateNextSettingsTime)
|
2024-03-14 16:43:51 +00:00
|
|
|
}
|
2022-06-08 10:31:08 +00:00
|
|
|
}
|
|
|
|
} else if err == nil && ev.Op&fsnotify.Write == fsnotify.Write {
|
2022-05-30 15:25:07 +00:00
|
|
|
log.Println("FSNOTIFY WRITE SEEN. Prefer looking at them, as it appears files are not atomically moved.")
|
|
|
|
watchedNotify = fsnotify.Write
|
2024-03-14 16:43:51 +00:00
|
|
|
treatNewFile(ev.Name)
|
2022-05-30 15:25:07 +00:00
|
|
|
} else if *debugINotify {
|
|
|
|
log.Println("Skipped event:", ev, "for", ev.Name)
|
|
|
|
}
|
|
|
|
case err := <-watcher.Errors:
|
|
|
|
log.Println("error:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|