/** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  @Override
  public CacheQueryFuture<?> queryFieldsDistributed(
      GridCacheQueryBean qry, Collection<ClusterNode> nodes) {
    assert cctx.config().getCacheMode() != LOCAL;

    if (log.isDebugEnabled()) log.debug("Executing distributed query: " + qry);

    long reqId = cctx.io().nextIoId();

    final GridCacheDistributedFieldsQueryFuture fut =
        new GridCacheDistributedFieldsQueryFuture(cctx, reqId, qry, nodes);

    try {
      qry.query().validate();

      GridCacheQueryRequest req =
          new GridCacheQueryRequest(
              cctx.cacheId(),
              reqId,
              cctx.name(),
              qry.query().type(),
              true,
              qry.query().clause(),
              null,
              null,
              null,
              qry.reducer(),
              qry.transform(),
              qry.query().pageSize(),
              qry.query().includeBackups(),
              qry.arguments(),
              qry.query().includeMetadata(),
              qry.query().keepPortable(),
              qry.query().subjectId(),
              qry.query().taskHash());

      addQueryFuture(req.id(), fut);

      final Object topic = topic(cctx.nodeId(), req.id());

      cctx.io().addOrderedHandler(topic, resHnd);

      fut.listen(
          new CI1<IgniteInternalFuture<?>>() {
            @Override
            public void apply(IgniteInternalFuture<?> fut) {
              cctx.io().removeOrderedHandler(topic);
            }
          });

      sendRequest(fut, req, nodes);
    } catch (IgniteCheckedException e) {
      fut.onDone(e);
    }

    return fut;
  }
  /**
   * Processes cache query response.
   *
   * @param sndId Sender node id.
   * @param res Query response.
   */
  @SuppressWarnings("unchecked")
  private void processQueryResponse(UUID sndId, GridCacheQueryResponse res) {
    if (log.isDebugEnabled()) log.debug("Received query response: " + res);

    GridCacheQueryFutureAdapter fut = getQueryFuture(res.requestId());

    if (fut != null)
      if (res.fields())
        ((GridCacheDistributedFieldsQueryFuture) fut)
            .onPage(
                sndId,
                res.metadata(),
                (Collection<Map<String, Object>>) ((Collection) res.data()),
                res.error(),
                res.isFinished());
      else fut.onPage(sndId, res.data(), res.error(), res.isFinished());
    else if (!cancelled.contains(res.requestId()))
      U.warn(
          log,
          "Received response for finished or unknown query [rmtNodeId="
              + sndId
              + ", res="
              + res
              + ']');
  }