This is an automated email from the ASF dual-hosted git repository. geniuspig pushed a commit to branch http in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
commit 262a3168c337d5f912782a27cc14754889ad548d Author: zhutianci <[email protected]> AuthorDate: Thu Feb 6 11:05:02 2020 +0800 add rest api. --- server/pom.xml | 5 + .../apache/iotdb/db/http/service/HttpService.java | 5 - .../apache/iotdb/db/metrics/server/JettyUtil.java | 25 +-- .../iotdb/db/metrics/server/MetricsSystem.java | 11 +- ...etricsServletSink.java => JsonServletSink.java} | 92 ++++----- .../apache/iotdb/db/metrics/ui/MetricsWebUI.java | 25 ++- .../org/apache/iotdb/db/qp/QueryProcessor.java | 6 + .../iotdb/db/rest/controller/RestController.java | 207 +++++++++++++++++++++ .../iotdb/db/{http => rest/model}/TimeValues.java | 2 +- .../apache/iotdb/db/rest/service/RestService.java | 177 ++++++++++++++++++ .../QueryServlet.java => rest/util/RestUtil.java} | 35 ++-- .../apache/iotdb/db/service/MetricsService.java | 7 +- .../src/main/resources/iotdb/ui/static/index.html | 4 +- 13 files changed, 487 insertions(+), 114 deletions(-) diff --git a/server/pom.xml b/server/pom.xml index b231975..180c31b 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -121,6 +121,11 @@ <artifactId>stream</artifactId> <version>2.9.5</version> </dependency> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet</artifactId> + <version>2.30</version> + </dependency> </dependencies> <build> <plugins> diff --git a/server/src/main/java/org/apache/iotdb/db/http/service/HttpService.java b/server/src/main/java/org/apache/iotdb/db/http/service/HttpService.java deleted file mode 100644 index 87ba8ee..0000000 --- a/server/src/main/java/org/apache/iotdb/db/http/service/HttpService.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.apache.iotdb.db.http.service; - -public class HttpService { - -} diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/server/JettyUtil.java b/server/src/main/java/org/apache/iotdb/db/metrics/server/JettyUtil.java index ab2cff1..ce3a38d 100644 --- a/server/src/main/java/org/apache/iotdb/db/metrics/server/JettyUtil.java +++ b/server/src/main/java/org/apache/iotdb/db/metrics/server/JettyUtil.java @@ -33,7 +33,7 @@ import org.eclipse.jetty.servlet.ServletHolder; public class JettyUtil { - public static ServletContextHandler createMetricsServletHandler(ObjectMapper mapper,MetricRegistry metricRegistry) { + public static ServletHolder createJsonServletHolder(ObjectMapper mapper,MetricRegistry metricRegistry) { HttpServlet httpServlet = new HttpServlet() { private static final long serialVersionUID = 1L; @@ -56,27 +56,14 @@ public class JettyUtil { doGet(req, resp); } }; - - return createServletHandler("/json", httpServlet, "/"); - } - public static ServletContextHandler createServletHandler(String path, HttpServlet servlet, String pathSpec) { - ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); - ServletHolder holder = new ServletHolder(servlet); - contextHandler.setContextPath(path); - contextHandler.addServlet(holder, pathSpec); - return contextHandler; + return new ServletHolder(httpServlet); } - public static ServletContextHandler createStaticHandler() { - ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); - URL res = JettyUtil.class.getClassLoader().getResource("iotdb/ui/static"); - HttpServlet servlet = new DefaultServlet(); - ServletHolder holder = new ServletHolder(servlet); - holder.setInitParameter("resourceBase", Objects.requireNonNull(res).toString()); - contextHandler.setContextPath("/static"); - contextHandler.addServlet(holder, "/"); - return contextHandler; + public static ServletHolder createStaticServletHolder() { + ServletHolder holder = new ServletHolder("static", DefaultServlet.class); + holder.setInitParameter("dirAllowed", "true"); + return holder; } public static Server getJettyServer(List<ServletContextHandler> handlers, int port) { diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/server/MetricsSystem.java b/server/src/main/java/org/apache/iotdb/db/metrics/server/MetricsSystem.java index 7872b14..cfc726a 100644 --- a/server/src/main/java/org/apache/iotdb/db/metrics/server/MetricsSystem.java +++ b/server/src/main/java/org/apache/iotdb/db/metrics/server/MetricsSystem.java @@ -15,12 +15,12 @@ package org.apache.iotdb.db.metrics.server; import java.util.ArrayList; -import org.apache.iotdb.db.metrics.sink.MetricsServletSink; +import org.apache.iotdb.db.metrics.sink.JsonServletSink; import org.apache.iotdb.db.metrics.sink.Sink; import org.apache.iotdb.db.metrics.source.MetricsSource; import org.apache.iotdb.db.metrics.source.Source; -import org.eclipse.jetty.servlet.ServletContextHandler; import com.codahale.metrics.MetricRegistry; +import org.eclipse.jetty.servlet.ServletHolder; public class MetricsSystem { @@ -40,8 +40,11 @@ public class MetricsSystem { return metricRegistry; } - public ServletContextHandler getServletHandlers() { - return new MetricsServletSink(metricRegistry).getHandler(); + /** + * to get a json Servlet Holder + */ + public ServletHolder getServletHolder() { + return new JsonServletSink(metricRegistry).getHolder(); } public void start() { diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/sink/MetricsServletSink.java b/server/src/main/java/org/apache/iotdb/db/metrics/sink/JsonServletSink.java similarity index 81% rename from server/src/main/java/org/apache/iotdb/db/metrics/sink/MetricsServletSink.java rename to server/src/main/java/org/apache/iotdb/db/metrics/sink/JsonServletSink.java index c88e447..16003e5 100644 --- a/server/src/main/java/org/apache/iotdb/db/metrics/sink/MetricsServletSink.java +++ b/server/src/main/java/org/apache/iotdb/db/metrics/sink/JsonServletSink.java @@ -1,46 +1,46 @@ -/* - * 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.iotdb.db.metrics.sink; - -import java.util.concurrent.TimeUnit; -import org.apache.iotdb.db.metrics.server.JettyUtil; -import org.eclipse.jetty.servlet.ServletContextHandler; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.json.MetricsModule; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class MetricsServletSink implements Sink { - - private MetricRegistry registry; - - public MetricsServletSink(MetricRegistry registry) { - this.registry = registry; - } - - public ServletContextHandler getHandler() { - ObjectMapper mapper = new ObjectMapper() - .registerModule(new MetricsModule(TimeUnit.SECONDS, TimeUnit.MILLISECONDS, false)); - return JettyUtil.createMetricsServletHandler(mapper, registry); - } - - @Override - public void start() {} - - @Override - public void stop() {} - - @Override - public void report() {} -} +/* + * 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.iotdb.db.metrics.sink; + +import java.util.concurrent.TimeUnit; +import org.apache.iotdb.db.metrics.server.JettyUtil; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.json.MetricsModule; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.jetty.servlet.ServletHolder; + +public class JsonServletSink implements Sink { + + private MetricRegistry registry; + + public JsonServletSink(MetricRegistry registry) { + this.registry = registry; + } + + public ServletHolder getHolder() { + ObjectMapper mapper = new ObjectMapper() + .registerModule(new MetricsModule(TimeUnit.SECONDS, TimeUnit.MILLISECONDS, false)); + return JettyUtil.createJsonServletHolder(mapper, registry); + } + + @Override + public void start() {} + + @Override + public void stop() {} + + @Override + public void report() {} +} diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/ui/MetricsWebUI.java b/server/src/main/java/org/apache/iotdb/db/metrics/ui/MetricsWebUI.java index fb52267..31395ef 100644 --- a/server/src/main/java/org/apache/iotdb/db/metrics/ui/MetricsWebUI.java +++ b/server/src/main/java/org/apache/iotdb/db/metrics/ui/MetricsWebUI.java @@ -14,37 +14,34 @@ */ package org.apache.iotdb.db.metrics.ui; -import java.util.ArrayList; -import java.util.List; import org.apache.iotdb.db.metrics.server.JettyUtil; import org.apache.iotdb.db.metrics.server.QueryServlet; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import com.codahale.metrics.MetricRegistry; +import org.eclipse.jetty.servlet.ServletHolder; public class MetricsWebUI { - private List<ServletContextHandler> handlers = new ArrayList<>(); + private ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); private MetricRegistry metricRegistry; public MetricsWebUI(MetricRegistry metricRegistry) { this.metricRegistry = metricRegistry; } - public List<ServletContextHandler> getHandlers() { - return handlers; - } - public void initialize() { MetricsPage masterPage = new MetricsPage(metricRegistry); QueryServlet queryServlet = new QueryServlet(masterPage); - ServletContextHandler staticHandler = JettyUtil.createStaticHandler(); - ServletContextHandler queryHandler = JettyUtil.createServletHandler("/",queryServlet, "/"); - handlers.add(staticHandler); - handlers.add(queryHandler); + handler.setContextPath("/metrics"); + handler.setResourceBase( + String.valueOf(MetricsWebUI.class.getClassLoader().getResource("iotdb/ui/static"))); + ServletHolder queryServletHolder = new ServletHolder(queryServlet); + handler.addServlet(queryServletHolder, "/query"); + ServletHolder staticServletHolder = JettyUtil.createStaticServletHolder(); + handler.addServlet(staticServletHolder, "/"); } - public Server getServer(int port) { - return JettyUtil.getJettyServer(handlers, port); + public ServletContextHandler getHandler() { + return handler; } } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java b/server/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java index 69c0156..cb624fa 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java @@ -68,6 +68,12 @@ public class QueryProcessor { return physicalGenerator.transformToPhysicalPlan(operator); } + public PhysicalPlan logicalPlanToPhysicalPlan(Operator operator) throws QueryProcessException { + operator = logicalOptimize(operator, executor); + PhysicalGenerator physicalGenerator = new PhysicalGenerator(executor); + return physicalGenerator.transformToPhysicalPlan(operator); + } + /** * given an unoptimized logical operator tree and return a optimized result. diff --git a/server/src/main/java/org/apache/iotdb/db/rest/controller/RestController.java b/server/src/main/java/org/apache/iotdb/db/rest/controller/RestController.java new file mode 100644 index 0000000..c0ed5f8 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/rest/controller/RestController.java @@ -0,0 +1,207 @@ +/* + * 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.iotdb.db.rest.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import java.io.BufferedReader; +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import org.apache.iotdb.db.auth.AuthException; +import org.apache.iotdb.db.auth.authorizer.IAuthorizer; +import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer; +import org.apache.iotdb.db.conf.IoTDBConstant; +import org.apache.iotdb.db.exception.StorageEngineException; +import org.apache.iotdb.db.exception.metadata.MetadataException; +import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.exception.storageGroup.StorageGroupException; +import org.apache.iotdb.db.rest.model.TimeValues; +import org.apache.iotdb.db.rest.service.RestService; +import org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException; +import org.apache.iotdb.tsfile.utils.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * It’s used for mapping http request. + */ + +@Path("/") +public class RestController { + + private static final Logger logger = LoggerFactory.getLogger(RestController.class); + private RestService restService = new RestService(); + + /** + * http request to login IoTDB + * @param username username for login IoTDB + * @param password password for login IoTDB + */ + + @Path("/login/{username}&&{password}") + @POST + public void login(@PathParam("username") String username, @PathParam("password") String password) + throws AuthException { + logger.info("{}: receive http request from username {}", IoTDBConstant.GLOBAL_DB_NAME, + username); + IAuthorizer authorizer = LocalFileAuthorizer.getInstance(); + boolean status = authorizer.login(username, password); + if (status) { + restService.setUsername(username); + logger.info("{}: Login successfully. User : {}", IoTDBConstant.GLOBAL_DB_NAME, username); + } else { + throw new AuthException("Wrong login password"); + } + } + + /** + * + * @param request this request will be in json format. + * @param response this response will be in json format. + * @return json in String + */ + @Path("/query") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public String query(HttpServletRequest request, HttpServletResponse response) { + String targetStr = "target"; + response.setStatus(200); + try { + JSONObject jsonObject = getRequestBodyJson(request); + assert jsonObject != null; + JSONObject range = (JSONObject) jsonObject.get("range"); + Pair<String, String> timeRange = new Pair<>((String) range.get("from"), (String) range.get("to")); + JSONArray array = (JSONArray) jsonObject.get("targets"); // [] + JSONArray result = new JSONArray(); + for (int i = 0; i < array.size(); i++) { + JSONObject object = (JSONObject) array.get(i); // {} + if (!object.containsKey(targetStr)) { + return "[]"; + } + String target = (String) object.get(targetStr); + String type = getJsonType(jsonObject); + JSONObject obj = new JSONObject(); + obj.put("target", target); + if (type.equals("table")) { + setJsonTable(obj, target, timeRange); + } else if (type.equals("timeserie")) { + setJsonTimeseries(obj, target, timeRange); + } + result.add(i, obj); + } + logger.info("query finished"); + return result.toString(); + } catch (Exception e) { + logger.error("/query failed", e); + } + return null; + } + + /** + * get request body JSON. + * + * @param request http request + * @return request JSON + * @throws JSONException JSONException + */ + private JSONObject getRequestBodyJson(HttpServletRequest request) throws JSONException { + try { + BufferedReader br = request.getReader(); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return JSON.parseObject(sb.toString()); + } catch (IOException e) { + logger.error("getRequestBodyJson failed", e); + } + return null; + } + + /** + * get JSON type of input JSON object. + * + * @param jsonObject JSON Object + * @return type (string) + * @throws JSONException JSONException + */ + private String getJsonType(JSONObject jsonObject) throws JSONException { + JSONArray array = (JSONArray) jsonObject.get("targets"); // [] + JSONObject object = (JSONObject) array.get(0); // {} + return (String) object.get("type"); + } + + private void setJsonTable(JSONObject obj, String target, + Pair<String, String> timeRange) + throws JSONException, StorageEngineException, QueryFilterOptimizationException, + MetadataException, IOException, StorageGroupException, SQLException, QueryProcessException, AuthException { + List<TimeValues> timeValues = restService.querySeries(target, timeRange); + JSONArray columns = new JSONArray(); + JSONObject column = new JSONObject(); + column.put("text", "Time"); + column.put("type", "time"); + columns.add(column); + column = new JSONObject(); + column.put("text", "Number"); + column.put("type", "number"); + columns.add(column); + obj.put("columns", columns); + JSONArray values = new JSONArray(); + for (TimeValues tv : timeValues) { + JSONArray value = new JSONArray(); + value.add(tv.getTime()); + value.add(tv.getValue()); + values.add(value); + } + obj.put("values", values); + } + + private void setJsonTimeseries(JSONObject obj, String target, + Pair<String, String> timeRange) + throws JSONException, StorageEngineException, QueryFilterOptimizationException, + MetadataException, IOException, StorageGroupException, SQLException, QueryProcessException, AuthException { + List<TimeValues> timeValues = restService.querySeries(target, timeRange); + logger.info("query size: {}", timeValues.size()); + JSONArray dataPoints = new JSONArray(); + for (TimeValues tv : timeValues) { + long time = tv.getTime(); + String value = tv.getValue(); + JSONArray jsonArray = new JSONArray(); + jsonArray.add(value); + jsonArray.add(time); + dataPoints.add(jsonArray); + } + obj.put("datapoints", dataPoints); + } + +} diff --git a/server/src/main/java/org/apache/iotdb/db/http/TimeValues.java b/server/src/main/java/org/apache/iotdb/db/rest/model/TimeValues.java similarity index 96% rename from server/src/main/java/org/apache/iotdb/db/http/TimeValues.java rename to server/src/main/java/org/apache/iotdb/db/rest/model/TimeValues.java index 8c7059d..49290b0 100644 --- a/server/src/main/java/org/apache/iotdb/db/http/TimeValues.java +++ b/server/src/main/java/org/apache/iotdb/db/rest/model/TimeValues.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.http; +package org.apache.iotdb.db.rest.model; public class TimeValues { diff --git a/server/src/main/java/org/apache/iotdb/db/rest/service/RestService.java b/server/src/main/java/org/apache/iotdb/db/rest/service/RestService.java new file mode 100644 index 0000000..3843555 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/rest/service/RestService.java @@ -0,0 +1,177 @@ +/* + * 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.iotdb.db.rest.service; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import org.apache.iotdb.db.auth.AuthException; +import org.apache.iotdb.db.auth.AuthorityChecker; +import org.apache.iotdb.db.conf.IoTDBConstant; +import org.apache.iotdb.db.conf.IoTDBDescriptor; +import org.apache.iotdb.db.exception.StorageEngineException; +import org.apache.iotdb.db.exception.metadata.MetadataException; +import org.apache.iotdb.db.exception.path.PathException; +import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.exception.runtime.SQLParserException; +import org.apache.iotdb.db.exception.storageGroup.StorageGroupException; +import org.apache.iotdb.db.metadata.MManager; +import org.apache.iotdb.db.qp.QueryProcessor; +import org.apache.iotdb.db.qp.constant.DatetimeUtils; +import org.apache.iotdb.db.qp.constant.SQLConstant; +import org.apache.iotdb.db.qp.executor.QueryProcessExecutor; +import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator; +import org.apache.iotdb.db.qp.logical.crud.FilterOperator; +import org.apache.iotdb.db.qp.logical.crud.FromOperator; +import org.apache.iotdb.db.qp.logical.crud.QueryOperator; +import org.apache.iotdb.db.qp.logical.crud.SelectOperator; +import org.apache.iotdb.db.qp.physical.PhysicalPlan; +import org.apache.iotdb.db.qp.physical.crud.QueryPlan; +import org.apache.iotdb.db.query.context.QueryContext; +import org.apache.iotdb.db.query.control.QueryResourceManager; +import org.apache.iotdb.db.rest.model.TimeValues; +import org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException; +import org.apache.iotdb.tsfile.read.common.Path; +import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet; +import org.apache.iotdb.tsfile.utils.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RestService { + + protected QueryProcessor processor = new QueryProcessor(new QueryProcessExecutor()); + private static final Logger logger = LoggerFactory.getLogger(RestService.class); + private static final String INFO_NOT_LOGIN = "{}: Not login."; + private String username; + + + public List<TimeValues> querySeries(String s, Pair<String, String> timeRange) + throws QueryProcessException, StorageGroupException, AuthException, MetadataException, QueryFilterOptimizationException, SQLException, StorageEngineException, IOException { + String from = timeRange.left; + String to = timeRange.right; + String suffixPath = s.substring(s.lastIndexOf('.') + 1); + String prefixPath = s.substring(0, s.lastIndexOf('.')); + String sql = "SELECT " + suffixPath + " FROM root." + + prefixPath + " WHERE time > " + from + " and time < " + to; + logger.info(sql); + QueryOperator queryOperator = generateOperator(suffixPath, prefixPath, timeRange); + QueryPlan plan = (QueryPlan) processor.logicalPlanToPhysicalPlan(queryOperator); + List<Path> paths = plan.getPaths(); + if (!checkLogin()) { + logger.info(INFO_NOT_LOGIN, IoTDBConstant.GLOBAL_DB_NAME); + } + + // check seriesPath exists + if (paths.isEmpty()) { + throw new PathException("The path doesn't exist"); + } + + // check file level set + try { + checkFileLevelSet(paths); + } catch (StorageGroupException e) { + logger.error("meet error while checking file level.", e); + throw new StorageGroupException(e.getMessage()); + } + + // check permissions + if (!checkAuthorization(paths, plan)) { + throw new AuthException("Don't have permissions"); + } + + QueryContext context = new QueryContext(QueryResourceManager.getInstance().assignQueryId(true)); + QueryDataSet queryDataSet = processor.getExecutor().processQuery(plan, context); + String[] args; + List<TimeValues> list = new ArrayList<>(); + while(queryDataSet.hasNext()) { + TimeValues timeValues = new TimeValues(); + args = queryDataSet.next().toString().split("\t"); + timeValues.setTime(Long.parseLong(args[1])); + timeValues.setValue(args[0]); + list.add(timeValues); + } + return list; + } + + private boolean checkLogin() { + return username != null; + } + + private boolean checkAuthorization(List<Path> paths, PhysicalPlan plan) throws AuthException { + return AuthorityChecker.check(username, paths, plan.getOperatorType(), null); + } + + private void checkFileLevelSet(List<Path> paths) throws StorageGroupException { + MManager.getInstance().checkFileLevel(paths); + } + + + /** + * generate select statement operator + */ + private QueryOperator generateOperator(String suffixPath, String prefixPath, Pair<String, String> timeRange) { + FilterOperator binaryOp = new FilterOperator(SQLConstant.KW_AND); + binaryOp.addChildOperator( + new BasicFunctionOperator(SQLConstant.GREATERTHAN, + new Path(SQLConstant.RESERVED_TIME), + String.valueOf(parseTimeFormat(timeRange.left)) + ) + ); + binaryOp.addChildOperator( + new BasicFunctionOperator(SQLConstant.LESSTHAN, + new Path(SQLConstant.RESERVED_TIME), + String.valueOf(parseTimeFormat(timeRange.right)) + ) + ); + QueryOperator queryOp = new QueryOperator(SQLConstant.TOK_QUERY); + SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT); + selectOp.addSelectPath(new Path(suffixPath)); + FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM); + fromOp.addPrefixTablePath(new Path(prefixPath)); + queryOp.setFilterOperator(binaryOp); + queryOp.setSelectOperator(selectOp); + queryOp.setFromOperator(fromOp); + return queryOp; + } + + /** + * function for parsing time format. + */ + private long parseTimeFormat(String timestampStr) throws SQLParserException { + if (timestampStr == null || timestampStr.trim().equals("")) { + throw new SQLParserException("input timestamp cannot be empty"); + } + if (timestampStr.equalsIgnoreCase(SQLConstant.NOW_FUNC)) { + return System.currentTimeMillis(); + } + try { + return DatetimeUtils.convertDatetimeStrToLong(timestampStr, IoTDBDescriptor.getInstance().getConfig().getZoneID()); + } catch (Exception e) { + throw new SQLParserException(String + .format("Input time format %s error. " + + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or " + + "refer to user document for more info.", timestampStr)); + } + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/http/QueryServlet.java b/server/src/main/java/org/apache/iotdb/db/rest/util/RestUtil.java similarity index 52% rename from server/src/main/java/org/apache/iotdb/db/http/QueryServlet.java rename to server/src/main/java/org/apache/iotdb/db/rest/util/RestUtil.java index d042663..5c0b4aa 100644 --- a/server/src/main/java/org/apache/iotdb/db/http/QueryServlet.java +++ b/server/src/main/java/org/apache/iotdb/db/rest/util/RestUtil.java @@ -16,29 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.iotdb.db.http; +package org.apache.iotdb.db.rest.util; -import java.io.IOException; -import java.io.PrintWriter; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.servlet.ServletContainer; -public class QueryServlet extends HttpServlet { +public class RestUtil { + public static ServletContextHandler getRestContextHandler() { + ServletContextHandler ctx = + new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - PrintWriter out = resp.getWriter(); - resp.setContentType("application/json"); - resp.setCharacterEncoding("UTF-8"); - - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - super.doPost(req, resp); + ctx.setContextPath("/rest"); + ServletHolder serHol = ctx.addServlet(ServletContainer.class, "/*"); + serHol.setInitParameter("jersey.config.server.provider.packages", + "org.apache.iotdb.db.rest.controller"); + serHol.setInitOrder(1); + return ctx; } } diff --git a/server/src/main/java/org/apache/iotdb/db/service/MetricsService.java b/server/src/main/java/org/apache/iotdb/db/service/MetricsService.java index e2b6e22..cc8d544 100644 --- a/server/src/main/java/org/apache/iotdb/db/service/MetricsService.java +++ b/server/src/main/java/org/apache/iotdb/db/service/MetricsService.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; +import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -30,9 +31,11 @@ import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBConstant; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.exception.StartupException; +import org.apache.iotdb.db.metrics.server.JettyUtil; import org.apache.iotdb.db.metrics.server.MetricsSystem; import org.apache.iotdb.db.metrics.server.ServerArgument; import org.apache.iotdb.db.metrics.ui.MetricsWebUI; +import org.apache.iotdb.db.rest.util.RestUtil; import org.eclipse.jetty.server.Server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,9 +88,9 @@ public class MetricsService implements MetricsServiceMBean, IService { int port = getMetricsPort(); MetricsSystem metricsSystem = new MetricsSystem(new ServerArgument(port)); MetricsWebUI metricsWebUI = new MetricsWebUI(metricsSystem.getMetricRegistry()); - metricsWebUI.getHandlers().add(metricsSystem.getServletHandlers()); + metricsWebUI.getHandler().addServlet(metricsSystem.getServletHolder(), "/json"); metricsWebUI.initialize(); - server = metricsWebUI.getServer(port); + server = JettyUtil.getJettyServer(Arrays.asList(metricsWebUI.getHandler(), RestUtil.getRestContextHandler()), 8181); metricsSystem.start(); try { executorService.execute(new MetricsServiceThread(server)); diff --git a/server/src/main/resources/iotdb/ui/static/index.html b/server/src/main/resources/iotdb/ui/static/index.html index 68e7881..6b85ced 100644 --- a/server/src/main/resources/iotdb/ui/static/index.html +++ b/server/src/main/resources/iotdb/ui/static/index.html @@ -18,7 +18,7 @@ limitations under the License. <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> -<link rel="stylesheet" href="/static/webui.css" type="text/css"> +<link rel="stylesheet" href="webui.css" type="text/css"> <title>IotDB Metrics Server</title> </head> <body> @@ -27,7 +27,7 @@ limitations under the License. <div class="brand"> <h3 style="vertical-align: middle; display: inline-block;"> <a href="" style="text-decoration: none"> - <img src="/static/iotdb-logo.png"> + <img src="iotdb-logo.png"> <span class="version" style="margin-right: 15px;">{version}</span> </a> IOTDB Metrics Server
