You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.3 KiB

  1. package lite
  2. import (
  3. log "github.com/tendermint/tendermint/libs/log"
  4. lerr "github.com/tendermint/tendermint/lite/errors"
  5. "github.com/tendermint/tendermint/types"
  6. )
  7. var _ PersistentProvider = (*multiProvider)(nil)
  8. // multiProvider allows you to place one or more caches in front of a source
  9. // Provider. It runs through them in order until a match is found.
  10. type multiProvider struct {
  11. logger log.Logger
  12. providers []PersistentProvider
  13. }
  14. // NewMultiProvider returns a new provider which wraps multiple other providers.
  15. func NewMultiProvider(providers ...PersistentProvider) *multiProvider {
  16. return &multiProvider{
  17. logger: log.NewNopLogger(),
  18. providers: providers,
  19. }
  20. }
  21. // SetLogger sets logger on self and all subproviders.
  22. func (mc *multiProvider) SetLogger(logger log.Logger) {
  23. mc.logger = logger
  24. for _, p := range mc.providers {
  25. p.SetLogger(logger)
  26. }
  27. }
  28. // SaveFullCommit saves on all providers, and aborts on the first error.
  29. func (mc *multiProvider) SaveFullCommit(fc FullCommit) (err error) {
  30. for _, p := range mc.providers {
  31. err = p.SaveFullCommit(fc)
  32. if err != nil {
  33. return
  34. }
  35. }
  36. return
  37. }
  38. // LatestFullCommit loads the latest from all providers and provides
  39. // the latest FullCommit that satisfies the conditions.
  40. // Returns the first error encountered.
  41. func (mc *multiProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (fc FullCommit, err error) {
  42. for _, p := range mc.providers {
  43. var fc_ FullCommit
  44. fc_, err = p.LatestFullCommit(chainID, minHeight, maxHeight)
  45. if lerr.IsErrCommitNotFound(err) {
  46. err = nil
  47. continue
  48. } else if err != nil {
  49. return
  50. }
  51. if fc == (FullCommit{}) {
  52. fc = fc_
  53. } else if fc_.Height() > fc.Height() {
  54. fc = fc_
  55. }
  56. if fc.Height() == maxHeight {
  57. return
  58. }
  59. }
  60. if fc == (FullCommit{}) {
  61. err = lerr.ErrCommitNotFound()
  62. return
  63. }
  64. return
  65. }
  66. // ValidatorSet returns validator set at height as provided by the first
  67. // provider which has it, or an error otherwise.
  68. func (mc *multiProvider) ValidatorSet(chainID string, height int64) (valset *types.ValidatorSet, err error) {
  69. for _, p := range mc.providers {
  70. valset, err = p.ValidatorSet(chainID, height)
  71. if err == nil {
  72. // TODO Log unexpected types of errors.
  73. return valset, nil
  74. }
  75. }
  76. return nil, lerr.ErrUnknownValidators(chainID, height)
  77. }