package sessionresolver // // Persistent on-disk state // import ( "errors" "sort" ) // storekey is the key used by the key value store to store // the state required by this package. const storekey = "sessionresolver.state" // resolverinfo contains info about a resolver. type resolverinfo struct { // URL is the URL of a resolver. URL string // Score is the score of a resolver. Score float64 } // ErrNilKVStore indicates that the KVStore is nil. var ErrNilKVStore = errors.New("sessionresolver: kvstore is nil") // readstate reads the resolver state from disk func (r *Resolver) readstate() ([]*resolverinfo, error) { if r.KVStore == nil { return nil, ErrNilKVStore } data, err := r.KVStore.Get(storekey) if err != nil { return nil, err } var ri []*resolverinfo if err := r.codec().Decode(data, &ri); err != nil { return nil, err } return ri, nil } // errNoEntries indicates that no entry remained after we pruned // all the available entries in readstateandprune. var errNoEntries = errors.New("sessionresolver: no available entries") // readstateandprune reads the state from disk and removes all the // entries that we don't actually support. func (r *Resolver) readstateandprune() ([]*resolverinfo, error) { ri, err := r.readstate() if err != nil { return nil, err } var out []*resolverinfo for _, e := range ri { if _, found := allbyurl[e.URL]; !found { continue // we don't support this specific entry } out = append(out, e) } if len(out) <= 0 { return nil, errNoEntries } return out, nil } // sortstate sorts the state by descending score func sortstate(ri []*resolverinfo) { sort.SliceStable(ri, func(i, j int) bool { return ri[i].Score >= ri[j].Score }) } // readstatedefault reads the state from disk and merges the state // so that all supported entries are represented. func (r *Resolver) readstatedefault() []*resolverinfo { ri, _ := r.readstateandprune() here := make(map[string]bool) for _, e := range ri { here[e.URL] = true // record what we already have } for _, e := range allmakers { if _, found := here[e.url]; found { continue // already here so no need to add } ri = append(ri, &resolverinfo{ URL: e.url, Score: e.score, }) } sortstate(ri) return ri } // writestate writes the state to the kvstore. func (r *Resolver) writestate(ri []*resolverinfo) error { if r.KVStore == nil { return ErrNilKVStore } data, err := r.codec().Encode(ri) if err != nil { return err } return r.KVStore.Set(storekey, data) }