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.

419 lines
14 KiB

8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
7 years ago
9 years ago
8 years ago
9 years ago
9 years ago
  1. package abcicli
  2. import (
  3. "fmt"
  4. "net"
  5. "sync"
  6. "time"
  7. "golang.org/x/net/context"
  8. "google.golang.org/grpc"
  9. "github.com/tendermint/tendermint/abci/types"
  10. tmnet "github.com/tendermint/tendermint/libs/net"
  11. "github.com/tendermint/tendermint/libs/service"
  12. tmsync "github.com/tendermint/tendermint/libs/sync"
  13. )
  14. var _ Client = (*grpcClient)(nil)
  15. // A stripped copy of the remoteClient that makes
  16. // synchronous calls using grpc
  17. type grpcClient struct {
  18. service.BaseService
  19. mustConnect bool
  20. client types.ABCIApplicationClient
  21. conn *grpc.ClientConn
  22. chReqRes chan *ReqRes // dispatches "async" responses to callbacks *in order*, needed by mempool
  23. mtx tmsync.RWMutex
  24. addr string
  25. err error
  26. resCb func(*types.Request, *types.Response) // listens to all callbacks
  27. }
  28. func NewGRPCClient(addr string, mustConnect bool) Client {
  29. cli := &grpcClient{
  30. addr: addr,
  31. mustConnect: mustConnect,
  32. // Buffering the channel is needed to make calls appear asynchronous,
  33. // which is required when the caller makes multiple async calls before
  34. // processing callbacks (e.g. due to holding locks). 64 means that a
  35. // caller can make up to 64 async calls before a callback must be
  36. // processed (otherwise it deadlocks). It also means that we can make 64
  37. // gRPC calls while processing a slow callback at the channel head.
  38. chReqRes: make(chan *ReqRes, 64),
  39. }
  40. cli.BaseService = *service.NewBaseService(nil, "grpcClient", cli)
  41. return cli
  42. }
  43. func dialerFunc(ctx context.Context, addr string) (net.Conn, error) {
  44. return tmnet.Connect(addr)
  45. }
  46. func (cli *grpcClient) OnStart() error {
  47. if err := cli.BaseService.OnStart(); err != nil {
  48. return err
  49. }
  50. // This processes asynchronous request/response messages and dispatches
  51. // them to callbacks.
  52. go func() {
  53. // Use a separate function to use defer for mutex unlocks (this handles panics)
  54. callCb := func(reqres *ReqRes) {
  55. cli.mtx.Lock()
  56. defer cli.mtx.Unlock()
  57. reqres.SetDone()
  58. reqres.Done()
  59. // Notify client listener if set
  60. if cli.resCb != nil {
  61. cli.resCb(reqres.Request, reqres.Response)
  62. }
  63. // Notify reqRes listener if set
  64. if cb := reqres.GetCallback(); cb != nil {
  65. cb(reqres.Response)
  66. }
  67. }
  68. for reqres := range cli.chReqRes {
  69. if reqres != nil {
  70. callCb(reqres)
  71. } else {
  72. cli.Logger.Error("Received nil reqres")
  73. }
  74. }
  75. }()
  76. RETRY_LOOP:
  77. for {
  78. conn, err := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithContextDialer(dialerFunc))
  79. if err != nil {
  80. if cli.mustConnect {
  81. return err
  82. }
  83. cli.Logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr), "err", err)
  84. time.Sleep(time.Second * dialRetryIntervalSeconds)
  85. continue RETRY_LOOP
  86. }
  87. cli.Logger.Info("Dialed server. Waiting for echo.", "addr", cli.addr)
  88. client := types.NewABCIApplicationClient(conn)
  89. cli.conn = conn
  90. ENSURE_CONNECTED:
  91. for {
  92. _, err := client.Echo(context.Background(), &types.RequestEcho{Message: "hello"}, grpc.WaitForReady(true))
  93. if err == nil {
  94. break ENSURE_CONNECTED
  95. }
  96. cli.Logger.Error("Echo failed", "err", err)
  97. time.Sleep(time.Second * echoRetryIntervalSeconds)
  98. }
  99. cli.client = client
  100. return nil
  101. }
  102. }
  103. func (cli *grpcClient) OnStop() {
  104. cli.BaseService.OnStop()
  105. if cli.conn != nil {
  106. cli.conn.Close()
  107. }
  108. close(cli.chReqRes)
  109. }
  110. func (cli *grpcClient) StopForError(err error) {
  111. if !cli.IsRunning() {
  112. return
  113. }
  114. cli.mtx.Lock()
  115. if cli.err == nil {
  116. cli.err = err
  117. }
  118. cli.mtx.Unlock()
  119. cli.Logger.Error(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error()))
  120. if err := cli.Stop(); err != nil {
  121. cli.Logger.Error("Error stopping abci.grpcClient", "err", err)
  122. }
  123. }
  124. func (cli *grpcClient) Error() error {
  125. cli.mtx.RLock()
  126. defer cli.mtx.RUnlock()
  127. return cli.err
  128. }
  129. // Set listener for all responses
  130. // NOTE: callback may get internally generated flush responses.
  131. func (cli *grpcClient) SetResponseCallback(resCb Callback) {
  132. cli.mtx.Lock()
  133. defer cli.mtx.Unlock()
  134. cli.resCb = resCb
  135. }
  136. //----------------------------------------
  137. // GRPC calls are synchronous, but some callbacks expect to be called asynchronously
  138. // (eg. the mempool expects to be able to lock to remove bad txs from cache).
  139. // To accommodate, we finish each call in its own go-routine,
  140. // which is expensive, but easy - if you want something better, use the socket protocol!
  141. // maybe one day, if people really want it, we use grpc streams,
  142. // but hopefully not :D
  143. func (cli *grpcClient) EchoAsync(msg string) *ReqRes {
  144. req := types.ToRequestEcho(msg)
  145. res, err := cli.client.Echo(context.Background(), req.GetEcho(), grpc.WaitForReady(true))
  146. if err != nil {
  147. cli.StopForError(err)
  148. }
  149. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Echo{Echo: res}})
  150. }
  151. func (cli *grpcClient) FlushAsync() *ReqRes {
  152. req := types.ToRequestFlush()
  153. res, err := cli.client.Flush(context.Background(), req.GetFlush(), grpc.WaitForReady(true))
  154. if err != nil {
  155. cli.StopForError(err)
  156. }
  157. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Flush{Flush: res}})
  158. }
  159. func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes {
  160. req := types.ToRequestInfo(params)
  161. res, err := cli.client.Info(context.Background(), req.GetInfo(), grpc.WaitForReady(true))
  162. if err != nil {
  163. cli.StopForError(err)
  164. }
  165. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Info{Info: res}})
  166. }
  167. func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes {
  168. req := types.ToRequestSetOption(params)
  169. res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.WaitForReady(true))
  170. if err != nil {
  171. cli.StopForError(err)
  172. }
  173. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_SetOption{SetOption: res}})
  174. }
  175. func (cli *grpcClient) DeliverTxAsync(params types.RequestDeliverTx) *ReqRes {
  176. req := types.ToRequestDeliverTx(params)
  177. res, err := cli.client.DeliverTx(context.Background(), req.GetDeliverTx(), grpc.WaitForReady(true))
  178. if err != nil {
  179. cli.StopForError(err)
  180. }
  181. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_DeliverTx{DeliverTx: res}})
  182. }
  183. func (cli *grpcClient) CheckTxAsync(params types.RequestCheckTx) *ReqRes {
  184. req := types.ToRequestCheckTx(params)
  185. res, err := cli.client.CheckTx(context.Background(), req.GetCheckTx(), grpc.WaitForReady(true))
  186. if err != nil {
  187. cli.StopForError(err)
  188. }
  189. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_CheckTx{CheckTx: res}})
  190. }
  191. func (cli *grpcClient) QueryAsync(params types.RequestQuery) *ReqRes {
  192. req := types.ToRequestQuery(params)
  193. res, err := cli.client.Query(context.Background(), req.GetQuery(), grpc.WaitForReady(true))
  194. if err != nil {
  195. cli.StopForError(err)
  196. }
  197. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Query{Query: res}})
  198. }
  199. func (cli *grpcClient) CommitAsync() *ReqRes {
  200. req := types.ToRequestCommit()
  201. res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.WaitForReady(true))
  202. if err != nil {
  203. cli.StopForError(err)
  204. }
  205. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Commit{Commit: res}})
  206. }
  207. func (cli *grpcClient) InitChainAsync(params types.RequestInitChain) *ReqRes {
  208. req := types.ToRequestInitChain(params)
  209. res, err := cli.client.InitChain(context.Background(), req.GetInitChain(), grpc.WaitForReady(true))
  210. if err != nil {
  211. cli.StopForError(err)
  212. }
  213. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_InitChain{InitChain: res}})
  214. }
  215. func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes {
  216. req := types.ToRequestBeginBlock(params)
  217. res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.WaitForReady(true))
  218. if err != nil {
  219. cli.StopForError(err)
  220. }
  221. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_BeginBlock{BeginBlock: res}})
  222. }
  223. func (cli *grpcClient) EndBlockAsync(params types.RequestEndBlock) *ReqRes {
  224. req := types.ToRequestEndBlock(params)
  225. res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock(), grpc.WaitForReady(true))
  226. if err != nil {
  227. cli.StopForError(err)
  228. }
  229. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_EndBlock{EndBlock: res}})
  230. }
  231. func (cli *grpcClient) ListSnapshotsAsync(params types.RequestListSnapshots) *ReqRes {
  232. req := types.ToRequestListSnapshots(params)
  233. res, err := cli.client.ListSnapshots(context.Background(), req.GetListSnapshots(), grpc.WaitForReady(true))
  234. if err != nil {
  235. cli.StopForError(err)
  236. }
  237. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ListSnapshots{ListSnapshots: res}})
  238. }
  239. func (cli *grpcClient) OfferSnapshotAsync(params types.RequestOfferSnapshot) *ReqRes {
  240. req := types.ToRequestOfferSnapshot(params)
  241. res, err := cli.client.OfferSnapshot(context.Background(), req.GetOfferSnapshot(), grpc.WaitForReady(true))
  242. if err != nil {
  243. cli.StopForError(err)
  244. }
  245. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_OfferSnapshot{OfferSnapshot: res}})
  246. }
  247. func (cli *grpcClient) LoadSnapshotChunkAsync(params types.RequestLoadSnapshotChunk) *ReqRes {
  248. req := types.ToRequestLoadSnapshotChunk(params)
  249. res, err := cli.client.LoadSnapshotChunk(context.Background(), req.GetLoadSnapshotChunk(), grpc.WaitForReady(true))
  250. if err != nil {
  251. cli.StopForError(err)
  252. }
  253. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_LoadSnapshotChunk{LoadSnapshotChunk: res}})
  254. }
  255. func (cli *grpcClient) ApplySnapshotChunkAsync(params types.RequestApplySnapshotChunk) *ReqRes {
  256. req := types.ToRequestApplySnapshotChunk(params)
  257. res, err := cli.client.ApplySnapshotChunk(context.Background(), req.GetApplySnapshotChunk(), grpc.WaitForReady(true))
  258. if err != nil {
  259. cli.StopForError(err)
  260. }
  261. return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}})
  262. }
  263. // finishAsyncCall creates a ReqRes for an async call, and immediately populates it
  264. // with the response. We don't complete it until it's been ordered via the channel.
  265. func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes {
  266. reqres := NewReqRes(req)
  267. reqres.Response = res
  268. cli.chReqRes <- reqres // use channel for async responses, since they must be ordered
  269. return reqres
  270. }
  271. // finishSyncCall waits for an async call to complete. It is necessary to call all
  272. // sync calls asynchronously as well, to maintain call and response ordering via
  273. // the channel, and this method will wait until the async call completes.
  274. func (cli *grpcClient) finishSyncCall(reqres *ReqRes) *types.Response {
  275. // It's possible that the callback is called twice, since the callback can
  276. // be called immediately on SetCallback() in addition to after it has been
  277. // set. This is because completing the ReqRes happens in a separate critical
  278. // section from the one where the callback is called: there is a race where
  279. // SetCallback() is called between completing the ReqRes and dispatching the
  280. // callback.
  281. //
  282. // We also buffer the channel with 1 response, since SetCallback() will be
  283. // called synchronously if the reqres is already completed, in which case
  284. // it will block on sending to the channel since it hasn't gotten around to
  285. // receiving from it yet.
  286. //
  287. // ReqRes should really handle callback dispatch internally, to guarantee
  288. // that it's only called once and avoid the above race conditions.
  289. var once sync.Once
  290. ch := make(chan *types.Response, 1)
  291. reqres.SetCallback(func(res *types.Response) {
  292. once.Do(func() {
  293. ch <- res
  294. })
  295. })
  296. return <-ch
  297. }
  298. //----------------------------------------
  299. func (cli *grpcClient) FlushSync() error {
  300. return nil
  301. }
  302. func (cli *grpcClient) EchoSync(msg string) (*types.ResponseEcho, error) {
  303. reqres := cli.EchoAsync(msg)
  304. // StopForError should already have been called if error is set
  305. return cli.finishSyncCall(reqres).GetEcho(), cli.Error()
  306. }
  307. func (cli *grpcClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) {
  308. reqres := cli.InfoAsync(req)
  309. return cli.finishSyncCall(reqres).GetInfo(), cli.Error()
  310. }
  311. func (cli *grpcClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) {
  312. reqres := cli.SetOptionAsync(req)
  313. return reqres.Response.GetSetOption(), cli.Error()
  314. }
  315. func (cli *grpcClient) DeliverTxSync(params types.RequestDeliverTx) (*types.ResponseDeliverTx, error) {
  316. reqres := cli.DeliverTxAsync(params)
  317. return cli.finishSyncCall(reqres).GetDeliverTx(), cli.Error()
  318. }
  319. func (cli *grpcClient) CheckTxSync(params types.RequestCheckTx) (*types.ResponseCheckTx, error) {
  320. reqres := cli.CheckTxAsync(params)
  321. return cli.finishSyncCall(reqres).GetCheckTx(), cli.Error()
  322. }
  323. func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) {
  324. reqres := cli.QueryAsync(req)
  325. return cli.finishSyncCall(reqres).GetQuery(), cli.Error()
  326. }
  327. func (cli *grpcClient) CommitSync() (*types.ResponseCommit, error) {
  328. reqres := cli.CommitAsync()
  329. return cli.finishSyncCall(reqres).GetCommit(), cli.Error()
  330. }
  331. func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (*types.ResponseInitChain, error) {
  332. reqres := cli.InitChainAsync(params)
  333. return cli.finishSyncCall(reqres).GetInitChain(), cli.Error()
  334. }
  335. func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (*types.ResponseBeginBlock, error) {
  336. reqres := cli.BeginBlockAsync(params)
  337. return cli.finishSyncCall(reqres).GetBeginBlock(), cli.Error()
  338. }
  339. func (cli *grpcClient) EndBlockSync(params types.RequestEndBlock) (*types.ResponseEndBlock, error) {
  340. reqres := cli.EndBlockAsync(params)
  341. return cli.finishSyncCall(reqres).GetEndBlock(), cli.Error()
  342. }
  343. func (cli *grpcClient) ListSnapshotsSync(params types.RequestListSnapshots) (*types.ResponseListSnapshots, error) {
  344. reqres := cli.ListSnapshotsAsync(params)
  345. return cli.finishSyncCall(reqres).GetListSnapshots(), cli.Error()
  346. }
  347. func (cli *grpcClient) OfferSnapshotSync(params types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) {
  348. reqres := cli.OfferSnapshotAsync(params)
  349. return cli.finishSyncCall(reqres).GetOfferSnapshot(), cli.Error()
  350. }
  351. func (cli *grpcClient) LoadSnapshotChunkSync(
  352. params types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
  353. reqres := cli.LoadSnapshotChunkAsync(params)
  354. return cli.finishSyncCall(reqres).GetLoadSnapshotChunk(), cli.Error()
  355. }
  356. func (cli *grpcClient) ApplySnapshotChunkSync(
  357. params types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
  358. reqres := cli.ApplySnapshotChunkAsync(params)
  359. return cli.finishSyncCall(reqres).GetApplySnapshotChunk(), cli.Error()
  360. }