forked from TrueCloudLab/frostfs-node
73ba35b379
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>
126 lines
2.3 KiB
Go
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
|
|
}
|