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"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
mu sync.Mutex
|
||||||
config *exportableConfig
|
config *exportableConfig
|
||||||
fn string
|
fn string
|
||||||
}
|
}
|
||||||
@@ -49,6 +51,12 @@ type eUser struct {
|
|||||||
// SaveConfig atomically replaces the persisted configuration. Errors are
|
// SaveConfig atomically replaces the persisted configuration. Errors are
|
||||||
// returned so an unavailable directory cannot crash the client.
|
// returned so an unavailable directory cannot crash the client.
|
||||||
func (c *Config) SaveConfig() error {
|
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)
|
data, err := toml.Marshal(c.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -254,18 +262,24 @@ func (c *Config) findUser(address string, username string) *eUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) ToggleMute(u *gumble.User) {
|
func (c *Config) ToggleMute(u *gumble.User) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
j := c.findUser(u.GetClient().Config.Address, u.Name)
|
j := c.findUser(u.GetClient().Config.Address, u.Name)
|
||||||
j.LocallyMuted = !j.LocallyMuted
|
j.LocallyMuted = !j.LocallyMuted
|
||||||
u.SetLocallyMuted(j.LocallyMuted)
|
u.SetLocallyMuted(j.LocallyMuted)
|
||||||
c.SaveConfig()
|
_ = c.saveConfigLocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) SetMicVolume(v float32) {
|
func (c *Config) SetMicVolume(v float32) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
t := float32(v)
|
t := float32(v)
|
||||||
c.config.MicVolume = &t
|
c.config.MicVolume = &t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetMicVolume() float32 {
|
func (c *Config) GetMicVolume() float32 {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
if c.config.MicVolume == nil {
|
if c.config.MicVolume == nil {
|
||||||
return 1.0
|
return 1.0
|
||||||
}
|
}
|
||||||
@@ -308,6 +322,8 @@ func (c *Config) GetCertificate() *string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetNoiseSuppressionEnabled() bool {
|
func (c *Config) GetNoiseSuppressionEnabled() bool {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
if c.config.NoiseSuppressionEnabled == nil {
|
if c.config.NoiseSuppressionEnabled == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -315,11 +331,15 @@ func (c *Config) GetNoiseSuppressionEnabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) SetNoiseSuppressionEnabled(enabled bool) {
|
func (c *Config) SetNoiseSuppressionEnabled(enabled bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
c.config.NoiseSuppressionEnabled = &enabled
|
c.config.NoiseSuppressionEnabled = &enabled
|
||||||
c.SaveConfig()
|
_ = c.saveConfigLocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetRecordingFormat() string {
|
func (c *Config) GetRecordingFormat() string {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
if c.config.RecordingFormat == nil {
|
if c.config.RecordingFormat == nil {
|
||||||
return "flac"
|
return "flac"
|
||||||
}
|
}
|
||||||
@@ -327,6 +347,8 @@ func (c *Config) GetRecordingFormat() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetRecordingDirectory() string {
|
func (c *Config) GetRecordingDirectory() string {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
if c.config.RecordingDirectory == nil {
|
if c.config.RecordingDirectory == nil {
|
||||||
return resolvePath("~/Audio")
|
return resolvePath("~/Audio")
|
||||||
}
|
}
|
||||||
@@ -334,6 +356,8 @@ func (c *Config) GetRecordingDirectory() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) UpdateUser(u *gumble.User) {
|
func (c *Config) UpdateUser(u *gumble.User) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
var j *eUser
|
var j *eUser
|
||||||
var uc *gumble.Client
|
var uc *gumble.Client
|
||||||
uc = u.GetClient()
|
uc = u.GetClient()
|
||||||
@@ -349,6 +373,8 @@ func (c *Config) UpdateUser(u *gumble.User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) UpdateConfig(u *gumble.User) {
|
func (c *Config) UpdateConfig(u *gumble.User) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
var j *eUser
|
var j *eUser
|
||||||
j = c.findUser(u.GetClient().Config.Address, u.Name)
|
j = c.findUser(u.GetClient().Config.Address, u.Name)
|
||||||
j.Boost = u.Boost()
|
j.Boost = u.Boost()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,3 +15,20 @@ func TestSaveConfigReturnsWriteError(t *testing.T) {
|
|||||||
t.Fatal("expected configuration write error")
|
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