frostfs-node/pkg/innerring/indexer.go
Pavel Karpy 73ba35b379 [#705] pkg/innerring: Fix disable notary mode
Get innerring list and committee in innerring
indexer from interfaces, not from structs.
Passing IR fetcher to indexer constructor depends
on having Notary contract in sidechain(use NeoFS
role or netmap contract).

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2021-07-22 15:12:06 +03:00

126 lines
2.3 KiB
Go

package innerring
import (
"bytes"
"fmt"
"sync"
"time"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
)
type (
irFetcher interface {
InnerRingKeys() (keys.PublicKeys, error)
}
committeeFetcher interface {
Committee() (keys.PublicKeys, error)
}
innerRingIndexer struct {
sync.RWMutex
irFetcher irFetcher
commFetcher committeeFetcher
key *keys.PublicKey
timeout time.Duration
ind indexes
lastAccess time.Time
}
indexes struct {
innerRingIndex, innerRingSize int32
alphabetIndex int32
}
)
func newInnerRingIndexer(comf committeeFetcher, irf irFetcher, key *keys.PublicKey, to time.Duration) *innerRingIndexer {
return &innerRingIndexer{
irFetcher: irf,
commFetcher: comf,
key: key,
timeout: to,
}
}
func (s *innerRingIndexer) update() (ind indexes, err error) {
s.RLock()
if time.Since(s.lastAccess) < s.timeout {
s.RUnlock()
return s.ind, nil
}
s.RUnlock()
s.Lock()
defer s.Unlock()
if time.Since(s.lastAccess) < s.timeout {
return s.ind, nil
}
innerRing, err := s.irFetcher.InnerRingKeys()
if err != nil {
return indexes{}, err
}
s.ind.innerRingIndex = keyPosition(s.key, innerRing)
s.ind.innerRingSize = int32(len(innerRing))
alphabet, err := s.commFetcher.Committee()
if err != nil {
return indexes{}, err
}
s.ind.alphabetIndex = keyPosition(s.key, alphabet)
s.lastAccess = time.Now()
return s.ind, nil
}
func (s *innerRingIndexer) InnerRingIndex() (int32, error) {
ind, err := s.update()
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.innerRingIndex, nil
}
func (s *innerRingIndexer) InnerRingSize() (int32, error) {
ind, err := s.update()
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.innerRingSize, nil
}
func (s *innerRingIndexer) AlphabetIndex() (int32, error) {
ind, err := s.update()
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.alphabetIndex, nil
}
// keyPosition returns "-1" if key is not found in the list, otherwise returns
// index of the key.
func keyPosition(key *keys.PublicKey, list keys.PublicKeys) (result int32) {
result = -1
rawBytes := key.Bytes()
for i := range list {
if bytes.Equal(list[i].Bytes(), rawBytes) {
result = int32(i)
break
}
}
return result
}