class ClientRequestFuture extends GridFutureAdapter<MappingExchangeResult> {
    /** */
    private static final AtomicReference<IgniteLogger> logRef = new AtomicReference<>();

    /** */
    private static IgniteLogger log;

    /** */
    private final GridIoManager ioMgr;

    /** */
    private final GridDiscoveryManager discoMgr;

    /** */
    private final MarshallerMappingItem item;

    /** */
    private final Map<MarshallerMappingItem, ClientRequestFuture> syncMap;

    /** */
    private final Queue<ClusterNode> aliveSrvNodes;

    /** */
    private ClusterNode pendingNode;

    /**
     * @param ctx Context.
     * @param item Item.
     * @param syncMap Sync map.
     */
    ClientRequestFuture(
            GridKernalContext ctx,
            MarshallerMappingItem item,
            Map<MarshallerMappingItem, ClientRequestFuture> syncMap
    ) {
        ioMgr = ctx.io();
        discoMgr = ctx.discovery();
        aliveSrvNodes = new LinkedList<>(discoMgr.aliveServerNodes());
        this.item = item;
        this.syncMap = syncMap;

        if (log == null)
            log = U.logger(ctx, logRef, ClientRequestFuture.class);
    }

    /**
     *
     */
    void requestMapping() {<FILL_FUNCTION_BODY>}

    /**
     * @param nodeId Node ID.
     * @param res Mapping Request Result.
     */
    void onResponse(UUID nodeId, MappingExchangeResult res) {
        MappingExchangeResult res0 = null;

        synchronized (this) {
            if (pendingNode != null && pendingNode.id().equals(nodeId))
                res0 = res;
        }

        if (res0 != null)
            onDone(res0);
    }

    /**
     * If left node is actually the one latest mapping request was sent to,
     * request is sent again to the next node in topology.
     *
     * @param leftNodeId Left node id.
     */
    void onNodeLeft(UUID leftNodeId) {
        boolean reqAgain = false;

        synchronized (this) {
            if (pendingNode != null && pendingNode.id().equals(leftNodeId)) {
                aliveSrvNodes.remove(pendingNode);

                pendingNode = null;

                reqAgain = true;
            }
        }

        if (reqAgain)
            requestMapping();
    }

    /** {@inheritDoc} */
    @Override public boolean onDone(@Nullable MappingExchangeResult res, @Nullable Throwable err) {
        assert res != null;

        boolean done = super.onDone(res, err);

        if (done)
            syncMap.remove(item);

        return done;
    }
}

        boolean noSrvsInCluster;

        synchronized (this) {
            while (!aliveSrvNodes.isEmpty()) {
                ClusterNode srvNode = aliveSrvNodes.poll();

                try {
                    ioMgr.sendToGridTopic(
                        srvNode,
                        GridTopic.TOPIC_MAPPING_MARSH,
                        new MissingMappingRequestMessage(
                            item.platformId(),
                            item.typeId()),
                        GridIoPolicy.SYSTEM_POOL);

                    if (discoMgr.node(srvNode.id()) == null)
                        continue;

                    pendingNode = srvNode;

                    break;
                }
                catch (IgniteCheckedException ignored) {
                    U.warn(log,
                        "Failed to request marshaller mapping from remote node (proceeding with the next one): "
                            + srvNode);
                }
            }

            noSrvsInCluster = pendingNode == null;
        }

        if (noSrvsInCluster) {
            onDone(MappingExchangeResult.createFailureResult(
                new IgniteCheckedException(
                    "All server nodes have left grid, cannot request mapping [platformId: "
                        + item.platformId()
                        + "; typeId: "
                        + item.typeId() + "]")));
        }
    
<methods>public non-sealed void <init>() ,public boolean cancel() throws org.apache.ignite.IgniteCheckedException,public IgniteInternalFuture<T> chain(IgniteClosure<? super IgniteInternalFuture<org.apache.ignite.internal.processors.marshaller.MappingExchangeResult>,T>) ,public IgniteInternalFuture<T> chain(IgniteOutClosure<T>) ,public IgniteInternalFuture<T> chain(IgniteClosure<? super IgniteInternalFuture<org.apache.ignite.internal.processors.marshaller.MappingExchangeResult>,T>, java.util.concurrent.Executor) ,public IgniteInternalFuture<T> chain(IgniteOutClosure<T>, java.util.concurrent.Executor) ,public IgniteInternalFuture<T> chainCompose(IgniteClosure<? super IgniteInternalFuture<org.apache.ignite.internal.processors.marshaller.MappingExchangeResult>,IgniteInternalFuture<T>>) ,public IgniteInternalFuture<T> chainCompose(IgniteClosure<? super IgniteInternalFuture<org.apache.ignite.internal.processors.marshaller.MappingExchangeResult>,IgniteInternalFuture<T>>, java.util.concurrent.Executor) ,public java.lang.Throwable error() ,public org.apache.ignite.internal.processors.marshaller.MappingExchangeResult get() throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.marshaller.MappingExchangeResult get(long) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.marshaller.MappingExchangeResult get(long, java.util.concurrent.TimeUnit) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.marshaller.MappingExchangeResult getUninterruptibly() throws org.apache.ignite.IgniteCheckedException,public void ignoreInterrupts() ,public boolean isCancelled() ,public boolean isDone() ,public boolean isFailed() ,public void listen(IgniteInClosure<? super IgniteInternalFuture<org.apache.ignite.internal.processors.marshaller.MappingExchangeResult>>) ,public void listen(org.apache.ignite.lang.IgniteRunnable) ,public org.apache.ignite.IgniteLogger logger() ,public boolean onCancelled() ,public final boolean onDone() ,public final boolean onDone(org.apache.ignite.internal.processors.marshaller.MappingExchangeResult) ,public final boolean onDone(java.lang.Throwable) ,public boolean onDone(org.apache.ignite.internal.processors.marshaller.MappingExchangeResult, java.lang.Throwable) ,public void reset() ,public org.apache.ignite.internal.processors.marshaller.MappingExchangeResult result() ,public java.lang.String toString() <variables>private static final java.lang.Object CANCELLED,private static final java.lang.String DONE,private static final org.apache.ignite.internal.util.future.GridFutureAdapter.Node INIT,private volatile boolean ignoreInterrupts,private volatile java.lang.Object state,private static final AtomicReferenceFieldUpdater<GridFutureAdapter#RAW,java.lang.Object> stateUpdater