diff options
author | Ben Morrison <ben@gbmor.dev> | 2019-05-27 21:10:39 -0400 |
---|---|---|
committer | Ben Morrison <ben@gbmor.dev> | 2019-05-27 23:07:15 -0400 |
commit | c6ced3e74b52df4ed8a63868f86e095058c41100 (patch) | |
tree | d7568ca8a651b7e4711bcd3fb31c9d0a34942aa7 | |
parent | d6d0c18cad6426a0562d19b2b0c66a7c2bb4e2c5 (diff) | |
download | getwtxt-c6ced3e74b52df4ed8a63868f86e095058c41100.tar.gz |
preventing race cond in refreshCache()
-rw-r--r-- | cache.go | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/cache.go b/cache.go index e0fedb1..6e58956 100644 --- a/cache.go +++ b/cache.go @@ -46,13 +46,19 @@ func cacheAndPush() { func refreshCache() { + // This clusterfuck of mutex read locks is + // necessary to avoid deadlock. This mess + // also avoids a panic that would occur + // should twtxtCache be written to during + // this loop. twtxtCache.Mu.RLock() for k := range twtxtCache.Users { + twtxtCache.Mu.RUnlock() err := twtxtCache.UpdateUser(k) if err != nil { log.Printf("%v\n", err) - continue } + twtxtCache.Mu.RLock() } twtxtCache.Mu.RUnlock() @@ -120,42 +126,47 @@ func pullDatabase() { urls := split[0] field := split[1] - if urls != "remote" { - data := registry.NewUser() - twtxtCache.Mu.RLock() - if _, ok := twtxtCache.Users[urls]; ok { - data = twtxtCache.Users[urls] - } - twtxtCache.Mu.RUnlock() - - switch field { - case "IP": - data.IP = net.ParseIP(val) - case "Nick": - data.Nick = val - case "URL": - data.URL = val - case "Date": - data.Date = val - case "Status": - thetime, err := time.Parse(time.RFC3339, split[2]) - if err != nil { - log.Printf("%v\n", err) - } - data.Status[thetime] = val - } - - twtxtCache.Mu.Lock() - twtxtCache.Users[urls] = data - twtxtCache.Mu.Unlock() - - } else { + if urls == "remote" { remoteRegistries.Mu.Lock() remoteRegistries.List = append(remoteRegistries.List, val) remoteRegistries.Mu.Unlock() + continue + } + + data := registry.NewUser() + twtxtCache.Mu.RLock() + if _, ok := twtxtCache.Users[urls]; ok { + data = twtxtCache.Users[urls] + } + twtxtCache.Mu.RUnlock() + + switch field { + case "IP": + data.IP = net.ParseIP(val) + case "Nick": + data.Nick = val + case "URL": + data.URL = val + case "Date": + data.Date = val + case "Status": + thetime, err := time.Parse(time.RFC3339, split[2]) + if err != nil { + log.Printf("%v\n", err) + } + data.Status[thetime] = val } + + twtxtCache.Mu.Lock() + twtxtCache.Users[urls] = data + twtxtCache.Mu.Unlock() + } + remoteRegistries.Mu.Lock() + remoteRegistries.List = dedupe(remoteRegistries.List) + remoteRegistries.Mu.Unlock() + iter.Release() err := iter.Error() if err != nil { @@ -209,3 +220,18 @@ func pingAssets() { staticCache.cssMod = cssStat.ModTime() } } + +// Simple function to deduplicate entries in a []string +func dedupe(list []string) []string { + var out []string + var seen = map[string]bool{} + + for _, e := range list { + if !seen[e] { + out = append(out, e) + seen[e] = true + } + } + + return out +} |