// package store -- хранилище на диске package store import ( "fmt" "os" "strings" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/util" "git.p78su.freemyip.com/svi/gostore/pkg/types" ) // StoreDisk -- хранилище на диске type Store struct { serv types.IService db *leveldb.DB } // NewStore -- возвращает новое хранилище на диске func NewStore(serv types.IService) (*Store, error) { if serv == nil { return nil, fmt.Errorf("NewStore(): IService==nil") } _ = os.MkdirAll("./store/db", 0750) db, err := leveldb.OpenFile("./store/db", nil) if err != nil { if !strings.Contains(err.Error(), "leveldb: manifest corrupted") { return nil, fmt.Errorf("NewStore(): in create IStoreDisk, err=\n\t%w", err) } db, err = leveldb.RecoverFile("./stor/db", nil) if err != nil { return nil, fmt.Errorf("NewStore(): in recovery DB, err=\n\t%w", err) } } sf := &Store{ serv: serv, db: db, } go sf.close() return sf, nil } // Put -- размещает в хранилище ключ и значение func (sf *Store) Put(key string, val []byte) error { if key == "" { return fmt.Errorf("Store.Put(): key is empty") } err := sf.db.Put([]byte(key), val, nil) if err != nil { return fmt.Errorf("Store.Put(): key=%q\terr=\n\t%w", key, err) } return nil } // Get -- возвращает значение ключа func (sf *Store) Get(key string) ([]byte, error) { val, err := sf.db.Get([]byte(key), nil) if err != nil { return nil, fmt.Errorf("Store.Get(): key=%q\terr=\n\t%w", key, err) } return val, nil } // Find -- ищет ключи по префиксу func (sf *Store) Find(prefixKey string) ([]string, error) { lstKey := []string{} iter := sf.db.NewIterator(util.BytesPrefix([]byte(prefixKey)), nil) for iter.Next() { key := iter.Key() lstKey = append(lstKey, string(key)) } iter.Release() err := iter.Error() if err != nil { return nil, fmt.Errorf("Store.Find(): preefixKey=%q\terr=\n\t%w", prefixKey, err) } return lstKey, nil } // Del -- удаление ключа из базы func (sf *Store) Del(key string) error { err := sf.db.Delete([]byte(key), nil) if err != nil { return fmt.Errorf("Store.Del(): key=%q\terr=\n\t%w", key, err) } return nil } // Ожидание закрытия приложения func (sf *Store) close() { <-sf.serv.Ctx().Done() _ = sf.db.Close() }