Further wip badger
This commit is contained in:
parent
700e04cc14
commit
a2d2c61f1e
@ -7,16 +7,11 @@ import (
|
||||
|
||||
var ErrIncorrectKey = errors.New("the key is incorrect")
|
||||
|
||||
func Has(db *badger.DB, key []byte) (has bool, err error) {
|
||||
err = db.View(func(txn *badger.Txn) error {
|
||||
func Has(db *badger.DB, key []byte) bool {
|
||||
return db.View(func(txn *badger.Txn) error {
|
||||
_, err := txn.Get(key)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
has = true
|
||||
return
|
||||
}) == nil
|
||||
}
|
||||
|
||||
func Put(db *badger.DB, key, value []byte) (err error) {
|
||||
@ -40,37 +35,10 @@ func Get(db *badger.DB, key []byte) (value []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetKeySuffix(txn *badger.Txn, keyPrefix []byte) (suffix []byte, err error) {
|
||||
iter := txn.NewIterator(badger.IteratorOptions{Prefix: keyPrefix})
|
||||
iter.Next()
|
||||
if !iter.Valid() {
|
||||
err = badger.ErrKeyNotFound
|
||||
func GetAndCopy(txn *badger.Txn, key []byte) (value []byte, err error) {
|
||||
item, err := txn.Get(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
suffix = iter.Item().Key()
|
||||
if len(suffix) <= len(keyPrefix)+1 {
|
||||
err = ErrIncorrectKey
|
||||
return
|
||||
}
|
||||
suffix = suffix[len(keyPrefix)+1:]
|
||||
return
|
||||
}
|
||||
|
||||
func GetKeySuffixAndValue(txn *badger.Txn, keyPrefix []byte) (suffix []byte, value []byte, err error) {
|
||||
iter := txn.NewIterator(badger.IteratorOptions{Prefix: keyPrefix})
|
||||
iter.Next()
|
||||
if !iter.Valid() {
|
||||
err = badger.ErrKeyNotFound
|
||||
return
|
||||
}
|
||||
|
||||
suffix = iter.Item().Key()
|
||||
if len(suffix) <= len(keyPrefix)+1 {
|
||||
err = ErrIncorrectKey
|
||||
return
|
||||
}
|
||||
suffix = suffix[len(keyPrefix)+1:]
|
||||
value, err = iter.Item().ValueCopy(value)
|
||||
return
|
||||
return item.ValueCopy(value)
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||
)
|
||||
|
||||
type aclKeys struct {
|
||||
@ -13,8 +13,8 @@ type aclKeys struct {
|
||||
func newACLKeys(spaceId string) aclKeys {
|
||||
return aclKeys{
|
||||
spaceId: spaceId,
|
||||
rootKey: joinStringsToBytes("space", spaceId, "a", "rootId"),
|
||||
headKey: joinStringsToBytes("space", spaceId, "a", "headId"),
|
||||
rootKey: storage.JoinStringsToBytes("space", spaceId, "a", "rootId"),
|
||||
headKey: storage.JoinStringsToBytes("space", spaceId, "a", "headId"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ func (a aclKeys) RootIdKey() []byte {
|
||||
}
|
||||
|
||||
func (a aclKeys) RawRecordKey(id string) []byte {
|
||||
return joinStringsToBytes("space", a.spaceId, "a", id)
|
||||
return storage.JoinStringsToBytes("space", a.spaceId, "a", id)
|
||||
}
|
||||
|
||||
type treeKeys struct {
|
||||
@ -41,8 +41,8 @@ func newTreeKeys(spaceId, id string) treeKeys {
|
||||
return treeKeys{
|
||||
id: id,
|
||||
spaceId: spaceId,
|
||||
headsKey: joinStringsToBytes("space", spaceId, "t", id, "heads"),
|
||||
rootKey: joinStringsToBytes("space", spaceId, "t", id),
|
||||
headsKey: storage.JoinStringsToBytes("space", spaceId, "t", id, "heads"),
|
||||
rootKey: storage.JoinStringsToBytes("space", spaceId, "t", "rootId", id),
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,37 +55,25 @@ func (t treeKeys) RootIdKey() []byte {
|
||||
}
|
||||
|
||||
func (t treeKeys) RawChangeKey(id string) []byte {
|
||||
return joinStringsToBytes("space", t.spaceId, "t", t.id, id)
|
||||
return storage.JoinStringsToBytes("space", t.spaceId, "t", t.id, id)
|
||||
}
|
||||
|
||||
type spaceKeys struct {
|
||||
headerKey []byte
|
||||
treePrefixKey []byte
|
||||
}
|
||||
|
||||
func newSpaceKeys(spaceId string) spaceKeys {
|
||||
return spaceKeys{headerKey: joinStringsToBytes("space", spaceId)}
|
||||
return spaceKeys{
|
||||
headerKey: storage.JoinStringsToBytes("space", spaceId),
|
||||
treePrefixKey: storage.JoinStringsToBytes("space", spaceId, "t", "rootId"),
|
||||
}
|
||||
}
|
||||
|
||||
func (s spaceKeys) HeaderKey() []byte {
|
||||
return s.headerKey
|
||||
}
|
||||
|
||||
func joinStringsToBytes(strs ...string) []byte {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
totalLen int
|
||||
)
|
||||
for _, s := range strs {
|
||||
totalLen += len(s)
|
||||
}
|
||||
// adding separators
|
||||
totalLen += len(strs) - 1
|
||||
b.Grow(totalLen)
|
||||
for idx, s := range strs {
|
||||
if idx > 0 {
|
||||
b.WriteString("/")
|
||||
}
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.Bytes()
|
||||
func (s spaceKeys) TreeRootPrefix() []byte {
|
||||
return s.treePrefixKey
|
||||
}
|
||||
|
||||
@ -20,23 +20,13 @@ type listStorage struct {
|
||||
|
||||
func newListStorage(spaceId string, db *badger.DB, txn *badger.Txn) (ls storage.ListStorage, err error) {
|
||||
keys := newACLKeys(spaceId)
|
||||
rootId, err := provider.GetKeySuffix(txn, keys.RootIdKey())
|
||||
rootId, err := provider.GetAndCopy(txn, keys.RootIdKey())
|
||||
if err != nil {
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = storage.ErrUnknownACLId
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
stringId := string(rootId)
|
||||
rootItem, err := txn.Get(keys.RawRecordKey(stringId))
|
||||
if err != nil {
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = storage.ErrUnknownACLId
|
||||
}
|
||||
return
|
||||
}
|
||||
var value []byte
|
||||
value, err = rootItem.ValueCopy(value)
|
||||
value, err := provider.GetAndCopy(txn, keys.RawRecordKey(stringId))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -57,19 +47,11 @@ func newListStorage(spaceId string, db *badger.DB, txn *badger.Txn) (ls storage.
|
||||
|
||||
func createListStorage(spaceId string, db *badger.DB, txn *badger.Txn, root *aclrecordproto.RawACLRecordWithId) (ls storage.ListStorage, err error) {
|
||||
keys := newACLKeys(spaceId)
|
||||
_, err = provider.GetKeySuffix(txn, keys.RootIdKey())
|
||||
if err != nil && err != badger.ErrKeyNotFound {
|
||||
return
|
||||
}
|
||||
_, err = provider.GetAndCopy(txn, keys.RootIdKey())
|
||||
if err != badger.ErrKeyNotFound {
|
||||
if err == nil {
|
||||
err = storage.ErrACLExists
|
||||
return
|
||||
return newListStorage(spaceId, db, txn)
|
||||
}
|
||||
aclRootKey := append(keys.RootIdKey(), '/')
|
||||
aclRootKey = append(aclRootKey, []byte(root.Id)...)
|
||||
|
||||
err = txn.Set(aclRootKey, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -82,6 +64,10 @@ func createListStorage(spaceId string, db *badger.DB, txn *badger.Txn, root *acl
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = txn.Set(keys.RootIdKey(), []byte(root.Id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ls = &listStorage{
|
||||
db: db,
|
||||
@ -110,12 +96,11 @@ func (l *listStorage) Head() (head string, err error) {
|
||||
}
|
||||
|
||||
func (l *listStorage) GetRawRecord(ctx context.Context, id string) (raw *aclrecordproto.RawACLRecordWithId, err error) {
|
||||
res, err := l.db.Get(l.keys.RawRecordKey(id))
|
||||
res, err := provider.Get(l.db, l.keys.RawRecordKey(id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if res == nil {
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = storage.ErrUnknownRecord
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,5 +112,5 @@ func (l *listStorage) GetRawRecord(ctx context.Context, id string) (raw *aclreco
|
||||
}
|
||||
|
||||
func (l *listStorage) AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error {
|
||||
return l.db.Put([]byte(rec.Id), rec.Payload)
|
||||
return provider.Put(l.db, []byte(rec.Id), rec.Payload)
|
||||
}
|
||||
|
||||
@ -1,23 +1,17 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"github.com/akrylysov/pogreb"
|
||||
provider "github.com/anytypeio/go-anytype-infrastructure-experiments/client/badgerprovider"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||
"github.com/dgraph-io/badger/v3"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var defPogrebOptions = &pogreb.Options{
|
||||
BackgroundCompactionInterval: time.Minute * 5,
|
||||
}
|
||||
|
||||
type spaceStorage struct {
|
||||
objDb *pogreb.DB
|
||||
spaceId string
|
||||
objDb *badger.DB
|
||||
keys spaceKeys
|
||||
aclStorage storage.ListStorage
|
||||
header *spacesyncproto.RawSpaceHeaderWithId
|
||||
@ -26,37 +20,19 @@ type spaceStorage struct {
|
||||
|
||||
func newSpaceStorage(objDb *badger.DB, spaceId string) (store spacestorage.SpaceStorage, err error) {
|
||||
keys := newSpaceKeys(spaceId)
|
||||
err = objDb.Update(func(txn *badger.Txn) error {
|
||||
header, err := txn.Get(keys.HeaderKey())
|
||||
err = objDb.View(func(txn *badger.Txn) error {
|
||||
header, err := provider.GetAndCopy(txn, keys.HeaderKey())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
})
|
||||
has, err := provider.Has(obj)
|
||||
aclStorage, err := newListStorage(spaceId, objDb, txn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
err = spacestorage.ErrSpaceStorageMissing
|
||||
return
|
||||
}
|
||||
|
||||
header, err := objDb.Get(keys.HeaderKey())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if header == nil {
|
||||
err = spacestorage.ErrSpaceStorageMissing
|
||||
return
|
||||
}
|
||||
|
||||
aclStorage, err := newListStorage(objDb)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
store = &spaceStorage{
|
||||
spaceId: spaceId,
|
||||
objDb: objDb,
|
||||
keys: keys,
|
||||
header: &spacesyncproto.RawSpaceHeaderWithId{
|
||||
@ -65,58 +41,45 @@ func newSpaceStorage(objDb *badger.DB, spaceId string) (store spacestorage.Space
|
||||
},
|
||||
aclStorage: aclStorage,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = spacesyncproto.ErrSpaceMissing
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreatePayload) (store spacestorage.SpaceStorage, err error) {
|
||||
dbPath := path.Join(rootPath, payload.SpaceHeaderWithId.Id)
|
||||
db, err := pogreb.Open(dbPath, defPogrebOptions)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
db.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
func createSpaceStorage(db *badger.DB, payload spacestorage.SpaceStorageCreatePayload) (store spacestorage.SpaceStorage, err error) {
|
||||
keys := newSpaceKeys(payload.SpaceHeaderWithId.Id)
|
||||
has, err := db.Has(keys.SpaceIdKey())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if has {
|
||||
if provider.Has(db, keys.HeaderKey()) {
|
||||
err = spacesyncproto.ErrSpaceExists
|
||||
return
|
||||
}
|
||||
|
||||
aclStorage, err := createListStorage(db, payload.RecWithId)
|
||||
err = db.Update(func(txn *badger.Txn) error {
|
||||
aclStorage, err := createListStorage(payload.SpaceHeaderWithId.Id, db, txn, payload.RecWithId)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Put(keys.HeaderKey(), payload.SpaceHeaderWithId.RawHeader)
|
||||
err = txn.Set(keys.HeaderKey(), payload.SpaceHeaderWithId.RawHeader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = db.Put(keys.SpaceIdKey(), []byte(payload.SpaceHeaderWithId.Id))
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
store = &spaceStorage{
|
||||
spaceId: payload.SpaceHeaderWithId.Id,
|
||||
objDb: db,
|
||||
keys: keys,
|
||||
aclStorage: aclStorage,
|
||||
header: payload.SpaceHeaderWithId,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (s *spaceStorage) TreeStorage(id string) (storage.TreeStorage, error) {
|
||||
return newTreeStorage(s.objDb, id)
|
||||
return newTreeStorage(s.objDb, s.spaceId, id)
|
||||
}
|
||||
|
||||
func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
|
||||
@ -124,7 +87,7 @@ func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayloa
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
||||
return createTreeStorage(s.objDb, payload)
|
||||
return createTreeStorage(s.objDb, s.spaceId, payload)
|
||||
}
|
||||
|
||||
func (s *spaceStorage) ACLStorage() (storage.ListStorage, error) {
|
||||
@ -136,21 +99,25 @@ func (s *spaceStorage) SpaceHeader() (header *spacesyncproto.RawSpaceHeaderWithI
|
||||
}
|
||||
|
||||
func (s *spaceStorage) StoredIds() (ids []string, err error) {
|
||||
index := s.objDb.Items()
|
||||
err = s.objDb.View(func(txn *badger.Txn) error {
|
||||
opts := badger.DefaultIteratorOptions
|
||||
opts.PrefetchValues = false
|
||||
opts.Prefix = s.keys.TreeRootPrefix()
|
||||
|
||||
key, val, err := index.Next()
|
||||
for err == nil {
|
||||
strKey := string(key)
|
||||
if isRootIdKey(strKey) {
|
||||
ids = append(ids, string(val))
|
||||
}
|
||||
key, val, err = index.Next()
|
||||
}
|
||||
it := txn.NewIterator(opts)
|
||||
defer it.Close()
|
||||
|
||||
if err != pogreb.ErrIterationDone {
|
||||
return
|
||||
for it.Rewind(); it.Valid(); it.Next() {
|
||||
item := it.Item()
|
||||
id := item.Key()
|
||||
if len(id) <= len(s.keys.TreeRootPrefix())+1 {
|
||||
continue
|
||||
}
|
||||
err = nil
|
||||
id = id[len(s.keys.TreeRootPrefix())+1:]
|
||||
ids = append(ids, string(id))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -26,9 +26,9 @@ func (s *storageService) Name() (name string) {
|
||||
}
|
||||
|
||||
func (s *storageService) SpaceStorage(id string) (storage.SpaceStorage, error) {
|
||||
return newSpaceStorage(s.rootPath, id)
|
||||
return newSpaceStorage(s.db, id)
|
||||
}
|
||||
|
||||
func (s *storageService) CreateSpaceStorage(payload storage.SpaceStorageCreatePayload) (storage.SpaceStorage, error) {
|
||||
return createSpaceStorage(s.rootPath, payload)
|
||||
return createSpaceStorage(s.db, payload)
|
||||
}
|
||||
|
||||
@ -1,57 +1,37 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/akrylysov/pogreb"
|
||||
provider "github.com/anytypeio/go-anytype-infrastructure-experiments/client/badgerprovider"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||
"strings"
|
||||
"github.com/dgraph-io/badger/v3"
|
||||
)
|
||||
|
||||
type treeStorage struct {
|
||||
db *pogreb.DB
|
||||
db *badger.DB
|
||||
keys treeKeys
|
||||
id string
|
||||
root *treechangeproto.RawTreeChangeWithId
|
||||
}
|
||||
|
||||
func newTreeStorage(db *pogreb.DB, treeId string) (ts storage.TreeStorage, err error) {
|
||||
keys := newTreeKeys(treeId)
|
||||
has, err := db.Has(keys.RootIdKey())
|
||||
func newTreeStorage(db *badger.DB, spaceId, treeId string) (ts storage.TreeStorage, err error) {
|
||||
keys := newTreeKeys(spaceId, treeId)
|
||||
err = db.View(func(txn *badger.Txn) error {
|
||||
_, err := txn.Get(keys.RootIdKey())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
err = storage.ErrUnknownTreeId
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
heads, err := db.Get(keys.HeadsKey())
|
||||
root, err := provider.GetAndCopy(txn, keys.RawChangeKey(treeId))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if heads == nil {
|
||||
err = storage.ErrUnknownTreeId
|
||||
return
|
||||
}
|
||||
|
||||
root, err := db.Get(keys.RawChangeKey(treeId))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if root == nil {
|
||||
err = storage.ErrUnknownTreeId
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
rootWithId := &treechangeproto.RawTreeChangeWithId{
|
||||
RawChange: root,
|
||||
Id: treeId,
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ts = &treeStorage{
|
||||
db: db,
|
||||
@ -59,42 +39,40 @@ func newTreeStorage(db *pogreb.DB, treeId string) (ts storage.TreeStorage, err e
|
||||
id: treeId,
|
||||
root: rootWithId,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func createTreeStorage(db *pogreb.DB, payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
|
||||
keys := newTreeKeys(payload.TreeId)
|
||||
has, err := db.Has(keys.RootIdKey())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if has {
|
||||
func createTreeStorage(db *badger.DB, spaceId string, payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
|
||||
keys := newTreeKeys(spaceId, payload.TreeId)
|
||||
if provider.Has(db, keys.RootIdKey()) {
|
||||
err = storage.ErrTreeExists
|
||||
return
|
||||
}
|
||||
|
||||
heads := createHeadsPayload(payload.Heads)
|
||||
err = db.Update(func(txn *badger.Txn) error {
|
||||
heads := storage.CreateHeadsPayload(payload.Heads)
|
||||
|
||||
for _, ch := range payload.Changes {
|
||||
err = db.Put(keys.RawChangeKey(ch.Id), ch.GetRawChange())
|
||||
err = txn.Set(keys.RawChangeKey(ch.Id), ch.GetRawChange())
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = db.Put(keys.RawChangeKey(payload.RootRawChange.Id), payload.RootRawChange.GetRawChange())
|
||||
err = txn.Set(keys.RawChangeKey(payload.RootRawChange.Id), payload.RootRawChange.GetRawChange())
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Put(keys.HeadsKey(), heads)
|
||||
err = txn.Set(keys.HeadsKey(), heads)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Put(keys.RootIdKey(), []byte(payload.RootRawChange.Id))
|
||||
err = txn.Set(keys.RootIdKey(), nil)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
ts = &treeStorage{
|
||||
@ -103,6 +81,8 @@ func createTreeStorage(db *pogreb.DB, payload storage.TreeStorageCreatePayload)
|
||||
id: payload.RootRawChange.Id,
|
||||
root: payload.RootRawChange,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -115,34 +95,33 @@ func (t *treeStorage) Root() (raw *treechangeproto.RawTreeChangeWithId, err erro
|
||||
}
|
||||
|
||||
func (t *treeStorage) Heads() (heads []string, err error) {
|
||||
headsBytes, err := t.db.Get(t.keys.HeadsKey())
|
||||
headsBytes, err := provider.Get(t.db, t.keys.HeadsKey())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if heads == nil {
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = storage.ErrUnknownTreeId
|
||||
}
|
||||
return
|
||||
}
|
||||
heads = parseHeads(headsBytes)
|
||||
heads = storage.ParseHeads(headsBytes)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *treeStorage) SetHeads(heads []string) (err error) {
|
||||
payload := createHeadsPayload(heads)
|
||||
return t.db.Put(t.keys.HeadsKey(), payload)
|
||||
payload := storage.CreateHeadsPayload(heads)
|
||||
return provider.Put(t.db, t.keys.HeadsKey(), payload)
|
||||
}
|
||||
|
||||
func (t *treeStorage) AddRawChange(change *treechangeproto.RawTreeChangeWithId) (err error) {
|
||||
return t.db.Put([]byte(change.Id), change.RawChange)
|
||||
return provider.Put(t.db, t.keys.RawChangeKey(change.Id), change.RawChange)
|
||||
}
|
||||
|
||||
func (t *treeStorage) GetRawChange(ctx context.Context, id string) (raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||
res, err := t.db.Get(t.keys.RawChangeKey(id))
|
||||
res, err := provider.Get(t.db, t.keys.RawChangeKey(id))
|
||||
if err != nil {
|
||||
return
|
||||
if err == badger.ErrKeyNotFound {
|
||||
err = storage.ErrUnknownTreeId
|
||||
}
|
||||
if res == nil {
|
||||
err = storage.ErrUnkownChange
|
||||
return
|
||||
}
|
||||
|
||||
raw = &treechangeproto.RawTreeChangeWithId{
|
||||
@ -153,29 +132,5 @@ func (t *treeStorage) GetRawChange(ctx context.Context, id string) (raw *treecha
|
||||
}
|
||||
|
||||
func (t *treeStorage) HasChange(ctx context.Context, id string) (bool, error) {
|
||||
return t.db.Has(t.keys.RawChangeKey(id))
|
||||
}
|
||||
|
||||
func parseHeads(headsPayload []byte) []string {
|
||||
return strings.Split(string(headsPayload), "/")
|
||||
}
|
||||
|
||||
func createHeadsPayload(heads []string) []byte {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
totalLen int
|
||||
)
|
||||
for _, s := range heads {
|
||||
totalLen += len(s)
|
||||
}
|
||||
// adding separators
|
||||
totalLen += len(heads) - 1
|
||||
b.Grow(totalLen)
|
||||
for idx, s := range heads {
|
||||
if idx > 0 {
|
||||
b.WriteString("/")
|
||||
}
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.Bytes()
|
||||
return provider.Has(t.db, t.keys.RawChangeKey(id)), nil
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -20,7 +20,7 @@ func (a aclKeys) RootIdKey() []byte {
|
||||
}
|
||||
|
||||
func (a aclKeys) RawRecordKey(id string) []byte {
|
||||
return joinStringsToBytes("a", id)
|
||||
return storage.JoinStringsToBytes("a", id)
|
||||
}
|
||||
|
||||
type treeKeys struct {
|
||||
@ -31,7 +31,7 @@ type treeKeys struct {
|
||||
func newTreeKeys(id string) treeKeys {
|
||||
return treeKeys{
|
||||
id: id,
|
||||
headsKey: joinStringsToBytes("t", id, "heads"),
|
||||
headsKey: storage.JoinStringsToBytes("t", id, "heads"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ func (t treeKeys) HeadsKey() []byte {
|
||||
}
|
||||
|
||||
func (t treeKeys) RawChangeKey(id string) []byte {
|
||||
return joinStringsToBytes("t", t.id, id)
|
||||
return storage.JoinStringsToBytes("t", t.id, id)
|
||||
}
|
||||
|
||||
type spaceKeys struct {
|
||||
@ -48,7 +48,7 @@ type spaceKeys struct {
|
||||
}
|
||||
|
||||
func newSpaceKeys(spaceId string) spaceKeys {
|
||||
return spaceKeys{headerKey: joinStringsToBytes("s", spaceId)}
|
||||
return spaceKeys{headerKey: storage.JoinStringsToBytes("s", spaceId)}
|
||||
}
|
||||
|
||||
var spaceIdKey = []byte("spaceId")
|
||||
@ -64,23 +64,3 @@ func (s spaceKeys) HeaderKey() []byte {
|
||||
func isRootIdKey(key string) bool {
|
||||
return strings.HasPrefix(key, "t/") && strings.HasSuffix(key, "rootId")
|
||||
}
|
||||
|
||||
func joinStringsToBytes(strs ...string) []byte {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
totalLen int
|
||||
)
|
||||
for _, s := range strs {
|
||||
totalLen += len(s)
|
||||
}
|
||||
// adding separators
|
||||
totalLen += len(strs) - 1
|
||||
b.Grow(totalLen)
|
||||
for idx, s := range strs {
|
||||
if idx > 0 {
|
||||
b.WriteString("/")
|
||||
}
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -55,8 +55,7 @@ func createListStorage(db *pogreb.DB, root *aclrecordproto.RawACLRecordWithId) (
|
||||
return
|
||||
}
|
||||
if has {
|
||||
err = storage.ErrACLExists
|
||||
return
|
||||
return newListStorage(db)
|
||||
}
|
||||
|
||||
err = db.Put(keys.HeadIdKey(), []byte(root.Id))
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/akrylysov/pogreb"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type treeStorage struct {
|
||||
@ -40,10 +38,6 @@ func newTreeStorage(db *pogreb.DB, treeId string) (ts storage.TreeStorage, err e
|
||||
RawChange: root,
|
||||
Id: treeId,
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ts = &treeStorage{
|
||||
db: db,
|
||||
keys: keys,
|
||||
@ -64,7 +58,7 @@ func createTreeStorage(db *pogreb.DB, payload storage.TreeStorageCreatePayload)
|
||||
return
|
||||
}
|
||||
|
||||
heads := createHeadsPayload(payload.Heads)
|
||||
heads := storage.CreateHeadsPayload(payload.Heads)
|
||||
|
||||
for _, ch := range payload.Changes {
|
||||
err = db.Put(keys.RawChangeKey(ch.Id), ch.GetRawChange())
|
||||
@ -109,17 +103,17 @@ func (t *treeStorage) Heads() (heads []string, err error) {
|
||||
err = storage.ErrUnknownTreeId
|
||||
return
|
||||
}
|
||||
heads = parseHeads(headsBytes)
|
||||
heads = storage.ParseHeads(headsBytes)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *treeStorage) SetHeads(heads []string) (err error) {
|
||||
payload := createHeadsPayload(heads)
|
||||
payload := storage.CreateHeadsPayload(heads)
|
||||
return t.db.Put(t.keys.HeadsKey(), payload)
|
||||
}
|
||||
|
||||
func (t *treeStorage) AddRawChange(change *treechangeproto.RawTreeChangeWithId) (err error) {
|
||||
return t.db.Put([]byte(change.Id), change.RawChange)
|
||||
return t.db.Put(t.keys.RawChangeKey(change.Id), change.RawChange)
|
||||
}
|
||||
|
||||
func (t *treeStorage) GetRawChange(ctx context.Context, id string) (raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||
@ -141,27 +135,3 @@ func (t *treeStorage) GetRawChange(ctx context.Context, id string) (raw *treecha
|
||||
func (t *treeStorage) HasChange(ctx context.Context, id string) (bool, error) {
|
||||
return t.db.Has(t.keys.RawChangeKey(id))
|
||||
}
|
||||
|
||||
func parseHeads(headsPayload []byte) []string {
|
||||
return strings.Split(string(headsPayload), "/")
|
||||
}
|
||||
|
||||
func createHeadsPayload(heads []string) []byte {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
totalLen int
|
||||
)
|
||||
for _, s := range heads {
|
||||
totalLen += len(s)
|
||||
}
|
||||
// adding separators
|
||||
totalLen += len(heads) - 1
|
||||
b.Grow(totalLen)
|
||||
for idx, s := range heads {
|
||||
if idx > 0 {
|
||||
b.WriteString("/")
|
||||
}
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
34
pkg/acl/storage/helpers.go
Normal file
34
pkg/acl/storage/helpers.go
Normal file
@ -0,0 +1,34 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseHeads(headsPayload []byte) []string {
|
||||
return strings.Split(string(headsPayload), "/")
|
||||
}
|
||||
|
||||
func CreateHeadsPayload(heads []string) []byte {
|
||||
return JoinStringsToBytes(heads...)
|
||||
}
|
||||
|
||||
func JoinStringsToBytes(strs ...string) []byte {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
totalLen int
|
||||
)
|
||||
for _, s := range strs {
|
||||
totalLen += len(s)
|
||||
}
|
||||
// adding separators
|
||||
totalLen += len(strs) - 1
|
||||
b.Grow(totalLen)
|
||||
for idx, s := range strs {
|
||||
if idx > 0 {
|
||||
b.WriteString("/")
|
||||
}
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user