ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [12/65] [abbrv] incubator-ignite git commit: # ignite-63
Date Thu, 22 Jan 2015 21:26:59 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTaskResultBean.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTaskResultBean.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTaskResultBean.java
new file mode 100644
index 0000000..dbd18fd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTaskResultBean.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.client.message;
+
+import org.apache.ignite.internal.util.portable.*;
+import org.apache.ignite.portables.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+import java.io.*;
+
+/**
+ * Task result.
+ */
+public class GridClientTaskResultBean implements Externalizable, PortableMarshalAware {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Synthetic ID containing task ID and result holding node ID. */
+    private String id;
+
+    /** Execution finished flag. */
+    private boolean finished;
+
+    /** Result. */
+    private Object res;
+
+    /** Error if any occurs while execution. */
+    private String error;
+
+    /**
+     * @return Task ID.
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * @param id Task ID.
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * @return {@code true} if execution finished.
+     */
+    public boolean isFinished() {
+        return finished;
+    }
+
+    /**
+     * @param finished {@code true} if execution finished.
+     */
+    public void setFinished(boolean finished) {
+        this.finished = finished;
+    }
+
+    /**
+     * @return Task result.
+     */
+    @SuppressWarnings("unchecked")
+    public <R> R getResult() {
+        return (R)res;
+    }
+
+    /**
+     * @param res Task result.
+     */
+    public void setResult(Object res) {
+        this.res = res;
+    }
+
+    /**
+     * @return Error.
+     */
+    public String getError() {
+        return error;
+    }
+
+    /**
+     * @param error Error.
+     */
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writePortable(PortableWriter writer) throws PortableException {
+        PortableRawWriterEx raw = (PortableRawWriterEx)writer.rawWriter();
+
+        raw.writeString(id);
+        raw.writeBoolean(finished);
+
+        raw.writeObject(res);
+
+        raw.writeString(error);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readPortable(PortableReader reader) throws PortableException {
+        PortableRawReaderEx raw = (PortableRawReaderEx)reader.rawReader();
+
+        id = raw.readString();
+        finished = raw.readBoolean();
+
+        res = raw.readObject();
+
+        error = raw.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        U.writeString(out, id);
+        out.writeBoolean(finished);
+        out.writeObject(res);
+        U.writeString(out, error);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        id = U.readString(in);
+        finished = in.readBoolean();
+        res = in.readObject();
+        error = U.readString(in);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return getClass().getSimpleName() + " [res=" + res + ", error=" + error +
+            ", finished=" + finished + ", id=" + id + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTopologyRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTopologyRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTopologyRequest.java
new file mode 100644
index 0000000..9c87c63
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientTopologyRequest.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.client.message;
+
+import org.apache.ignite.portables.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * {@code Topology} command request.
+ */
+public class GridClientTopologyRequest extends GridClientAbstractMessage {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Id of requested node. */
+    private UUID nodeId;
+
+    /** IP address of requested node. */
+    private String nodeIp;
+
+    /** Include metrics flag. */
+    private boolean includeMetrics;
+
+    /** Include node attributes flag. */
+    private boolean includeAttrs;
+
+    /**
+     * @return Include metrics flag.
+     */
+    public boolean includeMetrics() {
+        return includeMetrics;
+    }
+
+    /**
+     * @param includeMetrics Include metrics flag.
+     */
+    public void includeMetrics(boolean includeMetrics) {
+        this.includeMetrics = includeMetrics;
+    }
+
+    /**
+     * @return Include node attributes flag.
+     */
+    public boolean includeAttributes() {
+        return includeAttrs;
+    }
+
+    /**
+     * @param includeAttrs Include node attributes flag.
+     */
+    public void includeAttributes(boolean includeAttrs) {
+        this.includeAttrs = includeAttrs;
+    }
+
+    /**
+     * @return Node identifier, if specified, {@code null} otherwise.
+     */
+    public UUID nodeId() {
+        return nodeId;
+    }
+
+    /**
+     * @param nodeId Node identifier to lookup.
+     */
+    public void nodeId(UUID nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    /**
+     * @return Node ip address if specified, {@code null} otherwise.
+     */
+    public String nodeIp() {
+        return nodeIp;
+    }
+
+    /**
+     * @param nodeIp Node ip address to lookup.
+     */
+    public void nodeIp(String nodeIp) {
+        this.nodeIp = nodeIp;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        GridClientTopologyRequest other = (GridClientTopologyRequest)o;
+
+        return includeAttrs == other.includeAttrs &&
+            includeMetrics == other.includeMetrics;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return 31 * (includeMetrics ? 1 : 0) +
+            (includeAttrs ? 1 : 0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writePortable(PortableWriter writer) throws PortableException {
+        super.writePortable(writer);
+
+        PortableRawWriter raw = writer.rawWriter();
+
+        raw.writeUuid(nodeId);
+        raw.writeString(nodeIp);
+        raw.writeBoolean(includeMetrics);
+        raw.writeBoolean(includeAttrs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readPortable(PortableReader reader) throws PortableException {
+        super.readPortable(reader);
+
+        PortableRawReader raw = reader.rawReader();
+
+        nodeId = raw.readUuid();
+        nodeIp = raw.readString();
+        includeMetrics = raw.readBoolean();
+        includeAttrs = raw.readBoolean();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal(out);
+
+        U.writeUuid(out, nodeId);
+
+        U.writeString(out, nodeIp);
+
+        out.writeBoolean(includeMetrics);
+        out.writeBoolean(includeAttrs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        super.readExternal(in);
+
+        nodeId = U.readUuid(in);
+
+        nodeIp = U.readString(in);
+
+        includeMetrics = in.readBoolean();
+        includeAttrs = in.readBoolean();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return getClass().getSimpleName() + " [includeMetrics=" + includeMetrics +
+            ", includeAttrs=" + includeAttrs + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterRequest.java
new file mode 100644
index 0000000..34efcf6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterRequest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.client.message;
+
+import java.util.*;
+
+/**
+ * Container for routed message information.
+ */
+public class GridRouterRequest extends GridClientAbstractMessage {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Raw message. */
+    private final byte[] body;
+
+    /**
+     * @param body Message in raw form.
+     * @param clientId Client id.
+     * @param reqId Request id.
+     * @param destId Destination where this message should be delivered.
+     */
+    public GridRouterRequest(byte[] body, Long reqId, UUID clientId, UUID destId) {
+        this.body = body;
+        destinationId(destId);
+        clientId(clientId);
+        requestId(reqId);
+    }
+
+    /**
+     * @return Raw message.
+     */
+    public byte[] body() {
+        return body;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return "GridRouterRequest [clientId=" + clientId() + ", reqId=" + requestId() + ", " +
+            "destId=" + destinationId() + ", length=" + body.length + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterResponse.java
new file mode 100644
index 0000000..ce5104c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridRouterResponse.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.client.message;
+
+import java.util.*;
+
+/**
+ *
+ */
+public class GridRouterResponse extends GridClientAbstractMessage {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Raw message. */
+    private final byte[] body;
+
+    /** Error message. */
+    private final String errMsg;
+
+    /** Status. */
+    private final int status;
+
+    /**
+     * @param body Message in raw form.
+     * @param clientId Client id.
+     * @param reqId Request id.
+     * @param destId Destination where this message should be delivered.
+     */
+    public GridRouterResponse(byte[] body, Long reqId, UUID clientId, UUID destId) {
+        this.body = body;
+        errMsg = null;
+        status = GridClientResponse.STATUS_SUCCESS;
+
+        destinationId(destId);
+        clientId(clientId);
+        requestId(reqId);
+    }
+
+    /**
+     * @return Response body.
+     */
+    public byte[] body() {
+        return body;
+    }
+
+    /**
+     * @return Error message.
+     */
+    public String errorMessage() {
+        return errMsg;
+    }
+
+    /**
+     * @return Status.
+     */
+    public int status() {
+        return status;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return "GridRoutedResponse [" +
+            "clientId=" + clientId() +
+            ", reqId=" + requestId() +
+            ", destId=" + destinationId() +
+            ", status=" + status +
+            ", errMsg=" + errorMessage() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/package.html b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/package.html
new file mode 100644
index 0000000..9cf3550
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/package.html
@@ -0,0 +1,23 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<body>
+<!-- Package description. -->
+    Defines messages that are used in binary TCP communication between GridGain clients and nodes.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandler.java
new file mode 100644
index 0000000..1f585ce
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers;
+
+import org.apache.ignite.lang.*;
+import org.apache.ignite.internal.processors.rest.*;
+import org.apache.ignite.internal.processors.rest.request.*;
+
+import java.util.*;
+
+/**
+ * Command handler.
+ */
+public interface GridRestCommandHandler {
+    /**
+     * @return Collection of supported commands.
+     */
+    public Collection<GridRestCommand> supportedCommands();
+
+    /**
+     * @param req Request.
+     * @return Future.
+     */
+    public IgniteFuture<GridRestResponse> handleAsync(GridRestRequest req);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandlerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandlerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandlerAdapter.java
new file mode 100644
index 0000000..2fd0f2d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/GridRestCommandHandlerAdapter.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers;
+
+import org.apache.ignite.*;
+import org.apache.ignite.internal.*;
+
+/**
+ * Abstract command handler.
+ */
+public abstract class GridRestCommandHandlerAdapter implements GridRestCommandHandler {
+    /** Kernal context. */
+    protected final GridKernalContext ctx;
+
+    /** Log. */
+    protected final IgniteLogger log;
+
+    /**
+     * @param ctx Context.
+     */
+    protected GridRestCommandHandlerAdapter(GridKernalContext ctx) {
+        this.ctx = ctx;
+
+        log = ctx.log(getClass());
+    }
+
+    /**
+     * Return missing parameter error message.
+     *
+     * @param param Parameter name.
+     * @return Missing parameter error message.
+     */
+    protected static String missingParameter(String param) {
+        return "Failed to find mandatory parameter in request: " + param;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheClientQueryResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheClientQueryResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheClientQueryResult.java
new file mode 100644
index 0000000..fc845c4
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheClientQueryResult.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers.cache;
+
+import org.apache.ignite.portables.*;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Client query result.
+ */
+public class GridCacheClientQueryResult implements PortableMarshalAware, Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Query ID. */
+    private long qryId;
+
+    /** Result items. */
+    private Collection<?> items;
+
+    /** Last flag. */
+    private boolean last;
+
+    /** Node ID. */
+    private UUID nodeId;
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return qryId;
+    }
+
+    /**
+     * @param qryId Query ID.
+     */
+    public void queryId(long qryId) {
+        this.qryId = qryId;
+    }
+
+    /**
+     * @return Items.
+     */
+    public Collection<?> items() {
+        return items;
+    }
+
+    /**
+     * @param items Items.
+     */
+    public void items(Collection<?> items) {
+        this.items = items;
+    }
+
+    /**
+     * @return Last flag.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /**
+     * @param last Last flag.
+     */
+    public void last(boolean last) {
+        this.last = last;
+    }
+
+    /**
+     * @return Node ID.
+     */
+    public UUID nodeId() {
+        return nodeId;
+    }
+
+    /**
+     * @param nodeId Node ID.
+     */
+    public void nodeId(UUID nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writePortable(PortableWriter writer) throws PortableException {
+        PortableRawWriter rawWriter = writer.rawWriter();
+
+        rawWriter.writeBoolean(last);
+        rawWriter.writeLong(qryId);
+        rawWriter.writeUuid(nodeId);
+        rawWriter.writeCollection(items);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readPortable(PortableReader reader) throws PortableException {
+        PortableRawReader rawReader = reader.rawReader();
+
+        last = rawReader.readBoolean();
+        qryId = rawReader.readLong();
+        nodeId = rawReader.readUuid();
+        items = rawReader.readCollection();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
new file mode 100644
index 0000000..43dff3b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
@@ -0,0 +1,1149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cache.datastructures.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.resources.*;
+import org.apache.ignite.transactions.*;
+import org.gridgain.grid.kernal.processors.cache.*;
+import org.apache.ignite.internal.processors.license.*;
+import org.apache.ignite.internal.processors.rest.*;
+import org.apache.ignite.internal.processors.rest.handlers.*;
+import org.apache.ignite.internal.processors.rest.request.*;
+import org.apache.ignite.internal.processors.task.*;
+import org.apache.ignite.internal.util.future.*;
+import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
+
+import javax.cache.expiry.*;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.transactions.IgniteTxConcurrency.*;
+import static org.apache.ignite.transactions.IgniteTxIsolation.*;
+import static org.apache.ignite.internal.processors.rest.GridRestCommand.*;
+import static org.apache.ignite.internal.processors.license.GridLicenseSubsystem.*;
+
+/**
+ * Command handler for API requests.
+ */
+public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
+    /** Supported commands. */
+    private static final Collection<GridRestCommand> SUPPORTED_COMMANDS = U.sealList(
+        CACHE_GET,
+        CACHE_GET_ALL,
+        CACHE_PUT,
+        CACHE_ADD,
+        CACHE_PUT_ALL,
+        CACHE_REMOVE,
+        CACHE_REMOVE_ALL,
+        CACHE_REPLACE,
+        CACHE_INCREMENT,
+        CACHE_DECREMENT,
+        CACHE_CAS,
+        CACHE_APPEND,
+        CACHE_PREPEND,
+        CACHE_METRICS
+    );
+
+    /** Requests with required parameter {@code key}. */
+    private static final EnumSet<GridRestCommand> KEY_REQUIRED_REQUESTS = EnumSet.of(
+        CACHE_GET,
+        CACHE_PUT,
+        CACHE_ADD,
+        CACHE_REMOVE,
+        CACHE_REPLACE,
+        CACHE_INCREMENT,
+        CACHE_DECREMENT,
+        CACHE_CAS,
+        CACHE_APPEND,
+        CACHE_PREPEND
+    );
+
+    /** */
+    private static final GridCacheFlag[] EMPTY_FLAGS = new GridCacheFlag[0];
+
+    /**
+     * @param ctx Context.
+     */
+    public GridCacheCommandHandler(GridKernalContext ctx) {
+        super(ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridRestCommand> supportedCommands() {
+        return SUPPORTED_COMMANDS;
+    }
+
+    /**
+     * Retrieves cache flags from corresponding bits.
+     *
+     * @param cacheFlagsBits Integer representation of cache flags bit set.
+     * @return Array of cache flags.
+     */
+    public static GridCacheFlag[] parseCacheFlags(int cacheFlagsBits) {
+        if (cacheFlagsBits == 0)
+            return EMPTY_FLAGS;
+
+        EnumSet<GridCacheFlag> flagSet = EnumSet.noneOf(GridCacheFlag.class);
+
+        if ((cacheFlagsBits & 1) != 0)
+            flagSet.add(GridCacheFlag.SKIP_STORE);
+
+        if ((cacheFlagsBits & (1 << 1)) != 0)
+            flagSet.add(GridCacheFlag.SKIP_SWAP);
+
+        if ((cacheFlagsBits & (1 << 2)) != 0)
+            flagSet.add(GridCacheFlag.SYNC_COMMIT);
+
+        if ((cacheFlagsBits & (1 << 4)) != 0)
+            flagSet.add(GridCacheFlag.INVALIDATE);
+
+        return flagSet.toArray(new GridCacheFlag[flagSet.size()]);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFuture<GridRestResponse> handleAsync(final GridRestRequest req) {
+        assert req instanceof GridRestCacheRequest : "Invalid command for topology handler: " + req;
+
+        assert SUPPORTED_COMMANDS.contains(req.command());
+
+        GridLicenseUseRegistry.onUsage(DATA_GRID, getClass());
+
+        if (log.isDebugEnabled())
+            log.debug("Handling cache REST request: " + req);
+
+        GridRestCacheRequest req0 = (GridRestCacheRequest)req;
+
+        final String cacheName = req0.cacheName();
+
+        final Object key = req0.key();
+
+        final GridCacheFlag[] flags = parseCacheFlags(req0.cacheFlags());
+
+        try {
+            GridRestCommand cmd = req0.command();
+
+            if (key == null && KEY_REQUIRED_REQUESTS.contains(cmd))
+                throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("key"));
+
+            final Long ttl = req0.ttl();
+
+            IgniteFuture<GridRestResponse> fut;
+
+            switch (cmd) {
+                case CACHE_GET: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new GetCommand(key), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_GET_ALL: {
+                    Set<Object> keys = req0.values().keySet();
+
+                    if (F.isEmpty(keys))
+                        throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("keys"));
+
+                    // HashSet wrapping for correct serialization
+                    keys = new HashSet<>(keys);
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new GetAllCommand(keys), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_PUT: {
+                    final Object val = req0.value();
+
+                    if (val == null)
+                        throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("val"));
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key, new
+                        PutCommand(key, ttl, val), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_ADD: {
+                    final Object val = req0.value();
+
+                    if (val == null)
+                        throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("val"));
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new AddCommand(key, ttl, val), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_PUT_ALL: {
+                    Map<Object, Object> map = req0.values();
+
+                    if (F.isEmpty(map))
+                        throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("values"));
+
+                    for (Map.Entry<Object, Object> e : map.entrySet()) {
+                        if (e.getKey() == null)
+                            throw new IgniteCheckedException("Failing putAll operation (null keys are not allowed).");
+
+                        if (e.getValue() == null)
+                            throw new IgniteCheckedException("Failing putAll operation (null values are not allowed).");
+                    }
+
+                    // HashMap wrapping for correct serialization
+                    map = new HashMap<>(map);
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new PutAllCommand(map), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_REMOVE: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new RemoveCommand(key), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_REMOVE_ALL: {
+                    Map<Object, Object> map = req0.values();
+
+                    // HashSet wrapping for correct serialization
+                    Set<Object> keys = map == null ? null : new HashSet<>(map.keySet());
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new RemoveAllCommand(keys), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_REPLACE: {
+                    final Object val = req0.value();
+
+                    if (val == null)
+                        throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("val"));
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new ReplaceCommand(key, ttl, val), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_INCREMENT: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, key,
+                        new IncrementCommand(key, req0));
+
+                    break;
+                }
+
+                case CACHE_DECREMENT: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, key,
+                        new DecrementCommand(key, req0));
+
+                    break;
+                }
+
+                case CACHE_CAS: {
+                    final Object val1 = req0.value();
+                    final Object val2 = req0.value2();
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new CasCommand(val2, val1, key), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_APPEND: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new AppendCommand(key, req0), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_PREPEND: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, flags, key,
+                        new PrependCommand(key, req0), req.portableMode());
+
+                    break;
+                }
+
+                case CACHE_METRICS: {
+                    fut = executeCommand(req.destinationId(), req.clientId(), cacheName, key, new MetricsCommand());
+
+                    break;
+                }
+
+                default:
+                    throw new IllegalArgumentException("Invalid command for cache handler: " + req);
+            }
+
+            return fut;
+        }
+        catch (IgniteException e) {
+            U.error(log, "Failed to execute cache command: " + req, e);
+
+            return new GridFinishedFuture<>(ctx, e);
+        }
+        catch (IgniteCheckedException e) {
+            U.error(log, "Failed to execute cache command: " + req, e);
+
+            return new GridFinishedFuture<>(ctx, e);
+        }
+        finally {
+            if (log.isDebugEnabled())
+                log.debug("Handled cache REST request: " + req);
+        }
+    }
+
+    /**
+     * Executes command on flagged cache projection. Checks {@code destId} to find
+     * if command could be performed locally or routed to a remote node.
+     *
+     * @param destId Target node Id for the operation.
+     *      If {@code null} - operation could be executed anywhere.
+     * @param clientId Client ID.
+     * @param cacheName Cache name.
+     * @param flags Cache flags.
+     * @param key Key to set affinity mapping in the response.
+     * @param op Operation to perform.
+     * @param keepPortable Keep portable flag.
+     * @return Operation result in future.
+     * @throws IgniteCheckedException If failed
+     */
+    private IgniteFuture<GridRestResponse> executeCommand(
+        @Nullable UUID destId,
+        UUID clientId,
+        final String cacheName,
+        final GridCacheFlag[] flags,
+        final Object key,
+        final CacheProjectionCommand op,
+        final boolean keepPortable) throws IgniteCheckedException {
+
+        final boolean locExec =
+            destId == null || destId.equals(ctx.localNodeId()) || replicatedCacheAvailable(cacheName);
+
+        if (locExec) {
+            GridCacheProjection<?,?> prj = localCache(cacheName).forSubjectId(clientId).flagsOn(flags);
+
+            if (keepPortable)
+                prj = prj.keepPortable();
+
+            return op.apply((GridCacheProjection<Object, Object>)prj, ctx).
+                chain(resultWrapper((GridCacheProjection<Object, Object>)prj, key));
+        }
+        else {
+            ClusterGroup prj = ctx.grid().forPredicate(F.nodeForNodeId(destId));
+
+            IgniteCompute comp = ctx.grid().compute(prj).withNoFailover().enableAsync();
+
+            comp.call(new FlaggedCacheOperationCallable(clientId, cacheName, flags, op, key, keepPortable));
+
+            return comp.future();
+        }
+    }
+
+    /**
+     * Executes command on cache. Checks {@code destId} to find
+     * if command could be performed locally or routed to a remote node.
+     *
+     * @param destId Target node Id for the operation.
+     *      If {@code null} - operation could be executed anywhere.
+     * @param clientId Client ID.
+     * @param cacheName Cache name.
+     * @param key Key to set affinity mapping in the response.
+     * @param op Operation to perform.
+     * @return Operation result in future.
+     * @throws IgniteCheckedException If failed
+     */
+    private IgniteFuture<GridRestResponse> executeCommand(
+        @Nullable UUID destId,
+        UUID clientId,
+        final String cacheName,
+        final Object key,
+        final CacheCommand op) throws IgniteCheckedException {
+        final boolean locExec = destId == null || destId.equals(ctx.localNodeId()) ||
+            ctx.cache().cache(cacheName) != null;
+
+        if (locExec) {
+            final GridCacheProjection<Object, Object> cache = localCache(cacheName).forSubjectId(clientId);
+
+            return op.apply(cache, ctx).chain(resultWrapper(cache, key));
+        }
+        else {
+            ClusterGroup prj = ctx.grid().forPredicate(F.nodeForNodeId(destId));
+
+            IgniteCompute comp = ctx.grid().compute(prj).withNoFailover().enableAsync();
+
+            comp.call(new CacheOperationCallable(clientId, cacheName, op, key));
+
+            return comp.future();
+        }
+    }
+
+    /**
+     * Handles increment and decrement commands.
+     *
+     * @param cache Cache.
+     * @param key Key.
+     * @param req Request.
+     * @param decr Whether to decrement (increment otherwise).
+     * @return Future of operation result.
+     * @throws IgniteCheckedException In case of error.
+     */
+    private static IgniteFuture<?> incrementOrDecrement(GridCacheProjection<Object, Object> cache, String key,
+        GridRestCacheRequest req, final boolean decr) throws IgniteCheckedException {
+        assert cache != null;
+        assert key != null;
+        assert req != null;
+
+        Long init = req.initial();
+        Long delta = req.delta();
+
+        if (delta == null)
+            throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("delta"));
+
+        final GridCacheAtomicLong l = cache.cache().dataStructures().atomicLong(key, init != null ? init : 0, true);
+
+        final Long d = delta;
+
+        return ((GridKernal)cache.gridProjection().ignite()).context().closure().callLocalSafe(new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                return l.addAndGet(decr ? -d : d);
+            }
+        }, false);
+    }
+
+    /**
+     * Handles append and prepend commands.
+     *
+     * @param ctx Kernal context.
+     * @param cache Cache.
+     * @param key Key.
+     * @param req Request.
+     * @param prepend Whether to prepend.
+     * @return Future of operation result.
+     * @throws IgniteCheckedException In case of any exception.
+     */
+    private static IgniteFuture<?> appendOrPrepend(
+        final GridKernalContext ctx,
+        final GridCacheProjection<Object, Object> cache,
+        final Object key, GridRestCacheRequest req, final boolean prepend) throws IgniteCheckedException {
+        assert cache != null;
+        assert key != null;
+        assert req != null;
+
+        final Object val = req.value();
+
+        if (val == null)
+            throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("val"));
+
+        return ctx.closure().callLocalSafe(new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                try (IgniteTx tx = cache.txStart(PESSIMISTIC, REPEATABLE_READ)) {
+                    Object curVal = cache.get(key);
+
+                    if (curVal == null)
+                        return false;
+
+                    // Modify current value with appendix one.
+                    Object newVal = appendOrPrepend(curVal, val, !prepend);
+
+                    // Put new value asynchronously.
+                    cache.putx(key, newVal);
+
+                    tx.commit();
+                }
+
+                return true;
+            }
+        }, false);
+    }
+
+    /**
+     * Append or prepend new value to the current one.
+     *
+     * @param origVal Original value.
+     * @param appendVal Appendix value to add to the original one.
+     * @param appendPlc Append or prepend policy flag.
+     * @return Resulting value.
+     * @throws IgniteCheckedException In case of grid exceptions.
+     */
+    private static Object appendOrPrepend(Object origVal, Object appendVal, boolean appendPlc) throws IgniteCheckedException {
+        // Strings.
+        if (appendVal instanceof String && origVal instanceof String)
+            return appendPlc ? origVal + (String)appendVal : (String)appendVal + origVal;
+
+        // Maps.
+        if (appendVal instanceof Map && origVal instanceof Map) {
+            Map<Object, Object> origMap = (Map<Object, Object>)origVal;
+            Map<Object, Object> appendMap = (Map<Object, Object>)appendVal;
+
+            Map<Object, Object> map = X.cloneObject(origMap, false, true);
+
+            if (appendPlc)
+                map.putAll(appendMap); // Append.
+            else {
+                map.clear();
+                map.putAll(appendMap); // Prepend.
+                map.putAll(origMap);
+            }
+
+            for (Map.Entry<Object, Object> e : appendMap.entrySet()) // Remove zero-valued entries.
+                if (e.getValue() == null && map.get(e.getKey()) == null)
+                    map.remove(e.getKey());
+
+            return map;
+        }
+
+        // Generic collection.
+        if (appendVal instanceof Collection<?> && origVal instanceof Collection<?>) {
+            Collection<Object> origCol = (Collection<Object>)origVal;
+            Collection<Object> appendCol = (Collection<Object>)appendVal;
+
+            Collection<Object> col = X.cloneObject(origCol, false, true);
+
+            if (appendPlc)
+                col.addAll(appendCol); // Append.
+            else {
+                col.clear();
+                col.addAll(appendCol); // Prepend.
+                col.addAll(origCol);
+            }
+
+            return col;
+        }
+
+        throw new IgniteCheckedException("Incompatible types [appendVal=" + appendVal + ", old=" + origVal + ']');
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridCacheCommandHandler.class, this);
+    }
+
+    /**
+     * Creates a transformation function from {@link CacheCommand}'s results into {@link GridRestResponse}.
+     *
+     * @param c Cache instance to obtain affinity data.
+     * @param key Affinity key for previous operation.
+     * @return Rest response.
+     */
+    private static IgniteClosure<IgniteFuture<?>, GridRestResponse> resultWrapper(
+        final GridCacheProjection<Object, Object> c, @Nullable final Object key) {
+        return new CX1<IgniteFuture<?>, GridRestResponse>() {
+            @Override public GridRestResponse applyx(IgniteFuture<?> f) throws IgniteCheckedException {
+                GridCacheRestResponse resp = new GridCacheRestResponse();
+
+                resp.setResponse(f.get());
+
+                if (key != null)
+                    resp.setAffinityNodeId(c.cache().affinity().mapKeyToNode(key).id().toString());
+
+                return resp;
+            }
+        };
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @return If replicated cache with given name is locally available.
+     */
+    private boolean replicatedCacheAvailable(String cacheName) {
+        GridCacheAdapter<Object,Object> cache = ctx.cache().internalCache(cacheName);
+
+        return cache != null && cache.configuration().getCacheMode() == GridCacheMode.REPLICATED;
+    }
+
+    /**
+     * Used for test purposes.
+     *
+     * @param cacheName Name of the cache.
+     * @return Instance on the named cache.
+     * @throws IgniteCheckedException If cache not found.
+     */
+    protected GridCacheProjectionEx<Object, Object> localCache(String cacheName) throws IgniteCheckedException {
+        GridCacheProjectionEx<Object, Object> cache = (GridCacheProjectionEx<Object, Object>)ctx.cache().cache(cacheName);
+
+        if (cache == null)
+            throw new IgniteCheckedException(
+                "Failed to find cache for given cache name (null for default cache): " + cacheName);
+
+        return cache;
+    }
+
+    /**
+     * @param ignite Grid instance.
+     * @param cacheName Name of the cache.
+     * @return Instance on the named cache.
+     * @throws IgniteCheckedException If cache not found.
+     */
+    private static GridCacheProjectionEx<Object, Object> cache(Ignite ignite, String cacheName) throws IgniteCheckedException {
+        GridCache<Object, Object> cache = ignite.cache(cacheName);
+
+        if (cache == null)
+            throw new IgniteCheckedException(
+                "Failed to find cache for given cache name (null for default cache): " + cacheName);
+
+        return (GridCacheProjectionEx<Object, Object>)cache;
+    }
+
+    /**
+     * Fixed result closure.
+     */
+    private static final class FixedResult extends CX1<IgniteFuture<?>, Object> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Closure result. */
+        private final Object res;
+
+        /**
+         * @param res Closure result.
+         */
+        private FixedResult(Object res) {
+            this.res = res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object applyx(IgniteFuture<?> f) throws IgniteCheckedException {
+            f.get();
+
+            return res;
+        }
+    }
+
+    /**
+     * Type alias.
+     */
+    private abstract static class CacheCommand
+        extends IgniteClosure2X<GridCacheProjection<Object, Object>, GridKernalContext, IgniteFuture<?>> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        // No-op.
+    }
+
+    /**
+     * Type alias.
+     */
+    private abstract static class CacheProjectionCommand
+        extends IgniteClosure2X<GridCacheProjection<Object, Object>, GridKernalContext, IgniteFuture<?>> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        // No-op.
+    }
+
+    /**
+     * Class for flagged cache operations.
+     */
+    @GridInternal
+    private static class FlaggedCacheOperationCallable implements Callable<GridRestResponse>, Serializable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Client ID. */
+        private UUID clientId;
+
+        /** */
+        private final String cacheName;
+
+        /** */
+        private final GridCacheFlag[] flags;
+
+        /** */
+        private final CacheProjectionCommand op;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final boolean keepPortable;
+
+        /** */
+        @IgniteInstanceResource
+        private Ignite g;
+
+        /**
+         * @param clientId Client ID.
+         * @param cacheName Cache name.
+         * @param flags Flags.
+         * @param op Operation.
+         * @param key Key.
+         * @param keepPortable Keep portable flag.
+         */
+        private FlaggedCacheOperationCallable(UUID clientId, String cacheName, GridCacheFlag[] flags,
+            CacheProjectionCommand op, Object key, boolean keepPortable) {
+            this.clientId = clientId;
+            this.cacheName = cacheName;
+            this.flags = flags;
+            this.op = op;
+            this.key = key;
+            this.keepPortable = keepPortable;
+        }
+
+        /** {@inheritDoc} */
+        @Override public GridRestResponse call() throws Exception {
+            GridCacheProjection<?, ?> prj = cache(g, cacheName).forSubjectId(clientId).flagsOn(flags);
+
+            if (keepPortable)
+                prj = prj.keepPortable();
+
+            // Need to apply both operation and response transformation remotely
+            // as cache could be inaccessible on local node and
+            // exception processing should be consistent with local execution.
+            return op.apply((GridCacheProjection<Object, Object>)prj, ((GridKernal)g).context()).
+                chain(resultWrapper((GridCacheProjection<Object, Object>)prj, key)).get();
+        }
+    }
+
+    /**
+     * Class for cache operations.
+     */
+    @GridInternal
+    private static class CacheOperationCallable implements Callable<GridRestResponse>, Serializable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Client ID. */
+        private UUID clientId;
+
+        /** */
+        private final String cacheName;
+
+        /** */
+        private final CacheCommand op;
+
+        /** */
+        private final Object key;
+
+        /** */
+        @IgniteInstanceResource
+        private Ignite g;
+
+        /**
+         * @param clientId Client ID.
+         * @param cacheName Cache name.
+         * @param op Operation.
+         * @param key Key.
+         */
+        private CacheOperationCallable(UUID clientId, String cacheName, CacheCommand op, Object key) {
+            this.clientId = clientId;
+            this.cacheName = cacheName;
+            this.op = op;
+            this.key = key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public GridRestResponse call() throws Exception {
+            final GridCacheProjection<Object, Object> cache = cache(g, cacheName).forSubjectId(clientId);
+
+            // Need to apply both operation and response transformation remotely
+            // as cache could be inaccessible on local node and
+            // exception processing should be consistent with local execution.
+            return op.apply(cache, ((GridKernal)g).context()).chain(resultWrapper(cache, key)).get();
+        }
+    }
+
+    /** */
+    private static class GetCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /**
+         * @param key Key.
+         */
+        GetCommand(Object key) {
+            this.key = key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return c.getAsync(key);
+        }
+    }
+
+    /** */
+    private static class GetAllCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Collection<Object> keys;
+
+        /**
+         * @param keys Keys.
+         */
+        GetAllCommand(Collection<Object> keys) {
+            this.keys = keys;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return c.getAllAsync(keys);
+        }
+    }
+
+    /** */
+    private static class PutAllCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Map<Object, Object> map;
+
+        /**
+         * @param map Objects to put.
+         */
+        PutAllCommand(Map<Object, Object> map) {
+            this.map = map;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return c.putAllAsync(map).chain(new FixedResult(true));
+        }
+    }
+
+    /** */
+    private static class RemoveCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /**
+         * @param key Key.
+         */
+        RemoveCommand(Object key) {
+            this.key = key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return c.removexAsync(key);
+        }
+    }
+
+    /** */
+    private static class RemoveAllCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Collection<Object> keys;
+
+        /**
+         * @param keys Keys to remove.
+         */
+        RemoveAllCommand(Collection<Object> keys) {
+            this.keys = keys;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return (F.isEmpty(keys) ? c.removeAllAsync() : c.removeAllAsync(keys))
+                .chain(new FixedResult(true));
+        }
+    }
+
+    /** */
+    private static class CasCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object exp;
+
+        /** */
+        private final Object val;
+
+        /** */
+        private final Object key;
+
+        /**
+         * @param exp Expected previous value.
+         * @param val New value.
+         * @param key Key.
+         */
+        CasCommand(Object exp, Object val, Object key) {
+            this.val = val;
+            this.exp = exp;
+            this.key = key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            return exp == null && val == null ? c.removexAsync(key) :
+                exp == null ? c.putxIfAbsentAsync(key, val) :
+                    val == null ? c.removeAsync(key, exp) :
+                        c.replaceAsync(key, exp, val);
+        }
+    }
+
+    /** */
+    private static class PutCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final Long ttl;
+
+        /** */
+        private final Object val;
+
+        /**
+         * @param key Key.
+         * @param ttl TTL.
+         * @param val Value.
+         */
+        PutCommand(Object key, Long ttl, Object val) {
+            this.key = key;
+            this.ttl = ttl;
+            this.val = val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            if (ttl != null && ttl > 0) {
+                Duration duration = new Duration(MILLISECONDS, ttl);
+
+                c = ((GridCacheProjectionEx<Object, Object>)c).withExpiryPolicy(new ModifiedExpiryPolicy(duration));
+            }
+
+            return c.putxAsync(key, val);
+        }
+    }
+
+    /** */
+    private static class AddCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final Long ttl;
+
+        /** */
+        private final Object val;
+
+        /**
+         * @param key Key.
+         * @param ttl TTL.
+         * @param val Value.
+         */
+        AddCommand(Object key, Long ttl, Object val) {
+            this.key = key;
+            this.ttl = ttl;
+            this.val = val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            if (ttl != null && ttl > 0) {
+                Duration duration = new Duration(MILLISECONDS, ttl);
+
+                c = ((GridCacheProjectionEx<Object, Object>)c).withExpiryPolicy(new ModifiedExpiryPolicy(duration));
+            }
+
+            return c.putxIfAbsentAsync(key, val);
+        }
+    }
+
+    /** */
+    private static class ReplaceCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final Long ttl;
+
+        /** */
+        private final Object val;
+
+        /**
+         * @param key Key.
+         * @param ttl TTL.
+         * @param val Value.
+         */
+        ReplaceCommand(Object key, Long ttl, Object val) {
+            this.key = key;
+            this.ttl = ttl;
+            this.val = val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            if (ttl != null && ttl > 0) {
+                Duration duration = new Duration(MILLISECONDS, ttl);
+
+                c = ((GridCacheProjectionEx<Object, Object>)c).withExpiryPolicy(new ModifiedExpiryPolicy(duration));
+            }
+
+            return c.replacexAsync(key, val);
+        }
+    }
+
+    /** */
+    private static class IncrementCommand extends CacheCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final GridRestCacheRequest req;
+
+        /**
+         * @param key Key.
+         * @param req Operation request.
+         */
+        IncrementCommand(Object key, GridRestCacheRequest req) {
+            this.key = key;
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx)
+            throws IgniteCheckedException {
+            return incrementOrDecrement(c, (String)key, req, false);
+        }
+    }
+
+    /** */
+    private static class DecrementCommand extends CacheCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final GridRestCacheRequest req;
+
+        /**
+         * @param key Key.
+         * @param req Operation request.
+         */
+        DecrementCommand(Object key, GridRestCacheRequest req) {
+            this.key = key;
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) throws IgniteCheckedException {
+            return incrementOrDecrement(c, (String)key, req, true);
+        }
+    }
+
+    /** */
+    private static class AppendCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final GridRestCacheRequest req;
+
+        /**
+         * @param key Key.
+         * @param req Operation request.
+         */
+        AppendCommand(Object key, GridRestCacheRequest req) {
+            this.key = key;
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx)
+            throws IgniteCheckedException {
+            return appendOrPrepend(ctx, c, key, req, false);
+        }
+    }
+
+    /** */
+    private static class PrependCommand extends CacheProjectionCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final GridRestCacheRequest req;
+
+        /**
+         * @param key Key.
+         * @param req Operation request.
+         */
+        PrependCommand(Object key, GridRestCacheRequest req) {
+            this.key = key;
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx)
+            throws IgniteCheckedException {
+            return appendOrPrepend(ctx, c, key, req, true);
+        }
+    }
+
+    /** */
+    private static class MetricsCommand extends CacheCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** {@inheritDoc} */
+        @Override public IgniteFuture<?> applyx(GridCacheProjection<Object, Object> c, GridKernalContext ctx) {
+            GridCacheMetrics metrics = c.cache().metrics();
+
+            assert metrics != null;
+
+            return new GridFinishedFuture<Object>(ctx, new GridCacheRestMetrics(
+                metrics.createTime(), metrics.readTime(), metrics.writeTime(),
+                metrics.reads(), metrics.writes(), metrics.hits(), metrics.misses()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheQueryCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheQueryCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheQueryCommandHandler.java
new file mode 100644
index 0000000..c67dbd2
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheQueryCommandHandler.java
@@ -0,0 +1,493 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cache.query.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.resources.*;
+import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.cache.query.*;
+import org.apache.ignite.internal.processors.rest.*;
+import org.apache.ignite.internal.processors.rest.client.message.GridClientCacheQueryRequest;
+import org.apache.ignite.internal.processors.rest.handlers.*;
+import org.apache.ignite.internal.processors.rest.request.*;
+import org.apache.ignite.internal.util.future.*;
+import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import static org.apache.ignite.internal.processors.rest.GridRestCommand.*;
+
+/**
+ * Cache query command handler.
+ */
+public class GridCacheQueryCommandHandler extends GridRestCommandHandlerAdapter {
+    /** Supported commands. */
+    private static final Collection<GridRestCommand> SUPPORTED_COMMANDS = U.sealList(
+        CACHE_QUERY_EXECUTE,
+        CACHE_QUERY_FETCH,
+        CACHE_QUERY_REBUILD_INDEXES
+    );
+
+    /** Query ID sequence. */
+    private static final AtomicLong qryIdGen = new AtomicLong();
+
+    /**
+     * @param ctx Context.
+     */
+    public GridCacheQueryCommandHandler(GridKernalContext ctx) {
+        super(ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridRestCommand> supportedCommands() {
+        return SUPPORTED_COMMANDS;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFuture<GridRestResponse> handleAsync(GridRestRequest req) {
+        assert req instanceof GridRestCacheQueryRequest;
+        assert SUPPORTED_COMMANDS.contains(req.command());
+
+        GridRestCacheQueryRequest qryReq = (GridRestCacheQueryRequest)req;
+
+        UUID destId = qryReq.destinationId();
+        String cacheName = qryReq.cacheName();
+
+        switch (qryReq.command()) {
+            case CACHE_QUERY_EXECUTE: {
+                return execute(destId, cacheName, new ExecuteQuery(qryReq));
+            }
+
+            case CACHE_QUERY_FETCH: {
+                return execute(destId, cacheName, new FetchQueryResults(qryReq));
+            }
+
+            case CACHE_QUERY_REBUILD_INDEXES: {
+                return broadcast(qryReq.cacheName(), new RebuildIndexes(qryReq.cacheName(), qryReq.className()));
+            }
+
+            default:
+                return new GridFinishedFutureEx<>(new IgniteCheckedException("Unsupported query command: " + req.command()));
+        }
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @return If replicated cache with given name is locally available.
+     */
+    private boolean replicatedCacheAvailable(String cacheName) {
+        GridCacheAdapter<Object,Object> cache = ctx.cache().internalCache(cacheName);
+
+        return cache != null && cache.configuration().getCacheMode() == GridCacheMode.REPLICATED;
+    }
+
+    /**
+     * Executes given closure either locally or on specified node.
+     *
+     * @param destId Destination node ID.
+     * @param cacheName Cache name.
+     * @param c Closure to execute.
+     * @return Execution future.
+     */
+    private IgniteFuture<GridRestResponse> execute(UUID destId, String cacheName, Callable<GridRestResponse> c) {
+        boolean locExec = destId == null || destId.equals(ctx.localNodeId()) || replicatedCacheAvailable(cacheName);
+
+        if (locExec)
+            return ctx.closure().callLocalSafe(c, false);
+        else {
+            if (ctx.discovery().node(destId) == null)
+                return new GridFinishedFutureEx<>(new IgniteCheckedException("Destination node ID has left the grid (retry " +
+                    "the query): " + destId));
+
+            try {
+                IgniteCompute comp = ctx.grid().compute(ctx.grid().forNodeId(destId)).withNoFailover().enableAsync();
+
+                comp.call(c);
+
+                return comp.future();
+            }
+            catch (IgniteCheckedException e) {
+                // Should not be thrown since uses asynchronous execution.
+                return new GridFinishedFutureEx<>(e);
+            }
+        }
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param c Closure to execute.
+     * @return Execution future.
+     */
+    private IgniteFuture<GridRestResponse> broadcast(String cacheName, Callable<Object> c) {
+        IgniteCompute comp = ctx.grid().compute(ctx.grid().forCache(cacheName)).withNoFailover().enableAsync();
+
+        try {
+            comp.broadcast(c);
+
+            IgniteFuture<Collection<Object>> fut = comp.future();
+
+            return fut.chain(new C1<IgniteFuture<Collection<Object>>, GridRestResponse>() {
+                @Override public GridRestResponse apply(IgniteFuture<Collection<Object>> fut) {
+                    try {
+                        fut.get();
+
+                        return new GridRestResponse();
+                    }
+                    catch (IgniteCheckedException e) {
+                        throw new GridClosureException(e);
+                    }
+                }
+            });
+        }
+        catch (IgniteCheckedException e) {
+            // Should not be thrown since uses asynchronous execution.
+            return new GridFinishedFutureEx<>(e);
+        }
+    }
+
+    /**
+     * @param qryId Query ID.
+     * @param wrapper Query future wrapper.
+     * @param locMap Queries map.
+     * @param locNodeId Local node ID.
+     * @return Rest response.
+     * @throws IgniteCheckedException If failed.
+     */
+    private static GridRestResponse fetchQueryResults(
+        long qryId,
+        QueryFutureWrapper wrapper,
+        ConcurrentMap<QueryExecutionKey, QueryFutureWrapper> locMap,
+        UUID locNodeId
+    ) throws IgniteCheckedException {
+        if (wrapper == null)
+            throw new IgniteCheckedException("Failed to find query future (query has been expired).");
+
+        GridCacheQueryFutureAdapter<?, ?, ?> fut = wrapper.future();
+
+        Collection<Object> col = (Collection<Object>)fut.nextPage();
+
+        GridCacheRestResponse res = new GridCacheRestResponse();
+
+        GridCacheClientQueryResult qryRes = new GridCacheClientQueryResult();
+
+        if (col == null) {
+            col = Collections.emptyList();
+
+            qryRes.last(true);
+
+            locMap.remove(new QueryExecutionKey(qryId), wrapper);
+        }
+
+        qryRes.items(col);
+        qryRes.queryId(qryId);
+        qryRes.nodeId(locNodeId);
+
+        res.setResponse(qryRes);
+
+        return res;
+    }
+
+    /**
+     * Creates class instance.
+     *
+     * @param cls Target class.
+     * @param clsName Implementing class name.
+     * @return Class instance.
+     * @throws IgniteCheckedException If failed.
+     */
+    private static <T> T instance(Class<? extends T> cls, String clsName) throws IgniteCheckedException {
+        try {
+            Class<?> implCls = Class.forName(clsName);
+
+            if (!cls.isAssignableFrom(implCls))
+                throw new IgniteCheckedException("Failed to create instance (target class does not extend or implement " +
+                    "required class or interface) [cls=" + cls.getName() + ", clsName=" + clsName + ']');
+
+            Constructor<?> ctor = implCls.getConstructor();
+
+            return (T)ctor.newInstance();
+        }
+        catch (ClassNotFoundException e) {
+            throw new IgniteCheckedException("Failed to find target class: " + clsName, e);
+        }
+        catch (NoSuchMethodException e) {
+            throw new IgniteCheckedException("Failed to find constructor for provided arguments " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (InstantiationException e) {
+            throw new IgniteCheckedException("Failed to instantiate target class " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (IllegalAccessException e) {
+            throw new IgniteCheckedException("Failed to instantiate class (constructor is not available) " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (InvocationTargetException e) {
+            throw new IgniteCheckedException("Failed to instantiate class (constructor threw an exception) " +
+                "[clsName=" + clsName + ']', e.getCause());
+        }
+    }
+
+    /**
+     *
+     */
+    private static class ExecuteQuery implements IgniteCallable<GridRestResponse> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Injected grid. */
+        @IgniteInstanceResource
+        private Ignite g;
+
+        /** Query request. */
+        private GridRestCacheQueryRequest req;
+
+        /**
+         * @param req Request.
+         */
+        private ExecuteQuery(GridRestCacheQueryRequest req) {
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings({"unchecked", "IfMayBeConditional"})
+        @Override public GridRestResponse call() throws Exception {
+            long qryId = qryIdGen.getAndIncrement();
+
+            GridCacheQueries<Object,Object> queries = g.cache(req.cacheName()).queries();
+
+            GridCacheQuery<?> qry;
+
+            switch (req.type()) {
+                case SQL:
+                    qry = queries.createSqlQuery(req.className(), req.clause());
+
+                    break;
+
+                case SQL_FIELDS:
+                    qry = queries.createSqlFieldsQuery(req.clause());
+
+                    break;
+
+                case FULL_TEXT:
+                    qry = queries.createFullTextQuery(req.className(), req.clause());
+
+                    break;
+
+                case SCAN:
+                    qry = queries.createScanQuery(instance(IgniteBiPredicate.class, req.className()));
+
+                    break;
+
+                default:
+                    throw new IgniteCheckedException("Unsupported query type: " + req.type());
+            }
+
+            boolean keepPortable = req.keepPortable();
+
+            if (!keepPortable) {
+                if (req.type() != GridClientCacheQueryRequest.GridQueryType.SCAN &&
+                    (req.remoteReducerClassName() == null && req.remoteTransformerClassName() == null))
+                    // Do not deserialize values on server if not needed.
+                    keepPortable = true;
+            }
+
+            ((GridCacheQueryAdapter)qry).keepPortable(keepPortable);
+            ((GridCacheQueryAdapter)qry).subjectId(req.clientId());
+
+            if (req.pageSize() > 0)
+                qry = qry.pageSize(req.pageSize());
+
+            if (req.timeout() > 0)
+                qry = qry.timeout(req.timeout());
+
+            qry = qry.includeBackups(req.includeBackups()).enableDedup(req.enableDedup()).keepAll(false);
+
+            GridCacheQueryFutureAdapter<?, ?, ?> fut;
+
+            if (req.remoteReducerClassName() != null)
+                fut = (GridCacheQueryFutureAdapter<?, ?, ?>)qry.execute(
+                    instance(IgniteReducer.class, req.remoteReducerClassName()),
+                    req.queryArguments());
+            else if (req.remoteTransformerClassName() != null)
+                fut = (GridCacheQueryFutureAdapter<?, ?, ?>)qry.execute(
+                    instance(IgniteClosure.class, req.remoteTransformerClassName()),
+                    req.queryArguments());
+            else
+                fut = (GridCacheQueryFutureAdapter<?, ?, ?>)qry.execute(req.queryArguments());
+
+            ClusterNodeLocalMap<QueryExecutionKey, QueryFutureWrapper> locMap =
+                g.cluster().nodeLocalMap();
+
+            QueryFutureWrapper wrapper = new QueryFutureWrapper(fut);
+
+            QueryFutureWrapper old = locMap.putIfAbsent(new QueryExecutionKey(qryId), wrapper);
+
+            assert old == null;
+
+            return fetchQueryResults(qryId, wrapper, locMap, g.cluster().localNode().id());
+        }
+    }
+
+    /**
+     *
+     */
+    private static class FetchQueryResults implements IgniteCallable<GridRestResponse> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Injected grid. */
+        @IgniteInstanceResource
+        private Ignite g;
+
+        /** Query request. */
+        private GridRestCacheQueryRequest req;
+
+        /**
+         * @param req Request.
+         */
+        private FetchQueryResults(GridRestCacheQueryRequest req) {
+            this.req = req;
+        }
+
+        /** {@inheritDoc} */
+        @Override public GridRestResponse call() throws Exception {
+            ClusterNodeLocalMap<QueryExecutionKey, QueryFutureWrapper> locMap =
+                g.cluster().nodeLocalMap();
+
+            return fetchQueryResults(req.queryId(), locMap.get(new QueryExecutionKey(req.queryId())),
+                locMap, g.cluster().localNode().id());
+        }
+    }
+
+    /**
+     * Rebuild indexes closure.
+     */
+    private static class RebuildIndexes implements IgniteCallable<Object> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Injected grid. */
+        @IgniteInstanceResource
+        private Ignite g;
+
+        /** Cache name. */
+        private String cacheName;
+
+        /** Class name. */
+        private String clsName;
+
+        /**
+         * @param cacheName Cache name.
+         * @param clsName Optional class name to rebuild indexes for.
+         */
+        private RebuildIndexes(String cacheName, String clsName) {
+            this.cacheName = cacheName;
+            this.clsName = clsName;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object call() throws Exception {
+            if (clsName == null)
+                g.cache(cacheName).queries().rebuildAllIndexes();
+            else
+                g.cache(cacheName).queries().rebuildIndexes(clsName);
+
+            return null;
+        }
+    }
+
+    /**
+     *
+     */
+    private static class QueryExecutionKey {
+        /** Query ID. */
+        private long qryId;
+
+        /**
+         * @param qryId Query ID.
+         */
+        private QueryExecutionKey(long qryId) {
+            this.qryId = qryId;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof QueryExecutionKey))
+                return false;
+
+            QueryExecutionKey that = (QueryExecutionKey)o;
+
+            return qryId == that.qryId;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return (int)(qryId ^ (qryId >>> 32));
+        }
+    }
+
+    /**
+     * Query future wrapper.
+     */
+    private static class QueryFutureWrapper {
+        /** Query future. */
+        private final GridCacheQueryFutureAdapter<?, ?, ?> qryFut;
+
+        /** Last future use timestamp. */
+        private volatile long lastUseTs;
+
+        /**
+         * @param qryFut Query future.
+         */
+        private QueryFutureWrapper(GridCacheQueryFutureAdapter<?, ?, ?> qryFut) {
+            this.qryFut = qryFut;
+
+            lastUseTs = U.currentTimeMillis();
+        }
+
+        /**
+         * @return Query future.
+         */
+        private GridCacheQueryFutureAdapter<?, ?, ?> future() {
+            lastUseTs = U.currentTimeMillis();
+
+            return qryFut;
+        }
+
+        /**
+         * @return Last use timestamp.
+         */
+        private long lastUseTimestamp() {
+            return lastUseTs;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1b0e45a2/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheRestMetrics.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheRestMetrics.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheRestMetrics.java
new file mode 100644
index 0000000..f7d45c0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheRestMetrics.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers.cache;
+
+import org.apache.ignite.internal.util.*;
+
+import java.util.*;
+
+/**
+ * Grid cache metrics for rest.
+ */
+public class GridCacheRestMetrics {
+    /** Create time. */
+    private long createTime;
+
+    /** Last read time. */
+    private long readTime;
+
+    /** Last update time. */
+    private long writeTime;
+
+    /** Number of reads. */
+    private int reads;
+
+    /** Number of writes. */
+    private int writes;
+
+    /** Number of hits. */
+    private int hits;
+
+    /** Number of misses. */
+    private int misses;
+
+    /**
+     * Constructor.
+     *
+     * @param createTime Create time.
+     * @param readTime Read time.
+     * @param writeTime Write time.
+     * @param reads Reads.
+     * @param writes Writes.
+     * @param hits Hits.
+     * @param misses Misses.
+     */
+    public GridCacheRestMetrics(long createTime, long readTime, long writeTime, int reads, int writes, int hits,
+        int misses) {
+        this.createTime = createTime;
+        this.readTime = readTime;
+        this.writeTime = writeTime;
+        this.reads = reads;
+        this.writes = writes;
+        this.hits = hits;
+        this.misses = misses;
+    }
+
+    /**
+     * Gets create time.
+     *
+     * @return Create time.
+     */
+    public long getCreateTime() {
+        return createTime;
+    }
+
+    /**
+     * Sets create time.
+     *
+     * @param createTime Create time.
+     */
+    public void setCreateTime(long createTime) {
+        this.createTime = createTime;
+    }
+
+    /**
+     * Gets read time.
+     *
+     * @return Read time.
+     */
+    public long getReadTime() {
+        return readTime;
+    }
+
+    /**
+     * Sets read time.
+     *
+     * @param readTime Read time.
+     */
+    public void setReadTime(long readTime) {
+        this.readTime = readTime;
+    }
+
+    /**
+     * Gets write time.
+     *
+     * @return Write time.
+     */
+    public long getWriteTime() {
+        return writeTime;
+    }
+
+    /**
+     * Sets write time.
+     *
+     * @param writeTime Write time.
+     */
+    public void setWriteTime(long writeTime) {
+        this.writeTime = writeTime;
+    }
+
+    /**
+     * Gets reads.
+     *
+     * @return Reads.
+     */
+    public int getReads() {
+        return reads;
+    }
+
+    /**
+     * Sets reads.
+     *
+     * @param reads Reads.
+     */
+    public void setReads(int reads) {
+        this.reads = reads;
+    }
+
+    /**
+     * Gets writes.
+     *
+     * @return Writes.
+     */
+    public int getWrites() {
+        return writes;
+    }
+
+    /**
+     * Sets writes.
+     *
+     * @param writes Writes.
+     */
+    public void setWrites(int writes) {
+        this.writes = writes;
+    }
+
+    /**
+     * Gets hits.
+     *
+     * @return Hits.
+     */
+    public int getHits() {
+        return hits;
+    }
+
+    /**
+     * Sets hits.
+     *
+     * @param hits Hits.
+     */
+    public void setHits(int hits) {
+        this.hits = hits;
+    }
+
+    /**
+     * Gets misses.
+     *
+     * @return Misses.
+     */
+    public int getMisses() {
+        return misses;
+    }
+
+    /**
+     * Sets misses.
+     *
+     * @param misses Misses.
+     */
+    public void setMisses(int misses) {
+        this.misses = misses;
+    }
+
+    /**
+     * Creates map with strings.
+     *
+     * @return Map.
+     */
+    public Map<String, Long> map() {
+        Map<String, Long> map = new GridLeanMap<>(7);
+
+        map.put("createTime", createTime);
+        map.put("readTime", readTime);
+        map.put("writeTime", writeTime);
+        map.put("reads", (long)reads);
+        map.put("writes", (long)writes);
+        map.put("hits", (long)hits);
+        map.put("misses", (long)misses);
+
+        return map;
+    }
+}


Mime
View raw message