forked from TrueCloudLab/frostfs-s3-gw
128 lines
3.3 KiB
Go
128 lines
3.3 KiB
Go
package contract
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"sync"
|
|
|
|
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
)
|
|
|
|
type InMemoryContract struct {
|
|
iamChains *syncedMap
|
|
containerChains *syncedMap
|
|
namespaceChains *syncedMap
|
|
}
|
|
|
|
type syncedMap struct {
|
|
mu sync.RWMutex
|
|
data map[string][]byte
|
|
}
|
|
|
|
var _ policy.Contract = (*InMemoryContract)(nil)
|
|
|
|
var ErrChainNotFound = errors.New("chain not found")
|
|
|
|
// NewInMemoryContract creates new inmemory Policy contract wrapper.
|
|
func NewInMemoryContract() *InMemoryContract {
|
|
return &InMemoryContract{
|
|
iamChains: &syncedMap{data: map[string][]byte{}},
|
|
containerChains: &syncedMap{data: map[string][]byte{}},
|
|
namespaceChains: &syncedMap{data: map[string][]byte{}},
|
|
}
|
|
}
|
|
|
|
func (c *InMemoryContract) AddChain(kind policycontract.Kind, entity string, name []byte, chain []byte) (util.Uint256, uint32, error) {
|
|
syncMap := c.getMap(kind)
|
|
syncMap.mu.Lock()
|
|
syncMap.data[entity+string(name)] = chain
|
|
syncMap.mu.Unlock()
|
|
|
|
return util.Uint256{}, 0, nil
|
|
}
|
|
|
|
func (c *InMemoryContract) GetChain(kind policycontract.Kind, entity string, name []byte) ([]byte, error) {
|
|
syncMap := c.getMap(kind)
|
|
syncMap.mu.RLock()
|
|
defer syncMap.mu.RUnlock()
|
|
|
|
val, ok := syncMap.data[entity+string(name)]
|
|
if !ok {
|
|
return nil, ErrChainNotFound
|
|
}
|
|
return val, nil
|
|
}
|
|
|
|
func (c *InMemoryContract) RemoveChain(kind policycontract.Kind, entity string, name []byte) (util.Uint256, uint32, error) {
|
|
syncMap := c.getMap(kind)
|
|
syncMap.mu.Lock()
|
|
delete(syncMap.data, entity+string(name))
|
|
syncMap.mu.Unlock()
|
|
|
|
return util.Uint256{}, 0, nil
|
|
}
|
|
|
|
func (c *InMemoryContract) ListChains(kind policycontract.Kind, entity string, name []byte) ([][]byte, error) {
|
|
syncMap := c.getMap(kind)
|
|
syncMap.mu.RLock()
|
|
defer syncMap.mu.RUnlock()
|
|
|
|
var res [][]byte
|
|
for key, val := range syncMap.data {
|
|
if strings.HasPrefix(key, entity+string(name)) {
|
|
res = append(res, val)
|
|
}
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (c *InMemoryContract) Wait(_ util.Uint256, _ uint32, err error) error {
|
|
return err
|
|
}
|
|
|
|
func (c *InMemoryContract) StartTx() policy.MultiTransaction {
|
|
return &inMemoryTx{operations: make([]func(*InMemoryContract), 0)}
|
|
}
|
|
|
|
func (c *InMemoryContract) SendTx(tx policy.MultiTransaction) error {
|
|
for _, operation := range tx.(*inMemoryTx).operations {
|
|
operation(c)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *InMemoryContract) getMap(kind policycontract.Kind) *syncedMap {
|
|
switch kind {
|
|
case policycontract.IAM:
|
|
return c.iamChains
|
|
case policycontract.Container:
|
|
return c.containerChains
|
|
case policycontract.Namespace:
|
|
return c.namespaceChains
|
|
default:
|
|
return &syncedMap{data: map[string][]byte{}}
|
|
}
|
|
}
|
|
|
|
type inMemoryTx struct {
|
|
operations []func(contract *InMemoryContract)
|
|
}
|
|
|
|
func (t *inMemoryTx) AddChain(kind policycontract.Kind, entity string, name []byte, chain []byte) {
|
|
t.operations = append(t.operations, func(c *InMemoryContract) {
|
|
_, _, _ = c.AddChain(kind, entity, name, chain)
|
|
})
|
|
}
|
|
|
|
func (t *inMemoryTx) RemoveChain(kind policycontract.Kind, entity string, name []byte) {
|
|
t.operations = append(t.operations, func(c *InMemoryContract) {
|
|
_, _, _ = c.RemoveChain(kind, entity, name)
|
|
})
|
|
}
|
|
|
|
func (t *inMemoryTx) Scripts() ([][]byte, error) {
|
|
return nil, nil
|
|
}
|