| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- // package store_mem -- хранилище-кеш в памяти
- package store_mem
- import (
- "fmt"
- "sync"
- "git.p78su.freemyip.com/svi/gostore/internal/store_mem/mem_pool_record"
- "git.p78su.freemyip.com/svi/gostore/pkg/types"
- )
- // StoreMem -- хранилище-кеш в памяти
- type StoreMem struct {
- dict map[string]types.IMemRecord // Кеш в памяти с данными
- pool types.IMemPoolRecord // Пул доступных записей
- lifeTime types.ILifeTime // Счётчик жизни для очистки кеша
- block sync.Mutex
- cap int // Предельная ёмкость кеша
- }
- // NewStoreMem -- возвращает новое хранилище в памяти
- func NewStoreMem() (types.IStoreMem, error) {
- pool, err := mem_pool_record.NewMemPoolRecord()
- if err != nil {
- return nil, fmt.Errorf("NewStoreMem(): in create IMemPoolRecord, err=\n\t%w", err)
- }
- sf := &StoreMem{
- dict: map[string]types.IMemRecord{},
- pool: pool,
- cap: pool.Cap() - pool.Cap()/10,
- }
- return sf, nil
- }
- // Сбрасывает словарь по требованию
- func (sf *StoreMem) reset() {
- for _, rec := range sf.dict {
- sf.pool.Put(rec)
- }
- sf.dict = map[string]types.IMemRecord{}
- }
- // Del -- удаляет запись по ключу
- func (sf *StoreMem) Del(key string) {
- sf.block.Lock()
- defer sf.block.Unlock()
- rec := sf.dict[key]
- if rec == nil {
- return
- }
- delete(sf.dict, key)
- sf.pool.Put(rec)
- }
- // Put -- размещает запись в памяти
- func (sf *StoreMem) Put(key string, val []byte) error {
- sf.block.Lock()
- defer sf.block.Unlock()
- nextTime := sf.lifeTime.Next()
- if nextTime <= 0 {
- sf.reset()
- nextTime = sf.lifeTime.Next()
- }
- // Проверить что такая запись есть в памяти
- rec := sf.dict[key]
- if rec != nil {
- rec.Set(val, nextTime)
- return nil
- }
- // Такой записи нет, проверить что словарь не переполнен
- if len(sf.dict) > sf.cap {
- sf.clear()
- }
- rec = sf.pool.Get()
- rec.Set(val, nextTime)
- sf.dict[key] = rec
- return nil
- }
- // Снижает уровень заполнения словаря меньше 90% по требованию
- func (sf *StoreMem) clear() {
- nextTime := sf.lifeTime.Next()
- if nextTime <= 0 {
- sf.reset()
- nextTime = sf.lifeTime.Next()
- }
- nextTime -= sf.cap
- for key, rec := range sf.dict {
- if rec.IsOld(nextTime) {
- delete(sf.dict, key)
- }
- if len(sf.dict) < sf.cap {
- return
- }
- }
- }
- // Get -- возвращает хранимую запись (если есть)
- func (sf *StoreMem) Get(key string) ([]byte, error) {
- sf.block.Lock()
- defer sf.block.Unlock()
- rec := sf.dict[key]
- if rec == nil {
- return nil, fmt.Errorf("StoreMem.Get(): not found")
- }
- nextTime := sf.lifeTime.Next()
- if nextTime <= 0 {
- sf.reset()
- nextTime = sf.lifeTime.Next()
- }
- rec.Update(nextTime)
- return rec.Get(), nil
- }
|