* app: optimize config file reading
* read config file just once (even when upgrading) * don't call os.Stat()
This commit is contained in:
parent
2dd6ea5161
commit
3ee8051e97
31
app.go
31
app.go
|
@ -93,16 +93,17 @@ func run(args options) {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Do the upgrade if necessary
|
if !config.firstRun {
|
||||||
err := upgradeConfig()
|
// Do the upgrade if necessary
|
||||||
if err != nil {
|
err := upgradeConfig()
|
||||||
log.Fatal(err)
|
if err != nil {
|
||||||
}
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// parse from config file
|
err = parseConfig()
|
||||||
err = parseConfig()
|
if err != nil {
|
||||||
if err != nil {
|
os.Exit(1)
|
||||||
log.Fatal(err)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
|
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
|
||||||
|
@ -120,10 +121,12 @@ func run(args options) {
|
||||||
|
|
||||||
loadFilters()
|
loadFilters()
|
||||||
|
|
||||||
// Save the updated config
|
if !config.firstRun {
|
||||||
err = config.write()
|
// Save the updated config
|
||||||
if err != nil {
|
err := config.write()
|
||||||
log.Fatal(err)
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the DNS server instance before registering HTTP handlers
|
// Init the DNS server instance before registering HTTP handlers
|
||||||
|
@ -131,7 +134,7 @@ func run(args options) {
|
||||||
initDNSServer(dnsBaseDir)
|
initDNSServer(dnsBaseDir)
|
||||||
|
|
||||||
if !config.firstRun {
|
if !config.firstRun {
|
||||||
err = startDNSServer()
|
err := startDNSServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
31
config.go
31
config.go
|
@ -30,6 +30,10 @@ type logSettings struct {
|
||||||
// configuration is loaded from YAML
|
// configuration is loaded from YAML
|
||||||
// field ordering is important -- yaml fields will mirror ordering from here
|
// field ordering is important -- yaml fields will mirror ordering from here
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
|
// Raw file data to avoid re-reading of configuration file
|
||||||
|
// It's reset after config is parsed
|
||||||
|
fileData []byte
|
||||||
|
|
||||||
ourConfigFilename string // Config filename (can be overridden via the command line arguments)
|
ourConfigFilename string // Config filename (can be overridden via the command line arguments)
|
||||||
ourWorkingDir string // Location of our directory, used to protect against CWD being somewhere else
|
ourWorkingDir string // Location of our directory, used to protect against CWD being somewhere else
|
||||||
firstRun bool // if set to true, don't run any services except HTTP web inteface, and serve only first-run html
|
firstRun bool // if set to true, don't run any services except HTTP web inteface, and serve only first-run html
|
||||||
|
@ -174,7 +178,7 @@ func (c *configuration) getConfigFilename() string {
|
||||||
func getLogSettings() logSettings {
|
func getLogSettings() logSettings {
|
||||||
l := logSettings{}
|
l := logSettings{}
|
||||||
yamlFile, err := readConfigFile()
|
yamlFile, err := readConfigFile()
|
||||||
if err != nil || yamlFile == nil {
|
if err != nil {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
err = yaml.Unmarshal(yamlFile, &l)
|
err = yaml.Unmarshal(yamlFile, &l)
|
||||||
|
@ -190,13 +194,9 @@ func parseConfig() error {
|
||||||
log.Debug("Reading config file: %s", configFile)
|
log.Debug("Reading config file: %s", configFile)
|
||||||
yamlFile, err := readConfigFile()
|
yamlFile, err := readConfigFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Couldn't read config file: %s", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if yamlFile == nil {
|
config.fileData = nil
|
||||||
log.Error("YAML file doesn't exist, skipping it")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = yaml.Unmarshal(yamlFile, &config)
|
err = yaml.Unmarshal(yamlFile, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Couldn't parse config file: %s", err)
|
log.Error("Couldn't parse config file: %s", err)
|
||||||
|
@ -213,22 +213,23 @@ func parseConfig() error {
|
||||||
|
|
||||||
// readConfigFile reads config file contents if it exists
|
// readConfigFile reads config file contents if it exists
|
||||||
func readConfigFile() ([]byte, error) {
|
func readConfigFile() ([]byte, error) {
|
||||||
configFile := config.getConfigFilename()
|
if len(config.fileData) != 0 {
|
||||||
if _, err := os.Stat(configFile); os.IsNotExist(err) {
|
return config.fileData, nil
|
||||||
// do nothing, file doesn't exist
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
return ioutil.ReadFile(configFile)
|
|
||||||
|
configFile := config.getConfigFilename()
|
||||||
|
d, err := ioutil.ReadFile(configFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Couldn't read config file %s: %s", configFile, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saves configuration to the YAML file and also saves the user filter contents to a file
|
// Saves configuration to the YAML file and also saves the user filter contents to a file
|
||||||
func (c *configuration) write() error {
|
func (c *configuration) write() error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
if config.firstRun {
|
|
||||||
log.Debug("Silently refusing to write config because first run and not configured yet")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
configFile := config.getConfigFilename()
|
configFile := config.getConfigFilename()
|
||||||
log.Debug("Writing YAML file: %s", configFile)
|
log.Debug("Writing YAML file: %s", configFile)
|
||||||
yamlText, err := yaml.Marshal(&config)
|
yamlText, err := yaml.Marshal(&config)
|
||||||
|
|
12
upgrade.go
12
upgrade.go
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -16,21 +15,15 @@ const currentSchemaVersion = 3 // used for upgrading from old configs to new con
|
||||||
// Performs necessary upgrade operations if needed
|
// Performs necessary upgrade operations if needed
|
||||||
func upgradeConfig() error {
|
func upgradeConfig() error {
|
||||||
// read a config file into an interface map, so we can manipulate values without losing any
|
// read a config file into an interface map, so we can manipulate values without losing any
|
||||||
configFile := config.getConfigFilename()
|
|
||||||
if _, err := os.Stat(configFile); os.IsNotExist(err) {
|
|
||||||
log.Printf("config file %s does not exist, nothing to upgrade", configFile)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
diskConfig := map[string]interface{}{}
|
diskConfig := map[string]interface{}{}
|
||||||
body, err := ioutil.ReadFile(configFile)
|
body, err := readConfigFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Couldn't read config file '%s': %s", configFile, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = yaml.Unmarshal(body, &diskConfig)
|
err = yaml.Unmarshal(body, &diskConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Couldn't parse config file '%s': %s", configFile, err)
|
log.Printf("Couldn't parse config file: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +80,7 @@ func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.fileData = body
|
||||||
err = file.SafeWrite(configFile, body)
|
err = file.SafeWrite(configFile, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Couldn't save YAML config: %s", err)
|
log.Printf("Couldn't save YAML config: %s", err)
|
||||||
|
|
Loading…
Reference in New Issue