Beispiel #1
0
  private <R> ChannelBuffer encode(final KuduRpc<R> rpc) {
    final int rpcid = this.rpcid.incrementAndGet();
    ChannelBuffer payload;
    final String service = rpc.serviceName();
    final String method = rpc.method();
    try {
      final RpcHeader.RequestHeader.Builder headerBuilder =
          RpcHeader.RequestHeader.newBuilder()
              .setCallId(rpcid)
              .addAllRequiredFeatureFlags(rpc.getRequiredFeatures())
              .setRemoteMethod(
                  RpcHeader.RemoteMethodPB.newBuilder()
                      .setServiceName(service)
                      .setMethodName(method));

      // If any timeout is set, find the lowest non-zero one, since this will be the deadline that
      // the server must respect.
      if (rpc.deadlineTracker.hasDeadline() || socketReadTimeoutMs > 0) {
        long millisBeforeDeadline = Long.MAX_VALUE;
        if (rpc.deadlineTracker.hasDeadline()) {
          millisBeforeDeadline = rpc.deadlineTracker.getMillisBeforeDeadline();
        }

        long localRpcTimeoutMs = Long.MAX_VALUE;
        if (socketReadTimeoutMs > 0) {
          localRpcTimeoutMs = socketReadTimeoutMs;
        }

        headerBuilder.setTimeoutMillis((int) Math.min(millisBeforeDeadline, localRpcTimeoutMs));
      }

      payload = rpc.serialize(headerBuilder.build());
    } catch (Exception e) {
      LOG.error("Uncaught exception while serializing RPC: " + rpc, e);
      rpc.errback(e); // Make the RPC fail with the exception.
      return null;
    }
    final KuduRpc<?> oldrpc = rpcs_inflight.put(rpcid, rpc);
    if (oldrpc != null) {
      final String wtf =
          getPeerUuidLoggingString()
              + "WTF?  There was already an RPC in flight with"
              + " rpcid="
              + rpcid
              + ": "
              + oldrpc
              + ".  This happened when sending out: "
              + rpc;
      LOG.error(wtf);
      // Make it fail. This isn't an expected failure mode.
      oldrpc.errback(new NonRecoverableException(wtf));
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug(
          getPeerUuidLoggingString()
              + chan
              + " Sending RPC #"
              + rpcid
              + ", payload="
              + payload
              + ' '
              + Bytes.pretty(payload));
    }

    payload = secureRpcHelper.wrap(payload);

    return payload;
  }
Beispiel #2
0
  <R> void sendRpc(KuduRpc<R> rpc) {
    if (!rpc.deadlineTracker.hasDeadline()) {
      LOG.warn(getPeerUuidLoggingString() + " sending an rpc without a timeout " + rpc);
    }
    if (chan != null) {
      if (!rpc.getRequiredFeatures().isEmpty()
          && !secureRpcHelper
              .getServerFeatures()
              .contains(RpcHeader.RpcFeatureFlag.APPLICATION_FEATURE_FLAGS)) {
        rpc.errback(
            new NonRecoverableException(
                "the server does not support the APPLICATION_FEATURE_FLAGS RPC feature"));
      }

      final ChannelBuffer serialized = encode(rpc);
      if (serialized == null) { // Error during encoding.
        return; // Stop here.  RPC has been failed already.
      }

      final Channel chan = this.chan; // Volatile read.
      if (chan != null) { // Double check if we disconnected during encode().
        Channels.write(chan, serialized);
      } else {
        // The RPC was already added to rpcs_inflight so we don't need to fall down in the next big
        // block of code, cleanup() will take care of it.
        if (LOG.isDebugEnabled()) {
          LOG.debug(
              getPeerUuidLoggingString() + " connection was closed before sending rpcid {}, rpc=",
              rpcid,
              rpc);
        }
      }
      return;
    }
    boolean tryagain = false;
    boolean copyOfDead;
    synchronized (this) {
      copyOfDead = this.dead;
      // Check if we got connected while entering this synchronized block.
      if (chan != null) {
        tryagain = true;
      } else if (!copyOfDead) {
        if (pending_rpcs == null) {
          pending_rpcs = new ArrayList<KuduRpc<?>>();
        }
        pending_rpcs.add(rpc);
      }
    }
    if (copyOfDead) {
      failOrRetryRpc(rpc, new ConnectionResetException(null));
      return;
    } else if (tryagain) {
      // This recursion will not lead to a loop because we only get here if we
      // connected while entering the synchronized block above. So when trying
      // a second time,  we will either succeed to send the RPC if we're still
      // connected, or fail through to the code below if we got disconnected
      // in the mean time.
      sendRpc(rpc);
      return;
    }
  }