Serialize configuration updates and writes
This commit is contained in:
committed by
Brandon McGinty
parent
874cbb7818
commit
118799d112
+28
-2
@@ -10,9 +10,11 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
mu sync.Mutex
|
||||
config *exportableConfig
|
||||
fn string
|
||||
}
|
||||
@@ -49,6 +51,12 @@ type eUser struct {
|
||||
// SaveConfig atomically replaces the persisted configuration. Errors are
|
||||
// returned so an unavailable directory cannot crash the client.
|
||||
func (c *Config) SaveConfig() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.saveConfigLocked()
|
||||
}
|
||||
|
||||
func (c *Config) saveConfigLocked() error {
|
||||
data, err := toml.Marshal(c.config)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -254,18 +262,24 @@ func (c *Config) findUser(address string, username string) *eUser {
|
||||
}
|
||||
|
||||
func (c *Config) ToggleMute(u *gumble.User) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
j := c.findUser(u.GetClient().Config.Address, u.Name)
|
||||
j.LocallyMuted = !j.LocallyMuted
|
||||
u.SetLocallyMuted(j.LocallyMuted)
|
||||
c.SaveConfig()
|
||||
_ = c.saveConfigLocked()
|
||||
}
|
||||
|
||||
func (c *Config) SetMicVolume(v float32) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
t := float32(v)
|
||||
c.config.MicVolume = &t
|
||||
}
|
||||
|
||||
func (c *Config) GetMicVolume() float32 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.config.MicVolume == nil {
|
||||
return 1.0
|
||||
}
|
||||
@@ -308,6 +322,8 @@ func (c *Config) GetCertificate() *string {
|
||||
}
|
||||
|
||||
func (c *Config) GetNoiseSuppressionEnabled() bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.config.NoiseSuppressionEnabled == nil {
|
||||
return false
|
||||
}
|
||||
@@ -315,11 +331,15 @@ func (c *Config) GetNoiseSuppressionEnabled() bool {
|
||||
}
|
||||
|
||||
func (c *Config) SetNoiseSuppressionEnabled(enabled bool) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.config.NoiseSuppressionEnabled = &enabled
|
||||
c.SaveConfig()
|
||||
_ = c.saveConfigLocked()
|
||||
}
|
||||
|
||||
func (c *Config) GetRecordingFormat() string {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.config.RecordingFormat == nil {
|
||||
return "flac"
|
||||
}
|
||||
@@ -327,6 +347,8 @@ func (c *Config) GetRecordingFormat() string {
|
||||
}
|
||||
|
||||
func (c *Config) GetRecordingDirectory() string {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.config.RecordingDirectory == nil {
|
||||
return resolvePath("~/Audio")
|
||||
}
|
||||
@@ -334,6 +356,8 @@ func (c *Config) GetRecordingDirectory() string {
|
||||
}
|
||||
|
||||
func (c *Config) UpdateUser(u *gumble.User) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
var j *eUser
|
||||
var uc *gumble.Client
|
||||
uc = u.GetClient()
|
||||
@@ -349,6 +373,8 @@ func (c *Config) UpdateUser(u *gumble.User) {
|
||||
}
|
||||
|
||||
func (c *Config) UpdateConfig(u *gumble.User) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
var j *eUser
|
||||
j = c.findUser(u.GetClient().Config.Address, u.Name)
|
||||
j.Boost = u.Boost()
|
||||
|
||||
@@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -14,3 +15,20 @@ func TestSaveConfigReturnsWriteError(t *testing.T) {
|
||||
t.Fatal("expected configuration write error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConcurrentConfigurationUpdatesAndWrites(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "barnard.toml")
|
||||
cfg := NewConfig(&path)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 20; i++ {
|
||||
wg.Add(1)
|
||||
go func(enabled bool) {
|
||||
defer wg.Done()
|
||||
cfg.SetNoiseSuppressionEnabled(enabled)
|
||||
if err := cfg.SaveConfig(); err != nil {
|
||||
t.Errorf("SaveConfig: %v", err)
|
||||
}
|
||||
}(i%2 == 0)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user