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.

92 lines
2.7 KiB

8 years ago
8 years ago
8 years ago
  1. package proxy
  2. import (
  3. "fmt"
  4. "io"
  5. abcicli "github.com/tendermint/tendermint/abci/client"
  6. "github.com/tendermint/tendermint/abci/example/kvstore"
  7. "github.com/tendermint/tendermint/abci/types"
  8. tmsync "github.com/tendermint/tendermint/internal/libs/sync"
  9. )
  10. // ClientCreator creates new ABCI clients.
  11. type ClientCreator interface {
  12. // NewABCIClient returns a new ABCI client.
  13. NewABCIClient() (abcicli.Client, error)
  14. }
  15. //----------------------------------------------------
  16. // local proxy uses a mutex on an in-proc app
  17. type localClientCreator struct {
  18. mtx *tmsync.RWMutex
  19. app types.Application
  20. }
  21. // NewLocalClientCreator returns a ClientCreator for the given app,
  22. // which will be running locally.
  23. func NewLocalClientCreator(app types.Application) ClientCreator {
  24. return &localClientCreator{
  25. mtx: new(tmsync.RWMutex),
  26. app: app,
  27. }
  28. }
  29. func (l *localClientCreator) NewABCIClient() (abcicli.Client, error) {
  30. return abcicli.NewLocalClient(l.mtx, l.app), nil
  31. }
  32. //---------------------------------------------------------------
  33. // remote proxy opens new connections to an external app process
  34. type remoteClientCreator struct {
  35. addr string
  36. transport string
  37. mustConnect bool
  38. }
  39. // NewRemoteClientCreator returns a ClientCreator for the given address (e.g.
  40. // "192.168.0.1") and transport (e.g. "tcp"). Set mustConnect to true if you
  41. // want the client to connect before reporting success.
  42. func NewRemoteClientCreator(addr, transport string, mustConnect bool) ClientCreator {
  43. return &remoteClientCreator{
  44. addr: addr,
  45. transport: transport,
  46. mustConnect: mustConnect,
  47. }
  48. }
  49. func (r *remoteClientCreator) NewABCIClient() (abcicli.Client, error) {
  50. remoteApp, err := abcicli.NewClient(r.addr, r.transport, r.mustConnect)
  51. if err != nil {
  52. return nil, fmt.Errorf("failed to connect to proxy: %w", err)
  53. }
  54. return remoteApp, nil
  55. }
  56. // DefaultClientCreator returns a default ClientCreator, which will create a
  57. // local client if addr is one of: 'kvstore',
  58. // 'persistent_kvstore' or 'noop', otherwise - a remote client.
  59. //
  60. // The Closer is a noop except for persistent_kvstore applications,
  61. // which will clean up the store.
  62. func DefaultClientCreator(addr, transport, dbDir string) (ClientCreator, io.Closer) {
  63. switch addr {
  64. case "kvstore":
  65. return NewLocalClientCreator(kvstore.NewApplication()), noopCloser{}
  66. case "persistent_kvstore":
  67. app := kvstore.NewPersistentKVStoreApplication(dbDir)
  68. return NewLocalClientCreator(app), app
  69. case "noop":
  70. return NewLocalClientCreator(types.NewBaseApplication()), noopCloser{}
  71. default:
  72. mustConnect := false // loop retrying
  73. return NewRemoteClientCreator(addr, transport, mustConnect), noopCloser{}
  74. }
  75. }
  76. type noopCloser struct{}
  77. func (noopCloser) Close() error { return nil }