// Copyright 2023 PingCAP, Inc. // // 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 mapcache import ( "github.com/pingcap/tidb/pkg/statistics" "github.com/pingcap/tidb/pkg/statistics/handle/cache/internal" ) type cacheItem struct { value *statistics.Table key int64 cost int64 } func (c cacheItem) copy() cacheItem { return cacheItem{ key: c.key, value: c.value, cost: c.cost, } } // MapCache is a cache based on map. type MapCache struct { tables map[int64]cacheItem memUsage int64 } // NewMapCache creates a new map cache. func NewMapCache() *MapCache { return &MapCache{ tables: make(map[int64]cacheItem), memUsage: 0, } } // Get implements StatsCacheInner func (m *MapCache) Get(k int64) (*statistics.Table, bool) { v, ok := m.tables[k] return v.value, ok } // Put implements StatsCacheInner func (m *MapCache) Put(k int64, v *statistics.Table) bool { item, ok := m.tables[k] if ok { oldCost := item.cost newCost := v.MemoryUsage().TotalMemUsage item.value = v item.cost = newCost m.tables[k] = item m.memUsage += newCost - oldCost return true } cost := v.MemoryUsage().TotalMemUsage item = cacheItem{ key: k, value: v, cost: cost, } m.tables[k] = item m.memUsage += cost return true } // Del implements StatsCacheInner func (m *MapCache) Del(k int64) { item, ok := m.tables[k] if !ok { return } delete(m.tables, k) m.memUsage -= item.cost } // Cost implements StatsCacheInner func (m *MapCache) Cost() int64 { return m.memUsage } // Keys implements StatsCacheInner func (m *MapCache) Keys() []int64 { ks := make([]int64, 0, len(m.tables)) for k := range m.tables { ks = append(ks, k) } return ks } // Values implements StatsCacheInner func (m *MapCache) Values() []*statistics.Table { vs := make([]*statistics.Table, 0, len(m.tables)) for _, v := range m.tables { vs = append(vs, v.value) } return vs } // Len implements StatsCacheInner func (m *MapCache) Len() int { return len(m.tables) } // Copy implements StatsCacheInner func (m *MapCache) Copy() internal.StatsCacheInner { newM := &MapCache{ tables: make(map[int64]cacheItem, len(m.tables)), memUsage: m.memUsage, } for k, v := range m.tables { newM.tables[k] = v.copy() } return newM } // SetCapacity implements StatsCacheInner func (*MapCache) SetCapacity(int64) {} // Close implements StatsCacheInner func (*MapCache) Close() {} // TriggerEvict implements statsCacheInner func (*MapCache) TriggerEvict() {}