/* * * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package grpc import ( "container/list" ) type linkedMapKVPair struct { key string value *stickyStoreEntry } // linkedMap is an implementation of a map that supports removing the oldest // entry. // // linkedMap is NOT thread safe. // // It's for use of stickiness only! type linkedMap struct { m map[string]*list.Element l *list.List // Head of the list is the oldest element. } // newLinkedMap returns a new LinkedMap. func newLinkedMap() *linkedMap { return &linkedMap{ m: make(map[string]*list.Element), l: list.New(), } } // put adds entry (key, value) to the map. Existing key will be overridden. func (m *linkedMap) put(key string, value *stickyStoreEntry) { if oldE, ok := m.m[key]; ok { // Remove existing entry. m.l.Remove(oldE) } e := m.l.PushBack(&linkedMapKVPair{key: key, value: value}) m.m[key] = e } // get returns the value of the given key. func (m *linkedMap) get(key string) (*stickyStoreEntry, bool) { e, ok := m.m[key] if !ok { return nil, false } m.l.MoveToBack(e) return e.Value.(*linkedMapKVPair).value, true } // remove removes key from the map, and returns the value. The map is not // modified if key is not in the map. func (m *linkedMap) remove(key string) (*stickyStoreEntry, bool) { e, ok := m.m[key] if !ok { return nil, false } delete(m.m, key) m.l.Remove(e) return e.Value.(*linkedMapKVPair).value, true } // len returns the len of the map. func (m *linkedMap) len() int { return len(m.m) } // clear removes all elements from the map. func (m *linkedMap) clear() { m.m = make(map[string]*list.Element) m.l = list.New() } // removeOldest removes the oldest key from the map. func (m *linkedMap) removeOldest() { e := m.l.Front() m.l.Remove(e) delete(m.m, e.Value.(*linkedMapKVPair).key) }