Skip to content

Commit

Permalink
cherrypick to 3.4 (#517)
Browse files Browse the repository at this point in the history
* check connection by default #401 (#456)

* enhancement:support more type value as parameter in session.value2Nvalue (#511)

* enhancement:support more type value as parameter in session.value2Nvalue

* code style for #511

* code style for #511

* Add maven wrapper (#513)

Co-authored-by: Will Droste <[email protected]>

* recreate session for both session error and connection exception

* fix style check

* sleep for docker restart

---------

Co-authored-by: vchangpengfei <[email protected]>
Co-authored-by: 大叶 <[email protected]>
Co-authored-by: Will Droste <[email protected]>
  • Loading branch information
4 people authored Mar 30, 2023
1 parent 21415fe commit 9e484eb
Show file tree
Hide file tree
Showing 10 changed files with 777 additions and 76 deletions.
18 changes: 18 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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
#
# https://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.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ public void release() {
connection.signout(sessionID);
connection.close();
} catch (Exception e) {
log.warn("release session failed, " + e.getMessage());
// not print the warn to avoid confuse for session and connect,
// when connection is broken, release will failed, just make connection as null.
// log.warn("release session failed, " + e.getMessage());
}
connection = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package com.vesoft.nebula.client.graph;

import static com.vesoft.nebula.client.graph.exception.IOErrorException.E_CONNECT_BROKEN;

import com.alibaba.fastjson.JSON;
import com.vesoft.nebula.ErrorCode;
import com.vesoft.nebula.client.graph.data.HostAddress;
Expand Down Expand Up @@ -138,22 +140,27 @@ public ResultSet execute(String stmt) throws IOErrorException,
stmtCheck(stmt);
checkSessionPool();
NebulaSession nebulaSession = getSession();
ResultSet resultSet;
try {
resultSet = nebulaSession.execute(stmt);

// re-execute for session error
if (isSessionError(resultSet)) {
ResultSet resultSet = null;
int tryTimes = 3;
while (tryTimes-- > 0) {
try {
resultSet = nebulaSession.execute(stmt);
if (!isSessionError(resultSet)) {
useSpace(nebulaSession, resultSet);
return resultSet;
} else {
throw new IOErrorException(E_CONNECT_BROKEN, resultSet.getErrorMessage());
}
} catch (IOErrorException e) {
nebulaSession.release();
sessionList.remove(nebulaSession);
nebulaSession = getSession();
resultSet = nebulaSession.execute(stmt);
if (tryTimes > 0) {
nebulaSession = createSessionObject(SessionState.USED);
} else {
throw e;
}
}
} catch (IOErrorException e) {
useSpace(nebulaSession, null);
throw e;
}
useSpace(nebulaSession, resultSet);
return resultSet;
}

Expand Down Expand Up @@ -339,7 +346,8 @@ public HostAddress getAddress() {
private void useSpace(NebulaSession nebulaSession, ResultSet resultSet)
throws IOErrorException {
if (resultSet == null) {
releaseSession(nebulaSession);
nebulaSession.release();
sessionList.remove(nebulaSession);
return;
}
// space has been drop, close the SessionPool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public boolean init(List<HostAddress> addresses, NebulaPoolConfig config)
objConfig.setMaxTotal(config.getMaxConnSize());
objConfig.setTestOnBorrow(true);
objConfig.setTestOnReturn(true);
objConfig.setTestOnCreate(true);
objConfig.setTestWhileIdle(true);
objConfig.setTimeBetweenEvictionRunsMillis(config.getIntervalIdle() <= 0
? BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS
: config.getIntervalIdle());
Expand Down
170 changes: 119 additions & 51 deletions client/src/main/java/com/vesoft/nebula/client/graph/net/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,34 @@

package com.vesoft.nebula.client.graph.net;

import com.vesoft.nebula.Date;
import static com.vesoft.nebula.util.ReflectUtil.isCurrentTypeOrParentType;

import com.vesoft.nebula.DataSet;
import com.vesoft.nebula.DateTime;
import com.vesoft.nebula.Duration;
import com.vesoft.nebula.Edge;
import com.vesoft.nebula.Geography;
import com.vesoft.nebula.NList;
import com.vesoft.nebula.NMap;
import com.vesoft.nebula.NSet;
import com.vesoft.nebula.NullType;
import com.vesoft.nebula.Path;
import com.vesoft.nebula.Time;
import com.vesoft.nebula.Value;
import com.vesoft.nebula.Vertex;
import com.vesoft.nebula.client.graph.data.HostAddress;
import com.vesoft.nebula.client.graph.data.ResultSet;
import com.vesoft.nebula.client.graph.exception.IOErrorException;
import com.vesoft.nebula.graph.ExecutionResponse;
import com.vesoft.nebula.util.ReflectUtil;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down Expand Up @@ -414,68 +425,125 @@ private static NMap map2Nmap(Map<String, Object> map) throws UnsupportedOperatio
return nmap;
}


/**
* convert java value type to nebula thrift value type
*
* @param value java obj
* @return nebula value
*/
public static Value value2Nvalue(Object value) throws UnsupportedOperationException {
Value nvalue = new Value();
if (value == null) {
nvalue.setNVal(NullType.__NULL__);
} else if (value instanceof Boolean) {
boolean bval = (Boolean) value;
nvalue.setBVal(bval);
} else if (value instanceof Integer) {
int ival = (Integer) value;
nvalue.setIVal(ival);
} else if (value instanceof Short) {
int ival = (Short) value;
nvalue.setIVal(ival);
} else if (value instanceof Byte) {
int ival = (Byte) value;
nvalue.setIVal(ival);
} else if (value instanceof Long) {
long ival = (Long) value;
nvalue.setIVal(ival);
} else if (value instanceof Float) {
float fval = (Float) value;
nvalue.setFVal(fval);
} else if (value instanceof Double) {
double dval = (Double) value;
nvalue.setFVal(dval);
} else if (value instanceof String) {
byte[] sval = ((String) value).getBytes();
nvalue.setSVal(sval);
} else if (value instanceof List) {
nvalue.setLVal(list2Nlist((List<Object>) value));
} else if (value instanceof Map) {
nvalue.setMVal(map2Nmap((Map<String, Object>) value));
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Date) {
nvalue.setDVal((Date) value);
} else if (value instanceof Time) {
nvalue.setTVal((Time) value);
} else if (value instanceof Duration) {
nvalue.setDuVal((Duration) value);
} else if (value instanceof DateTime) {
nvalue.setDtVal((DateTime) value);
} else if (value instanceof Geography) {
nvalue.setGgVal((Geography) value);
} else {
// unsupport other Value type, use this function carefully
throw new UnsupportedOperationException(
"Only support convert boolean/float/int/string/map/list to nebula.Value but was"
+ value.getClass().getTypeName());
try {
if (value == null) {
Value nullValue = new Value();
nullValue.setNVal(NullType.__NULL__);
return nullValue;
}
Class<?> type = value.getClass();
Setter<Object> setter = LEAF_TYPE_AND_SETTER.get(type);
if (setter != null) {
return setter.set(value);
}
for (Class<?> parentType : COMPLEX_TYPE_AND_SETTER.keySet()) {
if (isCurrentTypeOrParentType(type, parentType)) {
return COMPLEX_TYPE_AND_SETTER.get(parentType).set(value);
}
}
} catch (Exception e) {
throw new UnsupportedOperationException(e);
}
return nvalue;
throw new UnsupportedOperationException(
"Only support convert boolean/float/int/string/map/list/date/pojo to nebula.Value but was"
+ value.getClass().getTypeName());
}

@Override
public synchronized void close() {
release();
}

/**
* some value setter for java type (basic or nebula special type) that need convert to NValue
*/
public static Map<Class<?>, Setter> LEAF_TYPE_AND_SETTER =
new HashMap<Class<?>, Setter>() {{
put(Value.class, (Setter<Value>) (param) -> param);
put(Boolean.class, (Setter<Boolean>) Value::bVal);
put(Integer.class, (Setter<Integer>) Value::iVal);
put(Short.class, (Setter<Short>) Value::iVal);
put(Byte.class, (Setter<Short>) Value::iVal);
put(Long.class, (Setter<Long>) Value::iVal);
put(Float.class, (Setter<Float>) Value::fVal);
put(Double.class, (Setter<Double>) Value::fVal);
put(byte[].class, (Setter<byte[]>) Value::sVal);
put(Byte[].class, (Setter<byte[]>) Value::sVal);
put(String.class, (Setter<String>) (param) -> Value.sVal(param.getBytes()));
put(com.vesoft.nebula.Date.class, (Setter<com.vesoft.nebula.Date>) Value::dVal);
put(Time.class, (Setter<Time>) Value::tVal);
put(DateTime.class, (Setter<DateTime>) Value::dtVal);
put(Vertex.class, (Setter<Vertex>) Value::vVal);
put(Edge.class, (Setter<Edge>) Value::eVal);
put(Path.class, (Setter<Path>) Value::pVal);
put(NList.class, (Setter<NList>) Value::lVal);
put(NMap.class, (Setter<NMap>) Value::mVal);
put(NSet.class, (Setter<NSet>) Value::uVal);
put(DataSet.class, (Setter<DataSet>) Value::gVal);
put(Geography.class, (Setter<Geography>) Value::ggVal);
put(Duration.class, (Setter<Duration>) Value::duVal);
}};

/**
* some value setter for java type (complex java type include collections or date) that need
* convert to NValue
*/
public static Map<Class<?>, Setter> COMPLEX_TYPE_AND_SETTER =
new LinkedHashMap<Class<?>, Setter>() {{
put(Collection.class, (Setter<Collection>) (collection) -> {
Value value = new Value();
List<Object> list = new ArrayList<>();
collection.forEach(el -> list.add(value2Nvalue(el)));
value.setLVal(list2Nlist(list));
return value;
});

put(Map.class, (Setter<Map<String, Object>>) (map) -> {
Value value = new Value();
Map<String, Object> valueMap = new HashMap<>();
map.forEach((k, v) -> {
valueMap.put(k, value2Nvalue(v));
});
value.setMVal(map2Nmap(valueMap));
return value;
});

put(java.util.Date.class, (Setter<java.util.Date>) (date) -> {
Calendar calendar = new Calendar.Builder().setInstant(date).build();
return Value.dtVal(new DateTime(
new Short(String.valueOf(calendar.get(Calendar.YEAR))),
new Byte(String.valueOf(calendar.get(Calendar.MONTH))),
new Byte(String.valueOf(calendar.get(Calendar.DATE))),
new Byte(String.valueOf(calendar.get(Calendar.HOUR))),
new Byte(String.valueOf(calendar.get(Calendar.MINUTE))),
new Byte(String.valueOf(calendar.get(Calendar.SECOND))),
new Short(String.valueOf(calendar.get(Calendar.MILLISECOND)))
));
});

put(Object.class, (Setter<Object>) (obj) -> {
Value value = new Value();
Map<String, Object> pojoFields = new HashMap<>();
Class<?> paramType = obj.getClass();
Field[] declaredFields = paramType.getDeclaredFields();
for (Field declaredField : declaredFields) {
pojoFields.put(declaredField.getName(),
value2Nvalue(ReflectUtil.getValue(obj, declaredField)));
}
value.setMVal(map2Nmap(pojoFields));
return value;
});
}};

interface Setter<T> {

Value set(T param);
}
}
85 changes: 85 additions & 0 deletions client/src/main/java/com/vesoft/nebula/util/ReflectUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* Copyright (c) 2023 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License.
*/

package com.vesoft.nebula.util;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
* The util of reflect
*
* @author yeweicheng
* <br>Now is history!
*/
public class ReflectUtil {

/**
* Break through the access rights of the object
* and obtain the specified field value.
*
* @param o object of field value source
* @param field field used for get value
* @return field value in obj
*/
public static Object getValue(Object o, Field field) {
try {
boolean accessible = field.isAccessible();
if (accessible) {
return field.get(o);
} else {
field.setAccessible(true);
Object value = field.get(o);
field.setAccessible(false);
return value;
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

/**
* Determine whether parentType is paramType or its parent class or interface
*
* @param paramType type to be determined - subclass
* @param parentType type to be determined - parent class or interface
* @return whether paramType is a subclass or implementation class of parentType
*/
public static boolean isCurrentTypeOrParentType(Class<?> paramType, Class<?> parentType) {
if (paramType == parentType) {
return true;
}
Set<Class<?>> parentTypes = getParentTypes(paramType);
return parentTypes.contains(parentType);
}

/**
* Get the super class and interface type collection according to paramType.
*
* @param paramType subclass type.
* @return super class and interface.
*/
public static Set<Class<?>> getParentTypes(Class<?> paramType) {
if (paramType == null) {
return Collections.EMPTY_SET;
}
List<Class<?>> interfaces = Arrays.asList(paramType.getInterfaces());
Set<Class<?>> parents = new HashSet<>(interfaces);

for (Class<?> anInterface : interfaces) {
parents.addAll(getParentTypes(anInterface));
}

Class<?> superclass = paramType.getSuperclass();
parents.add(superclass);
parents.addAll(getParentTypes(superclass));
return parents;
}
}
Loading

0 comments on commit 9e484eb

Please sign in to comment.