Till Westmann has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/1522

Change subject: Handle error conditions in the /query/status API
......................................................................

Handle error conditions in the /query/status API

Change-Id: I30176c5c70dcc5f7f6605ad79dd0e41967373d9c
---
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
A 
asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryStatusApiServletTest.java
M 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
M 
hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
M 
hyracks-fullstack/hyracks/hyracks-client/src/main/java/org/apache/hyracks/client/dataset/HyracksDatasetReader.java
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/dataset/DatasetDirectoryService.java
M 
hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/impl/IPCSystem.java
7 files changed, 167 insertions(+), 16 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/22/1522/1

diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
index 5a62eaa..2a5c1f6 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
@@ -29,6 +29,7 @@
 
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
+import org.apache.hyracks.api.dataset.DatasetJobRecord;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.api.dataset.ResultSetId;
 import org.apache.hyracks.api.job.JobId;
@@ -38,11 +39,11 @@
 import org.apache.hyracks.http.server.AbstractServlet;
 import org.apache.hyracks.http.server.utils.HttpUtil;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
-import io.netty.handler.codec.http.HttpMethod;
 import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class QueryStatusApiServlet extends AbstractServlet {
@@ -63,6 +64,11 @@
             return;
         }
         String strHandle = request.getParameter("handle");
+        if (strHandle == null) {
+            LOGGER.log(Level.WARNING, "No handle provided");
+            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            return;
+        }
         PrintWriter out = response.writer();
         try {
             IHyracksDataset hds = (IHyracksDataset) 
ctx.get(HYRACKS_DATASET_ATTR);
@@ -77,8 +83,11 @@
                 }
             }
             ObjectMapper om = new ObjectMapper();
-            JsonNode handleObj = om.readTree(strHandle);
-            JsonNode handle = handleObj.get("handle");
+            JsonNode handle = parseHandle(om, strHandle);
+            if (handle == null) {
+                response.setStatus(HttpResponseStatus.BAD_REQUEST);
+                return;
+            }
             JobId jobId = new JobId(handle.get(0).asLong());
             ResultSetId rsId = new ResultSetId(handle.get(1).asLong());
 
@@ -89,7 +98,13 @@
             resultReader.open(jobId, rsId);
 
             ObjectNode jsonResponse = om.createObjectNode();
-            jsonResponse.put("status", resultReader.getStatus().name());
+            final DatasetJobRecord.Status status = resultReader.getStatus();
+            if (status == null) {
+                LOGGER.log(Level.INFO, "No results for: \"" + strHandle + 
"\"");
+                response.setStatus(HttpResponseStatus.NOT_FOUND);
+                return;
+            }
+            jsonResponse.put("status", status.name());
             out.write(jsonResponse.toString());
 
         } catch (Exception e) {
@@ -99,4 +114,13 @@
         }
     }
 
