core: Make config slightly more reliable in handling errors

This commit is contained in:
John Brooks 2016-11-05 20:05:37 -06:00
parent bbc58e5815
commit 12422351d2
1 changed files with 21 additions and 14 deletions

View File

@ -74,10 +74,10 @@ func LoadConfig(filePath string) (*Config, error) {
// This function may block. // This function may block.
func (c *Config) OpenRead() *ConfigRoot { func (c *Config) OpenRead() *ConfigRoot {
c.mutex.RLock() c.mutex.RLock()
root := c.root root := c.root.Clone()
root.writable = false root.writable = false
root.config = c root.config = c
return &root return root
} }
// Return a writable snapshot of the current configuration. This object // Return a writable snapshot of the current configuration. This object
@ -85,10 +85,19 @@ func (c *Config) OpenRead() *ConfigRoot {
// finished with it. This function may block. // finished with it. This function may block.
func (c *Config) OpenWrite() *ConfigRoot { func (c *Config) OpenWrite() *ConfigRoot {
c.mutex.Lock() c.mutex.Lock()
root := c.root root := c.root.Clone()
root.writable = true root.writable = true
root.config = c root.config = c
return &root return root
}
func (root *ConfigRoot) Clone() *ConfigRoot {
re := *root
re.Contacts = make(map[string]ConfigContact)
for k, v := range root.Contacts {
re.Contacts[k] = v
}
return &re
} }
func (root *ConfigRoot) Close() { func (root *ConfigRoot) Close() {
@ -102,9 +111,8 @@ func (root *ConfigRoot) Close() {
root.config = nil root.config = nil
} }
// Save saves the state to the Config object, and attempts to write to // Save writes the state to disk, and updates the Config object if
// disk. An error is returned if the write fails, but changes to the // successful. Changes to the object are discarded on error.
// object are not discarded on error. XXX This is bad API
func (root *ConfigRoot) Save() error { func (root *ConfigRoot) Save() error {
if !root.writable { if !root.writable {
log.Panic("Save called on read-only config object") log.Panic("Save called on read-only config object")
@ -115,15 +123,13 @@ func (root *ConfigRoot) Save() error {
c := root.config c := root.config
root.writable = false root.writable = false
root.config = nil root.config = nil
c.root = *root err := c.save(root)
err := c.save()
c.mutex.Unlock() c.mutex.Unlock()
return err return err
} }
// Discard cannot be relied on to restore the state exactly as it was, // Discard closes a config write without saving any changes to disk
// because of potentially shared slice or map objects, but does not do // or to the Config object.
// an immediate save to disk. XXX This is bad API
func (root *ConfigRoot) Discard() { func (root *ConfigRoot) Discard() {
if !root.writable { if !root.writable {
log.Panic("Discard called on read-only config object") log.Panic("Discard called on read-only config object")
@ -136,8 +142,8 @@ func (root *ConfigRoot) Discard() {
c.mutex.Unlock() c.mutex.Unlock()
} }
func (c *Config) save() error { func (c *Config) save(newRoot *ConfigRoot) error {
data, err := json.MarshalIndent(c.root, "", " ") data, err := json.MarshalIndent(newRoot, "", " ")
if err != nil { if err != nil {
log.Printf("Config encoding error: %v", err) log.Printf("Config encoding error: %v", err)
return err return err
@ -166,5 +172,6 @@ func (c *Config) save() error {
return err return err
} }
c.root = *newRoot
return nil return nil
} }