[#2164] network/cache: Separate mutex for addr

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
carpawell/fix/multiple-cache-update-requests-FROST
Evgenii Stratonikov 2022-12-13 16:10:45 +03:00 committed by Anton Nikiforov
parent 0ace28e43d
commit f3caf6acfe
1 changed files with 26 additions and 2 deletions

View File

@ -17,7 +17,9 @@ type multiClient struct {
clients map[string]clientcore.Client
addr network.AddressGroup
// addrMtx protects addr field. Should not be taken before the mtx.
addrMtx sync.RWMutex
addr network.AddressGroup
opts ClientCacheOpts
}
@ -74,6 +76,22 @@ func (x *multiClient) updateGroup(group network.AddressGroup) {
return false
})
x.addrMtx.RLock()
oldGroup := x.addr
x.addrMtx.RUnlock()
if len(oldGroup) == len(cache) {
needUpdate := false
for i := range oldGroup {
if cache[i] != oldGroup[i].String() {
needUpdate = true
break
}
}
if !needUpdate {
return
}
}
x.mtx.Lock()
defer x.mtx.Unlock()
loop:
@ -87,13 +105,19 @@ loop:
}
// Then add new clients.
x.addrMtx.Lock()
x.addr = group
x.addrMtx.Unlock()
}
func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Client) error) error {
var firstErr error
x.addr.IterateAddresses(func(addr network.Address) bool {
x.addrMtx.RLock()
group := x.addr
x.addrMtx.RUnlock()
group.IterateAddresses(func(addr network.Address) bool {
select {
case <-ctx.Done():
firstErr = context.Canceled