| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // package store -- главный тип плагина хранилища
- package store
- import (
- "fmt"
- "log"
- "sync"
- "github.com/syndtr/goleveldb/leveldb"
- "github.com/syndtr/goleveldb/leveldb/util"
- "wartank/pkg/components/safe_bool"
- "wartank/pkg/types"
- )
- const (
- стрХранилище = "Хранилище"
- )
- // Хранилище -- главный тип плагина хранилища
- type Хранилище struct {
- ядро types.ИЯдро
- path string // Путь к хранилищу
- isWork *safe_bool.БезопБул // Признак открытой базы
- бд *leveldb.DB // Объект хранилища
- block sync.Mutex // Блокировка для безопасности потоков
- }
- // НовХранилище -- возвращает новое хранилище
- func НовХранилище(ядро types.ИЯдро, path string) (*Хранилище, error) {
- { // Прдусловия
- if ядро == nil {
- return nil, fmt.Errorf("НовХранилище: ядро == nil")
- }
- if path == "" {
- return nil, fmt.Errorf("НовХранилище: path == nil")
- }
- }
- сам := &Хранилище{
- ядро: ядро,
- path: path,
- isWork: safe_bool.НовБезопБул(),
- }
- if err := сам.открыть(); err != nil {
- return nil, fmt.Errorf("НовХранилище: при открытии БД, err=\n\t%w", err)
- }
- if ош := ядро.Wg().Add(стрХранилище); ош != nil {
- return nil, fmt.Errorf("НовХранилище: при добавлении группы ожидания, ош=\n\t%v", ош)
- }
- _ = types.ИХранилище(сам)
- return сам, nil
- }
- // Уст -- добавляет в хранилище значение по ключу
- func (сам *Хранилище) Уст(ключ string, знач []byte) error {
- сам.block.Lock()
- defer сам.block.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 *Хранилище) Получ(key string) ([]byte, error) {
- sf.block.Lock()
- defer sf.block.Unlock()
- value, err := sf.бд.Get([]byte(key), 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.block.Lock()
- defer sf.block.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.block.Lock()
- defer sf.block.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 (сам *Хранилище) открыть() error {
- сам.block.Lock()
- defer сам.block.Unlock()
- бд, ош := leveldb.OpenFile(сам.path, nil)
- фнОткрыть := func() {
- сам.бд = бд
- сам.isWork.Уст()
- go сам.закрыть()
- }
- if ош == nil {
- фнОткрыть()
- return nil
- }
- log.Printf("Хранилище.открыть(): при открытии БД, ош=\n\t%v", ош)
- бд, ош = leveldb.RecoverFile(сам.path, nil)
- if ош != nil {
- return fmt.Errorf("Хранилище.открыть(): при попытке восстановлении БД, ош=\n\t%w", ош)
- }
- фнОткрыть()
- return nil
- }
- // закрыть -- закрывает хранилище по требованию
- func (sf *Хранилище) закрыть() {
- <-sf.ядро.Контекст().Done()
- sf.block.Lock()
- defer sf.block.Unlock()
- sf.isWork.Сброс()
- if err := sf.бд.Close(); err != nil {
- log.Printf("Хранилище.закрыть(): при закрытти БД, err=\n\t%v", err)
- return
- }
- ош := sf.ядро.Wg().Done(стрХранилище)
- if ош != nil {
- log.Printf("Хранилище.закрыть(): при удалении группы ожидания, ош=\n\t%v", ош)
- }
- }
|