1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
package main
import (
"bytes"
"io/ioutil"
"log"
"os"
"time"
)
func checkCacheTime() bool {
confObj.Mu.RLock()
answer := time.Since(confObj.LastCache) > confObj.CacheInterval
confObj.Mu.RUnlock()
return answer
}
// Launched by init as a coroutine to watch
// for the update intervals to pass.
func cacheAndPush() {
for {
if checkCacheTime() {
refreshCache()
}
if checkDBtime() {
if err := pushDatabase(); err != nil {
log.Printf("Error pushing cache to database: %v\n", err.Error())
}
}
time.Sleep(1000 * time.Millisecond)
}
}
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.Error())
}
twtxtCache.Mu.RLock()
}
twtxtCache.Mu.RUnlock()
remoteRegistries.Mu.RLock()
for _, v := range remoteRegistries.List {
err := twtxtCache.CrawlRemoteRegistry(v)
if err != nil {
log.Printf("Error while refreshing local copy of remote registry user data: %v\n", err.Error())
}
}
remoteRegistries.Mu.RUnlock()
confObj.Mu.Lock()
confObj.LastCache = time.Now()
confObj.Mu.Unlock()
}
// pingAssets checks if the local static assets
// need to be re-cached. If they do, they are
// pulled back into memory from disk.
func pingAssets() {
confObj.Mu.RLock()
assetsDir := confObj.AssetsDir
confObj.Mu.RUnlock()
cssStat, err := os.Stat(assetsDir + "/style.css")
if err != nil {
log.Printf("%v\n", err.Error())
}
indexStat, err := os.Stat(assetsDir + "/tmpl/index.html")
if err != nil {
log.Printf("%v\n", err.Error())
}
indexMod := staticCache.indexMod
cssMod := staticCache.cssMod
if !indexMod.Equal(indexStat.ModTime()) {
tmpls = initTemplates()
var b []byte
buf := bytes.NewBuffer(b)
confObj.Mu.RLock()
err = tmpls.ExecuteTemplate(buf, "index.html", confObj.Instance)
confObj.Mu.RUnlock()
if err != nil {
log.Printf("%v\n", err.Error())
}
staticCache.index = buf.Bytes()
staticCache.indexMod = indexStat.ModTime()
}
if !cssMod.Equal(cssStat.ModTime()) {
css, err := ioutil.ReadFile(assetsDir + "/style.css")
if err != nil {
log.Printf("%v\n", err.Error())
}
staticCache.css = css
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
}
|