store_mem.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // package store_mem -- хранилище-кеш в памяти
  2. package store_mem
  3. import (
  4. "fmt"
  5. "sync"
  6. "git.p78su.freemyip.com/svi/gostore/internal/store_mem/mem_pool_record"
  7. "git.p78su.freemyip.com/svi/gostore/pkg/types"
  8. )
  9. // StoreMem -- хранилище-кеш в памяти
  10. type StoreMem struct {
  11. dict map[string]types.IMemRecord // Кеш в памяти с данными
  12. pool types.IMemPoolRecord // Пул доступных записей
  13. lifeTime types.ILifeTime // Счётчик жизни для очистки кеша
  14. block sync.Mutex
  15. cap int // Предельная ёмкость кеша
  16. }
  17. // NewStoreMem -- возвращает новое хранилище в памяти
  18. func NewStoreMem() (types.IStoreMem, error) {
  19. pool, err := mem_pool_record.NewMemPoolRecord()
  20. if err != nil {
  21. return nil, fmt.Errorf("NewStoreMem(): in create IMemPoolRecord, err=\n\t%w", err)
  22. }
  23. sf := &StoreMem{
  24. dict: map[string]types.IMemRecord{},
  25. pool: pool,
  26. cap: pool.Cap() - pool.Cap()/10,
  27. }
  28. return sf, nil
  29. }
  30. // Сбрасывает словарь по требованию
  31. func (sf *StoreMem) reset() {
  32. for _, rec := range sf.dict {
  33. sf.pool.Put(rec)
  34. }
  35. sf.dict = map[string]types.IMemRecord{}
  36. }
  37. // Del -- удаляет запись по ключу
  38. func (sf *StoreMem) Del(key string) {
  39. sf.block.Lock()
  40. defer sf.block.Unlock()
  41. rec := sf.dict[key]
  42. if rec == nil {
  43. return
  44. }
  45. delete(sf.dict, key)
  46. sf.pool.Put(rec)
  47. }
  48. // Put -- размещает запись в памяти
  49. func (sf *StoreMem) Put(key string, val []byte) error {
  50. sf.block.Lock()
  51. defer sf.block.Unlock()
  52. nextTime := sf.lifeTime.Next()
  53. if nextTime <= 0 {
  54. sf.reset()
  55. nextTime = sf.lifeTime.Next()
  56. }
  57. // Проверить что такая запись есть в памяти
  58. rec := sf.dict[key]
  59. if rec != nil {
  60. rec.Set(val, nextTime)
  61. return nil
  62. }
  63. // Такой записи нет, проверить что словарь не переполнен
  64. if len(sf.dict) > sf.cap {
  65. sf.clear()
  66. }
  67. rec = sf.pool.Get()
  68. rec.Set(val, nextTime)
  69. sf.dict[key] = rec
  70. return nil
  71. }
  72. // Снижает уровень заполнения словаря меньше 90% по требованию
  73. func (sf *StoreMem) clear() {
  74. nextTime := sf.lifeTime.Next()
  75. if nextTime <= 0 {
  76. sf.reset()
  77. nextTime = sf.lifeTime.Next()
  78. }
  79. nextTime -= sf.cap
  80. for key, rec := range sf.dict {
  81. if rec.IsOld(nextTime) {
  82. delete(sf.dict, key)
  83. }
  84. if len(sf.dict) < sf.cap {
  85. return
  86. }
  87. }
  88. }
  89. // Get -- возвращает хранимую запись (если есть)
  90. func (sf *StoreMem) Get(key string) ([]byte, error) {
  91. sf.block.Lock()
  92. defer sf.block.Unlock()
  93. rec := sf.dict[key]
  94. if rec == nil {
  95. return nil, fmt.Errorf("StoreMem.Get(): not found")
  96. }
  97. nextTime := sf.lifeTime.Next()
  98. if nextTime <= 0 {
  99. sf.reset()
  100. nextTime = sf.lifeTime.Next()
  101. }
  102. rec.Update(nextTime)
  103. return rec.Get(), nil
  104. }