/**
   * @param id Handshake ID.
   * @param c Closure to run on reserve.
   * @return {@code True} if reserved.
   */
  public boolean tryReserve(long id, IgniteInClosure<Boolean> c) {
    synchronized (this) {
      if (connected) {
        c.apply(false);

        return false;
      }

      if (reserved) {
        if (handshakeReq != null) {
          assert handshakeReq.get1() != null;

          long id0 = handshakeReq.get1();

          assert id0 != id : id0;

          if (id > id0) {
            IgniteInClosure<Boolean> c0 = handshakeReq.get2();

            assert c0 != null;

            c0.apply(false);

            handshakeReq = new IgniteBiTuple<>(id, c);
          } else c.apply(false);
        } else handshakeReq = new IgniteBiTuple<>(id, c);

        return false;
      } else {
        reserved = true;

        return true;
      }
    }
  }
  public void release() {
    GridNioFuture<?>[] futs = null;

    synchronized (this) {
      connected = false;

      if (handshakeReq != null) {
        IgniteInClosure<Boolean> c = handshakeReq.get2();

        assert c != null;

        handshakeReq = null;

        c.apply(true);
      } else {
        reserved = false;

        notifyAll();
      }

      if (nodeLeft && !msgFuts.isEmpty()) {
        futs = msgFuts.toArray(new GridNioFuture<?>[msgFuts.size()]);

        msgFuts.clear();
      }
    }

    if (futs != null) completeOnNodeLeft(futs);
  }
  public void connected() {
    synchronized (this) {
      assert reserved : this;
      assert !connected : this;

      connected = true;

      if (handshakeReq != null) {
        IgniteInClosure<Boolean> c = handshakeReq.get2();

        assert c != null;

        c.apply(false);

        handshakeReq = null;
      }

      notifyAll();
    }
  }
  /** {@inheritDoc} */
  @Override
  public synchronized boolean sendMessage(
      @Nullable UUID nodeId, Message msg, IgniteInClosure<IgniteException> closure)
      throws IgniteCheckedException {
    if (closed()) throw new IgniteCheckedException("Communication client was closed: " + this);

    assert writeBuf.hasArray();

    try {
      int cnt = U.writeMessageFully(msg, shmem.outputStream(), writeBuf, formatter.writer());

      metricsLsnr.onBytesSent(cnt);
    } catch (IOException e) {
      throw new IgniteCheckedException("Failed to send message to remote node: " + shmem, e);
    }

    markUsed();

    if (closure != null) closure.apply(null);

    return false;
  }