+    private JsonNode parseHandle(ObjectMapper om, String strHandle) throws 
IOException {
+        try {
+            JsonNode handleObj = om.readTree(strHandle);
+            return handleObj.get("handle");
+        } catch (JsonProcessingException e) {
+            LOGGER.log(Level.WARNING, "Invalid handle: \"" + strHandle + "\"");
+            return null;
+        }
+    }
 }
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryStatusApiServletTest.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryStatusApiServletTest.java
new file mode 100644
index 0000000..4da384f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryStatusApiServletTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.asterix.api.http.servlet;
+
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.asterix.api.http.server.VersionApiServlet;
+import org.apache.asterix.common.config.BuildProperties;
+import org.apache.asterix.runtime.utils.AppContextInfo;
+import org.apache.asterix.test.runtime.SqlppExecutionTest;
+import org.apache.hyracks.api.client.IHyracksClientConnection;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpMethod;
+
+public class QueryStatusApiServletTest {
+
+    @Test
+    public void testGet() throws Exception {
+        // Starts test asterixdb cluster.
+        SqlppExecutionTest.setUp();
+
+        // Configures a test version api servlet.
+        VersionApiServlet servlet = new VersionApiServlet(new 
ConcurrentHashMap<>(), new String[] { "/" });
+        Map<String, String> propMap = new HashMap<>();
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        PrintWriter outputWriter = new PrintWriter(outputStream);
+
+        // Creates mocks.
+        AppContextInfo mockCtx = mock(AppContextInfo.class);
+        IServletRequest mockRequest = mock(IServletRequest.class);
+        IHyracksClientConnection mockHcc = 
mock(IHyracksClientConnection.class);
+        IServletResponse mockResponse = mock(IServletResponse.class);
+        BuildProperties mockProperties = mock(BuildProperties.class);
+        FullHttpRequest mockHttpRequest = mock(FullHttpRequest.class);
+
+        // Put stuff in let map
+        servlet.ctx().put(HYRACKS_CONNECTION_ATTR, mockHcc);
+        servlet.ctx().put(ASTERIX_BUILD_PROP_ATTR, mockCtx);
+        // Sets up mock returns.
+        when(mockResponse.writer()).thenReturn(outputWriter);
+        when(mockRequest.getHttpRequest()).thenReturn(mockHttpRequest);
+        when(mockHttpRequest.method()).thenReturn(HttpMethod.GET);
+        when(mockCtx.getBuildProperties()).thenReturn(mockProperties);
+        when(mockProperties.getAllProps()).thenReturn(propMap);
+
+        propMap.put("git.build.user.email", "[email protected]");
+        propMap.put("git.build.host", "fulliautomatix");
+        propMap.put("git.dirty", "true");
+        propMap.put("git.remote.origin.url", 
"[email protected]:apache/incubator-asterixdb.git");
+        propMap.put("git.closest.tag.name", "asterix-0.8.7-incubating");
+        propMap.put("git.commit.id.describe-short", 
"asterix-0.8.7-incubating-19-dirty");
+        propMap.put("git.commit.user.email", "[email protected]");
+        propMap.put("git.commit.time", "21.10.2015 @ 23:36:41 PDT");
+        propMap.put("git.commit.message.full",
+                "ASTERIXDB-1045: fix log file reading during 
recovery\n\nChange-Id: Ic83ee1dd2d7ba88180c25f4ec6c7aa8d0a5a7162\nReviewed-on: 
https://asterix-gerrit.ics.uci.edu/465\nTested-by: Jenkins 
<[email protected]>");
+        propMap.put("git.build.version", "0.8.8-SNAPSHOT");
+        propMap.put("git.commit.message.short", "ASTERIXDB-1045: fix log file 
reading during recovery");
+        propMap.put("git.commit.id.abbrev", "e1dad19");
+        propMap.put("git.branch", "foo/bar");
+        propMap.put("git.build.user.name", "Asterix");
+        propMap.put("git.closest.tag.commit.count", "19");
+        propMap.put("git.commit.id.describe", 
"asterix-0.8.7-incubating-19-ge1dad19-dirty");
+        propMap.put("git.commit.id", 
"e1dad1984640517366a7e73e323c9de27b0676f7");
+        propMap.put("git.tags", "");
+        propMap.put("git.build.time", "22.10.2015 @ 17:11:07 PDT");
+        propMap.put("git.commit.user.name", "Obelix");
+
+        // Calls VersionAPIServlet.formResponseObject.
+        servlet.handle(mockRequest, mockResponse);
+
+        // Constructs the actual response.
+
+        ObjectMapper om = new ObjectMapper();
+        ObjectNode actualResponse = (ObjectNode) 
om.readTree(outputStream.toByteArray());
+        ObjectNode expectedResponse = om.createObjectNode();
+        for (Map.Entry<String, String> e : propMap.entrySet()) {
+            expectedResponse.put(e.getKey(), e.getValue());
+        }
+
+        // Checks the response contains all the expected keys.
+        Assert.assertEquals(actualResponse.toString(), 
expectedResponse.toString());
+
+        // Tears down the asterixdb cluster.
+        SqlppExecutionTest.tearDown();
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
index 8d312d5..bc8925d 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
@@ -58,6 +58,7 @@
     public static final int ERROR_FINDING_DISTRIBUTED_JOB = 21;
     public static final int DUPLICATE_DISTRIBUTED_JOB = 22;
     public static final int DISTRIBUTED_JOB_FAILURE = 23;
+    public static final int NO_RESULTSET = 24;
 
     // Compilation error codes.
     public static final int RULECOLLECTION_NOT_INSTANCE_OF_LIST = 10001;
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
index 7f90c35..67cbfd5 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
@@ -42,5 +42,6 @@
 21 = The distributed job %1$s was not found
 22 = The distributed job %1$s already exists
 23 = The distributed work failed for %1$s at %2$s
+24 = No result set %1$s for job %2$s
 
 10000 = The given rule collection %1$s is not an instance of the List class.
diff --git 
a/hyracks-fullstack/hyracks/hyracks-client/src/main/java/org/apache/hyracks/client/dataset/HyracksDatasetReader.java
 
b/hyracks-fullstack/hyracks/hyracks-client/src/main/java/org/apache/hyracks/client/dataset/HyracksDatasetReader.java
index f6f05d2..e47d822 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-client/src/main/java/org/apache/hyracks/client/dataset/HyracksDatasetReader.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-client/src/main/java/org/apache/hyracks/client/dataset/HyracksDatasetReader.java
@@ -25,6 +25,7 @@
 import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.hyracks.api.channels.IInputChannel;
@@ -37,6 +38,7 @@
 import 
org.apache.hyracks.api.dataset.IHyracksDatasetDirectoryServiceConnection;
 import org.apache.hyracks.api.dataset.IHyracksDatasetReader;
 import org.apache.hyracks.api.dataset.ResultSetId;
+import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.exceptions.HyracksException;
 import org.apache.hyracks.api.job.JobId;
@@ -87,13 +89,16 @@
 
     @Override
     public Status getResultStatus() {
-        Status status = null;
         try {
-            status = 
datasetDirectoryServiceConnection.getDatasetResultStatus(jobId, resultSetId);
+            return 
datasetDirectoryServiceConnection.getDatasetResultStatus(jobId, resultSetId);
+        } catch (HyracksDataException e) {
+            if (e.getErrorCode() != ErrorCode.NO_RESULTSET) {
+                LOGGER.log(Level.WARNING, "Exception retrieving result set for 
job " + jobId, e);
+            }
         } catch (Exception e) {
-            // TODO(madhusudancs): Decide what to do in case of error
+            LOGGER.log(Level.WARNING, "Exception retrieving result set for job 
" + jobId, e);
         }
-        return status;
+        return null;
     }
 
     private DatasetDirectoryRecord getRecord(int partition) throws Exception {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/dataset/DatasetDirectoryService.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/dataset/DatasetDirectoryService.java
index c4cf38d..ceeb9fa 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/dataset/DatasetDirectoryService.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/dataset/DatasetDirectoryService.java
@@ -162,13 +162,9 @@
 
     @Override
     public synchronized Status getResultStatus(JobId jobId, ResultSetId rsId) 
throws HyracksDataException {
-        DatasetJobRecord djr;
-        while ((djr = getDatasetJobRecord(jobId)) == null) {
-            try {
-                wait();
-            } catch (InterruptedException e) {
-                throw new HyracksDataException(e);
-            }
+        DatasetJobRecord djr = getDatasetJobRecord(jobId);
+        if (djr == null) {
+            throw HyracksDataException.create(ErrorCode.NO_RESULTSET, rsId, 
jobId);
         }
         return djr.getStatus();
     }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/impl/IPCSystem.java
 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/impl/IPCSystem.java
index 62be1b0..0997e57 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/impl/IPCSystem.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/impl/IPCSystem.java
@@ -21,6 +21,8 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import org.apache.hyracks.ipc.api.IIPCHandle;
 import org.apache.hyracks.ipc.api.IIPCI;
@@ -29,6 +31,8 @@
 import org.apache.hyracks.ipc.exceptions.IPCException;
 
 public class IPCSystem {
+    private static final Logger LOGGER = 
Logger.getLogger(IPCSystem.class.getName());
+
     private final IPCConnectionManager cMgr;
 
     private final IIPCI ipci;
@@ -88,7 +92,7 @@
         Exception exception = null;
         if (message.getFlag() == Message.ERROR) {
             exception = (Exception) message.getPayload();
-            exception.printStackTrace();
+            LOGGER.log(Level.INFO, "Exception in message " + 
message.toString());
         } else {
             payload = message.getPayload();
         }

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/1522
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I30176c5c70dcc5f7f6605ad79dd0e41967373d9c
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Till Westmann <[email protected]>

Reply via email to