* app: optimize config file reading

* read config file just once (even when upgrading)
* don't call os.Stat()
This commit is contained in:
Simon Zolin 2019-04-30 14:38:24 +03:00
parent 2dd6ea5161
commit 3ee8051e97
3 changed files with 36 additions and 38 deletions

31
app.go
View File

@ -93,16 +93,17 @@ func run(args options) {
os.Exit(0)
}()
// Do the upgrade if necessary
err := upgradeConfig()
if err != nil {
log.Fatal(err)
}
if !config.firstRun {
// Do the upgrade if necessary
err := upgradeConfig()
if err != nil {
log.Fatal(err)
}
// parse from config file
err = parseConfig()
if err != nil {
log.Fatal(err)
err = parseConfig()
if err != nil {
os.Exit(1)
}
}
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
@ -120,10 +121,12 @@ func run(args options) {
loadFilters()
// Save the updated config
err = config.write()
if err != nil {
log.Fatal(err)
if !config.firstRun {
// Save the updated config
err := config.write()
if err != nil {
log.Fatal(err)
}
}
// Init the DNS server instance before registering HTTP handlers
@ -131,7 +134,7 @@ func run(args options) {
initDNSServer(dnsBaseDir)
if !config.firstRun {
err = startDNSServer()
err := startDNSServer()
if err != nil {
log.Fatal(err)
}

View File

@ -30,6 +30,10 @@ type logSettings struct {
// configuration is loaded from YAML
// field ordering is important -- yaml fields will mirror ordering from here
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)
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
@ -174,7 +178,7 @@ func (c *configuration) getConfigFilename() string {
func getLogSettings() logSettings {
l := logSettings{}
yamlFile, err := readConfigFile()
if err != nil || yamlFile == nil {
if err != nil {
return l
}
err = yaml.Unmarshal(yamlFile, &l)
@ -190,13 +194,9 @@ func parseConfig() error {
log.Debug("Reading config file: %s", configFile)
yamlFile, err := readConfigFile()
if err != nil {
log.Error("Couldn't read config file: %s", err)
return err
}
if yamlFile == nil {
log.Error("YAML file doesn't exist, skipping it")
return nil
}
config.fileData = nil
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
log.Error("Couldn't parse config file: %s", err)
@ -213,22 +213,23 @@ func parseConfig() error {
// readConfigFile reads config file contents if it exists
func readConfigFile() ([]byte, error) {
configFile := config.getConfigFilename()
if _, err := os.Stat(configFile); os.IsNotExist(err) {
// do nothing, file doesn't exist
return nil, nil
if len(config.fileData) != 0 {
return config.fileData, 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
func (c *configuration) write() error {
c.Lock()
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()
log.Debug("Writing YAML file: %s", configFile)
yamlText, err := yaml.Marshal(&config)

View File

@ -2,7 +2,6 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
@ -16,21 +15,15 @@ const currentSchemaVersion = 3 // used for upgrading from old configs to new con
// Performs necessary upgrade operations if needed
func upgradeConfig() error {
// 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{}{}
body, err := ioutil.ReadFile(configFile)
body, err := readConfigFile()
if err != nil {
log.Printf("Couldn't read config file '%s': %s", configFile, err)
return err
}
err = yaml.Unmarshal(body, &diskConfig)
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
}
@ -87,6 +80,7 @@ func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) err
return err
}
config.fileData = body
err = file.SafeWrite(configFile, body)
if err != nil {
log.Printf("Couldn't save YAML config: %s", err)