store.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // package store -- главный тип плагина хранилища
  2. package store
  3. import (
  4. "fmt"
  5. "sync"
  6. "wartank/pkg/components/kernel/logger"
  7. "wartank/pkg/components/safe_bool"
  8. "wartank/pkg/types"
  9. "github.com/syndtr/goleveldb/leveldb"
  10. "github.com/syndtr/goleveldb/leveldb/util"
  11. )
  12. const (
  13. стрХранилище = "Хранилище"
  14. )
  15. // Хранилище -- главный тип плагина хранилища
  16. type Хранилище struct {
  17. ядро types.ИЯдро
  18. genm string // Путь к хранилищу
  19. isWork *safe_bool.БезопБул // Признак открытой базы
  20. бд *leveldb.DB // Объект хранилища
  21. блок sync.Mutex // Блокировка для безопасности потоков
  22. лог types.ИЛоггер
  23. }
  24. // НовХранилище -- возвращает новое хранилище
  25. func НовХранилище(ядро types.ИЯдро, путь string) (*Хранилище, error) {
  26. лог := logger.НовЛоггер("Хранилище")
  27. лог.Инфо("НовХранилище()\n")
  28. лог.Проверить(ядро != nil, "НовХранилище(): ИЯдро == nil\n")
  29. лог.Проверить(путь != "", "НовХранилище(): путь пустой\n")
  30. сам := &Хранилище{
  31. ядро: ядро,
  32. genm: путь,
  33. isWork: safe_bool.НовБезопБул(),
  34. лог: лог,
  35. }
  36. сам.открыть()
  37. if ош := ядро.Wg().Add(стрХранилище); ош != nil {
  38. return nil, fmt.Errorf("НовХранилище: при добавлении группы ожидания, ош=\n\t%v", ош)
  39. }
  40. _ = types.ИХранилище(сам)
  41. return сам, nil
  42. }
  43. // Уст -- добавляет в хранилище значение по ключу
  44. func (сам *Хранилище) Уст(ключ string, знач []byte) error {
  45. сам.блок.Lock()
  46. defer сам.блок.Unlock()
  47. if ключ == "" {
  48. return fmt.Errorf("Хранилище.Уст(): ключ пустой")
  49. }
  50. if знач == nil {
  51. return fmt.Errorf("Хранилище.Уст(): знач == nil")
  52. }
  53. if ош := сам.бд.Put([]byte(ключ), знач, nil); ош != nil {
  54. return fmt.Errorf("Хранилище.Уст(): при устнановке значения, ош=\n\t%w", ош)
  55. }
  56. return nil
  57. }
  58. // Получ -- возвращает значение по ключу
  59. func (sf *Хранилище) Получ(ключ string) ([]byte, error) {
  60. sf.блок.Lock()
  61. defer sf.блок.Unlock()
  62. value, err := sf.бд.Get([]byte(ключ), nil)
  63. if err != nil {
  64. return nil, fmt.Errorf("Хранилище.Get(): in get value, err=\n\t%w", err)
  65. }
  66. return value, nil
  67. }
  68. // Найти -- возвращает список ключей по префиксу
  69. func (sf *Хранилище) Найти(prefix string) ([]string, error) {
  70. sf.блок.Lock()
  71. defer sf.блок.Unlock()
  72. var keys []string
  73. slice := &util.Range{Start: []byte(prefix)}
  74. iter := sf.бд.NewIterator(slice, nil)
  75. for iter.Next() {
  76. key := string(iter.Key())
  77. keys = append(keys, key)
  78. }
  79. iter.Release()
  80. if err := iter.Error(); err != nil {
  81. return nil, fmt.Errorf("Хранилище.Find(): in find keys, err=\n\t%w", err)
  82. }
  83. return keys, nil
  84. }
  85. // Удалить -- удаляет значение по ключу
  86. func (sf *Хранилище) Удалить(key string) error {
  87. sf.блок.Lock()
  88. defer sf.блок.Unlock()
  89. if err := sf.бд.Delete([]byte(key), nil); err != nil {
  90. return fmt.Errorf("Хранилище.Del(): in delete key, err=\n\t%w", err)
  91. }
  92. return nil
  93. }
  94. // открыть -- открывает хранилище
  95. func (сам *Хранилище) открыть() {
  96. сам.блок.Lock()
  97. defer сам.блок.Unlock()
  98. бд, ош := leveldb.OpenFile(сам.genm, nil)
  99. фнОткрыть := func() {
  100. сам.бд = бд
  101. сам.isWork.Уст()
  102. go сам.закрыть()
  103. }
  104. if ош == nil {
  105. фнОткрыть()
  106. return
  107. }
  108. сам.лог.Внимание("Хранилище.открыть(): при открытии БД, ош=\n\t%v\n", ош)
  109. бд, ош = leveldb.RecoverFile(сам.genm, nil)
  110. сам.лог.Проверить(ош == nil, "Хранилище.открыть(): при восстановлении БД, ош=\n\t%v\n", ош)
  111. фнОткрыть()
  112. }
  113. // закрыть -- закрывает хранилище по требованию
  114. func (сам *Хранилище) закрыть() {
  115. <-сам.ядро.Контекст().Done()
  116. сам.блок.Lock()
  117. defer сам.блок.Unlock()
  118. сам.isWork.Сброс()
  119. err := сам.бд.Close()
  120. сам.лог.Проверить(err == nil, "Хранилище.закрыть(): при закрытии БД, err=\n\t%v\n", err)
  121. ош := сам.ядро.Wg().Done(стрХранилище)
  122. сам.лог.Проверить(ош == nil, "Хранилище.закрыть(): при удалении группы ожидания, ош=\n\t%v\n", ош)
  123. }