summary refs log tree commit diff stats
path: root/cache.go
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-05-27 21:10:39 -0400
committerBen Morrison <ben@gbmor.dev>2019-05-27 23:07:15 -0400
commitc6ced3e74b52df4ed8a63868f86e095058c41100 (patch)
treed7568ca8a651b7e4711bcd3fb31c9d0a34942aa7 /cache.go
parentd6d0c18cad6426a0562d19b2b0c66a7c2bb4e2c5 (diff)
downloadgetwtxt-c6ced3e74b52df4ed8a63868f86e095058c41100.tar.gz
preventing race cond in refreshCache()
Diffstat (limited to 'cache.go')
-rw-r--r--cache.go88
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
+}