pass SetConfig a mutator func, as per PR feedback

- fsLockedRepo.config gets a mutex
- add missing checkToken call to lockedMemRepo#GetStorage and lockedMemRepo#SetStorage
- LockedRepo#SetConfig accepts a mutating function as per @magik
This commit is contained in:
laser 2020-06-10 09:07:47 -07:00
parent cf321f7667
commit fb1d5197fa
4 changed files with 59 additions and 21 deletions

View File

@ -230,6 +230,7 @@ type fsLockedRepo struct {
dsOnce sync.Once dsOnce sync.Once
storageLk sync.Mutex storageLk sync.Mutex
configLk sync.Mutex
} }
func (fsr *fsLockedRepo) Path() string { func (fsr *fsLockedRepo) Path() string {
@ -266,28 +267,43 @@ func (fsr *fsLockedRepo) stillValid() error {
} }
func (fsr *fsLockedRepo) Config() (interface{}, error) { func (fsr *fsLockedRepo) Config() (interface{}, error) {
if err := fsr.stillValid(); err != nil { fsr.configLk.Lock()
return nil, err defer fsr.configLk.Unlock()
}
return fsr.loadConfigFromDisk()
}
func (fsr *fsLockedRepo) loadConfigFromDisk() (interface{}, error) {
return config.FromFile(fsr.join(fsConfig), defConfForType(fsr.repoType)) return config.FromFile(fsr.join(fsConfig), defConfForType(fsr.repoType))
} }
func (fsr *fsLockedRepo) SetConfig(cfg interface{}) error { func (fsr *fsLockedRepo) SetConfig(c func(interface{})) error {
if err := fsr.stillValid(); err != nil { if err := fsr.stillValid(); err != nil {
return err return err
} }
tmp, err := ioutil.TempFile("", "lotus-config-temp") fsr.configLk.Lock()
defer fsr.configLk.Unlock()
cfg, err := fsr.loadConfigFromDisk()
if err != nil { if err != nil {
return err return err
} }
err = toml.NewEncoder(tmp).Encode(cfg) // mutate in-memory representation of config
c(cfg)
// buffer into which we write TOML bytes
buf := new(bytes.Buffer)
// encode now-mutated config as TOML and write to buffer
err = toml.NewEncoder(buf).Encode(cfg)
if err != nil { if err != nil {
return err return err
} }
err = os.Rename(tmp.Name(), fsr.join(fsConfig)) // write buffer of TOML bytes to config file
err = ioutil.WriteFile(fsr.join(fsConfig), buf.Bytes(), 0644)
if err != nil { if err != nil {
return err return err
} }

View File

@ -38,7 +38,7 @@ type LockedRepo interface {
// Returns config in this repo // Returns config in this repo
Config() (interface{}, error) Config() (interface{}, error)
SetConfig(interface{}) error SetConfig(func(interface{})) error
GetStorage() (stores.StorageConfig, error) GetStorage() (stores.StorageConfig, error)
SetStorage(func(*stores.StorageConfig)) error SetStorage(func(*stores.StorageConfig)) error

View File

@ -36,7 +36,10 @@ type MemRepo struct {
configF func(t RepoType) interface{} configF func(t RepoType) interface{}
// holds the current config value // holds the current config value
config interface{} config struct {
sync.Mutex
val interface{}
}
} }
type lockedMemRepo struct { type lockedMemRepo struct {
@ -50,6 +53,10 @@ type lockedMemRepo struct {
} }
func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) { func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) {
if err := lmem.checkToken(); err != nil {
return stores.StorageConfig{}, err
}
if lmem.sc == nil { if lmem.sc == nil {
lmem.sc = &stores.StorageConfig{StoragePaths: []stores.LocalPath{ lmem.sc = &stores.StorageConfig{StoragePaths: []stores.LocalPath{
{Path: lmem.Path()}, {Path: lmem.Path()},
@ -60,6 +67,10 @@ func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) {
} }
func (lmem *lockedMemRepo) SetStorage(c func(*stores.StorageConfig)) error { func (lmem *lockedMemRepo) SetStorage(c func(*stores.StorageConfig)) error {
if err := lmem.checkToken(); err != nil {
return err
}
_, _ = lmem.GetStorage() _, _ = lmem.GetStorage()
c(lmem.sc) c(lmem.sc)
@ -227,23 +238,33 @@ func (lmem *lockedMemRepo) Config() (interface{}, error) {
return nil, err return nil, err
} }
if lmem.mem.config == nil { lmem.mem.config.Lock()
lmem.mem.config = lmem.mem.configF(lmem.t) defer lmem.mem.config.Unlock()
if lmem.mem.config.val == nil {
lmem.mem.config.val = lmem.mem.configF(lmem.t)
} }
return lmem.mem.config, nil return lmem.mem.config.val, nil
} }
func (lmem *lockedMemRepo) SetConfig(cfg interface{}) error { func (lmem *lockedMemRepo) SetConfig(c func(interface{})) error {
lmem.mem.config = cfg if err := lmem.checkToken(); err != nil {
return err
}
lmem.mem.config.Lock()
defer lmem.mem.config.Unlock()
if lmem.mem.config.val == nil {
lmem.mem.config.val = lmem.mem.configF(lmem.t)
}
c(lmem.mem.config.val)
return nil return nil
} }
func (lmem *lockedMemRepo) Storage() (stores.StorageConfig, error) {
panic("implement me")
}
func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error { func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {
if err := lmem.checkToken(); err != nil { if err := lmem.checkToken(); err != nil {
return err return err

View File

@ -54,9 +54,10 @@ func basicTest(t *testing.T, repo Repo) {
assert.NoError(t, err, "config should not error") assert.NoError(t, err, "config should not error")
// mutate config and persist back to repo // mutate config and persist back to repo
cfg1 := c1.(*config.FullNode) err = lrepo.SetConfig(func(c interface{}) {
cfg1.Client.IpfsMAddr = "duvall" cfg := c.(*config.FullNode)
err = lrepo.SetConfig(cfg1) cfg.Client.IpfsMAddr = "duvall"
})
assert.NoError(t, err) assert.NoError(t, err)
// load config and verify changes // load config and verify changes