package lite
|
|
|
|
import (
|
|
log "github.com/tendermint/tendermint/libs/log"
|
|
lerr "github.com/tendermint/tendermint/lite/errors"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
var _ PersistentProvider = (*multiProvider)(nil)
|
|
|
|
// multiProvider allows you to place one or more caches in front of a source
|
|
// Provider. It runs through them in order until a match is found.
|
|
type multiProvider struct {
|
|
logger log.Logger
|
|
providers []PersistentProvider
|
|
}
|
|
|
|
// NewMultiProvider returns a new provider which wraps multiple other providers.
|
|
func NewMultiProvider(providers ...PersistentProvider) PersistentProvider {
|
|
return &multiProvider{
|
|
logger: log.NewNopLogger(),
|
|
providers: providers,
|
|
}
|
|
}
|
|
|
|
// SetLogger sets logger on self and all subproviders.
|
|
func (mc *multiProvider) SetLogger(logger log.Logger) {
|
|
mc.logger = logger
|
|
for _, p := range mc.providers {
|
|
p.SetLogger(logger)
|
|
}
|
|
}
|
|
|
|
// SaveFullCommit saves on all providers, and aborts on the first error.
|
|
func (mc *multiProvider) SaveFullCommit(fc FullCommit) (err error) {
|
|
for _, p := range mc.providers {
|
|
err = p.SaveFullCommit(fc)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// LatestFullCommit loads the latest from all providers and provides
|
|
// the latest FullCommit that satisfies the conditions.
|
|
// Returns the first error encountered.
|
|
func (mc *multiProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (fc FullCommit, err error) {
|
|
for _, p := range mc.providers {
|
|
var commit FullCommit
|
|
commit, err = p.LatestFullCommit(chainID, minHeight, maxHeight)
|
|
if lerr.IsErrCommitNotFound(err) {
|
|
err = nil
|
|
continue
|
|
} else if err != nil {
|
|
return
|
|
}
|
|
if fc == (FullCommit{}) {
|
|
fc = commit
|
|
} else if commit.Height() > fc.Height() {
|
|
fc = commit
|
|
}
|
|
if fc.Height() == maxHeight {
|
|
return
|
|
}
|
|
}
|
|
if fc == (FullCommit{}) {
|
|
err = lerr.ErrCommitNotFound()
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// ValidatorSet returns validator set at height as provided by the first
|
|
// provider which has it, or an error otherwise.
|
|
func (mc *multiProvider) ValidatorSet(chainID string, height int64) (valset *types.ValidatorSet, err error) {
|
|
for _, p := range mc.providers {
|
|
valset, err = p.ValidatorSet(chainID, height)
|
|
if err == nil {
|
|
// TODO Log unexpected types of errors.
|
|
return valset, nil
|
|
}
|
|
}
|
|
return nil, lerr.ErrUnknownValidators(chainID, height)
|
|
}
|