summary refs log tree commit diff stats
path: root/cache.go
blob: 7f15d45e92e22ace0c8d94ad9dbc2a79c2be1a7a (plain) (blame)
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
}