| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- // package store -- главный тип плагина хранилища
- package store
- import (
- "fmt"
- "sync"
- "wartank/pkg/components/kernel/logger"
- "wartank/pkg/components/safe_bool"
- "wartank/pkg/types"
- "github.com/syndtr/goleveldb/leveldb"
- "github.com/syndtr/goleveldb/leveldb/util"
- )
- const (
- стрХранилище = "Хранилище"
- )
- // Хранилище -- главный тип плагина хранилища
- type Хранилище struct {
- ядро types.ИЯдро
- genm string // Путь к хранилищу
- isWork *safe_bool.БезопБул // Признак открытой базы
- бд *leveldb.DB // Объект хранилища
- блок sync.Mutex // Блокировка для безопасности потоков
- лог types.ИЛоггер
- }
- // НовХранилище -- возвращает новое хранилище
- func НовХранилище(ядро types.ИЯдро, путь string) (*Хранилище, error) {
- лог := logger.НовЛоггер("Хранилище")
- лог.Инфо("НовХранилище()\n")
- лог.Проверить(ядро != nil, "НовХранилище(): ИЯдро == nil\n")
- лог.Проверить(путь != "", "НовХранилище(): путь пустой\n")
- сам := &Хранилище{
- ядро: ядро,
- genm: путь,
- isWork: safe_bool.НовБезопБул(),
- лог: лог,
- }
- сам.открыть()
- if ош := ядро.Wg().Add(стрХранилище); ош != nil {
- return nil, fmt.Errorf("НовХранилище: при добавлении группы ожидания, ош=\n\t%v", ош)
- }
- _ = types.ИХранилище(сам)
- return сам, nil
- }
- // Уст -- добавляет в хранилище значение по ключу
- func (сам *Хранилище) Уст(ключ string, знач []byte) error {
- сам.блок.Lock()
- defer сам.блок.Unlock()
- if ключ == "" {
- return fmt.Errorf("Хранилище.Уст(): ключ пустой")
- }
- if знач == nil {
- return fmt.Errorf("Хранилище.Уст(): знач == nil")
- }
- if ош := сам.бд.Put([]byte(ключ), знач, nil); ош != nil {
- return fmt.Errorf("Хранилище.Уст(): при устнановке значения, ош=\n\t%w", ош)
- }
- return nil
- }
- // Получ -- возвращает значение по ключу
- func (sf *Хранилище) Получ(ключ string) ([]byte, error) {
- sf.блок.Lock()
- defer sf.блок.Unlock()
- value, err := sf.бд.Get([]byte(ключ), nil)
- if err != nil {
- return nil, fmt.Errorf("Хранилище.Get(): in get value, err=\n\t%w", err)
- }
- return value, nil
- }
- // Найти -- возвращает список ключей по префиксу
- func (sf *Хранилище) Найти(prefix string) ([]string, error) {
- sf.блок.Lock()
- defer sf.блок.Unlock()
- var keys []string
- slice := &util.Range{Start: []byte(prefix)}
- iter := sf.бд.NewIterator(slice, nil)
- for iter.Next() {
- key := string(iter.Key())
- keys = append(keys, key)
- }
- iter.Release()
- if err := iter.Error(); err != nil {
- return nil, fmt.Errorf("Хранилище.Find(): in find keys, err=\n\t%w", err)
- }
- return keys, nil
- }
- // Удалить -- удаляет значение по ключу
- func (sf *Хранилище) Удалить(key string) error {
- sf.блок.Lock()
- defer sf.блок.Unlock()
- if err := sf.бд.Delete([]byte(key), nil); err != nil {
- return fmt.Errorf("Хранилище.Del(): in delete key, err=\n\t%w", err)
- }
- return nil
- }
- // открыть -- открывает хранилище
- func (сам *Хранилище) открыть() {
- сам.блок.Lock()
- defer сам.блок.Unlock()
- бд, ош := leveldb.OpenFile(сам.genm, nil)
- фнОткрыть := func() {
- сам.бд = бд
- сам.isWork.Уст()
- go сам.закрыть()
- }
- if ош == nil {
- фнОткрыть()
- return
- }
- сам.лог.Внимание("Хранилище.открыть(): при открытии БД, ош=\n\t%v\n", ош)
- бд, ош = leveldb.RecoverFile(сам.genm, nil)
- сам.лог.Проверить(ош == nil, "Хранилище.открыть(): при восстановлении БД, ош=\n\t%v\n", ош)
- фнОткрыть()
- }
- // закрыть -- закрывает хранилище по требованию
- func (сам *Хранилище) закрыть() {
- <-сам.ядро.Контекст().Done()
- сам.блок.Lock()
- defer сам.блок.Unlock()
- сам.isWork.Сброс()
- err := сам.бд.Close()
- сам.лог.Проверить(err == nil, "Хранилище.закрыть(): при закрытии БД, err=\n\t%v\n", err)
- ош := сам.ядро.Wg().Done(стрХранилище)
- сам.лог.Проверить(ош == nil, "Хранилище.закрыть(): при удалении группы ожидания, ош=\n\t%v\n", ош)
- }
|