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]>