mirror of
https://github.com/rkfg/regolancer
synced 2024-11-18 21:26:29 +00:00
96 lines
1.9 KiB
Go
96 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/gofrs/flock"
|
|
)
|
|
|
|
func lock() *flock.Flock {
|
|
return flock.New(filepath.Join(os.TempDir(), "regolancer.lock"))
|
|
}
|
|
|
|
func (r *regolancer) loadNodeCache(filename string, exp int, doLock bool) error {
|
|
if filename == "" {
|
|
return nil
|
|
}
|
|
defer func() {
|
|
err := recover()
|
|
if err == nil {
|
|
return
|
|
}
|
|
log.Printf("Loading failed, cache format might be outdated: %s", err)
|
|
r.nodeCache = map[string]cachedNodeInfo{}
|
|
}()
|
|
if doLock {
|
|
log.Printf("Loading node cache from %s", filename)
|
|
l := lock()
|
|
err := l.RLock()
|
|
defer l.Unlock()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("error taking shared lock on file %s: %s", filename, err)
|
|
}
|
|
}
|
|
f, err := os.Open(filename)
|
|
if err != nil {
|
|
if !os.IsNotExist(err) {
|
|
return fmt.Errorf("error opening node cache file: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
defer f.Close()
|
|
err = gob.NewDecoder(f).Decode(&r.nodeCache)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for k, v := range r.nodeCache {
|
|
since := time.Since(v.Timestamp)
|
|
if since > time.Minute*time.Duration(exp) {
|
|
delete(r.nodeCache, k)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *regolancer) saveNodeCache(filename string, exp int) error {
|
|
if filename == "" {
|
|
return nil
|
|
}
|
|
log.Printf("Saving node cache to %s", filename)
|
|
|
|
l := lock()
|
|
err := l.Lock()
|
|
defer l.Unlock()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("error taking exclusive lock on file %s: %s", filename, err)
|
|
}
|
|
|
|
old := regolancer{nodeCache: map[string]cachedNodeInfo{}}
|
|
err = old.loadNodeCache(filename, exp, false)
|
|
|
|
if err != nil {
|
|
logErrorF("Error merging cache, saving anew: %s", err)
|
|
}
|
|
for k, v := range old.nodeCache {
|
|
if n, ok := r.nodeCache[k]; !ok ||
|
|
n.Timestamp.Before(v.Timestamp) {
|
|
r.nodeCache[k] = v
|
|
}
|
|
}
|
|
|
|
f, err := os.Create(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating node cache file: %s", err)
|
|
}
|
|
defer f.Close()
|
|
err = gob.NewEncoder(f).Encode(r.nodeCache)
|
|
return err
|
|
}
|