@@ -2,6 +2,7 @@ package main
22
33import (
44 "encoding/csv"
5+ "errors"
56 "fmt"
67 "io/ioutil"
78 "net/http"
@@ -23,6 +24,7 @@ const (
2324
2425const (
2526 SourcesUpdateDelayAfterFailure = time .Duration (1 ) * time .Minute
27+ SourcesUpdateDelay = time .Duration (24 ) * time .Hour
2628)
2729
2830type Source struct {
@@ -31,67 +33,59 @@ type Source struct {
3133 in string
3234}
3335
34- func fetchFromCache (cacheFile string ) ([]byte , error ) {
35- dlog .Debugf ("Loading source information from cache file [%s]" , cacheFile )
36- return ioutil .ReadFile (cacheFile )
36+ func fetchFromCache (cacheFile string ) (in string , delayTillNextUpdate time.Duration , err error ) {
37+ fi , err := os .Stat (cacheFile )
38+ if err != nil {
39+ delayTillNextUpdate = time .Duration (0 )
40+ return
41+ }
42+ elapsed := time .Since (fi .ModTime ())
43+ if elapsed < SourcesUpdateDelay {
44+ dlog .Debugf ("Cache file [%s] is still fresh" , cacheFile )
45+ delayTillNextUpdate = SourcesUpdateDelay - elapsed
46+ } else {
47+ dlog .Debugf ("Cache file [%s] needs to be refreshed" , cacheFile )
48+ delayTillNextUpdate = time .Duration (0 )
49+ }
50+ var bin []byte
51+ bin , err = ioutil .ReadFile (cacheFile )
52+ if err != nil {
53+ delayTillNextUpdate = time .Duration (0 )
54+ return
55+ }
56+ in = string (bin )
57+ return
3758}
3859
39- func fetchWithCache (url string , cacheFile string , refreshDelay time.Duration ) (in string , cached bool , fromBackup bool , delayTillNextUpdate time.Duration , err error ) {
40- var bin []byte
41- cached , fromBackup , usableCache , hotCache := false , false , false , false
42- delayTillNextUpdate = refreshDelay
43- fi , err := os .Stat (cacheFile )
44- var elapsed time.Duration
60+ func fetchWithCache (url string , cacheFile string ) (in string , cached bool , delayTillNextUpdate time.Duration , err error ) {
61+ cached = false
62+ in , delayTillNextUpdate , err = fetchFromCache (cacheFile )
4563 if err == nil {
46- usableCache = true
47- dlog .Debugf ("Cache file present for [%s]" , url )
48- elapsed = time .Since (fi .ModTime ())
49- if elapsed < refreshDelay && elapsed >= 0 {
50- hotCache = true
51- }
64+ dlog .Debugf ("Delay till next update: %v" , delayTillNextUpdate )
65+ cached = true
66+ return
67+ }
68+ var resp * http.Response
69+ dlog .Infof ("Loading source information from URL [%s]" , url )
70+ resp , err = http .Get (url )
71+ if err == nil && resp != nil && (resp .StatusCode < 200 || resp .StatusCode > 299 ) {
72+ err = fmt .Errorf ("Webserver returned code %d" , resp .StatusCode )
73+ return
74+ } else if err != nil {
75+ return
76+ } else if resp == nil {
77+ err = errors .New ("Webserver returned an error" )
78+ return
5279 }
53- if hotCache {
54- bin , err = fetchFromCache (cacheFile )
55- if err == nil {
56- dlog .Debugf ("Cache is still fresh for [%s]" , url )
57- cached = true
58- delayTillNextUpdate = refreshDelay - elapsed
59- }
60- }
61- if ! cached {
62- var resp * http.Response
63- dlog .Infof ("Loading source information from URL [%s]" , url )
64- resp , err = http .Get (url )
65- if err == nil && resp != nil && (resp .StatusCode < 200 || resp .StatusCode > 299 ) {
66- err = fmt .Errorf ("Webserver returned code %d" , resp .StatusCode )
67- }
68- if err != nil {
69- delayTillNextUpdate = time .Duration (0 )
70- if usableCache {
71- dlog .Debugf ("Falling back to cached version of [%s]" , url )
72- bin , err = fetchFromCache (cacheFile )
73- }
74- if err != nil {
75- return
76- }
77- fromBackup = true
78- } else {
79- bin , err = ioutil .ReadAll (resp .Body )
80- resp .Body .Close ()
81- if err != nil {
82- delayTillNextUpdate = time .Duration (0 )
83- if usableCache {
84- bin , err = fetchFromCache (cacheFile )
85- }
86- if err != nil {
87- return
88- }
89- fromBackup = true
90- }
91- }
80+ var bin []byte
81+ bin , err = ioutil .ReadAll (resp .Body )
82+ resp .Body .Close ()
83+ if err != nil {
84+ return
9285 }
9386 err = nil
9487 in = string (bin )
88+ delayTillNextUpdate = SourcesUpdateDelay
9589 return
9690}
9791
@@ -106,6 +100,7 @@ type URLToPrefetch struct {
106100}
107101
108102func NewSource (url string , minisignKeyStr string , cacheFile string , formatStr string , refreshDelay time.Duration ) (Source , []URLToPrefetch , error ) {
103+ _ = refreshDelay
109104 source := Source {url : url }
110105 if formatStr != "v1" {
111106 return source , []URLToPrefetch {}, fmt .Errorf ("Unsupported source format: [%s]" , formatStr )
@@ -115,23 +110,17 @@ func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr st
115110 if err != nil {
116111 return source , []URLToPrefetch {}, err
117112 }
113+ now := time .Now ()
114+ urlsToPrefetch := []URLToPrefetch {}
115+
118116 sigURL := url + ".minisig"
119- when := time .Now ()
120- urlsToPrefetch := []URLToPrefetch {
121- URLToPrefetch {url : url , cacheFile : cacheFile , when : when },
122- URLToPrefetch {url : sigURL , cacheFile : cacheFile , when : when },
123- }
124- in , cached , fromBackup , delayTillNextUpdate , err := fetchWithCache (url , cacheFile , refreshDelay )
125- if err != nil {
126- dlog .Debugf ("Scheduling [%s] for prefetch" , url )
127- return source , urlsToPrefetch , err
128- }
117+ in , cached , delayTillNextUpdate , err := fetchWithCache (url , cacheFile )
118+ urlsToPrefetch = append (urlsToPrefetch , URLToPrefetch {url : url , cacheFile : cacheFile , when : now .Add (delayTillNextUpdate )})
119+
129120 sigCacheFile := cacheFile + ".minisig"
130- sigStr , sigCached , sigFromBackup , sigDelayTillNextUpdate , err := fetchWithCache (sigURL , sigCacheFile , refreshDelay )
131- if err != nil {
132- dlog .Debugf ("Scheduling [%s] for prefetch" , sigURL )
133- return source , urlsToPrefetch , err
134- }
121+ sigStr , sigCached , sigDelayTillNextUpdate , err := fetchWithCache (sigURL , sigCacheFile )
122+ urlsToPrefetch = append (urlsToPrefetch , URLToPrefetch {url : sigURL , cacheFile : sigCacheFile , when : now .Add (sigDelayTillNextUpdate )})
123+
135124 signature , err := minisign .DecodeSignature (sigStr )
136125 if err != nil {
137126 os .Remove (cacheFile )
@@ -144,27 +133,18 @@ func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr st
144133 os .Remove (sigCacheFile )
145134 return source , urlsToPrefetch , err
146135 }
147- if ! cached && ! fromBackup {
136+ if ! cached {
148137 if err = AtomicFileWrite (cacheFile , []byte (in )); err != nil {
149- return source , urlsToPrefetch , err
138+ dlog . Warnf ( "%s: %s" , cacheFile , err )
150139 }
151140 }
152- if ! sigCached && ! fromBackup {
141+ if ! sigCached {
153142 if err = AtomicFileWrite (sigCacheFile , []byte (sigStr )); err != nil {
154- return source , urlsToPrefetch , err
143+ dlog . Warnf ( "%s: %s" , sigCacheFile , err )
155144 }
156145 }
157146 dlog .Noticef ("Source [%s] loaded" , url )
158147 source .in = in
159- if sigDelayTillNextUpdate < delayTillNextUpdate {
160- delayTillNextUpdate = sigDelayTillNextUpdate
161- }
162- when = time .Now ().Add (delayTillNextUpdate )
163- if ! fromBackup && ! sigFromBackup {
164- for i := range urlsToPrefetch {
165- urlsToPrefetch [i ].when = when
166- }
167- }
168148 return source , urlsToPrefetch , nil
169149}
170150
@@ -210,13 +190,10 @@ func (source *Source) Parse() ([]RegisteredServer, error) {
210190}
211191
212192func PrefetchSourceURL (urlToPrefetch * URLToPrefetch ) error {
213- _ , _ , fromBackup , _ , err := fetchWithCache (urlToPrefetch .url , urlToPrefetch .cacheFile , time .Duration (0 ))
214- if err != nil {
215- dlog .Debugf ("[%s]: %s" , urlToPrefetch .url , err )
216- return err
217- }
218- if ! fromBackup {
219- urlToPrefetch .when = urlToPrefetch .when .Add (24 * time .Hour )
193+ in , _ , delayTillNextUpdate , err := fetchWithCache (urlToPrefetch .url , urlToPrefetch .cacheFile )
194+ if err == nil {
195+ AtomicFileWrite (urlToPrefetch .cacheFile , []byte (in ))
220196 }
221- return nil
197+ urlToPrefetch .when = time .Now ().Add (delayTillNextUpdate )
198+ return err
222199}
0 commit comments