diff options
-rw-r--r-- | getwtxt.json | 5 | ||||
-rw-r--r-- | handlers.go | 2 | ||||
-rw-r--r-- | init.go | 95 | ||||
-rw-r--r-- | main.go | 6 | ||||
-rw-r--r-- | types.go | 13 |
5 files changed, 106 insertions, 15 deletions
diff --git a/getwtxt.json b/getwtxt.json index 60afa6a..912975a 100644 --- a/getwtxt.json +++ b/getwtxt.json @@ -1,7 +1,10 @@ { "port": 9001, "stdoutLogging": true, - "logfile": "getwtxt.log", + "logFile": "getwtxt.log", + "databasePath": "getwtxt.db", + "databasePushInterval": "5m", + "reCacheInterval": "1h", "instance": { "name": "getwtxt", "url": "https://twtxt.example.com", diff --git a/handlers.go b/handlers.go index 4ec511d..151eb60 100644 --- a/handlers.go +++ b/handlers.go @@ -30,7 +30,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { // Pass the confObj.Instance data to the template, // then send it to the client. + confObj.mu.RLock() err := tmpls.ExecuteTemplate(w, "index.html", confObj.Instance) + confObj.mu.RUnlock() if err != nil { log500(w, r, err) return diff --git a/init.go b/init.go index 08ac5b6..47304c5 100644 --- a/init.go +++ b/init.go @@ -12,8 +12,11 @@ import ( "github.com/getwtxt/registry" "github.com/spf13/pflag" "github.com/spf13/viper" + "github.com/syndtr/goleveldb/leveldb" ) +const getwtxt = "0.1" + // command line flags var ( flagVersion *bool = pflag.BoolP("version", "v", false, "Display version information, then exit") @@ -26,6 +29,10 @@ var confObj = &configuration{} // signals to close the log file var closelog = make(chan bool, 1) +// used to transmit database pointer after +// initialization +var dbChan = make(chan *leveldb.DB, 1) + // templates var tmpls *template.Template @@ -51,8 +58,8 @@ func checkFlags() { os.Exit(0) } if *flagHelp { - fmt.Printf("\nplaceholder\n") - fmt.Printf("will add info later\n") + titleScreen() + helpScreen() os.Exit(0) } } @@ -80,29 +87,54 @@ func initConfig() { }) viper.SetDefault("port", 9001) - viper.SetDefault("logfile", "getwtxt.log") + viper.SetDefault("logFile", "getwtxt.log") + viper.SetDefault("databasePath", "getwtxt.db") viper.SetDefault("stdoutLogging", false) + viper.SetDefault("reCacheInterval", "1h") + viper.SetDefault("databasePushInterval", "5m") + + updateInterval := viper.GetString("reCacheInterval") + dur, err := time.ParseDuration(updateInterval) + if err != nil { + log.Printf("Unable to parse registry cache update interval. Defaulting to hourly. Msg: %v\n", err) + dur, _ = time.ParseDuration("1h") + } + + dbPushInterval := viper.GetString("databasePushInterval") + dbDur, err := time.ParseDuration(dbPushInterval) + if err != nil { + log.Printf("Unable to parse database push interval. Defaulting to every five minutes. Msg: %v\n", err) + dbDur, _ = time.ParseDuration("5m") + } + confObj.mu.Lock() confObj.port = viper.GetInt("port") - confObj.logfile = viper.GetString("logfile") + confObj.logFile = viper.GetString("logFile") + confObj.dbPath = viper.GetString("databasePath") confObj.stdoutLogging = viper.GetBool("stdoutLogging") + confObj.cacheInterval = dur + confObj.dbInterval = dbDur + confObj.lastCache = time.Now() confObj.version = getwtxt confObj.Instance.Name = viper.GetString("instance.name") confObj.Instance.URL = viper.GetString("instance.url") confObj.Instance.Owner = viper.GetString("instance.owner") confObj.Instance.Mail = viper.GetString("instance.mail") confObj.Instance.Desc = viper.GetString("instance.description") + confObj.mu.Unlock() } func initLogging() { // only open a log file if it's necessary + confObj.mu.RLock() + if confObj.stdoutLogging { log.SetOutput(os.Stdout) } else { - logfile, err := os.OpenFile(confObj.logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + logfile, err := os.OpenFile(confObj.logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) if err != nil { log.Printf("Could not open log file: %v\n", err) } @@ -112,8 +144,10 @@ func initLogging() { // to prevent race conditions when the config is // reloaded. go func(logfile *os.File) { + <-closelog log.Printf("Closing log file ...\n") + err = logfile.Close() if err != nil { log.Printf("Couldn't close log file: %v\n", err) @@ -122,24 +156,48 @@ func initLogging() { log.SetOutput(logfile) } + confObj.mu.RUnlock() } func rebindConfig() { // signal to close the log file then wait + confObj.mu.RLock() if !confObj.stdoutLogging { closelog <- true } + confObj.mu.RUnlock() + + // re-parse update interval + nter := viper.GetString("reCacheInterval") + dur, err := time.ParseDuration(nter) + if err != nil { + log.Printf("Unable to parse update interval. Defaulting to once daily. Msg: %v\n", err) + dur, _ = time.ParseDuration("1h") + } + + // re-parse database backup interval + dbPushInterval := viper.GetString("databasePushInterval") + dbDur, err := time.ParseDuration(dbPushInterval) + if err != nil { + log.Printf("Unable to parse database push interval. Defaulting to every five minutes. Msg: %v\n", err) + dbDur, _ = time.ParseDuration("5m") + } // reassign values to the config object + confObj.mu.Lock() confObj.port = viper.GetInt("port") - confObj.logfile = viper.GetString("logfile") + confObj.logFile = viper.GetString("logFile") confObj.stdoutLogging = viper.GetBool("stdoutLogging") + confObj.dbPath = viper.GetString("databasePath") + confObj.cacheInterval = dur + confObj.dbInterval = dbDur confObj.Instance.Name = viper.GetString("instance.name") confObj.Instance.URL = viper.GetString("instance.url") confObj.Instance.Owner = viper.GetString("instance.owner") confObj.Instance.Mail = viper.GetString("instance.mail") confObj.Instance.Desc = viper.GetString("instance.description") + confObj.mu.Unlock() // reinitialize logging initLogging() @@ -150,6 +208,16 @@ func initTemplates() *template.Template { return template.Must(template.ParseFiles("assets/tmpl/index.html")) } +// Pull DB data into cache, if available +func initDatabase() { + db, err := leveldb.OpenFile(confObj.dbPath, nil) + if err != nil { + log.Fatalf("%v\n", err) + } + + dbChan <- db +} + // Watch for SIGINT aka ^C // Close the log file then exit func watchForInterrupt() { @@ -160,10 +228,12 @@ func watchForInterrupt() { for sigint := range c { log.Printf("\n\nCaught %v. Cleaning up ...\n", sigint) + confObj.mu.RLock() if !confObj.stdoutLogging { // signal to close the log file closelog <- true } + confObj.mu.RUnlock() close(closelog) @@ -184,8 +254,15 @@ func titleScreen() { \__, |\___|\__| \_/\_/ \__/_/\_\\__| |___/ version ` + getwtxt + ` - github.com/gbmor/getwtxt - GPL v3 - + github.com/getwtxt/getwtxt + GPL v3 +`) +} + +func helpScreen() { + fmt.Printf(` + Help File + + Sections: `) } diff --git a/main.go b/main.go index 448ff1a..9c4a4ab 100644 --- a/main.go +++ b/main.go @@ -10,8 +10,6 @@ import ( "github.com/gorilla/mux" ) -const getwtxt = "0.1" - func main() { // StrictSlash(true) allows /api and /api/ @@ -69,7 +67,9 @@ func main() { HandlerFunc(apiTagsHandler) // format the port for the http.Server object + confObj.mu.RLock() portnum := fmt.Sprintf(":%v", confObj.port) + confObj.mu.RUnlock() // defines options for the http server. // handlers.CompressHandler gzips all responses. // Write/Read timeouts are self explanatory. @@ -80,7 +80,7 @@ func main() { ReadTimeout: 15 * time.Second, } - log.Printf("Listening on port %v\n", confObj.port) + log.Printf("Listening on %v\n", portnum) err := server.ListenAndServe() if err != nil { log.Printf("%v\n", err) diff --git a/types.go b/types.go index 018e26e..1aaf7a8 100644 --- a/types.go +++ b/types.go @@ -1,6 +1,9 @@ package main -import "sync" +import ( + "sync" + "time" +) // content-type consts const txtutf8 = "text/plain; charset=utf-8" @@ -9,10 +12,16 @@ const cssutf8 = "text/css; charset=utf-8" // config object definition type configuration struct { + mu sync.RWMutex port int - logfile string + logFile string + dbPath string stdoutLogging bool version string + cacheInterval time.Duration + dbInterval time.Duration + lastCache time.Time + lastPush time.Time Instance } |