From abebfac25cc584ada6a5f7e65da44d1044b681f3 Mon Sep 17 00:00:00 2001 From: Linary Date: Fri, 31 May 2019 17:06:40 +0800 Subject: [PATCH] Add api white list and rate limiter for gc (#522) Also add ProfileAPI Change-Id: Ia7ac5dc5d7d91676701738f2a0ae5073f9ceb01e --- hugegraph-api/pom.xml | 2 +- .../java/com/baidu/hugegraph/api/API.java | 2 +- .../api/filter/LoadDetectFilter.java | 37 +++ .../baidu/hugegraph/api/graph/BatchAPI.java | 2 +- .../api/{ => gremlin}/GremlinAPI.java | 5 +- .../baidu/hugegraph/api/job/GremlinAPI.java | 2 +- .../hugegraph/api/metrics/MetricsAPI.java | 6 +- .../api/{ => profile}/GraphsAPI.java | 3 +- .../hugegraph/api/profile/ProfileAPI.java | 230 ++++++++++++++++++ .../api/{ => profile}/VersionAPI.java | 3 +- .../baidu/hugegraph/core/GraphManager.java | 4 +- .../{metric => metrics}/MetricsModule.java | 2 +- .../{metric => metrics}/MetricsUtil.java | 2 +- .../{metric => metrics}/ServerReporter.java | 2 +- .../{metric => metrics}/SystemMetrics.java | 2 +- .../baidu/hugegraph/version/ApiVersion.java | 5 +- .../baidu/hugegraph/type/define/DataType.java | 20 +- .../src/main/resources/hugegraph.properties | 8 +- .../baidu/hugegraph/unit/UnitTestSuite.java | 2 + .../hugegraph/unit/core/DataTypeTest.java | 83 +++++++ 20 files changed, 391 insertions(+), 31 deletions(-) rename hugegraph-api/src/main/java/com/baidu/hugegraph/api/{ => gremlin}/GremlinAPI.java (97%) rename hugegraph-api/src/main/java/com/baidu/hugegraph/api/{ => profile}/GraphsAPI.java (98%) create mode 100644 hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/ProfileAPI.java rename hugegraph-api/src/main/java/com/baidu/hugegraph/api/{ => profile}/VersionAPI.java (95%) rename hugegraph-api/src/main/java/com/baidu/hugegraph/{metric => metrics}/MetricsModule.java (99%) rename hugegraph-api/src/main/java/com/baidu/hugegraph/{metric => metrics}/MetricsUtil.java (98%) rename hugegraph-api/src/main/java/com/baidu/hugegraph/{metric => metrics}/ServerReporter.java (99%) rename hugegraph-api/src/main/java/com/baidu/hugegraph/{metric => metrics}/SystemMetrics.java (99%) create mode 100644 hugegraph-test/src/main/java/com/baidu/hugegraph/unit/core/DataTypeTest.java diff --git a/hugegraph-api/pom.xml b/hugegraph-api/pom.xml index 253b8a8074..fc27f55e2c 100644 --- a/hugegraph-api/pom.xml +++ b/hugegraph-api/pom.xml @@ -86,7 +86,7 @@ - 0.38.0.0 + 0.39.0.0 diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/API.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/API.java index 3f477f2409..48aa9fefc4 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/API.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/API.java @@ -35,7 +35,7 @@ import com.baidu.hugegraph.HugeGraph; import com.baidu.hugegraph.api.schema.Checkable; import com.baidu.hugegraph.core.GraphManager; -import com.baidu.hugegraph.metric.MetricsUtil; +import com.baidu.hugegraph.metrics.MetricsUtil; import com.baidu.hugegraph.server.RestServer; import com.baidu.hugegraph.type.HugeType; import com.baidu.hugegraph.util.E; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/filter/LoadDetectFilter.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/filter/LoadDetectFilter.java index 272114a77e..317b2ec35d 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/filter/LoadDetectFilter.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/filter/LoadDetectFilter.java @@ -19,24 +19,42 @@ package com.baidu.hugegraph.api.filter; +import java.util.List; +import java.util.Set; + import javax.inject.Singleton; import javax.ws.rs.ServiceUnavailableException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.Context; +import javax.ws.rs.core.PathSegment; import javax.ws.rs.ext.Provider; import com.baidu.hugegraph.config.HugeConfig; import com.baidu.hugegraph.config.ServerOptions; import com.baidu.hugegraph.core.WorkLoad; import com.baidu.hugegraph.util.Bytes; +import com.baidu.hugegraph.util.E; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.RateLimiter; @Provider @Singleton @PreMatching public class LoadDetectFilter implements ContainerRequestFilter { + private static final Set WHITE_API_LIST = ImmutableSet.of( + "", + "apis", + "metrics", + "versions" + ); + + // Call gc every 30+ seconds if memory is low and request frequently + private static final RateLimiter GC_RATE_LIMITER = + RateLimiter.create(1.0 / 30); + @Context private javax.inject.Provider configProvider; @Context @@ -44,6 +62,10 @@ public class LoadDetectFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext context) { + if (isWhiteAPI(context)) { + return; + } + HugeConfig config = this.configProvider.get(); long minFreeMemory = config.get(ServerOptions.MIN_FREE_MEMORY); long allocatedMem = Runtime.getRuntime().totalMemory() - @@ -51,6 +73,7 @@ public void filter(ContainerRequestContext context) { long presumableFreeMem = (Runtime.getRuntime().maxMemory() - allocatedMem) / Bytes.MB; if (presumableFreeMem < minFreeMemory) { + gcIfNeeded(); throw new ServiceUnavailableException(String.format( "The server available memory %s(MB) is below than " + "threshold %s(MB) and can't process the request, " + @@ -69,4 +92,18 @@ public void filter(ContainerRequestContext context) { ServerOptions.MAX_WORKER_THREADS.name())); } } + + private static boolean isWhiteAPI(ContainerRequestContext context) { + List segments = context.getUriInfo().getPathSegments(); + E.checkArgument(segments.size() > 0, "Invalid request uri '%s'", + context.getUriInfo().getPath()); + String rootPath = segments.get(0).getPath(); + return WHITE_API_LIST.contains(rootPath); + } + + private static void gcIfNeeded() { + if (GC_RATE_LIMITER.tryAcquire(1)) { + System.gc(); + } + } } diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/graph/BatchAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/graph/BatchAPI.java index bfa6a47d6c..517581da52 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/graph/BatchAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/graph/BatchAPI.java @@ -29,7 +29,7 @@ import com.baidu.hugegraph.api.API; import com.baidu.hugegraph.config.HugeConfig; import com.baidu.hugegraph.config.ServerOptions; -import com.baidu.hugegraph.metric.MetricsUtil; +import com.baidu.hugegraph.metrics.MetricsUtil; import com.baidu.hugegraph.server.RestServer; import com.baidu.hugegraph.util.Log; import com.codahale.metrics.Meter; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/GremlinAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java similarity index 97% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/api/GremlinAPI.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java index 3973f4d1eb..361f334b02 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/GremlinAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.api; +package com.baidu.hugegraph.api.gremlin; import javax.inject.Singleton; import javax.ws.rs.Consumes; @@ -34,11 +34,12 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import com.baidu.hugegraph.api.API; import com.baidu.hugegraph.api.filter.CompressInterceptor; import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress; import com.baidu.hugegraph.config.HugeConfig; import com.baidu.hugegraph.config.ServerOptions; -import com.baidu.hugegraph.metric.MetricsUtil; +import com.baidu.hugegraph.metrics.MetricsUtil; import com.codahale.metrics.Histogram; import com.codahale.metrics.annotation.Timed; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/job/GremlinAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/job/GremlinAPI.java index 46c3988cd5..1d710ba9d7 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/job/GremlinAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/job/GremlinAPI.java @@ -50,7 +50,7 @@ import com.baidu.hugegraph.core.GraphManager; import com.baidu.hugegraph.job.Job; import com.baidu.hugegraph.job.JobBuilder; -import com.baidu.hugegraph.metric.MetricsUtil; +import com.baidu.hugegraph.metrics.MetricsUtil; import com.baidu.hugegraph.server.RestServer; import com.baidu.hugegraph.traversal.optimize.HugeScriptTraversal; import com.baidu.hugegraph.util.E; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/metrics/MetricsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/metrics/MetricsAPI.java index 629090196c..a886cb49b6 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/metrics/MetricsAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/metrics/MetricsAPI.java @@ -38,9 +38,9 @@ import com.baidu.hugegraph.backend.store.BackendMetrics; import com.baidu.hugegraph.backend.tx.GraphTransaction; import com.baidu.hugegraph.core.GraphManager; -import com.baidu.hugegraph.metric.MetricsModule; -import com.baidu.hugegraph.metric.ServerReporter; -import com.baidu.hugegraph.metric.SystemMetrics; +import com.baidu.hugegraph.metrics.MetricsModule; +import com.baidu.hugegraph.metrics.ServerReporter; +import com.baidu.hugegraph.metrics.SystemMetrics; import com.baidu.hugegraph.util.InsertionOrderUtil; import com.baidu.hugegraph.util.JsonUtil; import com.baidu.hugegraph.util.Log; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/GraphsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/GraphsAPI.java similarity index 98% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/api/GraphsAPI.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/GraphsAPI.java index bd085bfbba..429505c54c 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/GraphsAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/GraphsAPI.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.api; +package com.baidu.hugegraph.api.profile; import java.io.File; import java.util.Map; @@ -40,6 +40,7 @@ import org.slf4j.Logger; import com.baidu.hugegraph.HugeGraph; +import com.baidu.hugegraph.api.API; import com.baidu.hugegraph.core.GraphManager; import com.baidu.hugegraph.server.RestServer; import com.baidu.hugegraph.type.define.GraphMode; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/ProfileAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/ProfileAPI.java new file mode 100644 index 0000000000..5860117f5b --- /dev/null +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/ProfileAPI.java @@ -0,0 +1,230 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * 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 com.baidu.hugegraph.api.profile; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import javax.inject.Singleton; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.apache.commons.lang3.StringUtils; +import org.apache.tinkerpop.shaded.jackson.annotation.JsonProperty; +import org.glassfish.jersey.server.model.Parameter; +import org.glassfish.jersey.server.model.Parameter.Source; +import org.glassfish.jersey.server.model.Resource; +import org.glassfish.jersey.server.model.ResourceMethod; + +import com.baidu.hugegraph.util.E; +import com.baidu.hugegraph.util.InsertionOrderUtil; +import com.baidu.hugegraph.util.JsonUtil; +import com.baidu.hugegraph.version.CoreVersion; +import com.codahale.metrics.annotation.Timed; + +@Path("/") +@Singleton +public class ProfileAPI { + + private static final String SERVICE = "hugegraph"; + private static final String DOC = "https://hugegraph.github.io/hugegraph-doc/"; + private static final String API_DOC = DOC + "clients/hugegraph-api.html"; + + private static String SERVER_PROFILES = null; + private static String API_PROFILES = null; + + @GET + @Timed + @Produces(MediaType.APPLICATION_JSON) + public String getProfile(@Context Application application) { + // May init multi times by multi threads, but no effect on the results + if (SERVER_PROFILES != null) { + return SERVER_PROFILES; + } + + Map profiles = InsertionOrderUtil.newMap(); + profiles.put("service", SERVICE); + profiles.put("version", CoreVersion.VERSION.toString()); + profiles.put("doc", DOC); + profiles.put("api_doc", API_DOC); + Set apis = new TreeSet<>(); + for (Class clazz : application.getClasses()) { + if (!isAnnotatedPathClass(clazz)) { + continue; + } + Resource resource = Resource.from(clazz); + APICategory apiCategory = APICategory.parse(resource.getName()); + apis.add(apiCategory.dir); + } + profiles.put("apis", apis); + SERVER_PROFILES = JsonUtil.toJson(profiles); + return SERVER_PROFILES; + } + + @GET + @Path("apis") + @Timed + @Produces(MediaType.APPLICATION_JSON) + public String showAllAPIs(@Context Application application) { + if (API_PROFILES != null) { + return API_PROFILES; + } + + APIProfiles apiProfiles = new APIProfiles(); + for (Class clazz : application.getClasses()) { + if (!isAnnotatedPathClass(clazz)) { + continue; + } + + Resource resource = Resource.from(clazz); + APICategory apiCategory = APICategory.parse(resource.getName()); + + String url = resource.getPath(); + // List all methods of this resource + for (ResourceMethod rm : resource.getResourceMethods()) { + APIProfile profile = APIProfile.parse(url, rm); + apiProfiles.put(apiCategory, profile); + } + // List all methods of this resource's child resources + for (Resource childResource : resource.getChildResources()) { + String childUrl = url + "/" + childResource.getPath(); + for (ResourceMethod rm : childResource.getResourceMethods()) { + APIProfile profile = APIProfile.parse(childUrl, rm); + apiProfiles.put(apiCategory, profile); + } + } + } + API_PROFILES = JsonUtil.toJson(apiProfiles); + return API_PROFILES; + } + + private static boolean isAnnotatedPathClass(Class clazz) { + if (clazz.isAnnotationPresent(Path.class)) { + return true; + } + for (Class i : clazz.getInterfaces()) { + if (i.isAnnotationPresent(Path.class)) { + return true; + } + } + return false; + } + + private static class APIProfiles { + + @JsonProperty("apis") + private final Map>> apis; + + public APIProfiles() { + this.apis = new TreeMap<>(); + } + + public void put(APICategory category, APIProfile profile) { + Map> categories; + categories = this.apis.computeIfAbsent(category.dir, + k -> new TreeMap<>()); + List profiles = categories.computeIfAbsent( + category.category, + k -> new ArrayList<>()); + profiles.add(profile); + } + } + + private static class APIProfile { + + @JsonProperty("url") + private final String url; + @JsonProperty("method") + private final String method; + @JsonProperty("parameters") + private final List parameters; + + public APIProfile(String url, String method, + List parameters) { + this.url = url; + this.method = method; + this.parameters = parameters; + } + + public static APIProfile parse(String url, ResourceMethod resource) { + String method = resource.getHttpMethod(); + List params = new ArrayList<>(); + for (Parameter param : resource.getInvocable().getParameters()) { + if (param.getSource() == Source.QUERY) { + String name = param.getSourceName(); + String type = param.getType().getTypeName(); + String defaultValue = param.getDefaultValue(); + params.add(new ParamInfo(name, type, defaultValue)); + } else if (param.getSource() == Source.ENTITY) { + String type = param.getType().getTypeName(); + params.add(new ParamInfo("body", type)); + } + } + return new APIProfile(url, method, params); + } + + private static class ParamInfo { + + @JsonProperty("name") + private final String name; + @JsonProperty("type") + private final String type; + @JsonProperty("default_value") + private final String defaultValue; + + public ParamInfo(String name, String type) { + this(name, type, null); + } + + public ParamInfo(String name, String type, String defaultValue) { + this.name = name; + this.type = type; + this.defaultValue = defaultValue; + } + } + } + + private static class APICategory { + + private final String dir; + private final String category; + + public APICategory(String dir, String category) { + this.dir = dir; + this.category = category; + } + + public static APICategory parse(String fullName) { + String[] parts = StringUtils.split(fullName, "."); + E.checkState(parts.length >= 2, "Invalid api name"); + String dir = parts[parts.length - 2]; + String category = parts[parts.length - 1]; + return new APICategory(dir, category); + } + } +} diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/VersionAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/VersionAPI.java similarity index 95% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/api/VersionAPI.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/VersionAPI.java index ab849cc6dd..b4e0343b7d 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/VersionAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/profile/VersionAPI.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.api; +package com.baidu.hugegraph.api.profile; import java.util.Map; @@ -27,6 +27,7 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; +import com.baidu.hugegraph.api.API; import com.baidu.hugegraph.version.ApiVersion; import com.baidu.hugegraph.version.CoreVersion; import com.codahale.metrics.annotation.Timed; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/core/GraphManager.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/core/GraphManager.java index 5d52b8458b..7eb53b53b8 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/core/GraphManager.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/core/GraphManager.java @@ -44,8 +44,8 @@ import com.baidu.hugegraph.config.HugeConfig; import com.baidu.hugegraph.config.ServerOptions; import com.baidu.hugegraph.exception.NotSupportException; -import com.baidu.hugegraph.metric.MetricsUtil; -import com.baidu.hugegraph.metric.ServerReporter; +import com.baidu.hugegraph.metrics.MetricsUtil; +import com.baidu.hugegraph.metrics.ServerReporter; import com.baidu.hugegraph.serializer.JsonSerializer; import com.baidu.hugegraph.serializer.Serializer; import com.baidu.hugegraph.server.RestServer; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsModule.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsModule.java similarity index 99% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsModule.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsModule.java index eecfe28065..8c0cc8ba67 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsModule.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsModule.java @@ -15,7 +15,7 @@ * under the License. */ -package com.baidu.hugegraph.metric; +package com.baidu.hugegraph.metrics; import java.io.IOException; import java.util.Arrays; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsUtil.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsUtil.java similarity index 98% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsUtil.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsUtil.java index 5025f45361..576af23a88 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/MetricsUtil.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/MetricsUtil.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.metric; +package com.baidu.hugegraph.metrics; import org.apache.tinkerpop.gremlin.server.util.MetricManager; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/ServerReporter.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/ServerReporter.java similarity index 99% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/metric/ServerReporter.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/ServerReporter.java index cd53b3f005..956235edd4 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/ServerReporter.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/ServerReporter.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.metric; +package com.baidu.hugegraph.metrics; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/SystemMetrics.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/SystemMetrics.java similarity index 99% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/metric/SystemMetrics.java rename to hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/SystemMetrics.java index 7de6c50f74..8d6c56fb07 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/metric/SystemMetrics.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/metrics/SystemMetrics.java @@ -17,7 +17,7 @@ * under the License. */ -package com.baidu.hugegraph.metric; +package com.baidu.hugegraph.metrics; import java.lang.management.ClassLoadingMXBean; import java.lang.management.GarbageCollectorMXBean; diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java index c6438adc49..80656b1552 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java @@ -84,10 +84,13 @@ public final class ApiVersion { * [0.36] Issue-360: Support paging for scan api * [0.37] Issue-391: Add skip_super_node for shortest path * [0.38] Issue-274: Add personalrank and neighborrank RESTful API + * + * version 0.10: + * [0.39] Issue-522: Add profile RESTful API */ // The second parameter of Version.of() is for IDE running without JAR - public static final Version VERSION = Version.of(ApiVersion.class, "0.38"); + public static final Version VERSION = Version.of(ApiVersion.class, "0.39"); public static final void check() { // Check version of hugegraph-core. Firstly do check from version 0.3 diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java index c39f1fdddb..c69e7c042a 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java @@ -123,24 +123,26 @@ public Number valueToNumber(V value) { } public Date valueToDate(V value) { + if (!this.isDate()) { + return null; + } if (value instanceof Date) { return (Date) value; - } - if (this.isDate()) { - if (value instanceof Number) { - return new Date(((Number) value).longValue()); - } else if (value instanceof String) { - return DateUtil.parse((String) value); - } + } else if (value instanceof Number) { + return new Date(((Number) value).longValue()); + } else if (value instanceof String) { + return DateUtil.parse((String) value); } return null; } public UUID valueToUUID(V value) { + if (!this.isUUID()) { + return null; + } if (value instanceof UUID) { return (UUID) value; - } - if (this.isUUID() && value instanceof String) { + } else if (value instanceof String) { return java.util.UUID.fromString((String) value); } return null; diff --git a/hugegraph-example/src/main/resources/hugegraph.properties b/hugegraph-example/src/main/resources/hugegraph.properties index fa596fb7f5..403ca84095 100644 --- a/hugegraph-example/src/main/resources/hugegraph.properties +++ b/hugegraph-example/src/main/resources/hugegraph.properties @@ -1,10 +1,10 @@ gremlin.graph=com.baidu.hugegraph.HugeFactory -backend=cassandra -serializer=cassandra +#backend=cassandra +#serializer=cassandra -#backend=rocksdb -#serializer=binary +backend=rocksdb +serializer=binary store=hugegraph rate_limit=0 diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/UnitTestSuite.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/UnitTestSuite.java index f8109d4fa2..3780dc15cf 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/UnitTestSuite.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/UnitTestSuite.java @@ -30,6 +30,7 @@ import com.baidu.hugegraph.unit.core.BackendMutationTest; import com.baidu.hugegraph.unit.core.CassandraTest; import com.baidu.hugegraph.unit.core.ConditionQueryFlattenTest; +import com.baidu.hugegraph.unit.core.DataTypeTest; import com.baidu.hugegraph.unit.core.DirectionsTest; import com.baidu.hugegraph.unit.core.EdgeIdTest; import com.baidu.hugegraph.unit.core.JsonUtilTest; @@ -47,6 +48,7 @@ CacheManagerTest.class, VersionTest.class, + DataTypeTest.class, DirectionsTest.class, SerialEnumTest.class, BackendMutationTest.class, diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/core/DataTypeTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/core/DataTypeTest.java new file mode 100644 index 0000000000..8e541d6e0f --- /dev/null +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/unit/core/DataTypeTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * 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 com.baidu.hugegraph.unit.core; + +import java.util.Date; +import java.util.UUID; + +import org.junit.Test; + +import com.baidu.hugegraph.testutil.Assert; +import com.baidu.hugegraph.testutil.Utils; +import com.baidu.hugegraph.type.define.DataType; + +public class DataTypeTest { + + @Test + public void testString() { + Assert.assertEquals("object", DataType.OBJECT.string()); + Assert.assertEquals("boolean", DataType.BOOLEAN.string()); + Assert.assertEquals("byte", DataType.BYTE.string()); + Assert.assertEquals("int", DataType.INT.string()); + Assert.assertEquals("long", DataType.LONG.string()); + Assert.assertEquals("float", DataType.FLOAT.string()); + Assert.assertEquals("double", DataType.DOUBLE.string()); + Assert.assertEquals("text", DataType.TEXT.string()); + Assert.assertEquals("blob", DataType.BLOB.string()); + Assert.assertEquals("date", DataType.DATE.string()); + Assert.assertEquals("uuid", DataType.UUID.string()); + } + + @Test + public void testValueToNumber() { + Assert.assertNull(DataType.BOOLEAN.valueToNumber(1)); + Assert.assertNull(DataType.INT.valueToNumber("not number")); + Assert.assertNull(DataType.INT.valueToNumber(1.0F)); + + Assert.assertEquals((byte) 1, DataType.BYTE.valueToNumber(1)); + Assert.assertEquals(1, DataType.INT.valueToNumber(1)); + Assert.assertEquals(1, DataType.INT.valueToNumber((byte) 1)); + Assert.assertEquals(1L, DataType.LONG.valueToNumber(1)); + Assert.assertEquals(1.0F, DataType.FLOAT.valueToNumber(1)); + Assert.assertEquals(1.0D, DataType.DOUBLE.valueToNumber(1)); + } + + @Test + public void testValueToDate() { + Date date = Utils.date("2019-01-01 12:00:00"); + Assert.assertEquals(date, DataType.DATE.valueToDate(date)); + Assert.assertEquals(date, + DataType.DATE.valueToDate("2019-01-01 12:00:00")); + Assert.assertEquals(date, DataType.DATE.valueToDate(date.getTime())); + + Assert.assertNull(DataType.TEXT.valueToDate("2019-01-01 12:00:00")); + Assert.assertNull(DataType.DATE.valueToDate(true)); + } + + @Test + public void testValueToUUID() { + UUID uuid = UUID.randomUUID(); + Assert.assertEquals(uuid, DataType.UUID.valueToUUID(uuid)); + Assert.assertEquals(uuid, DataType.UUID.valueToUUID(uuid.toString())); + + Assert.assertNull(DataType.TEXT.valueToUUID("2019-01-01 12:00:00")); + Assert.assertNull(DataType.UUID.valueToUUID(true)); + } +}