Sends an RPC out to the wire, or queues it if we're disconnected. IMPORTANT : Make sure you've got a reference to the Deferred of this RPC (HBaseRpc#getDeferred) before you call this method. Otherwise there's a race condition if the RPC completes before you get a chance to call {@
(HBaseRpc rpc)
| 980 | * return that Deferred or attach a callback to it). |
| 981 | */ |
| 982 | void sendRpc(HBaseRpc rpc) { |
| 983 | if (chan != null) { |
| 984 | // Now {@link GetRequest} is also a {@link BatchableRpc}, we don't want to retry |
| 985 | // the get request once it fails. |
| 986 | if (rpc instanceof BatchableRpc |
| 987 | && !(rpc instanceof GetRequest) |
| 988 | && (server_version >= SERVER_VERSION_092_OR_ABOVE // Before 0.92, |
| 989 | || rpc instanceof PutRequest)) { // we could only batch "put". |
| 990 | final BatchableRpc edit = (BatchableRpc) rpc; |
| 991 | if (edit.canBuffer() && hbase_client.getFlushInterval() > 0) { |
| 992 | bufferEdit(edit); |
| 993 | return; |
| 994 | } |
| 995 | addSingleEditCallbacks(edit); |
| 996 | } else if (rpc instanceof MultiAction) { |
| 997 | // Transform single-edit multi-put into single-put. |
| 998 | final MultiAction batch = (MultiAction) rpc; |
| 999 | if (batch.size() == 1) { |
| 1000 | rpc = multiActionToSingleAction(batch); |
| 1001 | } else { |
| 1002 | hbase_client.num_multi_rpcs.increment(); |
| 1003 | } |
| 1004 | } |
| 1005 | final ChannelBuffer serialized = encode(rpc); |
| 1006 | if (serialized == null) { // Error during encoding. |
| 1007 | return; // Stop here. RPC has been failed already. |
| 1008 | } |
| 1009 | final Channel chan = this.chan; // Volatile read. |
| 1010 | if (chan != null) { // Double check if we disconnected during encode(). |
| 1011 | // if our channel isn't able to write, we want to properly queue and |
| 1012 | // retry the RPC later or fail it immediately so we don't fill up the |
| 1013 | // channel's buffer. |
| 1014 | if (check_write_status && !chan.isWritable()) { |
| 1015 | rpc.callback(new PleaseThrottleException("Region client [" + this + |
| 1016 | " ] channel is not writeable.", null, rpc, rpc.getDeferred())); |
| 1017 | removeRpc(rpc, false); |
| 1018 | writes_blocked.incrementAndGet(); |
| 1019 | return; |
| 1020 | } |
| 1021 | |
| 1022 | rpc.enqueueTimeout(this); |
| 1023 | Channels.write(chan, serialized); |
| 1024 | rpcs_sent.incrementAndGet(); |
| 1025 | return; |
| 1026 | } // else: continue to the "we're disconnected" code path below. |
| 1027 | } |
| 1028 | |
| 1029 | boolean tryagain = false; |
| 1030 | boolean dead; // Shadows this.dead; |
| 1031 | synchronized (this) { |
| 1032 | dead = this.dead; |
| 1033 | // Check if we got connected while entering this synchronized block. |
| 1034 | if (chan != null) { |
| 1035 | tryagain = true; |
| 1036 | } else if (!dead) { |
| 1037 | if (pending_rpcs == null) { |
| 1038 | pending_rpcs = new ArrayList<HBaseRpc>(); |
| 1039 | } |