store.go 4.8 KB

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