From 8b45d698c2e80cec45882a7afa87b619cef069e5 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Sun, 16 Oct 2022 16:41:01 +0200 Subject: [PATCH] Further wip badger --- client/badgerprovider/helpers.go | 46 ++------ client/storage/keys.go | 42 +++---- client/storage/liststorage.go | 49 +++------ client/storage/spacestorage.go | 155 +++++++++++--------------- client/storage/storageservice.go | 4 +- client/storage/treestorage.go | 183 ++++++++++++------------------- node/storage/keys.go | 30 +---- node/storage/liststorage.go | 3 +- node/storage/treestorage.go | 38 +------ pkg/acl/storage/helpers.go | 34 ++++++ 10 files changed, 215 insertions(+), 369 deletions(-) create mode 100644 pkg/acl/storage/helpers.go diff --git a/client/badgerprovider/helpers.go b/client/badgerprovider/helpers.go index 96ed8acf..afaf5da4 100644 --- a/client/badgerprovider/helpers.go +++ b/client/badgerprovider/helpers.go @@ -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) } diff --git a/client/storage/keys.go b/client/storage/keys.go index 5ee5958f..08749a89 100644 --- a/client/storage/keys.go +++ b/client/storage/keys.go @@ -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 + 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 } diff --git a/client/storage/liststorage.go b/client/storage/liststorage.go index 30910d65..edb9a17d 100644 --- a/client/storage/liststorage.go +++ b/client/storage/liststorage.go @@ -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 - } - if err == nil { - err = storage.ErrACLExists - return - } - aclRootKey := append(keys.RootIdKey(), '/') - aclRootKey = append(aclRootKey, []byte(root.Id)...) - - err = txn.Set(aclRootKey, nil) - if err != nil { + _, err = provider.GetAndCopy(txn, keys.RootIdKey()) + if err != badger.ErrKeyNotFound { + if err == nil { + return newListStorage(spaceId, db, txn) + } 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 { - err = storage.ErrUnknownRecord + 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) } diff --git a/client/storage/spacestorage.go b/client/storage/spacestorage.go index 1affdc14..5fb03f72 100644 --- a/client/storage/spacestorage.go +++ b/client/storage/spacestorage.go @@ -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,97 +20,66 @@ 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 } + aclStorage, err := newListStorage(spaceId, objDb, txn) + if err != nil { + return err + } + + store = &spaceStorage{ + spaceId: spaceId, + objDb: objDb, + keys: keys, + header: &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: header, + Id: spaceId, + }, + aclStorage: aclStorage, + } + return nil }) - has, err := provider.Has(obj) - 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 - } - - store = &spaceStorage{ - objDb: objDb, - keys: keys, - header: &spacesyncproto.RawSpaceHeaderWithId{ - RawHeader: header, - Id: spaceId, - }, - aclStorage: aclStorage, + 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 } + err = db.Update(func(txn *badger.Txn) error { + aclStorage, err := createListStorage(payload.SpaceHeaderWithId.Id, db, txn, payload.RecWithId) + if err != nil { + return err + } - aclStorage, err := createListStorage(db, payload.RecWithId) - if err != nil { - return - } + err = txn.Set(keys.HeaderKey(), payload.SpaceHeaderWithId.RawHeader) + if err != nil { + return err + } - err = db.Put(keys.HeaderKey(), payload.SpaceHeaderWithId.RawHeader) - if err != nil { - return - } - - err = db.Put(keys.SpaceIdKey(), []byte(payload.SpaceHeaderWithId.Id)) - if err != nil { - return - } - - store = &spaceStorage{ - objDb: db, - keys: keys, - aclStorage: aclStorage, - header: payload.SpaceHeaderWithId, - } + 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)) + it := txn.NewIterator(opts) + defer it.Close() + + for it.Rewind(); it.Valid(); it.Next() { + item := it.Item() + id := item.Key() + if len(id) <= len(s.keys.TreeRootPrefix())+1 { + continue + } + id = id[len(s.keys.TreeRootPrefix())+1:] + ids = append(ids, string(id)) } - key, val, err = index.Next() - } - - if err != pogreb.ErrIterationDone { - return - } - err = nil + return nil + }) return } diff --git a/client/storage/storageservice.go b/client/storage/storageservice.go index ba9de309..0cc9250e 100644 --- a/client/storage/storageservice.go +++ b/client/storage/storageservice.go @@ -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) } diff --git a/client/storage/treestorage.go b/client/storage/treestorage.go index 6c6c0d57..aea492ac 100644 --- a/client/storage/treestorage.go +++ b/client/storage/treestorage.go @@ -1,108 +1,88 @@ 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()) - if err != nil { - return - } - if !has { - err = storage.ErrUnknownTreeId - return - } +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 err + } - heads, err := db.Get(keys.HeadsKey()) - if err != nil { - return - } - if heads == nil { - err = storage.ErrUnknownTreeId - return - } + root, err := provider.GetAndCopy(txn, keys.RawChangeKey(treeId)) + if err != nil { + return err + } - root, err := db.Get(keys.RawChangeKey(treeId)) - if err != nil { - return - } - if root == nil { - err = storage.ErrUnknownTreeId - return - } + rootWithId := &treechangeproto.RawTreeChangeWithId{ + RawChange: root, + Id: treeId, + } - rootWithId := &treechangeproto.RawTreeChangeWithId{ - RawChange: root, - Id: treeId, - } - if err != nil { - return - } - - ts = &treeStorage{ - db: db, - keys: keys, - id: treeId, - root: rootWithId, - } + ts = &treeStorage{ + db: db, + keys: keys, + 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 } + err = db.Update(func(txn *badger.Txn) error { + heads := storage.CreateHeadsPayload(payload.Heads) - heads := createHeadsPayload(payload.Heads) - - for _, ch := range payload.Changes { - err = db.Put(keys.RawChangeKey(ch.Id), ch.GetRawChange()) - if err != nil { - return + for _, ch := range payload.Changes { + err = txn.Set(keys.RawChangeKey(ch.Id), ch.GetRawChange()) + if err != nil { + return err + } } - } - err = db.Put(keys.RawChangeKey(payload.RootRawChange.Id), payload.RootRawChange.GetRawChange()) - if err != nil { - return - } + err = txn.Set(keys.RawChangeKey(payload.RootRawChange.Id), payload.RootRawChange.GetRawChange()) + if err != nil { + return err + } - err = db.Put(keys.HeadsKey(), heads) - if err != nil { - return - } + err = txn.Set(keys.HeadsKey(), heads) + if err != nil { + return err + } - err = db.Put(keys.RootIdKey(), []byte(payload.RootRawChange.Id)) - if err != nil { - return - } + err = txn.Set(keys.RootIdKey(), nil) + if err != nil { + return err + } - ts = &treeStorage{ - db: db, - keys: keys, - id: payload.RootRawChange.Id, - root: payload.RootRawChange, - } + ts = &treeStorage{ + db: db, + keys: keys, + id: payload.RootRawChange.Id, + root: payload.RootRawChange, + } + return nil + }) return } @@ -115,35 +95,34 @@ 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 { + if err == badger.ErrKeyNotFound { + err = storage.ErrUnknownTreeId + } return } - if heads == nil { - 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 { + if err == badger.ErrKeyNotFound { + err = storage.ErrUnknownTreeId + } return } - if res == nil { - err = storage.ErrUnkownChange - } raw = &treechangeproto.RawTreeChangeWithId{ RawChange: res, @@ -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 } diff --git a/node/storage/keys.go b/node/storage/keys.go index 7840334e..fe12046a 100644 --- a/node/storage/keys.go +++ b/node/storage/keys.go @@ -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() -} diff --git a/node/storage/liststorage.go b/node/storage/liststorage.go index e4d99add..966f3fe0 100644 --- a/node/storage/liststorage.go +++ b/node/storage/liststorage.go @@ -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)) diff --git a/node/storage/treestorage.go b/node/storage/treestorage.go index a1253492..f600b6a2 100644 --- a/node/storage/treestorage.go +++ b/node/storage/treestorage.go @@ -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() -} diff --git a/pkg/acl/storage/helpers.go b/pkg/acl/storage/helpers.go new file mode 100644 index 00000000..7796a15f --- /dev/null +++ b/pkg/acl/storage/helpers.go @@ -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() +}