store_mem.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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.IMemStore, 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. // Put -- размещает запись в памяти
  38. func (sf *StoreMem) Put(key string, val []byte) {
  39. sf.block.Lock()
  40. defer sf.block.Unlock()
  41. nextTime := sf.lifeTime.Next()
  42. if nextTime <= 0 {
  43. sf.reset()
  44. nextTime = sf.lifeTime.Next()
  45. }
  46. // Проверить что такая запись есть в памяти
  47. rec := sf.dict[key]
  48. if rec != nil {
  49. rec.Set(val, nextTime)
  50. return
  51. }
  52. // Такой записи нет, проверить что словарь не переполнен
  53. if len(sf.dict) > sf.cap {
  54. sf.clear()
  55. }
  56. rec = sf.pool.Get()
  57. rec.Set(val, nextTime)
  58. sf.dict[key] = rec
  59. }
  60. // Снижает уровень заполнения словаря меньше 90% по требованию
  61. func (sf *StoreMem) clear() {
  62. nextTime := sf.lifeTime.Next()
  63. if nextTime <= 0 {
  64. sf.reset()
  65. nextTime = sf.lifeTime.Next()
  66. }
  67. nextTime -= sf.cap
  68. for key, rec := range sf.dict {
  69. if rec.IsOld(nextTime) {
  70. delete(sf.dict, key)
  71. }
  72. if len(sf.dict) < sf.cap {
  73. return
  74. }
  75. }
  76. }
  77. // Get -- возвращает хранимую запись (если есть)
  78. func (sf *StoreMem) Get(key string) []byte {
  79. sf.block.Lock()
  80. defer sf.block.Unlock()
  81. rec := sf.dict[key]
  82. if rec == nil {
  83. return nil
  84. }
  85. nextTime := sf.lifeTime.Next()
  86. if nextTime <= 0 {
  87. sf.reset()
  88. nextTime = sf.lifeTime.Next()
  89. }
  90. rec.Update(nextTime)
  91. return rec.Get()
  92. }