|
@@ -3,8 +3,10 @@ package store
|
|
|
|
|
|
import (
|
|
import (
|
|
"fmt"
|
|
"fmt"
|
|
|
|
+ "log"
|
|
"os"
|
|
"os"
|
|
"strings"
|
|
"strings"
|
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
"github.com/syndtr/goleveldb/leveldb/util"
|
|
"github.com/syndtr/goleveldb/leveldb/util"
|
|
@@ -14,12 +16,19 @@ import (
|
|
|
|
|
|
// StoreDisk -- хранилище на диске
|
|
// StoreDisk -- хранилище на диске
|
|
type Store struct {
|
|
type Store struct {
|
|
- serv types.IService
|
|
|
|
- db *leveldb.DB
|
|
|
|
|
|
+ serv types.IService
|
|
|
|
+ db *leveldb.DB
|
|
|
|
+ isWork bool
|
|
|
|
+ block sync.RWMutex
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+var IsBad_ = false // Для тестов
|
|
|
|
+
|
|
// NewStore -- возвращает новое хранилище на диске
|
|
// NewStore -- возвращает новое хранилище на диске
|
|
func NewStore(serv types.IService) (*Store, error) {
|
|
func NewStore(serv types.IService) (*Store, error) {
|
|
|
|
+ if IsBad_ {
|
|
|
|
+ return nil, fmt.Errorf("NewStore(): IsBad_==true")
|
|
|
|
+ }
|
|
if serv == nil {
|
|
if serv == nil {
|
|
return nil, fmt.Errorf("NewStore(): IService==nil")
|
|
return nil, fmt.Errorf("NewStore(): IService==nil")
|
|
}
|
|
}
|
|
@@ -38,12 +47,24 @@ func NewStore(serv types.IService) (*Store, error) {
|
|
serv: serv,
|
|
serv: serv,
|
|
db: db,
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
+ sf.serv.Wg().Add(1)
|
|
|
|
+ sf.isWork = true
|
|
go sf.close()
|
|
go sf.close()
|
|
return sf, nil
|
|
return sf, nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Проверка на нерабочую схему
|
|
|
|
+func (sf *Store) isClosed() bool {
|
|
|
|
+ sf.block.RLock()
|
|
|
|
+ defer sf.block.RUnlock()
|
|
|
|
+ return !sf.isWork
|
|
|
|
+}
|
|
|
|
+
|
|
// Put -- размещает в хранилище ключ и значение
|
|
// Put -- размещает в хранилище ключ и значение
|
|
func (sf *Store) Put(key string, val []byte) error {
|
|
func (sf *Store) Put(key string, val []byte) error {
|
|
|
|
+ if sf.isClosed() {
|
|
|
|
+ return fmt.Errorf("Store.Put(): store is closed")
|
|
|
|
+ }
|
|
if key == "" {
|
|
if key == "" {
|
|
return fmt.Errorf("Store.Put(): key is empty")
|
|
return fmt.Errorf("Store.Put(): key is empty")
|
|
}
|
|
}
|
|
@@ -56,6 +77,9 @@ func (sf *Store) Put(key string, val []byte) error {
|
|
|
|
|
|
// Get -- возвращает значение ключа
|
|
// Get -- возвращает значение ключа
|
|
func (sf *Store) Get(key string) ([]byte, error) {
|
|
func (sf *Store) Get(key string) ([]byte, error) {
|
|
|
|
+ if sf.isClosed() {
|
|
|
|
+ return nil, fmt.Errorf("Store.Get(): store is closed")
|
|
|
|
+ }
|
|
val, err := sf.db.Get([]byte(key), nil)
|
|
val, err := sf.db.Get([]byte(key), nil)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Store.Get(): key=%q\terr=\n\t%w", key, err)
|
|
return nil, fmt.Errorf("Store.Get(): key=%q\terr=\n\t%w", key, err)
|
|
@@ -65,6 +89,9 @@ func (sf *Store) Get(key string) ([]byte, error) {
|
|
|
|
|
|
// Find -- ищет ключи по префиксу
|
|
// Find -- ищет ключи по префиксу
|
|
func (sf *Store) Find(prefixKey string) ([]string, error) {
|
|
func (sf *Store) Find(prefixKey string) ([]string, error) {
|
|
|
|
+ if sf.isClosed() {
|
|
|
|
+ return nil, fmt.Errorf("Store.Find(): store is closed")
|
|
|
|
+ }
|
|
lstKey := []string{}
|
|
lstKey := []string{}
|
|
iter := sf.db.NewIterator(util.BytesPrefix([]byte(prefixKey)), nil)
|
|
iter := sf.db.NewIterator(util.BytesPrefix([]byte(prefixKey)), nil)
|
|
for iter.Next() {
|
|
for iter.Next() {
|
|
@@ -81,6 +108,9 @@ func (sf *Store) Find(prefixKey string) ([]string, error) {
|
|
|
|
|
|
// Del -- удаление ключа из базы
|
|
// Del -- удаление ключа из базы
|
|
func (sf *Store) Del(key string) error {
|
|
func (sf *Store) Del(key string) error {
|
|
|
|
+ if sf.isClosed() {
|
|
|
|
+ return fmt.Errorf("Store.Del(): store is closed")
|
|
|
|
+ }
|
|
err := sf.db.Delete([]byte(key), nil)
|
|
err := sf.db.Delete([]byte(key), nil)
|
|
if err != nil {
|
|
if err != nil {
|
|
return fmt.Errorf("Store.Del(): key=%q\terr=\n\t%w", key, err)
|
|
return fmt.Errorf("Store.Del(): key=%q\terr=\n\t%w", key, err)
|
|
@@ -91,5 +121,15 @@ func (sf *Store) Del(key string) error {
|
|
// Ожидание закрытия приложения
|
|
// Ожидание закрытия приложения
|
|
func (sf *Store) close() {
|
|
func (sf *Store) close() {
|
|
<-sf.serv.Ctx().Done()
|
|
<-sf.serv.Ctx().Done()
|
|
- _ = sf.db.Close()
|
|
|
|
|
|
+ sf.block.Lock()
|
|
|
|
+ defer sf.block.Unlock()
|
|
|
|
+ if !sf.isWork {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sf.isWork = false
|
|
|
|
+ err := sf.db.Close()
|
|
|
|
+ if err != nil {
|
|
|
|
+ log.Printf("Store.close(): err=\n\t%v\n", err)
|
|
|
|
+ }
|
|
|
|
+ sf.serv.Wg().Done()
|
|
}
|
|
}
|