[LENS-1279] Imporve error messages and API responses
Project: http://git-wip-us.apache.org/repos/asf/lens/repo Commit: http://git-wip-us.apache.org/repos/asf/lens/commit/fae2773c Tree: http://git-wip-us.apache.org/repos/asf/lens/tree/fae2773c Diff: http://git-wip-us.apache.org/repos/asf/lens/diff/fae2773c Branch: refs/heads/master Commit: fae2773cd2a9c3a35875584493892abd5c1b6f18 Parents: 6e4d186 Author: Lavkesh Lahngir <[email protected]> Authored: Wed Aug 24 12:21:20 2016 +0530 Committer: Rajat Khandelwal <[email protected]> Committed: Wed Aug 24 12:21:21 2016 +0530 ---------------------------------------------------------------------- .../apache/lens/api/SupportedOperations.java | 55 ++++ .../query/SupportedQuerySubmitOperations.java | 55 ---- .../apache/lens/api/result/LensAPIResult.java | 11 +- .../lens/api/scheduler/SchedulerJobHandle.java | 14 +- .../scheduler/SchedulerJobInstanceHandle.java | 6 +- lens-api/src/main/resources/lens-errors.conf | 47 ++- .../lens/api/query/SupportedOperationsTest.java | 38 +++ .../SupportedQuerySubmitOperationsTest.java | 37 --- .../server/api/scheduler/SchedulerService.java | 32 +- .../server/error/LensSchedulerErrorCode.java | 42 +++ .../lens/server/error/LensServerErrorCode.java | 2 +- .../server/error/UnSupportedOpException.java | 54 ++++ .../UnSupportedQuerySubmitOpException.java | 55 ---- .../lens/server/query/QueryServiceResource.java | 30 +- .../lens/server/scheduler/AlarmService.java | 13 +- .../lens/server/scheduler/ScheduleResource.java | 310 +++++++++++++------ .../scheduler/SchedulerEventListener.java | 6 +- .../server/scheduler/SchedulerServiceImpl.java | 117 ++++--- .../apache/lens/server/util/UtilityMethods.java | 15 + .../server/query/QueryAPIErrorResponseTest.java | 8 +- .../scheduler/TestSchedulerServiceImpl.java | 66 +--- .../scheduler/util/SchedulerTestUtils.java | 70 +++++ 22 files changed, 683 insertions(+), 400 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/java/org/apache/lens/api/SupportedOperations.java ---------------------------------------------------------------------- diff --git a/lens-api/src/main/java/org/apache/lens/api/SupportedOperations.java b/lens-api/src/main/java/org/apache/lens/api/SupportedOperations.java new file mode 100644 index 0000000..fb767c8 --- /dev/null +++ b/lens-api/src/main/java/org/apache/lens/api/SupportedOperations.java @@ -0,0 +1,55 @@ +/** + * 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.lens.api; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.bind.annotation.*; + +import org.apache.commons.lang.StringUtils; + +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@XmlRootElement +@EqualsAndHashCode +@ToString +@XmlAccessorType(XmlAccessType.FIELD) +@NoArgsConstructor +public class SupportedOperations<T> implements Serializable { + + private static final String SEP = ", "; + + @XmlElementWrapper(name = "supportedOperations") + @XmlElement(name = "operation") + private List<String> supportedOps = new LinkedList<String>(); + + public SupportedOperations(T... supportedOps) { + for (T supportedOp : supportedOps) { + this.supportedOps.add(supportedOp.toString().toLowerCase()); + } + } + + public String getSupportedOperationsAsString() { + return StringUtils.join(supportedOps, SEP); + } +} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/java/org/apache/lens/api/query/SupportedQuerySubmitOperations.java ---------------------------------------------------------------------- diff --git a/lens-api/src/main/java/org/apache/lens/api/query/SupportedQuerySubmitOperations.java b/lens-api/src/main/java/org/apache/lens/api/query/SupportedQuerySubmitOperations.java deleted file mode 100644 index 8fcf608..0000000 --- a/lens-api/src/main/java/org/apache/lens/api/query/SupportedQuerySubmitOperations.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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.lens.api.query; - -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; - -import javax.xml.bind.annotation.*; - -import org.apache.commons.lang.StringUtils; - -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.ToString; - -@XmlRootElement -@EqualsAndHashCode -@ToString -@XmlAccessorType(XmlAccessType.FIELD) -@NoArgsConstructor -public class SupportedQuerySubmitOperations implements Serializable { - - private static final String SEP = ", "; - - @XmlElementWrapper(name = "supportedOperations") - @XmlElement(name = "operation") - private List<String> supportedOps = new LinkedList<String>(); - - public SupportedQuerySubmitOperations(SubmitOp... supportedOps) { - for (SubmitOp supportedOp : supportedOps) { - this.supportedOps.add(supportedOp.toString().toLowerCase()); - } - } - - public String getSupportedOperationsAsString() { - return StringUtils.join(supportedOps, SEP); - } -} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/java/org/apache/lens/api/result/LensAPIResult.java ---------------------------------------------------------------------- diff --git a/lens-api/src/main/java/org/apache/lens/api/result/LensAPIResult.java b/lens-api/src/main/java/org/apache/lens/api/result/LensAPIResult.java index e940b97..29288e7 100644 --- a/lens-api/src/main/java/org/apache/lens/api/result/LensAPIResult.java +++ b/lens-api/src/main/java/org/apache/lens/api/result/LensAPIResult.java @@ -25,8 +25,10 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.xml.bind.annotation.*; +import org.apache.lens.api.SupportedOperations; import org.apache.lens.api.query.QuerySubmitResult; -import org.apache.lens.api.query.SupportedQuerySubmitOperations; +import org.apache.lens.api.scheduler.SchedulerJobInfo; +import org.apache.lens.api.scheduler.SchedulerJobInstanceInfo; import org.apache.commons.lang.StringUtils; @@ -39,7 +41,8 @@ import lombok.*; * */ @XmlRootElement -@XmlSeeAlso({NoResultData.class, NoErrorPayload.class, QuerySubmitResult.class, SupportedQuerySubmitOperations.class}) +@XmlSeeAlso({NoResultData.class, NoErrorPayload.class, QuerySubmitResult.class, SupportedOperations.class, + SchedulerJobInfo.class, SchedulerJobInstanceInfo.class}) @NoArgsConstructor(access=AccessLevel.PACKAGE) @ToString @XmlAccessorType(XmlAccessType.FIELD) @@ -64,12 +67,12 @@ public class LensAPIResult<DATA> { private Response.StatusType httpStatusCode; public static <DATA> LensAPIResult<DATA> composedOf(final String apiVersion, - final String id, @NonNull final DATA data) { + final String id, final DATA data) { return composedOf(apiVersion, id, data, Status.OK); } public static <DATA> LensAPIResult<DATA> composedOf(final String apiVersion, - final String id, @NonNull final DATA data, @NonNull final Response.StatusType httpStatusCode) { + final String id, final DATA data, @NonNull final Response.StatusType httpStatusCode) { return new LensAPIResult<>(apiVersion, id, data, null, httpStatusCode); } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobHandle.java ---------------------------------------------------------------------- diff --git a/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobHandle.java b/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobHandle.java index 2e3aab8..a64350f 100644 --- a/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobHandle.java +++ b/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobHandle.java @@ -27,14 +27,16 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.lens.api.UUIDAdapter; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; /** * Handle for <code>SchedulerJob</code>. */ @XmlRootElement @AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(callSuper = false) public class SchedulerJobHandle implements Serializable { @@ -53,6 +55,13 @@ public class SchedulerJobHandle implements Serializable { private UUID handleId; /** + * Default constructor + */ + public SchedulerJobHandle() { + this(UUID.randomUUID()); + } + + /** * From string. * * @param handle the handle for scheduler job @@ -68,6 +77,7 @@ public class SchedulerJobHandle implements Serializable { /** * String representation of the SchedulerJobHandle. + * * @return string representation of the handleId */ @Override http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobInstanceHandle.java ---------------------------------------------------------------------- diff --git a/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobInstanceHandle.java b/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobInstanceHandle.java index 129afe1..752cdd7 100644 --- a/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobInstanceHandle.java +++ b/lens-api/src/main/java/org/apache/lens/api/scheduler/SchedulerJobInstanceHandle.java @@ -34,7 +34,6 @@ import lombok.*; */ @XmlRootElement @AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(callSuper = false) public class SchedulerJobInstanceHandle implements Serializable { @@ -42,7 +41,6 @@ public class SchedulerJobInstanceHandle implements Serializable { * The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; - /** * The handle id. */ @@ -52,6 +50,10 @@ public class SchedulerJobInstanceHandle implements Serializable { @NonNull private UUID handleId; + public SchedulerJobInstanceHandle() { + this(UUID.randomUUID()); + } + /** * From string. * http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/main/resources/lens-errors.conf ---------------------------------------------------------------------- diff --git a/lens-api/src/main/resources/lens-errors.conf b/lens-api/src/main/resources/lens-errors.conf index 537b458..162fb1d 100644 --- a/lens-api/src/main/resources/lens-errors.conf +++ b/lens-api/src/main/resources/lens-errors.conf @@ -94,7 +94,7 @@ lensServerErrors = [ errorCode = 2003 httpStatusCode = ${BAD_REQUEST} errorMsg = "Provided Operation is not supported. Supported Operations are: [%s]" - payloadClass = org.apache.lens.api.query.SupportedQuerySubmitOperations + payloadClass = org.apache.lens.api.SupportedOperations } { @@ -370,6 +370,49 @@ lensDriverErrors = [ lensCubeErrors = ${lensCubeErrorsForQuery}${lensCubeErrorsForMetastore} +lensSchedulerErrors = [ + { + errorCode = 5001 + httpStatusCode = ${INTERNAL_SERVER_ERROR} + errorMsg = "Can't submit the job %s" + } + { + errorCode = 5002 + httpStatusCode = ${BAD_REQUEST} + errorMsg = "Invalid event %s on current state %s for job %s" + } + { + errorCode = 5003 + httpStatusCode = ${BAD_REQUEST} + errorMsg = "Invalid event %s, for state %s of job instance %s of job %s" + } + { + errorCode = 5004 + httpStatusCode = ${BAD_REQUEST} + errorMsg = "The current user %s for session %s is not the same as job owner %s" + } + { + errorCode = 5005 + httpStatusCode = ${BAD_REQUEST} + errorMsg = "Job with handle %s is not scheduled. The current state of job is %s" + } + { + errorCode = 5006 + httpStatusCode = ${BAD_REQUEST} + errorMsg = "Job instance with handle %s of job %s is not yet run" + } + { + errorCode = 5007 + httpStatusCode = ${INTERNAL_SERVER_ERROR} + errorMsg = "Cannot update %s with handle %s" + } + { + errorCode = 5008 + httpStatusCode = ${INTERNAL_SERVER_ERROR} + errorMsg = "Cannot % job in AlarmService with handle %s" + } +] + # Overriding errors in lens-errors.conf via lens-errors-override.conf: # # Step 1: Copy contents of lens-errors.conf to lens-errors-override.conf @@ -401,4 +444,4 @@ lensCubeErrors = ${lensCubeErrorsForQuery}${lensCubeErrorsForMetastore} # Lens server and Lens client are only aware of errors array. They are not aware of any other array defined in # error configuration files. Hence an errors array is prepared which is a concatenation of all other error arrays. -errors = ${lensCommonErrors}${lensServerErrors}${lensCubeErrors}${lensDriverErrors} +errors = ${lensCommonErrors}${lensServerErrors}${lensCubeErrors}${lensDriverErrors}${lensSchedulerErrors} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/test/java/org/apache/lens/api/query/SupportedOperationsTest.java ---------------------------------------------------------------------- diff --git a/lens-api/src/test/java/org/apache/lens/api/query/SupportedOperationsTest.java b/lens-api/src/test/java/org/apache/lens/api/query/SupportedOperationsTest.java new file mode 100644 index 0000000..5e9a329 --- /dev/null +++ b/lens-api/src/test/java/org/apache/lens/api/query/SupportedOperationsTest.java @@ -0,0 +1,38 @@ +/* + * 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.lens.api.query; + +import org.apache.lens.api.SupportedOperations; +import org.apache.lens.api.serialize.SerializationTest; + +import org.testng.annotations.Test; + +public class SupportedOperationsTest { + + @Test + public void testIfSupportedQuerySubmitOperationsIsSerializable() { + + /* Payload class has to be Serializable because it is part of QueryContext collaboration graph, + which is serialized to be persisted on disk in lens */ + + SerializationTest st = new SerializationTest(); + st.verifySerializationAndDeserialization(new SupportedOperations()); + } +} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-api/src/test/java/org/apache/lens/api/query/SupportedQuerySubmitOperationsTest.java ---------------------------------------------------------------------- diff --git a/lens-api/src/test/java/org/apache/lens/api/query/SupportedQuerySubmitOperationsTest.java b/lens-api/src/test/java/org/apache/lens/api/query/SupportedQuerySubmitOperationsTest.java deleted file mode 100644 index 730904b..0000000 --- a/lens-api/src/test/java/org/apache/lens/api/query/SupportedQuerySubmitOperationsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.lens.api.query; - -import org.apache.lens.api.serialize.SerializationTest; - -import org.testng.annotations.Test; - -public class SupportedQuerySubmitOperationsTest { - - @Test - public void testIfSupportedQuerySubmitOperationsIsSerializable() { - - /* Payload class has to be Serializable because it is part of QueryContext collaboration graph, - which is serialized to be persisted on disk in lens */ - - SerializationTest st = new SerializationTest(); - st.verifySerializationAndDeserialization(new SupportedQuerySubmitOperations()); - } -} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server-api/src/main/java/org/apache/lens/server/api/scheduler/SchedulerService.java ---------------------------------------------------------------------- diff --git a/lens-server-api/src/main/java/org/apache/lens/server/api/scheduler/SchedulerService.java b/lens-server-api/src/main/java/org/apache/lens/server/api/scheduler/SchedulerService.java index 8e1606e..bfe73b9 100644 --- a/lens-server-api/src/main/java/org/apache/lens/server/api/scheduler/SchedulerService.java +++ b/lens-server-api/src/main/java/org/apache/lens/server/api/scheduler/SchedulerService.java @@ -52,10 +52,9 @@ public interface SchedulerService extends LensService, SessionValidator { * * @param sessionHandle handle for the current session. * @param jobHandle handle for the job to be scheduled. - * @return true if there is a successful schedule * @throws LensException the lens exception */ - boolean scheduleJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; + void scheduleJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; /** * Submit a job and also schedule it. @@ -93,10 +92,9 @@ public interface SchedulerService extends LensService, SessionValidator { * @param sessionHandle * @param jobHandle handle for the job which you want to update. * @param newJobDefinition - * @return true or false based on whether the update was successful or failed. * @throws LensException the lens exception */ - boolean updateJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle, XJob newJobDefinition) + void updateJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle, XJob newJobDefinition) throws LensException; /** @@ -104,10 +102,9 @@ public interface SchedulerService extends LensService, SessionValidator { * * @param sessionHandle handle for the current session. * @param jobHandle handle for the job - * @return true if the operation is successful. * @throws LensException the lens exception */ - boolean expireJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; + void expireJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; /** * Suspend a job. @@ -118,30 +115,27 @@ public interface SchedulerService extends LensService, SessionValidator { * * @param sessionHandle handle for the current session. * @param jobHandle handle for the job - * @return true if the job was suspended successfully, false otherwise. * @throws LensException the lens exception */ - boolean suspendJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; + void suspendJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; /** * Resume a job from a given time. * * @param sessionHandle handle for the session. * @param jobHandle handle for the job - * @return true if the job was resumed successfully, false otherwise. * @throws LensException the lens exception */ - boolean resumeJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; + void resumeJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; /** * Delete a job. * * @param sessionHandle handle for the session. * @param jobHandle handle for the job - * @return true if the job was deleted successfully. * @throws LensException the lens exception */ - boolean deleteJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; + void deleteJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException; /** * @param state filter for status, if specified only jobs in that state will be returned, @@ -189,7 +183,6 @@ public interface SchedulerService extends LensService, SessionValidator { * * @param sessionHandle handle for the session. * @param instanceHandle handle for the instance - * @return true if the instance was killed successfully, false otherwise. * @throws LensException the lens exception */ boolean killInstance(LensSessionHandle sessionHandle, SchedulerJobInstanceHandle instanceHandle) throws LensException; @@ -201,10 +194,9 @@ public interface SchedulerService extends LensService, SessionValidator { * * @param sessionHandle handle for the session. * @param instanceHandle handle for the instance - * @return true if the instance was re run successfully, false otherwise. * @throws LensException the lens exception */ - boolean rerunInstance(LensSessionHandle sessionHandle, SchedulerJobInstanceHandle instanceHandle) + void rerunInstance(LensSessionHandle sessionHandle, SchedulerJobInstanceHandle instanceHandle) throws LensException; /** @@ -222,4 +214,14 @@ public interface SchedulerService extends LensService, SessionValidator { * @return LensSessionHandle */ LensSessionHandle openSessionAsUser(String user) throws LensException; + + /** + * Get all jobs matching the filter parameters. + * @param user + * @param state + * @param start + * @param end + * @return List of all job handles matching the parameters. + */ + List<SchedulerJobHandle> getAllJobs(String user, SchedulerJobState state, Long start, Long end) throws LensException; } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/error/LensSchedulerErrorCode.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/error/LensSchedulerErrorCode.java b/lens-server/src/main/java/org/apache/lens/server/error/LensSchedulerErrorCode.java new file mode 100644 index 0000000..12c4851 --- /dev/null +++ b/lens-server/src/main/java/org/apache/lens/server/error/LensSchedulerErrorCode.java @@ -0,0 +1,42 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.lens.server.error; + +import org.apache.lens.server.api.LensErrorInfo; + +public enum LensSchedulerErrorCode { + CANT_SUBMIT_JOB(5001, 0), + INVALID_EVENT_FOR_JOB(5002, 0), + INVALID_EVENT_FOR_JOB_INSTANCE(5003, 0), + CURRENT_USER_IS_NOT_SAME_AS_OWNER(5004, 0), + JOB_IS_NOT_SCHEDULED(5005, 0), + JOB_INSTANCE_IS_NOT_YET_RUN(5006, 0), + CANT_UPDATE_RESOURCE_WITH_HANDLE(5007, 0), + FAILED_ALARM_SERVICE_OPERATION(5008, 0); + + private final LensErrorInfo errorInfo; + + LensSchedulerErrorCode(final int code, final int weight) { + this.errorInfo = new LensErrorInfo(code, weight, name()); + } + + public LensErrorInfo getLensErrorInfo() { + return this.errorInfo; + } +} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/error/LensServerErrorCode.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/error/LensServerErrorCode.java b/lens-server/src/main/java/org/apache/lens/server/error/LensServerErrorCode.java index cc622f2..14a31e2 100644 --- a/lens-server/src/main/java/org/apache/lens/server/error/LensServerErrorCode.java +++ b/lens-server/src/main/java/org/apache/lens/server/error/LensServerErrorCode.java @@ -24,7 +24,7 @@ public enum LensServerErrorCode { SESSION_ID_NOT_PROVIDED(2001, 0), NULL_OR_EMPTY_OR_BLANK_QUERY(2002, 0), - UNSUPPORTED_QUERY_SUBMIT_OPERATION(2003, 0), + UNSUPPORTED_OPERATION(2003, 0), TOO_MANY_OPEN_SESSIONS(2004, 0), SESSION_CLOSED(2005, 0), INVALID_HANDLE(2006, 0), http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedOpException.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedOpException.java b/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedOpException.java new file mode 100644 index 0000000..b5a22a6 --- /dev/null +++ b/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedOpException.java @@ -0,0 +1,54 @@ +/** + * 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.lens.server.error; + +import static org.apache.lens.server.error.LensServerErrorCode.UNSUPPORTED_OPERATION; + +import org.apache.lens.api.SupportedOperations; +import org.apache.lens.api.error.ErrorCollection; +import org.apache.lens.api.error.LensError; +import org.apache.lens.api.result.LensErrorTO; +import org.apache.lens.server.api.error.LensException; + +public class UnSupportedOpException extends LensException { + + private final SupportedOperations supportedOps; + + public UnSupportedOpException(Enum... supportedOps) { + super(UNSUPPORTED_OPERATION.getLensErrorInfo()); + this.supportedOps = new SupportedOperations<>(supportedOps); + } + + public UnSupportedOpException(final Throwable cause, Enum... supportedOps) { + super(UNSUPPORTED_OPERATION.getLensErrorInfo(), cause); + this.supportedOps = new SupportedOperations<>(supportedOps); + } + + @Override + public String getFormattedErrorMsg(LensError lensError) { + final String supportedOpsStr = supportedOps.getSupportedOperationsAsString(); + return lensError.getFormattedErrorMsg(supportedOpsStr); + } + + @Override + protected LensErrorTO buildLensErrorTO(final ErrorCollection errorCollection, final String errorMsg, + final String stackTrace) { + return LensErrorTO.composedOf(getErrorCode(), errorMsg, stackTrace, supportedOps, null); + } +} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedQuerySubmitOpException.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedQuerySubmitOpException.java b/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedQuerySubmitOpException.java deleted file mode 100644 index 9e600c8..0000000 --- a/lens-server/src/main/java/org/apache/lens/server/error/UnSupportedQuerySubmitOpException.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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.lens.server.error; - -import static org.apache.lens.server.error.LensServerErrorCode.UNSUPPORTED_QUERY_SUBMIT_OPERATION; - -import org.apache.lens.api.error.ErrorCollection; -import org.apache.lens.api.error.LensError; -import org.apache.lens.api.query.SubmitOp; -import org.apache.lens.api.query.SupportedQuerySubmitOperations; -import org.apache.lens.api.result.LensErrorTO; -import org.apache.lens.server.api.error.LensException; - -public class UnSupportedQuerySubmitOpException extends LensException { - - private final SupportedQuerySubmitOperations supportedOps; - - public UnSupportedQuerySubmitOpException(SubmitOp... supportedSubmitOps) { - super(UNSUPPORTED_QUERY_SUBMIT_OPERATION.getLensErrorInfo()); - this.supportedOps = new SupportedQuerySubmitOperations(supportedSubmitOps); - } - - public UnSupportedQuerySubmitOpException(final Throwable cause, SubmitOp... supportedSubmitOps) { - super(UNSUPPORTED_QUERY_SUBMIT_OPERATION.getLensErrorInfo(), cause); - this.supportedOps = new SupportedQuerySubmitOperations(supportedSubmitOps); - } - - @Override - public String getFormattedErrorMsg(LensError lensError) { - final String supportedOpsStr = supportedOps.getSupportedOperationsAsString(); - return lensError.getFormattedErrorMsg(supportedOpsStr); - } - - @Override - protected LensErrorTO buildLensErrorTO(final ErrorCollection errorCollection, final String errorMsg, - final String stackTrace) { - return LensErrorTO.composedOf(getErrorCode(), errorMsg, stackTrace, supportedOps, null); - } -} http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/query/QueryServiceResource.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/query/QueryServiceResource.java b/lens-server/src/main/java/org/apache/lens/server/query/QueryServiceResource.java index 7d8d300..4aa7872 100644 --- a/lens-server/src/main/java/org/apache/lens/server/query/QueryServiceResource.java +++ b/lens-server/src/main/java/org/apache/lens/server/query/QueryServiceResource.java @@ -39,8 +39,9 @@ import org.apache.lens.server.api.annotations.MultiPurposeResource; import org.apache.lens.server.api.error.LensException; import org.apache.lens.server.api.query.QueryExecutionService; import org.apache.lens.server.api.query.cost.QueryCostTOBuilder; -import org.apache.lens.server.error.UnSupportedQuerySubmitOpException; +import org.apache.lens.server.error.UnSupportedOpException; import org.apache.lens.server.model.LogSegregationContext; +import org.apache.lens.server.util.UtilityMethods; import org.apache.commons.lang.StringUtils; @@ -66,21 +67,6 @@ public class QueryServiceResource { queryServer.validateSession(sessionHandle); } - private SubmitOp checkAndGetQuerySubmitOperation(final String operation, SubmitOp... supportedOperations) - throws UnSupportedQuerySubmitOpException { - try { - SubmitOp op = SubmitOp.valueOf(operation.toUpperCase()); - for(SubmitOp supportedOperation: supportedOperations) { - if (op.equals(supportedOperation)) { - return op; - } - } - throw new UnSupportedQuerySubmitOpException(supportedOperations); - } catch (IllegalArgumentException e) { - throw new UnSupportedQuerySubmitOpException(e, supportedOperations); - } - } - private void validateQuery(String query) throws LensException { if (StringUtils.isBlank(query)) { throw new LensException(NULL_OR_EMPTY_OR_BLANK_QUERY.getLensErrorInfo()); @@ -179,7 +165,7 @@ public class QueryServiceResource { final String requestId = this.logSegregationContext.getLogSegragationId(); validateSessionId(sessionid); SubmitOp[] supportedOperations = new SubmitOp[]{ESTIMATE, EXECUTE, EXPLAIN, EXECUTE_WITH_TIMEOUT}; - SubmitOp sop = checkAndGetQuerySubmitOperation(operation, supportedOperations); + SubmitOp sop = UtilityMethods.checkAndGetOperation(operation, SubmitOp.class, supportedOperations); validateQuery(query); QuerySubmitResult result; switch (sop) { @@ -196,7 +182,7 @@ public class QueryServiceResource { result = queryServer.execute(sessionid, query, timeoutmillis, conf, queryName); break; default: - throw new UnSupportedQuerySubmitOpException(supportedOperations); + throw new UnSupportedOpException(supportedOperations); } return LensAPIResult.composedOf(null, requestId, result); } @@ -309,7 +295,7 @@ public class QueryServiceResource { validateSessionId(sessionid); validateQuery(query); SubmitOp[] supportedOperations = new SubmitOp[]{PREPARE, EXPLAIN_AND_PREPARE}; - SubmitOp sop = checkAndGetQuerySubmitOperation(operation, supportedOperations); + SubmitOp sop = UtilityMethods.checkAndGetOperation(operation, SubmitOp.class, supportedOperations); QuerySubmitResult result; switch (sop) { case PREPARE: @@ -319,7 +305,7 @@ public class QueryServiceResource { result = queryServer.explainAndPrepare(sessionid, query, conf, queryName); break; default: - throw new UnSupportedQuerySubmitOpException(supportedOperations); + throw new UnSupportedOpException(supportedOperations); } return LensAPIResult.composedOf(null, requestId, result); } @@ -555,14 +541,14 @@ public class QueryServiceResource { @DefaultValue("") @FormDataParam("queryName") String queryName) throws LensException { validateSessionId(sessionid); SubmitOp[] supportedOperations = new SubmitOp[]{EXECUTE, EXECUTE_WITH_TIMEOUT}; - SubmitOp sop = checkAndGetQuerySubmitOperation(operation, supportedOperations); + SubmitOp sop = UtilityMethods.checkAndGetOperation(operation, SubmitOp.class, supportedOperations); switch (sop) { case EXECUTE: return queryServer.executePrepareAsync(sessionid, getPrepareHandle(prepareHandle), conf, queryName); case EXECUTE_WITH_TIMEOUT: return queryServer.executePrepare(sessionid, getPrepareHandle(prepareHandle), timeoutmillis, conf, queryName); default: - throw new UnSupportedQuerySubmitOpException(supportedOperations); + throw new UnSupportedOpException(supportedOperations); } } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/scheduler/AlarmService.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/scheduler/AlarmService.java b/lens-server/src/main/java/org/apache/lens/server/scheduler/AlarmService.java index 2009a20..6487323 100644 --- a/lens-server/src/main/java/org/apache/lens/server/scheduler/AlarmService.java +++ b/lens-server/src/main/java/org/apache/lens/server/scheduler/AlarmService.java @@ -27,6 +27,7 @@ import org.apache.lens.server.api.error.LensException; import org.apache.lens.server.api.events.LensEventService; import org.apache.lens.server.api.events.SchedulerAlarmEvent; import org.apache.lens.server.api.health.HealthStatus; +import org.apache.lens.server.error.LensSchedulerErrorCode; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hive.service.AbstractService; @@ -153,7 +154,8 @@ public class AlarmService extends AbstractService implements LensService { scheduler.scheduleJob(job, trigger); } catch (SchedulerException e) { log.error("Error scheduling job with jobHandle: {}", jobHandle); - throw new LensException("Failed to schedule job with jobHandle: " + jobHandle, e); + throw new LensException(LensSchedulerErrorCode.FAILED_ALARM_SERVICE_OPERATION.getLensErrorInfo(), e, "schedule", + jobHandle); } } @@ -192,7 +194,8 @@ public class AlarmService extends AbstractService implements LensService { return scheduler.deleteJob(JobKey.jobKey(jobHandle.getHandleIdString(), LENS_JOBS)); } catch (SchedulerException e) { log.error("Failed to remove alarm triggers for job with jobHandle: {}", jobHandle); - throw new LensException("Failed to remove alarm triggers for job with jobHandle: " + jobHandle, e); + throw new LensException(LensSchedulerErrorCode.FAILED_ALARM_SERVICE_OPERATION.getLensErrorInfo(), e, "unschedule", + jobHandle.getHandleIdString()); } } @@ -210,7 +213,8 @@ public class AlarmService extends AbstractService implements LensService { scheduler.pauseJob(JobKey.jobKey(jobHandle.getHandleIdString(), LENS_JOBS)); } catch (SchedulerException e) { log.error("Failed to pause alarm triggers for job with jobHandle: {}", jobHandle); - throw new LensException("Failed to pause alarm triggers for job with jobHandle: " + jobHandle, e); + throw new LensException(LensSchedulerErrorCode.FAILED_ALARM_SERVICE_OPERATION.getLensErrorInfo(), e, "pause", + jobHandle.getHandleIdString()); } } @@ -219,7 +223,8 @@ public class AlarmService extends AbstractService implements LensService { scheduler.resumeJob(JobKey.jobKey(jobHandle.getHandleIdString(), LENS_JOBS)); } catch (SchedulerException e) { log.error("Failed to resume alarm triggers for job with jobHandle: {}", jobHandle); - throw new LensException("Failed to resume alarm triggers for job with jobHandle: " + jobHandle, e); + throw new LensException(LensSchedulerErrorCode.FAILED_ALARM_SERVICE_OPERATION.getLensErrorInfo(), e, "resume", + jobHandle.getHandleIdString()); } } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/scheduler/ScheduleResource.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/scheduler/ScheduleResource.java b/lens-server/src/main/java/org/apache/lens/server/scheduler/ScheduleResource.java index 7a0b485..ee6e888 100644 --- a/lens-server/src/main/java/org/apache/lens/server/scheduler/ScheduleResource.java +++ b/lens-server/src/main/java/org/apache/lens/server/scheduler/ScheduleResource.java @@ -6,9 +6,9 @@ * 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 - * + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> * 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 @@ -23,47 +23,34 @@ import java.util.List; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; -import javax.xml.bind.JAXBElement; -import org.apache.lens.api.APIResult; import org.apache.lens.api.LensSessionHandle; +import org.apache.lens.api.result.LensAPIResult; import org.apache.lens.api.scheduler.*; import org.apache.lens.server.LensServices; import org.apache.lens.server.api.error.LensException; import org.apache.lens.server.api.scheduler.SchedulerService; - -import org.apache.commons.lang3.StringUtils; +import org.apache.lens.server.error.UnSupportedOpException; +import org.apache.lens.server.model.LogSegregationContext; +import org.apache.lens.server.util.UtilityMethods; /** * REST end point for all scheduler operations. */ @Path("scheduler") -@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) +@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public class ScheduleResource { - private static final ObjectFactory OBJECT_FACTORY = new ObjectFactory(); - - public enum INSTANCE_ACTIONS { - KILL, RERUN; - - public static INSTANCE_ACTIONS fromString(String name) { - return valueOf(name.toUpperCase()); - } - } - public enum JOB_ACTIONS { - SCHEDULE, EXPIRE, SUSPEND, RESUME; + private final LogSegregationContext logSegregationContext; + private final SchedulerService schedulerService; - public static JOB_ACTIONS fromString(String name) { - return valueOf(name.toUpperCase()); - } + public ScheduleResource() { + this.logSegregationContext = LensServices.get().getLogSegregationContext(); + this.schedulerService = LensServices.get().getService(SchedulerService.NAME); } - public static SchedulerService getSchedulerService() { - return LensServices.get().getService(SchedulerService.NAME); - } - - private static void validateSession(LensSessionHandle sessionHandle) throws LensException { - getSchedulerService().validateSession(sessionHandle); + private void validateSession(LensSessionHandle sessionHandle) throws LensException { + schedulerService.validateSession(sessionHandle); } @GET @@ -72,147 +59,270 @@ public class ScheduleResource { return "Scheduler is running."; } + /** + * Submits a job to be scheduled at later point of time or submit and schedule simultaneously. + * + * @param sessionId Session ID, the logged-in user will be set as the owner of this job + * @param action Action could be submit for storing the job or it could be "submit-and-schedule" to schedule it + * just after submitting the job. + * @param job XJob definition of the job to be submitted + * @return A newly generated job handle for the job. Job handle is the unique ID of a job. + * @throws LensException + */ @POST - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("jobs") - public SchedulerJobHandle submitJob(@QueryParam("sessionid") LensSessionHandle sessionId, - @DefaultValue("") @QueryParam("action") String action, - XJob job) throws LensException { + public LensAPIResult<SchedulerJobHandle> submitJob(@QueryParam("sessionid") LensSessionHandle sessionId, + @QueryParam("action") String action, XJob job) throws LensException { validateSession(sessionId); - if (StringUtils.isBlank(action)) { - return getSchedulerService().submitJob(sessionId, job); - } else if (StringUtils.equalsIgnoreCase(action, "submit-and-schedule")) { - return getSchedulerService().submitAndScheduleJob(sessionId, job); - } else { - throw new BadRequestException("Optional Query param 'action' can only be 'submit-and-schedule'"); + SUBMIT_ACTION op = UtilityMethods.checkAndGetOperation(action, SUBMIT_ACTION.class, SUBMIT_ACTION.values()); + SchedulerJobHandle jobHandle; + switch (op) { + case SUBMIT: + jobHandle = schedulerService.submitJob(sessionId, job); + break; + case SUBMIT_AND_SCHEDULE: + jobHandle = schedulerService.submitAndScheduleJob(sessionId, job); + break; + default: + throw new UnSupportedOpException(SUBMIT_ACTION.values()); } + return LensAPIResult.composedOf(null, this.logSegregationContext.getLogSegragationId(), jobHandle); + } + + /** + * Get all job handles matching user, state and end_time >job_submission_time >=start time. + * If any of the values are null, it will not be considered while filtering. + * For example: user is "test" and state is null then it will return job handles irrespective of state of the job. + * + * @param sessionHandle Session ID + * @param user User of the job + * @param state State of job: for example: SUCCEED or EXPIRED + * @param start Submission time should be grater than or equal to start time + * @param end Submission time should be strictly less than the end time. + * @return A list of all jobs matching the filtering criteria. + * @throws LensException + */ + + @GET + @Path("jobs") + public List<SchedulerJobHandle> getAllJobs(@QueryParam("sessionid") LensSessionHandle sessionHandle, + @QueryParam("user") String user, @QueryParam("state") SchedulerJobState state, @QueryParam("start") Long start, + @QueryParam("end") Long end) throws LensException { + validateSession(sessionHandle); + return schedulerService.getAllJobs(user, state, start, end); } + /** + * Get all job stats + * + * @param sessionId Session ID + * @param status Job status + * @param jobName Name of the job + * @param user User of the job + * @param start start time + * @param end end time + * @return A list of SchedulerJobStats + * @throws LensException + */ @GET @Path("jobs/stats") public Collection<SchedulerJobStats> getAllJobStats(@QueryParam("sessionid") LensSessionHandle sessionId, - @DefaultValue("running") @QueryParam("status") String status, - @QueryParam("name") String jobName, - @DefaultValue("user") @QueryParam("user") String user, - @DefaultValue("-1") @QueryParam("start") long start, - @DefaultValue("-1") @QueryParam("end") long end) throws LensException { + @DefaultValue("running") @QueryParam("status") String status, @QueryParam("name") String jobName, + @DefaultValue("user") @QueryParam("user") String user, @DefaultValue("-1") @QueryParam("start") long start, + @DefaultValue("-1") @QueryParam("end") long end) throws LensException { validateSession(sessionId); - return getSchedulerService().getAllJobStats(status, user, jobName, start, end); + return schedulerService.getAllJobStats(status, user, jobName, start, end); } + /** + * Get XJob definition for a given job handle. + * + * @param sessionId SessionID + * @param jobHandle Job handle + * @return XJob definition + * @throws LensException + */ @GET @Path("jobs/{jobHandle}") - public JAXBElement<XJob> getJobDefinition(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { - - return OBJECT_FACTORY.createJob(getSchedulerService().getJobDefinition(jobHandle)); + public LensAPIResult<XJob> getJobDefinition(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { + validateSession(sessionId); + XJob job = schedulerService.getJobDefinition(jobHandle); + return LensAPIResult.composedOf(null, this.logSegregationContext.getLogSegragationId(), job); } + /** + * Marks the job for deletion. Jobs are not deleted immediately, rather they are marked for deletion. + * A deleted job is a dormant job which can't be elicited by any action. + * + * @param sessionId Session id + * @param jobHandle Job handle + * @return API result + * @throws LensException + */ @DELETE @Path("jobs/{jobHandle}") - public APIResult deleteJob(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { + public LensAPIResult deleteJob(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { validateSession(sessionId); - getSchedulerService().deleteJob(sessionId, jobHandle); - return APIResult.success(); + schedulerService.deleteJob(sessionId, jobHandle); + final String requestId = this.logSegregationContext.getLogSegragationId(); + return LensAPIResult.composedOf(null, requestId, null); } + /** + * Updates job definition of an existing job. New definition can have new query and configurations. + * + * @param sessionId Session Id + * @param jobHandle Job handle + * @param job New job definition. + * @return LensAPIResult + * @throws LensException + */ @PUT @Path("jobs/{jobHandle}/") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - public APIResult updateJob(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle, XJob job) throws LensException { + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public LensAPIResult updateJob(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("jobHandle") SchedulerJobHandle jobHandle, XJob job) throws LensException { validateSession(sessionId); - getSchedulerService().updateJob(sessionId, jobHandle, job); - return APIResult.success(); + schedulerService.updateJob(sessionId, jobHandle, job); + final String requestId = this.logSegregationContext.getLogSegragationId(); + return LensAPIResult.composedOf(null, requestId, null); } + /** + * Changes the job state + * + * @param sessionId Session Id + * @param jobHandle Job handle + * @param action An action can be SCHEDULE, EXPIRE, SUSPEND or RESUME + * @return LensAPIResult + * @throws LensException + */ @POST @Path("jobs/{jobHandle}") - public APIResult updateJob(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle, - @DefaultValue("schedule") @QueryParam("action") JOB_ACTIONS action) throws LensException { + public LensAPIResult updateJob(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("jobHandle") SchedulerJobHandle jobHandle, @DefaultValue("schedule") @QueryParam("action") String action) + throws LensException { validateSession(sessionId); - switch (action) { - + JOB_ACTION op = UtilityMethods.checkAndGetOperation(action, JOB_ACTION.class, JOB_ACTION.values()); + switch (op) { case SCHEDULE: - getSchedulerService().scheduleJob(sessionId, jobHandle); + schedulerService.scheduleJob(sessionId, jobHandle); break; case EXPIRE: - getSchedulerService().expireJob(sessionId, jobHandle); + schedulerService.expireJob(sessionId, jobHandle); break; case SUSPEND: - getSchedulerService().suspendJob(sessionId, jobHandle); + schedulerService.suspendJob(sessionId, jobHandle); break; case RESUME: - getSchedulerService().resumeJob(sessionId, jobHandle); + schedulerService.resumeJob(sessionId, jobHandle); break; default: - throw new BadRequestException("Unsupported action " + action.toString()); + throw new UnSupportedOpException(JOB_ACTION.values()); } - return APIResult.success(); + return LensAPIResult.composedOf(null, this.logSegregationContext.getLogSegragationId(), null); } + /** + * Returns the SchedulerJobInfo of a given job handle. + * + * @param sessionId Session ID + * @param jobHandle Job handle + * @return SchedulerJobinfo + * @throws LensException + */ @GET @Path("jobs/{jobHandle}/info") - public SchedulerJobInfo getJobDetails(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { + public LensAPIResult<SchedulerJobInfo> getJobDetails(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("jobHandle") SchedulerJobHandle jobHandle) throws LensException { validateSession(sessionId); - return getSchedulerService().getJobDetails(jobHandle); + SchedulerJobInfo info = schedulerService.getJobDetails(jobHandle); + return LensAPIResult.composedOf(null, this.logSegregationContext.getLogSegragationId(), info); } + /** + * Returns all the instances of a job. + * + * @param sessionId Session id + * @param jobHandle Job handle + * @param numResults Number of results to be returned + * @return A list of SchedulerInstanceInfo for a given job handle + * @throws LensException + */ @GET @Path("jobs/{jobHandle}/instances/") public List<SchedulerJobInstanceInfo> getJobInstances(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("jobHandle") SchedulerJobHandle jobHandle, - @QueryParam("numResults") Long numResults) throws LensException { + @PathParam("jobHandle") SchedulerJobHandle jobHandle, @QueryParam("numResults") Long numResults) + throws LensException { validateSession(sessionId); - return getSchedulerService().getJobInstances(jobHandle, numResults); + return schedulerService.getJobInstances(jobHandle, numResults); } + /** + * Returns a SchedulerInstanceInfo for a given instance handle. + * + * @param sessionId Session ID + * @param instanceHandle instance handle + * @return SchedulerInstanceInfo + * @throws LensException + */ @GET @Path("instances/{instanceHandle}") - public SchedulerJobInstanceInfo getInstanceDetails(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("instanceHandle") - SchedulerJobInstanceHandle instanceHandle) throws LensException { + public LensAPIResult<SchedulerJobInstanceInfo> getInstanceDetails( + @QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("instanceHandle") SchedulerJobInstanceHandle instanceHandle) throws LensException { validateSession(sessionId); - return getSchedulerService().getInstanceDetails(instanceHandle); + SchedulerJobInstanceInfo instance = schedulerService.getInstanceDetails(instanceHandle); + return LensAPIResult.composedOf(null, this.logSegregationContext.getLogSegragationId(), instance); } + /** + * Updates an instance + * + * @param sessionId Session ID + * @param instanceHandle Instance handle + * @param action the value of action could be KILL or RERUN. + * @return LensAPIResult + * @throws LensException + */ @POST @Path("instances/{instanceHandle}") - public APIResult updateInstance(@QueryParam("sessionid") LensSessionHandle sessionId, - @PathParam("instanceHandle") SchedulerJobInstanceHandle instanceHandle, - @QueryParam("action") INSTANCE_ACTIONS action) throws LensException { - APIResult res = null; + public LensAPIResult updateInstance(@QueryParam("sessionid") LensSessionHandle sessionId, + @PathParam("instanceHandle") SchedulerJobInstanceHandle instanceHandle, @QueryParam("action") String action) + throws LensException { + boolean res = true; validateSession(sessionId); - switch (action) { + INSTANCE_ACTION op = UtilityMethods.checkAndGetOperation(action, INSTANCE_ACTION.class, INSTANCE_ACTION.values()); + switch (op) { case KILL: - if (getSchedulerService().killInstance(sessionId, instanceHandle)) { - res = new APIResult(APIResult.Status.SUCCEEDED, - "Killing the instance with id " + instanceHandle + " was successful"); - } else { - res = new APIResult(APIResult.Status.FAILED, - "Killing the instance with id " + instanceHandle + " was not successful"); - } + res = schedulerService.killInstance(sessionId, instanceHandle); break; case RERUN: - if (getSchedulerService().rerunInstance(sessionId, instanceHandle)) { - res = new APIResult(APIResult.Status.SUCCEEDED, - "Rerunning the instance with id " + instanceHandle + " was successful"); - } else { - res = new APIResult(APIResult.Status.FAILED, - "Rerunning the instance with id " + instanceHandle + " was not successful"); - } + schedulerService.rerunInstance(sessionId, instanceHandle); break; default: - throw new BadRequestException("Unsupported action " + action.toString()); - + throw new UnSupportedOpException(INSTANCE_ACTION.values()); } - return res; + final String requestId = this.logSegregationContext.getLogSegragationId(); + return LensAPIResult.composedOf(null, requestId, res); + } + + private enum SUBMIT_ACTION { + SUBMIT, SUBMIT_AND_SCHEDULE; + } + + private enum INSTANCE_ACTION { + KILL, RERUN; + } + + private enum JOB_ACTION { + SCHEDULE, EXPIRE, SUSPEND, RESUME; } } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerEventListener.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerEventListener.java b/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerEventListener.java index d1d4a68..1db8136 100644 --- a/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerEventListener.java +++ b/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerEventListener.java @@ -66,10 +66,6 @@ public class SchedulerEventListener extends AsyncEventListener<SchedulerAlarmEve this.schedulerDAO = schedulerDAO; } - private LensSessionHandle getSessionHandle(String user) throws LensException { - return schedulerService.openSessionAsUser(user); - } - private void setSessionConf(LensSessionHandle sessionHandle, XJob job) throws LensException { XExecution execution = job.getExecution(); XSessionType executionSession = execution.getSession(); @@ -121,7 +117,7 @@ public class SchedulerEventListener extends AsyncEventListener<SchedulerAlarmEve LensSessionHandle sessionHandle = null; try { - sessionHandle = getSessionHandle(user); + sessionHandle = schedulerService.openSessionAsUser(user); setSessionConf(sessionHandle, job); if (event.getType() == SchedulerAlarmEvent.EventType.EXPIRE) { try { http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerServiceImpl.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerServiceImpl.java b/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerServiceImpl.java index 74b337c..323e053 100644 --- a/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerServiceImpl.java +++ b/lens-server/src/main/java/org/apache/lens/server/scheduler/SchedulerServiceImpl.java @@ -18,6 +18,9 @@ */ package org.apache.lens.server.scheduler; +import static org.apache.lens.api.scheduler.SchedulerJobInstanceEvent.ON_KILL; +import static org.apache.lens.api.scheduler.SchedulerJobInstanceEvent.ON_RERUN; + import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -25,17 +28,20 @@ import java.util.List; import org.apache.lens.api.LensConf; import org.apache.lens.api.LensSessionHandle; import org.apache.lens.api.error.InvalidStateTransitionException; +import org.apache.lens.api.error.LensCommonErrorCode; import org.apache.lens.api.query.QueryHandle; import org.apache.lens.api.scheduler.*; import org.apache.lens.cube.parse.CubeQueryConfUtil; import org.apache.lens.server.BaseLensService; import org.apache.lens.server.LensServices; +import org.apache.lens.server.api.LensErrorInfo; import org.apache.lens.server.api.error.LensException; import org.apache.lens.server.api.events.SchedulerAlarmEvent; import org.apache.lens.server.api.health.HealthStatus; import org.apache.lens.server.api.query.QueryEnded; import org.apache.lens.server.api.query.QueryExecutionService; import org.apache.lens.server.api.scheduler.SchedulerService; +import org.apache.lens.server.error.LensSchedulerErrorCode; import org.apache.lens.server.session.LensSessionImpl; import org.apache.lens.server.util.UtilityMethods; @@ -98,7 +104,8 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe private void doesSessionBelongToUser(LensSessionHandle sessionHandle, String user) throws LensException { LensSessionImpl session = getSession(sessionHandle); if (!session.getLoggedInUser().equals(user)) { - throw new LensException("Logged in user " + session.getLoggedInUser() + " is not same as " + user); + throw new LensException(LensSchedulerErrorCode.CURRENT_USER_IS_NOT_SAME_AS_OWNER.getLensErrorInfo(), null, + session.getLoggedInUser(), sessionHandle.getPublicId().toString(), user); } } @@ -126,6 +133,12 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe return openSession(user, "Mimbulus Mimbletonia", new HashMap<String, String>(), false); } + @Override + public List<SchedulerJobHandle> getAllJobs(String user, SchedulerJobState state, Long start, Long end) + throws LensException { + return this.schedulerDAO.getJobs(user, state, start, end); + } + /** * {@inheritDoc} */ @@ -143,7 +156,7 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe log.info("Successfully submitted job with handle {}", handle); return handle; } else { - throw new LensException("Could not Submit the job"); + throw new LensException(LensSchedulerErrorCode.CANT_SUBMIT_JOB.getLensErrorInfo(), null, job.getName()); } } @@ -154,8 +167,8 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe * {@inheritDoc} */ @Override - public boolean scheduleJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { - SchedulerJobInfo jobInfo = schedulerDAO.getSchedulerJobInfo(jobHandle); + public void scheduleJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo jobInfo = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, jobInfo.getUserName()); XJob job = jobInfo.getJob(); DateTime start = new DateTime(job.getStartTime().toGregorianCalendar().getTime()); @@ -165,7 +178,7 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe checkQuery(sessionHandle, job); alarmService.schedule(start, end, frequency, jobHandle.getHandleIdString()); log.info("Successfully scheduled job with handle {} in AlarmService", jobHandle); - return setStateOfJob(jobInfo, SchedulerJobEvent.ON_SCHEDULE) == 1; + setStateOfJob(jobInfo, SchedulerJobEvent.ON_SCHEDULE); } private void checkQuery(LensSessionHandle sessionHandle, XJob job) throws LensException { @@ -177,7 +190,6 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe queryConf.addProperty(CubeQueryConfUtil.FAIL_QUERY_ON_PARTIAL_DATA, false); queryService.estimate(LensServices.get().getLogSegregationContext().getLogSegragationId(), sessionHandle, job.getExecution().getQuery().getQuery(), queryConf); - return; } @Override @@ -200,72 +212,86 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe */ @Override public SchedulerJobInfo getJobDetails(SchedulerJobHandle jobHandle) throws LensException { - return schedulerDAO.getSchedulerJobInfo(jobHandle); + return checkAndGetSchedulerJobInfo(jobHandle); + } + + private SchedulerJobInfo checkAndGetSchedulerJobInfo(SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo jobInfo = schedulerDAO.getSchedulerJobInfo(jobHandle); + if (jobInfo == null) { + throw new LensException( + new LensErrorInfo(LensCommonErrorCode.RESOURCE_NOT_FOUND.getValue(), 0, "Job handle not found"), null, "job", + jobHandle.getHandleIdString()); + } + return jobInfo; } /** * {@inheritDoc} */ @Override - public boolean updateJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle, XJob newJobDefinition) + public void updateJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle, XJob newJobDefinition) throws LensException { - SchedulerJobInfo jobInfo = schedulerDAO.getSchedulerJobInfo(jobHandle); + SchedulerJobInfo jobInfo = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, jobInfo.getUserName()); // This will allow only the job definition and configuration change. jobInfo.setJob(newJobDefinition); jobInfo.setModifiedOn(System.currentTimeMillis()); int updated = schedulerDAO.updateJob(jobInfo); - return updated > 0; + if (updated > 0) { + return; + } + throw new LensException(LensSchedulerErrorCode.CANT_UPDATE_RESOURCE_WITH_HANDLE.getLensErrorInfo(), null, "job", + jobHandle.getHandleIdString()); } /** * {@inheritDoc} */ @Override - public boolean expireJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { - SchedulerJobInfo info = schedulerDAO.getSchedulerJobInfo(jobHandle); + public void expireJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo info = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, info.getUserName()); if (alarmService.checkExists(jobHandle)) { alarmService.unSchedule(jobHandle); log.info("Successfully unscheduled the job with handle {} in AlarmService ", jobHandle); } - return setStateOfJob(info, SchedulerJobEvent.ON_EXPIRE) == 1; + setStateOfJob(info, SchedulerJobEvent.ON_EXPIRE); } /** * {@inheritDoc} */ @Override - public boolean suspendJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { - SchedulerJobInfo info = schedulerDAO.getSchedulerJobInfo(jobHandle); + public void suspendJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo info = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, info.getUserName()); alarmService.pauseJob(jobHandle); - return setStateOfJob(info, SchedulerJobEvent.ON_SUSPEND) == 1; + setStateOfJob(info, SchedulerJobEvent.ON_SUSPEND); } /** * {@inheritDoc} */ @Override - public boolean resumeJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { - SchedulerJobInfo info = schedulerDAO.getSchedulerJobInfo(jobHandle); + public void resumeJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo info = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, info.getUserName()); alarmService.resumeJob(jobHandle); - return setStateOfJob(info, SchedulerJobEvent.ON_RESUME) == 1; + setStateOfJob(info, SchedulerJobEvent.ON_RESUME); } /** * {@inheritDoc} */ @Override - public boolean deleteJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { - SchedulerJobInfo info = schedulerDAO.getSchedulerJobInfo(jobHandle); + public void deleteJob(LensSessionHandle sessionHandle, SchedulerJobHandle jobHandle) throws LensException { + SchedulerJobInfo info = checkAndGetSchedulerJobInfo(jobHandle); doesSessionBelongToUser(sessionHandle, info.getUserName()); if (alarmService.checkExists(jobHandle)) { alarmService.unSchedule(jobHandle); log.info("Successfully unscheduled the job with handle {} ", jobHandle); } - return setStateOfJob(info, SchedulerJobEvent.ON_DELETE) == 1; + setStateOfJob(info, SchedulerJobEvent.ON_DELETE); } /** @@ -290,30 +316,33 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe * {@inheritDoc} */ @Override - public boolean rerunInstance(LensSessionHandle sessionHandle, SchedulerJobInstanceHandle instanceHandle) + public void rerunInstance(LensSessionHandle sessionHandle, SchedulerJobInstanceHandle instanceHandle) throws LensException { SchedulerJobInstanceInfo instanceInfo = schedulerDAO.getSchedulerJobInstanceInfo(instanceHandle); doesSessionBelongToUser(sessionHandle, schedulerDAO.getUser(instanceInfo.getJobId())); - if (schedulerDAO.getJobState(instanceInfo.getJobId()) != SchedulerJobState.SCHEDULED) { - throw new LensException("Job with handle " + instanceInfo.getJobId() + " is not scheduled"); + SchedulerJobState currentState = schedulerDAO.getJobState(instanceInfo.getJobId()); + if (currentState != SchedulerJobState.SCHEDULED) { + throw new LensException(LensSchedulerErrorCode.JOB_IS_NOT_SCHEDULED.getLensErrorInfo(), null, + instanceInfo.getJobId().getHandleIdString(), currentState); } // Get the latest run. List<SchedulerJobInstanceRun> runList = instanceInfo.getInstanceRunList(); if (runList.size() == 0) { - throw new LensException("Job instance " + instanceHandle + " is not yet run"); + throw new LensException(LensSchedulerErrorCode.JOB_INSTANCE_IS_NOT_YET_RUN.getLensErrorInfo(), null, + instanceHandle.getHandleIdString(), instanceInfo.getJobId().getHandleIdString()); } SchedulerJobInstanceRun latestRun = runList.get(runList.size() - 1); - // This call is for the test that it can be re run. try { - latestRun.getInstanceState().nextTransition(SchedulerJobInstanceEvent.ON_RERUN); + latestRun.getInstanceState().nextTransition(ON_RERUN); getEventService().notifyEvent( new SchedulerAlarmEvent(instanceInfo.getJobId(), new DateTime(instanceInfo.getScheduleTime()), SchedulerAlarmEvent.EventType.SCHEDULE, instanceHandle)); log.info("Rerunning the instance with {} for job {} ", instanceHandle, instanceInfo.getJobId()); } catch (InvalidStateTransitionException e) { - throw new LensException("Invalid State Transition ", e); + throw new LensException(LensSchedulerErrorCode.INVALID_EVENT_FOR_JOB_INSTANCE.getLensErrorInfo(), e, + ON_RERUN.name(), latestRun.getInstanceState().name(), instanceInfo.getId().getHandleIdString(), + instanceInfo.getJobId().getHandleIdString()); } - return true; } /** @@ -335,17 +364,20 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe doesSessionBelongToUser(sessionHandle, schedulerDAO.getUser(instanceInfo.getJobId())); List<SchedulerJobInstanceRun> runList = instanceInfo.getInstanceRunList(); if (runList.size() == 0) { - throw new LensException("Job instance " + instanceHandle + " is not yet run"); + throw new LensException(LensSchedulerErrorCode.JOB_INSTANCE_IS_NOT_YET_RUN.getLensErrorInfo(), null, + instanceHandle.getHandleIdString(), instanceInfo.getJobId().getHandleIdString()); } SchedulerJobInstanceRun latestRun = runList.get(runList.size() - 1); + SchedulerJobInstanceState state = latestRun.getInstanceState(); + try { + state = state.nextTransition(ON_KILL); + } catch (InvalidStateTransitionException e) { + throw new LensException(LensSchedulerErrorCode.INVALID_EVENT_FOR_JOB_INSTANCE.getLensErrorInfo(), e, + ON_KILL.name(), latestRun.getInstanceState().name(), instanceInfo.getId().getHandleIdString(), + instanceInfo.getJobId().getHandleIdString()); + } QueryHandle handle = latestRun.getQueryHandle(); if (handle == null || handle.getHandleIdString().isEmpty()) { - SchedulerJobInstanceState state = latestRun.getInstanceState(); - try { - state = state.nextTransition(SchedulerJobInstanceEvent.ON_KILL); - } catch (InvalidStateTransitionException e) { - throw new LensException("Invalid Transition of state ", e); - } latestRun.setEndTime(System.currentTimeMillis()); latestRun.setInstanceState(state); schedulerDAO.updateJobInstanceRun(latestRun); @@ -366,9 +398,9 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe return schedulerDAO.getSchedulerJobInstanceInfo(instanceHandle); } - private int setStateOfJob(SchedulerJobInfo info, SchedulerJobEvent event) throws LensException { + private void setStateOfJob(SchedulerJobInfo info, SchedulerJobEvent event) throws LensException { + SchedulerJobState currentState = info.getJobState(); try { - SchedulerJobState currentState = info.getJobState(); SchedulerJobState nextState = currentState.nextTransition(event); info.setJobState(nextState); info.setModifiedOn(System.currentTimeMillis()); @@ -376,10 +408,13 @@ public class SchedulerServiceImpl extends BaseLensService implements SchedulerSe if (ret == 1) { log.info("Successfully changed the status of job with handle {} from {} to {}", info.getId(), currentState, nextState); + } else { + throw new LensException(LensSchedulerErrorCode.CANT_UPDATE_RESOURCE_WITH_HANDLE.getLensErrorInfo(), null, "job", + info.getId().getHandleIdString()); } - return ret; } catch (InvalidStateTransitionException e) { - throw new LensException("Invalid state ", e); + throw new LensException(LensSchedulerErrorCode.INVALID_EVENT_FOR_JOB.getLensErrorInfo(), e, event.name(), + currentState.name(), info.getId().getHandleIdString()); } } } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/main/java/org/apache/lens/server/util/UtilityMethods.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/util/UtilityMethods.java b/lens-server/src/main/java/org/apache/lens/server/util/UtilityMethods.java index 2842ec3..90226d1 100644 --- a/lens-server/src/main/java/org/apache/lens/server/util/UtilityMethods.java +++ b/lens-server/src/main/java/org/apache/lens/server/util/UtilityMethods.java @@ -33,6 +33,7 @@ import javax.sql.DataSource; import org.apache.lens.api.scheduler.SchedulerJobHandle; import org.apache.lens.api.scheduler.SchedulerJobInstanceHandle; import org.apache.lens.server.api.LensConfConstants; +import org.apache.lens.server.error.UnSupportedOpException; import org.apache.commons.dbcp.*; import org.apache.commons.dbutils.QueryRunner; @@ -232,4 +233,18 @@ public final class UtilityMethods { public static SchedulerJobInstanceHandle generateSchedulerJobInstanceHandle() { return new SchedulerJobInstanceHandle(UUID.randomUUID()); } + public static <T extends Enum<T>> T checkAndGetOperation(final String operation, Class<T> enumType, + T... supportedOperations) throws UnSupportedOpException { + try { + T op = Enum.valueOf(enumType, operation.toUpperCase()); + for (T supportedOperation : supportedOperations) { + if (op.equals(supportedOperation)) { + return op; + } + } + throw new UnSupportedOpException(supportedOperations); + } catch (IllegalArgumentException e) { + throw new UnSupportedOpException(e, supportedOperations); + } + } } http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/test/java/org/apache/lens/server/query/QueryAPIErrorResponseTest.java ---------------------------------------------------------------------- diff --git a/lens-server/src/test/java/org/apache/lens/server/query/QueryAPIErrorResponseTest.java b/lens-server/src/test/java/org/apache/lens/server/query/QueryAPIErrorResponseTest.java index 8e21ae4..567c929 100644 --- a/lens-server/src/test/java/org/apache/lens/server/query/QueryAPIErrorResponseTest.java +++ b/lens-server/src/test/java/org/apache/lens/server/query/QueryAPIErrorResponseTest.java @@ -22,8 +22,10 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.apache.lens.api.error.LensCommonErrorCode.INTERNAL_SERVER_ERROR; + import static org.apache.lens.cube.error.LensCubeErrorCode.COLUMN_UNAVAILABLE_IN_TIME_RANGE; import static org.apache.lens.cube.error.LensCubeErrorCode.SYNTAX_ERROR; + import static org.apache.lens.server.common.RestAPITestUtil.*; import static org.apache.lens.server.common.TestDataUtils.*; import static org.apache.lens.server.error.LensServerErrorCode.*; @@ -38,9 +40,9 @@ import javax.xml.datatype.DatatypeConfigurationException; import org.apache.lens.api.LensConf; import org.apache.lens.api.LensSessionHandle; +import org.apache.lens.api.SupportedOperations; import org.apache.lens.api.jaxb.LensJAXBContextResolver; import org.apache.lens.api.metastore.*; -import org.apache.lens.api.query.SupportedQuerySubmitOperations; import org.apache.lens.api.result.LensAPIResult; import org.apache.lens.api.result.LensErrorTO; import org.apache.lens.api.util.MoxyJsonConfigurationContextResolver; @@ -138,8 +140,8 @@ public class QueryAPIErrorResponseTest extends LensJerseyTest { + "[estimate, execute, explain, execute_with_timeout]"; LensErrorTO expectedLensErrorTO = LensErrorTO.composedOf( - UNSUPPORTED_QUERY_SUBMIT_OPERATION.getLensErrorInfo().getErrorCode(), - expectedErrMsg, MOCK_STACK_TRACE, new SupportedQuerySubmitOperations()); + UNSUPPORTED_OPERATION.getLensErrorInfo().getErrorCode(), + expectedErrMsg, MOCK_STACK_TRACE, new SupportedOperations()); ErrorResponseExpectedData expectedData = new ErrorResponseExpectedData(BAD_REQUEST, expectedLensErrorTO); expectedData.verify(response); http://git-wip-us.apache.org/repos/asf/lens/blob/fae2773c/lens-server/src/test/java/org/apache/lens/server/scheduler/TestSchedulerServiceImpl.java ---------------------------------------------------------------------- diff --git a/lens-server/src/test/java/org/apache/lens/server/scheduler/TestSchedulerServiceImpl.java b/lens-server/src/test/java/org/apache/lens/server/scheduler/TestSchedulerServiceImpl.java index e182c72..130df5f 100644 --- a/lens-server/src/test/java/org/apache/lens/server/scheduler/TestSchedulerServiceImpl.java +++ b/lens-server/src/test/java/org/apache/lens/server/scheduler/TestSchedulerServiceImpl.java @@ -18,16 +18,14 @@ */ package org.apache.lens.server.scheduler; +import static org.apache.lens.server.scheduler.util.SchedulerTestUtils.getTestJob; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; -import java.util.GregorianCalendar; import java.util.List; import java.util.UUID; -import javax.xml.datatype.DatatypeFactory; -import javax.xml.datatype.XMLGregorianCalendar; - import org.apache.lens.api.LensConf; import org.apache.lens.api.LensSessionHandle; import org.apache.lens.api.query.QueryHandle; @@ -58,6 +56,8 @@ public class TestSchedulerServiceImpl { SchedulerServiceImpl scheduler; EventServiceImpl eventService; String user = "someuser"; + String queryString = "select ID from test_table"; + @BeforeMethod public void setup() throws Exception { System.setProperty(LensConfConstants.CONFIG_LOCATION, "target/test-classes/"); @@ -101,7 +101,7 @@ public class TestSchedulerServiceImpl { setupQueryService(); LensSessionHandle sessionHandle = scheduler.openSessionAsUser(user); long currentTime = System.currentTimeMillis(); - XJob job = getTestJob("0/5 * * * * ?", currentTime, currentTime + 15000); + XJob job = getTestJob("0/5 * * * * ?", queryString, currentTime, currentTime + 15000); SchedulerJobHandle jobHandle = scheduler.submitAndScheduleJob(sessionHandle, job); Assert.assertNotNull(jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.SCHEDULED); @@ -126,16 +126,16 @@ public class TestSchedulerServiceImpl { @Test(priority = 2) public void testSuspendResume() throws Exception { long currentTime = System.currentTimeMillis(); - XJob job = getTestJob("0/10 * * * * ?", currentTime, currentTime + 180000); + XJob job = getTestJob("0/10 * * * * ?", queryString, currentTime, currentTime + 180000); LensSessionHandle sessionHandle = scheduler.openSessionAsUser(user); SchedulerJobHandle jobHandle = scheduler.submitAndScheduleJob(sessionHandle, job); Assert.assertNotNull(jobHandle); - Assert.assertTrue(scheduler.suspendJob(sessionHandle, jobHandle)); + scheduler.suspendJob(sessionHandle, jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.SUSPENDED); - Assert.assertTrue(scheduler.resumeJob(sessionHandle, jobHandle)); + scheduler.resumeJob(sessionHandle, jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.SCHEDULED); Thread.sleep(10000); - Assert.assertTrue(scheduler.expireJob(sessionHandle, jobHandle)); + scheduler.expireJob(sessionHandle, jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.EXPIRED); scheduler.closeSession(sessionHandle); } @@ -144,7 +144,7 @@ public class TestSchedulerServiceImpl { public void testRerunInstance() throws Exception { long currentTime = System.currentTimeMillis(); - XJob job = getTestJob("0/10 * * * * ?", currentTime, currentTime + 180000); + XJob job = getTestJob("0/10 * * * * ?", queryString, currentTime, currentTime + 180000); LensSessionHandle sessionHandle = scheduler.openSessionAsUser(user); SchedulerJobHandle jobHandle = scheduler.submitAndScheduleJob(sessionHandle, job); // Wait for some instances. @@ -160,7 +160,7 @@ public class TestSchedulerServiceImpl { Assert.assertEquals(info.getInstanceRunList().get(0).getInstanceState(), SchedulerJobInstanceState.FAILED); // Rerun - Assert.assertTrue(scheduler.rerunInstance(sessionHandle, instanceHandleList.get(0).getId())); + scheduler.rerunInstance(sessionHandle, instanceHandleList.get(0).getId()); Thread.sleep(5000); eventService.notifyEvent(mockQueryEnded(instanceHandleList.get(0).getId(), QueryStatus.Status.SUCCESSFUL)); Thread.sleep(1000); @@ -169,7 +169,7 @@ public class TestSchedulerServiceImpl { Assert.assertEquals(info.getInstanceRunList().size(), 2); Assert.assertEquals(info.getInstanceRunList().get(1).getResultPath(), "/tmp/query1/result"); Assert.assertEquals(info.getInstanceRunList().get(1).getInstanceState(), SchedulerJobInstanceState.SUCCEEDED); - Assert.assertTrue(scheduler.expireJob(sessionHandle, jobHandle)); + scheduler.expireJob(sessionHandle, jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.EXPIRED); scheduler.closeSession(sessionHandle); } @@ -177,7 +177,7 @@ public class TestSchedulerServiceImpl { @Test(priority = 2) public void testKillRunningInstance() throws Exception { long currentTime = System.currentTimeMillis(); - XJob job = getTestJob("0/5 * * * * ?", currentTime, currentTime + 180000); + XJob job = getTestJob("0/5 * * * * ?", queryString, currentTime, currentTime + 180000); LensSessionHandle sessionHandle = scheduler.openSessionAsUser(user); SchedulerJobHandle jobHandle = scheduler.submitAndScheduleJob(sessionHandle, job); // Let it run @@ -194,46 +194,8 @@ public class TestSchedulerServiceImpl { Thread.sleep(2000); info = scheduler.getSchedulerDAO().getSchedulerJobInstanceInfo(instanceHandleList.get(0).getId()); Assert.assertEquals(info.getInstanceRunList().get(0).getInstanceState(), SchedulerJobInstanceState.KILLED); - Assert.assertTrue(scheduler.expireJob(sessionHandle, jobHandle)); + scheduler.expireJob(sessionHandle, jobHandle); Assert.assertEquals(scheduler.getSchedulerDAO().getJobState(jobHandle), SchedulerJobState.EXPIRED); scheduler.closeSession(sessionHandle); } - - private XTrigger getTestTrigger(String cron) { - XTrigger trigger = new XTrigger(); - XFrequency frequency = new XFrequency(); - frequency.setCronExpression(cron); - frequency.setTimezone("UTC"); - trigger.setFrequency(frequency); - return trigger; - } - - private XExecution getTestExecution() { - XExecution execution = new XExecution(); - XJobQuery query = new XJobQuery(); - query.setQuery("select ID from test_table"); - execution.setQuery(query); - XSessionType sessionType = new XSessionType(); - sessionType.setDb("default"); - execution.setSession(sessionType); - return execution; - } - - private XJob getTestJob(String cron, long start, long end) throws Exception { - XJob job = new XJob(); - job.setTrigger(getTestTrigger(cron)); - job.setName("Test lens Job"); - GregorianCalendar startTime = new GregorianCalendar(); - startTime.setTimeInMillis(start); - XMLGregorianCalendar startCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(startTime); - - GregorianCalendar endTime = new GregorianCalendar(); - endTime.setTimeInMillis(end); - XMLGregorianCalendar endCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(endTime); - - job.setStartTime(startCal); - job.setEndTime(endCal); - job.setExecution(getTestExecution()); - return job; - } }
