diff --git a/.github/workflows/pd-store-ci.yml b/.github/workflows/pd-store-ci.yml
index d7dd8f5009..6e0f16a53d 100644
--- a/.github/workflows/pd-store-ci.yml
+++ b/.github/workflows/pd-store-ci.yml
@@ -1,4 +1,4 @@
-name: "hugegraph-pd-store-ci"
+name: "pd-store-ci"
on:
push:
@@ -109,10 +109,39 @@ jobs:
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
+ - name: Package
+ run: |
+ mvn clean package -U -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -ntp
+
+ - name: Prepare env and service
+ run: |
+ $TRAVIS_DIR/start-pd.sh
+ $TRAVIS_DIR/start-store.sh
+
- name: Run common test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-common-test
+ - name: Run client test
+ run: |
+ mvn test -pl hugegraph-store/hg-store-test -am -P store-client-test
+
+ - name: Run core test
+ run: |
+ mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test
+
+ - name: Run rocksdb test
+ run: |
+ mvn test -pl hugegraph-store/hg-store-test -am -P store-rocksdb-test
+
+ - name: Run server test
+ run: |
+ mvn test -pl hugegraph-store/hg-store-test -am -P store-server-test
+
+ - name: Run raft-core test
+ run: |
+ mvn test -pl hugegraph-store/hg-store-test -am -P store-raftcore-test
+
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.0.0
with:
diff --git a/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/grpc/GrpcStoreNodeSessionImpl.java b/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/grpc/GrpcStoreNodeSessionImpl.java
index 77c8a45537..73e95515c7 100644
--- a/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/grpc/GrpcStoreNodeSessionImpl.java
+++ b/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/grpc/GrpcStoreNodeSessionImpl.java
@@ -220,7 +220,10 @@ public boolean merge(String table, HgOwnerKey key, byte[] value) {
private boolean prepareBatchEntry(OpType opType, String table
, HgOwnerKey startKey, HgOwnerKey endKey, byte[] value) {
this.batchEntryBuilder.clear().setOpType(opType);
- this.batchEntryBuilder.setTable(tables.get(table));
+ Integer tableCode = tables.get(table);
+ if (tableCode != null) {
+ this.batchEntryBuilder.setTable(tableCode);
+ }
if (startKey != null) {
this.batchEntryBuilder.setStartKey(toKey(startKey));
}
diff --git a/hugegraph-store/hg-store-test/pom.xml b/hugegraph-store/hg-store-test/pom.xml
index 2ecadb7de7..59f87eaa6d 100644
--- a/hugegraph-store/hg-store-test/pom.xml
+++ b/hugegraph-store/hg-store-test/pom.xml
@@ -98,10 +98,10 @@
-
-
-
-
+
+ org.apache.hugegraph
+ hg-store-core
+
org.apache.hugegraph
hg-pd-grpc
@@ -203,12 +203,12 @@
-
-
-
-
-
-
+
+ org.apache.hugegraph
+ hg-store-node
+ ${revision}
+ compile
+
@@ -217,31 +217,30 @@
maven-surefire-plugin
2.20
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ store-client-test
+
+ ${basedir}/src/main/java/
+
+ ${basedir}/target/classes/
+
+
+ **/ClientSuiteTest.java
+
+
+
+
+ store-core-test
+
+ ${basedir}/src/main/java/
+
+ ${basedir}/target/classes/
+
+
+ **/CoreSuiteTest.java
+
+
+
store-common-test
@@ -254,45 +253,45 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ store-rocksdb-test
+
+ ${basedir}/src/main/java/
+
+ ${basedir}/target/classes/
+
+
+ **/RocksDbSuiteTest.java
+
+
+
+
+ store-server-test
+
+ ${basedir}/src/main/java/
+
+ ${basedir}/target/classes/
+
+
+ **/ServerSuiteTest.java
+
+
+ **/node/**/*
+
+
+
+
+ store-raftcore-test
+
+ ${basedir}/src/main/java/
+
+ ${basedir}/target/classes/
+
+
+ **/RaftSuiteTest.java
+
+
+
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgBusinessImplTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgBusinessImplTest.java
new file mode 100644
index 0000000000..15deaa8462
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgBusinessImplTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.hugegraph.store;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.hugegraph.rocksdb.access.RocksDBFactory;
+import org.apache.hugegraph.rocksdb.access.RocksDBSession;
+import org.apache.hugegraph.rocksdb.access.ScanIterator;
+import org.apache.hugegraph.store.business.BusinessHandler;
+import org.apache.hugegraph.store.business.BusinessHandlerImpl;
+import org.apache.hugegraph.store.meta.PartitionManager;
+import org.apache.hugegraph.store.options.HgStoreEngineOptions;
+import org.apache.hugegraph.store.options.RaftRocksdbOptions;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.apache.hugegraph.store.pd.PdProvider;
+import org.apache.hugegraph.util.Bytes;
+import org.junit.Assert;
+
+public class HgBusinessImplTest {
+ static String GRAPH_NAME = "graph_test";
+ static String[] GRAPH_TABLE = {"table1", "table2"};
+
+ static String dbPath = "tmp/junit";
+
+ // @BeforeClass
+ public static void init() {
+ UnitTestBase.deleteDir(new File(dbPath));
+ Map configMap = new HashMap<>();
+ configMap.put("rocksdb.write_buffer_size", "1048576");
+
+ RaftRocksdbOptions.initRocksdbGlobalConfig(configMap);
+ BusinessHandlerImpl.initRocksdb(configMap, null);
+ }
+
+ public BusinessHandler getBusinessHandler() {
+
+ int partitionCount = 2;
+ HgStoreEngineOptions options = new HgStoreEngineOptions() {{
+ setDataPath(dbPath);
+ setFakePdOptions(new HgStoreEngineOptions.FakePdOptions() {{
+ setPartitionCount(partitionCount);
+ setPeersList("127.0.0.1");
+ setStoreList("127.0.0.1");
+
+ }});
+ }};
+
+ PdProvider pdProvider = new FakePdServiceProvider(options.getFakePdOptions());
+ PartitionManager partitionManager = new PartitionManager(pdProvider, options) {
+ @Override
+ public List getLeaderPartitionIds(String graph) {
+ List ids = new ArrayList<>();
+ for (int i = 0; i < partitionCount; i++) {
+ ids.add(i);
+ }
+ return ids;
+ }
+ };
+ BusinessHandler handler = new BusinessHandlerImpl(partitionManager);
+
+ return handler;
+ }
+
+ // @Test
+ public void testPut() {
+ String graph1 = "test-graph11";
+ String graph2 = "test-graph12";
+ String table = "test";
+ BusinessHandler handler = getBusinessHandler();
+ handler.doPut(graph1, 0, table, "key1".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xF, table, "key2".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xFF, table, "key3".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xFFF, table, "key4".getBytes(), "value1".getBytes());
+
+ handler.doPut(graph2, 0, table, "key21".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xF, table, "key22".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xFF, table, "key23".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xFFF, table, "key24".getBytes(), "value1".getBytes());
+
+ System.out.println("--------------------dump all -------");
+ dump(handler, graph1, 0);
+ System.out.println("--------------------dump scan 0 0xff -------");
+ ScanIterator iterator = handler.scan(graph1, table, 0, 0xff);
+ int count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(2, count);
+
+ System.out.println("--------------------dump scan prefix -------");
+ iterator = handler.scanPrefix(graph1, 0, table, "key".getBytes());
+
+ count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(4, count);
+ System.out.println("--------------------dump scan range key1 key4 -------");
+ iterator = handler.scan(graph1, 0, table, "key1".getBytes(), "key4".getBytes(),
+ ScanIterator.Trait.SCAN_LT_END);
+ count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(3, count);
+ }
+
+ // @Test
+ public void testLoadSnapshot() throws InterruptedException {
+
+ BusinessHandler handler = getBusinessHandler();
+ String graph1 = "test-graph1";
+ String graph2 = "test-graph2";
+ String table = "test";
+ for (int i = 0; i < 256; i++) {
+ handler.doPut(graph1, i, table, ("key" + i).getBytes(), "value1".getBytes());
+ }
+ ScanIterator iterator = handler.scanAll(graph1, table);
+
+ System.out.println(iterator.count());
+
+ String snapshotPath;
+ try (RocksDBSession session = handler.getSession(0)) {
+ snapshotPath = session.getDbPath();
+ }
+
+ handler.closeAll();
+
+ System.out.println("start loadSnapshot");
+ handler.loadSnapshot(snapshotPath, graph1, 0, 10);
+ iterator = handler.scanAll(graph1, table);
+ Assert.assertEquals(255, iterator.count());
+ try (RocksDBSession session = handler.getSession(0)) {
+ System.out.println(session.getDbPath());
+ }
+
+ CountDownLatch latch = new CountDownLatch(1);
+ RocksDBFactory.getInstance()
+ .addRocksdbChangedListener(new RocksDBFactory.RocksdbChangedListener() {
+ @Override
+ public void onCompacted(String dbName) {
+ RocksDBFactory.RocksdbChangedListener.super.onCompacted(dbName);
+ }
+
+ @Override
+ public void onDBDeleteBegin(String dbName, String filePath) {
+ RocksDBFactory.RocksdbChangedListener.super.onDBDeleteBegin(dbName,
+ filePath);
+ }
+
+ @Override
+ public void onDBDeleted(String dbName, String filePath) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onDBSessionReleased(RocksDBSession dbSession) {
+ RocksDBFactory.RocksdbChangedListener.super.onDBSessionReleased(
+ dbSession);
+ }
+ });
+ latch.await();
+
+ }
+
+ public void dump(BusinessHandler handler, String graph, int partId) {
+ ScanIterator cfIterator = handler.scanRaw(graph, partId, 0);
+ while (cfIterator.hasNext()) {
+ try (ScanIterator iterator = cfIterator.next()) {
+ byte[] cfName = cfIterator.position();
+ System.out.println(graph + "-" + +partId + "-" + new String(cfName) + "--------");
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn col = iterator.next();
+ System.out.println(new String(col.name) + " -- " + Bytes.toHex(col.name));
+ }
+ }
+ }
+ cfIterator.close();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
new file mode 100644
index 0000000000..b4e19f104d
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
@@ -0,0 +1,481 @@
+/*
+ * 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.hugegraph.store;
+
+import static org.apache.hugegraph.store.client.util.HgAssert.isInvalid;
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.ALL_PARTITION_OWNER;
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import org.apache.hugegraph.pd.common.PartitionUtils;
+import org.apache.hugegraph.store.client.HgStoreNodeManager;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+
+/**
+ * 使用fake-pd,支持raft的单元测试
+ */
+public class HgSessionManagerOneRaftFakePDTest {
+ private static final Map leaderMap = new ConcurrentHashMap<>();
+ private static final Map storeMap = new ConcurrentHashMap<>();
+
+ private static final int partitionCount = 3;
+ // 需要与store的application.yml的fake-pd.partition-count保持一致
+ private static final String[] storeAddress = {
+ "127.0.0.1:8500"
+ };
+
+ // @BeforeClass
+ public static void init() {
+ for (String address : storeAddress) {
+ storeMap.put((long) address.hashCode(), address);
+ }
+ for (int i = 0; i < partitionCount; i++) {
+ leaderMap.put(i, storeMap.keySet().iterator().next());
+ }
+
+ HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ nodeManager.setNodePartitioner((builder, graphName, startKey, endKey) -> {
+ int startCode = PartitionUtils.calcHashcode(startKey);
+ int endCode = PartitionUtils.calcHashcode(endKey);
+ if (ALL_PARTITION_OWNER == startKey) {
+ storeMap.forEach((k, v) -> {
+ builder.add(k, -1);
+ });
+ } else if (endKey == HgStoreClientConst.EMPTY_BYTES || startKey == endKey ||
+ Arrays.equals(startKey, endKey)) {
+ builder.add(leaderMap.get(startCode % partitionCount), startCode);
+ } else {
+ Assert.fail("OwnerKey转成HashCode后已经无序了, 按照OwnerKey范围查询没意义");
+ builder.add(leaderMap.get(startCode % partitionCount), startCode);
+ builder.add(leaderMap.get(endCode % partitionCount), endCode);
+ }
+ return 0;
+ });
+ nodeManager.setNodeProvider((graphName, nodeId) -> {
+ System.out.println("HgStoreNodeProvider apply " + graphName + " " + nodeId + " " +
+ storeMap.get(nodeId));
+ return nodeManager.getNodeBuilder().setNodeId(nodeId)
+ .setAddress(storeMap.get(nodeId)).build();
+ });
+ nodeManager.setNodeNotifier((graphName, storeNotice) -> {
+ System.out.println("recv node notifier " + storeNotice);
+ if (storeNotice.getPartitionLeaders().size() > 0) {
+ leaderMap.putAll(storeNotice.getPartitionLeaders());
+ System.out.println("leader changed ");
+ leaderMap.forEach((k, v) -> {
+ System.out.print(" " + k + " " + v + ",");
+ });
+ System.out.println();
+ }
+ return 0;
+ });
+ }
+
+ private static HgStoreSession getStoreSession() {
+ return HgSessionManager.getInstance().openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private static HgStoreSession getStoreSession(String graph) {
+ return HgSessionManager.getInstance().openSession(graph);
+ }
+
+ // @Test
+ public void put_get() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession();
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(HgStoreTestUtil.TABLE_NAME, key, value));
+
+ Assert.assertEquals(HgStoreTestUtil.toStr(value), HgStoreTestUtil.toStr(session.get(
+ HgStoreTestUtil.TABLE_NAME, key)));
+ }
+
+ // @Test
+ public void put_get2() {
+ System.out.println("--- test put & get 2---");
+
+ String GRAPH_NAME = "default/hugegraph/g2";
+ String TABLE_NAME = "put_get2";
+
+ HgStoreSession session = getStoreSession(GRAPH_NAME);
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(TABLE_NAME, key, value));
+
+ Assert.assertEquals(HgStoreTestUtil.toStr(value),
+ HgStoreTestUtil.toStr(session.get(TABLE_NAME, key)));
+
+ HgKvIterator iterator = session.scanIterator(TABLE_NAME);
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+
+ System.out.println(new String(entry.key()));
+ Assert.assertEquals(HgStoreTestUtil.toStr(key.getKey()),
+ HgStoreTestUtil.toStr(entry.key()));
+ }
+
+ }
+
+
+ // @Test
+ public void batchGet() {
+ System.out.println("--- test batchGet ---");
+ HgStoreSession session = getStoreSession();
+ String keyPrefix = "BATCH-GET-UNIT";
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix);
+ List keyList =
+ map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList());
+
+ //printOwner(keyList);
+ List resList = session.batchGetOwner(HgStoreTestUtil.TABLE_NAME, keyList);
+
+ Assert.assertFalse(isInvalid(resList));
+ Assert.assertEquals(resList.size(), keyList.size());
+
+ // println(list);
+ HgStoreTestUtil.println("--- batch-get result ---");
+ Assert.assertTrue((resList.stream()
+ .map(e -> map.containsKey(HgStoreTestUtil.toOwnerKey(e.key())))
+ .allMatch(Boolean::booleanValue))
+ );
+
+ }
+
+ // @Test
+ //CAUTION: ONLY FOR LONG!
+ //注意:目前只可以对long类型value进行Merge操作。
+ public void merge() {
+ System.out.println("--- test merge (1+1=2)---");
+ HgStoreSession session = getStoreSession();
+ String mergeKey = "merge-key";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(mergeKey);
+ byte[] value = HgStoreTestUtil.toBytes(1L);
+
+ System.out.println("- put " + mergeKey + ":1 -");
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ System.out.println("- merge " + mergeKey + ":1 -");
+ session.merge(HgStoreTestUtil.TABLE_NAME, key, value);
+ long res = HgStoreTestUtil.toLong(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.printf("after merge " + mergeKey + "=%s%n", res);
+ Assert.assertEquals(2L, res);
+
+ String putStr = "19";
+ session.put(HgStoreTestUtil.TABLE_NAME, key, HgStoreTestUtil.toBytes(putStr));
+ byte[] b1 = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ Assert.assertEquals(putStr, HgStoreTestUtil.toStr(b1));
+ }
+
+ // @Test
+ public void delete() {
+ System.out.println("--- test delete ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-key";
+ String delValue = "del-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put " + delKey + ": " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ HgStoreTestUtil.println("- delete " + delKey);
+ session.delete(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println("- get " + delKey + ": " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(EMPTY_BYTES, value);
+ }
+
+ // @Test
+ public void deleteSingle() {
+ System.out.println("--- test deleteSingle ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-single-key";
+ String delValue = "del-single-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put [" + delKey + "] = " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- before del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(delValue, HgStoreTestUtil.toStr(value));
+
+ HgStoreTestUtil.println("- delete-single : [" + delKey + "]");
+ session.deleteSingle(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- after del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals("", HgStoreTestUtil.toStr(value));
+
+ }
+
+ // @Test
+ public void deleteRange() {
+ HgStoreTestUtil.println("--- test deleteRange ---");
+ HgStoreSession session = getStoreSession();
+
+ String rangePrefix = "DEL-RANGE-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, rangePrefix, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ HgOwnerKey startKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-00");
+ HgOwnerKey endKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-05");
+
+ Assert.assertTrue(session.deleteRange(HgStoreTestUtil.TABLE_NAME, startKey, endKey));
+
+ HgStoreTestUtil.println("- after delete range from ["
+ + HgStoreTestUtil.toStr(startKey.getKey())
+ + "] to ["
+ + HgStoreTestUtil.toStr(endKey.getKey()) + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-" +
+ HgStoreTestUtil.padLeftZeros(
+ String.valueOf(i), 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ HgStoreTestUtil.println(
+ "- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+
+ // TODO: [start,end)?
+ if (i < 5) {
+ Assert.assertEquals("", value);
+ } else {
+ //println(value);
+ Assert.assertNotEquals("", value);
+ }
+ }
+
+ }
+
+ // @Test
+ public void deletePrefix() {
+ System.out.println("--- test deletePrefix ---");
+ HgStoreSession session = getStoreSession();
+
+ String prefixStr = "DEL-PREFIX-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, prefixStr, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ //printOwner(map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
+
+ HgOwnerKey prefix = HgStoreTestUtil.toOwnerKey(owner, prefixStr);
+
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+ session.deletePrefix(HgStoreTestUtil.TABLE_NAME, prefix);
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+
+ HgStoreTestUtil.println("- after delete by prefix:[" + prefixStr + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, prefixStr + HgStoreTestUtil.toSuffix(i, 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.println("- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+ Assert.assertEquals("", value);
+ }
+
+ }
+
+ // @Test
+ public void scanIterator() {
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = "UNIT_SCAN";
+ String keyName = "SCAN-ITER";
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 10000);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ HgStoreTestUtil.println("-- test 0 element --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey("__SCAN-001"),
+ HgStoreTestUtil.toAllPartitionKey("__SCAN-100"), 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ Assert.assertEquals(limit, count);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 not enough --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00001"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00005"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+
+ }
+
+ HgStoreTestUtil.println("-- test limit 0 (no limit) --");
+ limit = 0;
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan all --");
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan prefix --");
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-01"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(1000, count);
+ }
+
+
+ // @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String graph = "graph_truncate";
+ String tableName = "UNIT_TRUNCATE_1";
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ String tableName2 = "UNIT_TRUNCATE_2";
+ HgStoreTestUtil.batchPut(session, tableName2, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+ }
+
+ //// @Test
+ public void scanIteratorHuge() {
+
+ /*************** test no limit, with 10 millions **************/
+ String tableName = "UNIT_HUGE";
+ String keyName = "SCAN-HUGE";
+ int amount = 10_000_000;
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 10)) <
+ 10) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ int count = 0;
+ HgKvIterator iterator = session.scanIterator(tableName);
+
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % (amount / 10) == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ }
+
+ Assert.assertEquals(amount, count);
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java
new file mode 100644
index 0000000000..d014864870
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java
@@ -0,0 +1,648 @@
+/*
+ * 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.hugegraph.store;
+
+import static org.apache.hugegraph.store.client.util.HgAssert.isInvalid;
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.ALL_PARTITION_OWNER;
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import org.apache.hugegraph.pd.common.PartitionUtils;
+import org.apache.hugegraph.store.client.HgStoreNodeManager;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+
+/**
+ * 使用fake-pd,支持raft的单元测试
+ */
+public class HgSessionManagerRaftFakePDTest {
+ private static final Map leaderMap = new ConcurrentHashMap<>();
+ private static final Map storeMap = new ConcurrentHashMap<>();
+
+ private static final int partitionCount = 3;
+ // 需要与store的application.yml的fake-pd.partition-count保持一致
+ private static final String[] storeAddress =
+ { // 需要与store的application.yml的fake-pd.store-list保持一致
+ "127.0.0.1:8501", "127.0.0.1:8502", "127.0.0.1:8503"
+ };
+
+ /*private static String[] storeAddress = {
+ "127.0.0.1:9080"
+ };*/
+ // @BeforeClass
+ public static void init() {
+ for (String address : storeAddress) {
+ storeMap.put((long) address.hashCode(), address);
+ }
+ for (int i = 0; i < partitionCount; i++) {
+ leaderMap.put(i, storeMap.keySet().iterator().next());
+ }
+
+ HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ nodeManager.setNodePartitioner((builder, graphName, startKey, endKey) -> {
+ int startCode = PartitionUtils.calcHashcode(startKey);
+ int endCode = PartitionUtils.calcHashcode(endKey);
+ if (ALL_PARTITION_OWNER == startKey) {
+ storeMap.forEach((k, v) -> {
+ builder.add(k, -1);
+ });
+ } else if (endKey == HgStoreClientConst.EMPTY_BYTES || startKey == endKey ||
+ Arrays.equals(startKey, endKey)) {
+ builder.add(leaderMap.get(startCode % partitionCount), startCode);
+ } else {
+ Assert.fail("OwnerKey转成HashCode后已经无序了, 按照OwnerKey范围查询没意义");
+ builder.add(leaderMap.get(startCode % partitionCount), startCode);
+ builder.add(leaderMap.get(endCode % partitionCount), endCode);
+ }
+ return 0;
+ });
+ nodeManager.setNodeProvider((graphName, nodeId) -> {
+ System.out.println("HgStoreNodeProvider apply " + graphName + " " + nodeId + " " +
+ storeMap.get(nodeId));
+ return nodeManager.getNodeBuilder().setNodeId(nodeId)
+ .setAddress(storeMap.get(nodeId)).build();
+ });
+ nodeManager.setNodeNotifier((graphName, storeNotice) -> {
+ System.out.println("recv node notifier " + storeNotice);
+ if (storeNotice.getPartitionLeaders().size() > 0) {
+ leaderMap.putAll(storeNotice.getPartitionLeaders());
+ System.out.println("leader changed ");
+ leaderMap.forEach((k, v) -> {
+ System.out.print(" " + k + " " + v + ",");
+ });
+ System.out.println();
+ }
+ return 0;
+ });
+ }
+
+ private static HgStoreSession getStoreSession() {
+ return HgSessionManager.getInstance().openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private static HgStoreSession getStoreSession(String graph) {
+ return HgSessionManager.getInstance().openSession(graph);
+ }
+
+ // @Test
+ public void put_get() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession();
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(HgStoreTestUtil.TABLE_NAME, key, value));
+
+ Assert.assertEquals(HgStoreTestUtil.toStr(value), HgStoreTestUtil.toStr(session.get(
+ HgStoreTestUtil.TABLE_NAME, key)));
+ }
+
+// // @Test
+// public void batchPutOwner() {
+// Map> entries = new HashMap<>(2);
+//
+// int ownerNum = 10;
+// int keyNum = 10;
+// String keyPrefix = "BATCH-UNIT-TEST-";
+// long amount = ownerNum * keyNum;
+// Map kv = new HashMap<>(keyNum, 1);
+//
+// for (int i = 0; i < ownerNum; i++) {
+//
+// for (int ii = 0; ii < keyNum; ii++) {
+// HgOwnerKey ownerKey = new HgOwnerKey(toBytes("OWNER-" + i)
+// , toBytes(keyPrefix + i + "-" + ii));
+// byte[] value = toBytes(keyPrefix + "VALUE-" + ownerNum + "-" + ii);
+// kv.put(ownerKey, value);
+// }
+//
+// }
+//
+// entries.put(TABLE_NAME, kv);
+// HgStoreSession session = getStoreSession();
+// Assert.assertTrue(session.batchPutOwner(entries));
+// System.out.println("put ok");
+// Assert.assertEquals(amount, amountOf(session.scanIterator(TABLE_NAME, toAllPartitionKey
+// (keyPrefix))));
+//
+// }
+
+ // // @Test
+//
+// public void batchPutWithoutStop() {
+// final int loops = 6 * 10;
+// final int interval = 1000 * 10;
+// for(int j=0;j> entries = new HashMap<>(2);
+//
+// int ownerNum = 10;
+// int keyNum = 10;
+// String keyPrefix = "BATCH-UNIT-TEST-";
+// long amount = ownerNum * keyNum;
+// Map kv = new HashMap<>(keyNum, 1);
+//
+// for (int i = 0; i < ownerNum; i++) {
+//
+// for (int ii = 0; ii < keyNum; ii++) {
+// HgOwnerKey ownerKey = new HgOwnerKey(toBytes("OWNER-" + i * j)
+// , toBytes(keyPrefix + i + "-" + ii));
+// byte[] value = toBytes(keyPrefix + "VALUE-" + ownerNum + "-" + ii*j);
+// kv.put(ownerKey, value);
+// }
+// }
+//
+// entries.put(TABLE_NAME, kv);
+// HgStoreSession session = getStoreSession();
+// Assert.assertTrue(session.batchPutOwner(entries));
+// System.out.println("put ok");
+//
+// try {
+// Thread.sleep(interval);
+// } catch (InterruptedException e) {
+// System.out.println(e.getMessage());
+// }
+// }
+// }
+
+
+ // @Test
+ public void batchGet() {
+ System.out.println("--- test batchGet ---");
+ HgStoreSession session = getStoreSession();
+ String keyPrefix = "BATCH-GET-UNIT";
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix);
+ List keyList =
+ map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList());
+
+ //printOwner(keyList);
+ List resList = session.batchGetOwner(HgStoreTestUtil.TABLE_NAME, keyList);
+
+ Assert.assertFalse(isInvalid(resList));
+ Assert.assertEquals(resList.size(), keyList.size());
+
+ // println(list);
+ HgStoreTestUtil.println("--- batch-get result ---");
+ Assert.assertTrue((resList.stream()
+ .map(e -> map.containsKey(HgStoreTestUtil.toOwnerKey(e.key())))
+ .allMatch(Boolean::booleanValue))
+ );
+
+ }
+
+ // @Test
+ //CAUTION: ONLY FOR LONG!
+ //注意:目前只可以对long类型value进行Merge操作。
+ public void merge() {
+ System.out.println("--- test merge (1+1=2)---");
+ HgStoreSession session = getStoreSession();
+ String mergeKey = "merge-key";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(mergeKey);
+ byte[] value = HgStoreTestUtil.toBytes(1L);
+
+ System.out.println("- put " + mergeKey + ":1 -");
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ System.out.println("- merge " + mergeKey + ":1 -");
+ session.merge(HgStoreTestUtil.TABLE_NAME, key, value);
+ long res = HgStoreTestUtil.toLong(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.printf("after merge " + mergeKey + "=%s%n", res);
+ Assert.assertEquals(2L, res);
+
+ String putStr = "19";
+ session.put(HgStoreTestUtil.TABLE_NAME, key, HgStoreTestUtil.toBytes(putStr));
+ byte[] b1 = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ Assert.assertEquals(putStr, HgStoreTestUtil.toStr(b1));
+ }
+
+ // @Test
+ public void delete() {
+ System.out.println("--- test delete ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-key";
+ String delValue = "del-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put " + delKey + ": " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ HgStoreTestUtil.println("- delete " + delKey);
+ session.delete(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println("- get " + delKey + ": " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(EMPTY_BYTES, value);
+ }
+
+ // @Test
+ public void deleteSingle() {
+ System.out.println("--- test deleteSingle ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-single-key";
+ String delValue = "del-single-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put [" + delKey + "] = " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- before del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(delValue, HgStoreTestUtil.toStr(value));
+
+ HgStoreTestUtil.println("- delete-single : [" + delKey + "]");
+ session.deleteSingle(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- after del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals("", HgStoreTestUtil.toStr(value));
+
+ }
+
+ // @Test
+ public void deleteRange() {
+ HgStoreTestUtil.println("--- test deleteRange ---");
+ HgStoreSession session = getStoreSession();
+
+ String rangePrefix = "DEL-RANGE-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, rangePrefix, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ HgOwnerKey startKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-00");
+ HgOwnerKey endKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-05");
+
+ Assert.assertTrue(session.deleteRange(HgStoreTestUtil.TABLE_NAME, startKey, endKey));
+
+ HgStoreTestUtil.println("- after delete range from ["
+ + HgStoreTestUtil.toStr(startKey.getKey())
+ + "] to ["
+ + HgStoreTestUtil.toStr(endKey.getKey()) + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-" +
+ HgStoreTestUtil.padLeftZeros(
+ String.valueOf(i), 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ HgStoreTestUtil.println(
+ "- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+
+ // TODO: [start,end)?
+ if (i < 5) {
+ Assert.assertEquals("", value);
+ } else {
+ //println(value);
+ Assert.assertNotEquals("", value);
+ }
+ }
+
+ }
+
+ // @Test
+ public void deletePrefix() {
+ System.out.println("--- test deletePrefix ---");
+ HgStoreSession session = getStoreSession();
+
+ String prefixStr = "DEL-PREFIX-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, prefixStr, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ //printOwner(map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
+
+ HgOwnerKey prefix = HgStoreTestUtil.toOwnerKey(owner, prefixStr);
+
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+ session.deletePrefix(HgStoreTestUtil.TABLE_NAME, prefix);
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+
+ HgStoreTestUtil.println("- after delete by prefix:[" + prefixStr + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, prefixStr + HgStoreTestUtil.toSuffix(i, 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.println("- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+ Assert.assertEquals("", value);
+ }
+
+ }
+// // @Test
+// public void batchDeleteOwner() {
+// System.out.println("--- test batchDelete ---");
+// HgStoreSession session = getStoreSession();
+// String batchPrefix = "DEL-BATCH-KEY";
+// batchPut(session, batchPrefix, 10);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(batchPrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// Assert.assertNotEquals("", value);
+// }
+//
+// Set keys = new HashSet<>();
+// for (int i = 0; i < 5; i++) {
+// keys.add(toOwnerKey(batchPrefix + toSuffix(i, 2)));
+// }
+//
+// Map> map = new HashMap<>(1);
+// map.put(TABLE_NAME, keys);
+// session.batchDeleteOwner(map);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(batchPrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// // TODO: [,)?
+// if (i < 5) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+// }
+
+// // @Test
+// public void batchDeleteRangeOwner() {
+// System.out.println("--- test batchDeleteRange ---");
+// HgStoreSession session = getStoreSession();
+// String rangePrefix = "DEL-RANGE-KEY";
+// String owner="batch-delete-owner";
+//
+// batchPut(session, TABLE_NAME,rangePrefix, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+// batchPut(session, TABLE_NAME2, rangePrefix, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+//
+// HgOwnerKey startKey1 = toOwnerKey(owner,rangePrefix + "-03");
+// HgOwnerKey endKey1 = toOwnerKey(owner,rangePrefix + "-05");
+//
+// HgOwnerKey startKey2 = toOwnerKey(owner,rangePrefix + "-06");
+// HgOwnerKey endKey2 = toOwnerKey(owner,rangePrefix + "-09");
+//
+// Map> map = new HashMap<>();
+// map.put(TABLE_NAME, new HgPair<>(startKey1, endKey1));
+// map.put(TABLE_NAME2, new HgPair<>(startKey2, endKey2));
+//
+// session.batchDeleteRangeOwner(map);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(owner,rangePrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+//
+// if (i >= 3 && i < 5) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(owner,rangePrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME2, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// if (i >= 6 && i < 9) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+// }
+
+// // @Test
+// public void batchDeletePrefix() {
+// System.out.println("--- test batchDeletePrefix ---");
+// HgStoreSession session = getStoreSession();
+// String batchKey1 = "DEL-PREFIX-BATCH-1-KEY";
+// String batchKey2 = "DEL-PREFIX-BATCH-2-KEY";
+// String owner="batch-delete-owner";
+//
+// batchPut(session, TABLE_NAME, batchKey1, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+// batchPut(session, TABLE_NAME2, batchKey2, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+//
+// HgOwnerKey prefix1 = toOwnerKey(owner,batchKey1);
+// HgOwnerKey prefix2 = toOwnerKey(owner,batchKey2);
+//
+// Set set = new HashSet<>();
+//
+// set.add(prefix1);
+// set.add(prefix2);
+//
+// Map> map = new HashMap<>();
+// map.put(TABLE_NAME, set);
+// map.put(TABLE_NAME2, set);
+//
+// Assert.assertEquals(10, amountOf(session.scanIterator(TABLE_NAME, prefix1)));
+// Assert.assertEquals(10, amountOf(session.scanIterator(TABLE_NAME2, prefix2)));
+//
+// session.batchDeletePrefixOwner(map);
+//
+// Assert.assertEquals(0, amountOf(session.scanIterator(TABLE_NAME, prefix1)));
+// Assert.assertEquals(0, amountOf(session.scanIterator(TABLE_NAME2, prefix2)));
+//
+// }
+
+ // @Test
+ public void scanIterator() {
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = "UNIT_SCAN";
+ String keyName = "SCAN-ITER";
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 10000);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ HgStoreTestUtil.println("-- test 0 element --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey("__SCAN-001"),
+ HgStoreTestUtil.toAllPartitionKey("__SCAN-100"), 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ Assert.assertEquals(limit, count);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 not enough --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00001"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00005"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+
+ }
+
+ HgStoreTestUtil.println("-- test limit 0 (no limit) --");
+ limit = 0;
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan all --");
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan prefix --");
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-01"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(1000, count);
+ }
+
+
+ // @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String graph = "graph_truncate";
+ String tableName = "UNIT_TRUNCATE_1";
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ String tableName2 = "UNIT_TRUNCATE_2";
+ HgStoreTestUtil.batchPut(session, tableName2, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+ }
+
+ //// @Test
+ public void scanIteratorHuge() {
+
+ /*************** test no limit, with 10 millions **************/
+ String tableName = "UNIT_HUGE";
+ String keyName = "SCAN-HUGE";
+ int amount = 10_000_000;
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 10)) <
+ 10) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ int count = 0;
+ HgKvIterator iterator = session.scanIterator(tableName);
+
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % (amount / 10) == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ }
+
+ Assert.assertEquals(amount, count);
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java
new file mode 100644
index 0000000000..9820457d78
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java
@@ -0,0 +1,981 @@
+/*
+ * 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.hugegraph.store;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hugegraph.pd.client.PDClient;
+import org.apache.hugegraph.pd.client.PDConfig;
+import org.apache.hugegraph.store.client.grpc.KvCloseableIterator;
+import org.apache.hugegraph.store.client.util.HgStoreClientConfig;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.client.util.MetricX;
+import org.apache.hugegraph.store.grpc.common.ScanOrderType;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+
+/**
+ * 使用pd,支持raft的单元测试
+ */
+@Slf4j
+public class HgSessionManagerRaftPDTest {
+ public final static String GRAPH_NAME_X = "default/hugegraph/x";
+ public final static String GRAPH_NAME_Y = "default/hugegraph/y";
+ public final static String GRAPH_NAME_Z = "default/hugegraph/z";
+ public final static String TABLE_NAME_1 = "table1";
+ public final static String TABLE_NAME_2 = "table2";
+ public final static String TABLE_NAME_3 = "table3";
+ private static final String pdAddress = "localhost:8686";
+ public static HgStoreClient storeClient;
+ private static PDClient pdClient;
+
+ // @BeforeClass
+ public static void init() {
+ pdClient = PDClient.create(PDConfig.of(pdAddress).setEnableCache(true));
+ storeClient = HgStoreClient.create(pdClient);
+ }
+
+ private static HgStoreSession getStoreSession() {
+ return storeClient.openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private static HgStoreSession getStoreSession(String graph) {
+ return storeClient.openSession(graph);
+ }
+
+ // @Test
+ public void put_get() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession(HgStoreTestUtil.GRAPH_NAME);
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ // Assert.assertTrue(session.put(TABLE_NAME, key, value));
+
+ // Assert.assertEquals(toStr(value), toStr(session.get(TABLE_NAME, key)));
+
+ long stime = System.currentTimeMillis();
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, "BATCH-PUT-TEST", 30000);
+ System.out.println("Time is " + (System.currentTimeMillis() - stime));
+ }
+
+ public void put_get2() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession("testGraph");
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+ long stime = System.currentTimeMillis();
+ HgStoreTestUtil.batchPut(session, "testTable", "BATCH-PUT-TEST", 30000);
+ System.out.println("Time is " + (System.currentTimeMillis() - stime));
+ }
+
+ // @Test
+ public void scanPartition() {
+ HgStoreTestUtil.println("--- test scanPartition ---");
+
+ HgStoreSession session = getStoreSession();
+ // System.out.println(amountOf(session.scanIterator(TABLE_NAME)));
+
+
+ Iterator iterator = session.scanIterator(HgStoreTestUtil.TABLE_NAME, 0, 65535,
+ HgKvStore.SCAN_HASHCODE, EMPTY_BYTES);
+ System.out.println(HgStoreTestUtil.amountOf(iterator));
+ }
+
+ // @Test
+ public void check() {
+ System.out.println("--- test check ---");
+
+ HgStoreSession session = getStoreSession();
+ HgKvIterator iterator = session.scanIterator(HgStoreTestUtil.TABLE_NAME);
+ int count = 0;
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ }
+ System.out.println(count);
+ }
+
+ // @Test
+ public void put_get_unique() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession();
+
+ // add timestamp into key to avoid key duplication
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY-" + timestamp);
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(HgStoreTestUtil.TABLE_NAME, key, value));
+
+ Assert.assertEquals(HgStoreTestUtil.toStr(value), HgStoreTestUtil.toStr(session.get(
+ HgStoreTestUtil.TABLE_NAME, key)));
+ }
+
+
+ @Test
+ public void testBatchPutExt() throws IOException {
+ System.out.println("--- test batchPut ---");
+ HgStoreSession session = getStoreSession();
+ String keyPrefix = "BATCH-GET-UNIT";
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix, 1000);
+
+ File outputFile = new File("tmp/batch_put_list");
+ if (outputFile.exists()) {
+ FileUtils.forceDelete(outputFile);
+ }
+ FileUtils.forceMkdir(new File("tmp/"));
+
+ ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(outputFile));
+ oo.writeObject(map);
+ oo.close();
+ System.out.printf("%d entries have be put into graph %s\n", map.size(),
+ HgStoreTestUtil.GRAPH_NAME);
+
+
+ int count = 0;
+ HgKvIterator iterator = null;
+ iterator = session.scanIterator(HgStoreTestUtil.TABLE_NAME);
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ }
+ Assert.assertEquals(1000, count);
+
+ }
+
+
+ // @Test
+ public void testBatchGetExt() throws IOException, ClassNotFoundException {
+ File outputFile = new File("tmp/batch_put_list");
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(outputFile));
+ Map map = (Map) ois.readObject();
+ ois.close();
+ System.out.printf("%d entries get from %s\n", map.size(), outputFile.getPath());
+
+ HgStoreSession session = getStoreSession();
+ List keyList =
+ map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList());
+ List resList = session.batchGetOwner(HgStoreTestUtil.TABLE_NAME, keyList);
+
+ Assert.assertTrue((resList.stream()
+ .map(e -> map.containsKey(HgStoreTestUtil.toOwnerKey(e.key())))
+ .allMatch(Boolean::booleanValue))
+ );
+ }
+
+ @Test
+ public void testBatchPutUniqueExt() throws IOException {
+ System.out.println("--- test batchPut ---");
+ HgStoreSession session = getStoreSession();
+
+ // add timestamp into key to avoid key duplication
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+
+ String keyPrefix = "BATCH-GET-UNIT-" + timestamp;
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix, 300000);
+
+ File outputFile = new File("tmp/batch_put_list");
+ if (outputFile.exists()) {
+ FileUtils.forceDelete(outputFile);
+ }
+ FileUtils.forceMkdir(new File("tmp/"));
+
+ ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(outputFile));
+ oo.writeObject(map);
+ oo.close();
+ System.out.printf("%d entries have be put into graph %s\n", map.size(),
+ HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ // @Test
+ public void testBatchPutMultiGraph() throws IOException {
+ System.out.println("--- test testBatchPutMultiGraph ---");
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+ HgStoreSession session1 = getStoreSession(GRAPH_NAME_X);
+ HgStoreSession session2 = getStoreSession(GRAPH_NAME_Y);
+ HgStoreSession session3 = getStoreSession(GRAPH_NAME_Z);
+ String keyPrefix1 = "BATCH-PUT-UNIT-X-" + timestamp;
+ String keyPrefix2 = "BATCH-PUT-UNIT-Y-" + timestamp;
+ String keyPrefix3 = "BATCH-PUT-UNIT-Z-" + timestamp;
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_1, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_2, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_3, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_1, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_2, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_3, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_1, keyPrefix3, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_2, keyPrefix3, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_3, keyPrefix3, 1000);
+ }
+
+ // @Test
+ //CAUTION: ONLY FOR LONG!
+ //注意:目前只可以对long类型value进行Merge操作。
+ public void merge() {
+ System.out.println("--- test merge (1+1=2)---");
+ HgStoreSession session = getStoreSession();
+ String mergeKey = "merge-key";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(mergeKey);
+ byte[] value = HgStoreTestUtil.toBytes(1L);
+
+ System.out.println("- put " + mergeKey + ":1 -");
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ System.out.println("- merge " + mergeKey + ":1 -");
+ session.merge(HgStoreTestUtil.TABLE_NAME, key, value);
+ long res = HgStoreTestUtil.toLong(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.printf("after merge " + mergeKey + "=%s%n", res);
+ Assert.assertEquals(2L, res);
+
+ String putStr = "19";
+ session.put(HgStoreTestUtil.TABLE_NAME, key, HgStoreTestUtil.toBytes(putStr));
+ byte[] b1 = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ Assert.assertEquals(putStr, HgStoreTestUtil.toStr(b1));
+ }
+
+ // @Test
+ public void delete() {
+ System.out.println("--- test delete ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-key";
+ String delValue = "del-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put " + delKey + ": " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ HgStoreTestUtil.println("- delete " + delKey);
+ session.delete(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println("- get " + delKey + ": " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(EMPTY_BYTES, value);
+ }
+
+ // @Test
+ public void deleteSingle() {
+ System.out.println("--- test deleteSingle ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-single-key";
+ String delValue = "del-single-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put [" + delKey + "] = " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- before del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(delValue, HgStoreTestUtil.toStr(value));
+
+ HgStoreTestUtil.println("- delete-single : [" + delKey + "]");
+ session.deleteSingle(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- after del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals("", HgStoreTestUtil.toStr(value));
+
+ }
+
+ // @Test
+ public void deleteRange() {
+ HgStoreTestUtil.println("--- test deleteRange ---");
+ HgStoreSession session = getStoreSession();
+
+ String rangePrefix = "DEL-RANGE-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, rangePrefix, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ HgOwnerKey startKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-00");
+ HgOwnerKey endKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-05");
+
+ Assert.assertTrue(session.deleteRange(HgStoreTestUtil.TABLE_NAME, startKey, endKey));
+
+ HgStoreTestUtil.println("- after delete range from ["
+ + HgStoreTestUtil.toStr(startKey.getKey())
+ + "] to ["
+ + HgStoreTestUtil.toStr(endKey.getKey()) + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-" +
+ HgStoreTestUtil.padLeftZeros(
+ String.valueOf(i), 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ HgStoreTestUtil.println(
+ "- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+
+ // TODO: [start,end)?
+ if (i < 5) {
+ Assert.assertEquals("", value);
+ } else {
+ //println(value);
+ Assert.assertNotEquals("", value);
+ }
+ }
+
+ }
+
+ // @Test
+ public void deletePrefix() {
+ System.out.println("--- test deletePrefix ---");
+ HgStoreSession session = getStoreSession();
+
+ String prefixStr = "DEL-PREFIX-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, prefixStr, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ //printOwner(map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
+
+ HgOwnerKey prefix = HgStoreTestUtil.toOwnerKey(owner, prefixStr);
+
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+ session.deletePrefix(HgStoreTestUtil.TABLE_NAME, prefix);
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+
+ HgStoreTestUtil.println("- after delete by prefix:[" + prefixStr + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, prefixStr + HgStoreTestUtil.toSuffix(i, 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.println("- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+ Assert.assertEquals("", value);
+ }
+
+ }
+// // @Test
+// public void batchDeleteOwner() {
+// System.out.println("--- test batchDelete ---");
+// HgStoreSession session = getStoreSession();
+// String batchPrefix = "DEL-BATCH-KEY";
+// batchPut(session, batchPrefix, 10);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(batchPrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// Assert.assertNotEquals("", value);
+// }
+//
+// Set keys = new HashSet<>();
+// for (int i = 0; i < 5; i++) {
+// keys.add(toOwnerKey(batchPrefix + toSuffix(i, 2)));
+// }
+//
+// Map> map = new HashMap<>(1);
+// map.put(TABLE_NAME, keys);
+// session.batchDeleteOwner(map);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(batchPrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// // TODO: [,)?
+// if (i < 5) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+// }
+
+// // @Test
+// public void batchDeleteRangeOwner() {
+// System.out.println("--- test batchDeleteRange ---");
+// HgStoreSession session = getStoreSession();
+// String rangePrefix = "DEL-RANGE-KEY";
+// String owner="batch-delete-owner";
+//
+// batchPut(session, TABLE_NAME,rangePrefix, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+// batchPut(session, TABLE_NAME2, rangePrefix, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+//
+// HgOwnerKey startKey1 = toOwnerKey(owner,rangePrefix + "-03");
+// HgOwnerKey endKey1 = toOwnerKey(owner,rangePrefix + "-05");
+//
+// HgOwnerKey startKey2 = toOwnerKey(owner,rangePrefix + "-06");
+// HgOwnerKey endKey2 = toOwnerKey(owner,rangePrefix + "-09");
+//
+// Map> map = new HashMap<>();
+// map.put(TABLE_NAME, new HgPair<>(startKey1, endKey1));
+// map.put(TABLE_NAME2, new HgPair<>(startKey2, endKey2));
+//
+// session.batchDeleteRangeOwner(map);
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(owner,rangePrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+//
+// if (i >= 3 && i < 5) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+//
+// for (int i = 0; i < 10; i++) {
+// HgOwnerKey key = toOwnerKey(owner,rangePrefix + toSuffix(i, 2));
+// String value = toStr(session.get(TABLE_NAME2, key));
+// println("- get [" + toStr(key.getKey()) + "] = " + value);
+// if (i >= 6 && i < 9) {
+// Assert.assertEquals("", value);
+// } else {
+// Assert.assertNotEquals("", value);
+// }
+//
+// }
+// }
+
+// // @Test
+// public void batchDeletePrefix() {
+// System.out.println("--- test batchDeletePrefix ---");
+// HgStoreSession session = getStoreSession();
+// String batchKey1 = "DEL-PREFIX-BATCH-1-KEY";
+// String batchKey2 = "DEL-PREFIX-BATCH-2-KEY";
+// String owner="batch-delete-owner";
+//
+// batchPut(session, TABLE_NAME, batchKey1, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+// batchPut(session, TABLE_NAME2, batchKey2, 10,key->{
+// return toOwnerKey(owner,key);
+// });
+//
+// HgOwnerKey prefix1 = toOwnerKey(owner,batchKey1);
+// HgOwnerKey prefix2 = toOwnerKey(owner,batchKey2);
+//
+// Set set = new HashSet<>();
+//
+// set.add(prefix1);
+// set.add(prefix2);
+//
+// Map> map = new HashMap<>();
+// map.put(TABLE_NAME, set);
+// map.put(TABLE_NAME2, set);
+//
+// Assert.assertEquals(10, amountOf(session.scanIterator(TABLE_NAME, prefix1)));
+// Assert.assertEquals(10, amountOf(session.scanIterator(TABLE_NAME2, prefix2)));
+//
+// session.batchDeletePrefixOwner(map);
+//
+// Assert.assertEquals(0, amountOf(session.scanIterator(TABLE_NAME, prefix1)));
+// Assert.assertEquals(0, amountOf(session.scanIterator(TABLE_NAME2, prefix2)));
+//
+// }
+
+ // @Test
+ public void scanIterator() {
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = "UNIT_SCAN";
+ String keyName = "SCAN-ITER";
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 10000);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ HgStoreTestUtil.println("-- test 0 element --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey("__SCAN-001"),
+ HgStoreTestUtil.toAllPartitionKey("__SCAN-100"), 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ Assert.assertEquals(limit, count);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 not enough --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00001"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00005"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+
+ }
+
+ HgStoreTestUtil.println("-- test limit 0 (no limit) --");
+ limit = 0;
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan all --");
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan prefix --");
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-01"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(1000, count);
+ }
+
+ // @Test
+ public void paging() {
+ HgStoreTestUtil.println("--- test scanIterator_range ---");
+ String graph = "UNIT/paging";
+ String tableName = "UNIT_SCAN_PAGING";
+ String keyName = "SCAN-PAGING";
+ int keyAmt = 100;
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ count = 0;
+
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-000")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+ //HgStoreTestUtil.println(iterator);
+ // Assert.assertEquals(100, HgStoreTestUtil.amountOf(iterator));
+ List positionList = new LinkedList<>();
+ while (iterator.hasNext()) {
+ HgStoreTestUtil.print((count++) + " ");
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.print(entry);
+ HgStoreTestUtil.print(" " + Arrays.toString(iterator.position()) + "\n");
+ positionList.add(iterator.position());
+ if (count >= max) break;
+ }
+
+
+/* iterator = session.scanIterator(tableName
+ , toAllPartitionKey(keyName + "-000")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+
+ byte[] position=positionList.get(50);
+ println("seek: "+Arrays.toString(position));
+ iterator.seek(position);
+ //HgStoreTestUtil.println(iterator);
+ Assert.assertEquals(50, HgStoreTestUtil.amountOf(iterator));*/
+
+ iterator = session.scanIterator(tableName, 100);
+
+ byte[] position = positionList.get(50);
+ HgStoreTestUtil.println("seek: " + Arrays.toString(position));
+ iterator.seek(position);
+ HgStoreTestUtil.println(iterator);
+ //Assert.assertEquals(50, HgStoreTestUtil.amountOf(iterator));
+
+ }
+
+ // @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String graph = "graph_truncate";
+ String tableName = "UNIT_TRUNCATE_1";
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ String tableName2 = "UNIT_TRUNCATE_2";
+ HgStoreTestUtil.batchPut(session, tableName2, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+ }
+
+ //// @Test
+ public void scanIteratorHuge() {
+
+ /*************** test no limit, with 10 millions **************/
+ String tableName = "UNIT_HUGE";
+ String keyName = "SCAN-HUGE";
+ int amount = 10_000_000;
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 10)) <
+ 10) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ int count = 0;
+ HgKvIterator iterator = session.scanIterator(tableName);
+
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % (amount / 10) == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ }
+
+ Assert.assertEquals(amount, count);
+ }
+
+
+ // @Test
+ public void scanTable() {
+ HgStoreSession session = getStoreSession("DEFAULT/hg1/g");
+ HgStoreTestUtil.println(session.scanIterator("g+v", 10));
+
+
+ }
+
+ // @Test
+ public void testDelGraph() {
+ HgStoreSession session = getStoreSession();
+ session.deleteGraph(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ // @Test
+ public void benchmark_scanBatch() {
+ HgStoreTestUtil.println("--- Benchmark scanBatch ---");
+ String tableName = "Benchmark_SCAN_BATCH";
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 30001;
+
+ HgStoreSession session = getStoreSession();
+
+ /*if (amountOf(session.scanIterator(tableName, toAllPartitionKey(keyName), 1)) < 1) {
+ batchPut(session, tableName, keyName, keyAmt);
+ }*/
+ HgStoreTestUtil.println("-- Starting scan --");
+ MetricX metrics = MetricX.ofStart();
+ //HgStoreTestUtil.println(session.scanIterator(tableName));
+ List> iterators = session.scanBatch(HgScanQuery.tableOf(tableName));
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountIn(iterators));
+ metrics.end();
+ log.info("*************************************************");
+ log.info("*********** Batch Scan Completed **************");
+ log.info("Total : {} (sec)", metrics.past() / 1000);
+ log.info(" Sum : {} (sec)", MetricX.getIteratorWait() / 1000);
+ log.info(" Amt : {} (scans).", MetricX.getIteratorCount());
+ log.info(" Avg : {} (ms)", MetricX.getIteratorWaitAvg());
+ log.info(" Max : {} (ms)", MetricX.getIteratorWaitMax());
+ log.info(" Fail : {} (times)", metrics.getFailureCount());
+ log.info(" Page : {} (KVs)", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("Iters : {}", iterators.size());
+ log.info("*************************************************");
+
+ }
+
+ @Test
+ public void benchmark_scanBatch2() throws IOException {
+ HgStoreTestUtil.println("--- Benchmark scanBatch2 ---");
+ //String tableName = TABLE_NAME;
+ HgStoreSession session = getStoreSession();
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 3000;
+
+ Map data =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, keyName, keyAmt,
+ //(key) -> toOwnerKey(key.substring(0, keyName.length()
+ // + 2), key)
+ (key) -> HgStoreTestUtil.toOwnerKey(0, key)
+ );
+
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME2, keyName, keyAmt,
+ //(key) -> toOwnerKey(key.substring(0, keyName.length() + 2), key)
+ (key) -> HgStoreTestUtil.toOwnerKey(0, key)
+ );
+
+ MetricX metrics = MetricX.ofStart();
+ long t = System.currentTimeMillis();
+ int count = 0;
+ String queryTable = null;
+ KvCloseableIterator> iterators = null;
+ List queryKeys = null;
+ List keys = new ArrayList<>();
+ data.forEach((k, v) -> keys.add(k));
+
+ List prefixKeys = new ArrayList<>();
+ prefixKeys.add(HgStoreTestUtil.toOwnerKey(0, keyName + "-0"));
+ prefixKeys.add(HgStoreTestUtil.toOwnerKey(0, keyName + "-1"));
+ prefixKeys.add(HgStoreTestUtil.toOwnerKey(0, keyName + "-2"));
+ prefixKeys.add(HgStoreTestUtil.toOwnerKey(0, keyName + "-3"));
+
+ HgStoreTestUtil.println("-- test every key, one table --");
+ count = 0;
+ queryTable = HgStoreTestUtil.TABLE_NAME;
+ queryKeys = keys;
+ iterators = session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(queryTable, queryKeys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder()
+ .setScanType(0x40)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ iterators.close();
+ Assert.assertEquals(keyAmt, count);
+ log.info(" size is {}", count);
+
+ HgStoreTestUtil.println("-- test prefix key, one table --");
+ count = 0;
+ queryTable = HgStoreTestUtil.TABLE_NAME;
+ queryKeys = prefixKeys;
+ iterators = session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(queryTable, queryKeys.iterator(),
+ ScanOrderType.ORDER_STRICT)
+ .builder()
+ .setScanType(0x40)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ iterators.close();
+ Assert.assertEquals(keyAmt, count);
+ log.info(" size is {}", count);
+
+ HgStoreTestUtil.println("-- test prefix key, two table --");
+ count = 0;
+ queryTable = HgStoreTestUtil.TABLE_NAME + "," + HgStoreTestUtil.TABLE_NAME2;
+ queryKeys = prefixKeys;
+ iterators = session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(queryTable, queryKeys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder()
+ .setScanType(0x40)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ iterators.close();
+ Assert.assertEquals(keyAmt * 2, count);
+ log.info(" size is {}", count);
+
+ HgStoreTestUtil.println("-- test prefix key, two table, perKeyMax --");
+ count = 0;
+ queryTable = HgStoreTestUtil.TABLE_NAME + "," + HgStoreTestUtil.TABLE_NAME2;
+ queryKeys = prefixKeys;
+ queryKeys.remove(queryKeys.size() - 1);//remove the last one.
+ iterators = session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(queryTable, queryKeys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder()
+ .setScanType(0x40)
+ .setPerKeyMax(10)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ iterators.close();
+ Assert.assertEquals(queryKeys.size() * 10, count);
+ log.info(" size is {}", count);
+
+ keys.clear();
+
+ log.info("time is {}", System.currentTimeMillis() - t);
+ metrics.end();
+ log.info("*************************************************");
+ log.info("*********** Batch Scan Completed **************");
+ log.info("Total : {} (sec)", metrics.past() / 1000);
+ log.info(" Sum : {} (sec)", MetricX.getIteratorWait() / 1000);
+ log.info(" Amt : {} (scans).", MetricX.getIteratorCount());
+ log.info(" Avg : {} (ms)", MetricX.getIteratorWaitAvg());
+ log.info(" Max : {} (ms)", MetricX.getIteratorWaitMax());
+ log.info(" Fail : {} (times)", metrics.getFailureCount());
+ log.info(" Page : {} (KVs)", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info(" size is {}", count);
+ log.info("*************************************************");
+
+
+ }
+
+ // @Test
+ public void benchmark_scanBatch_SkipDegree() throws IOException {
+ HgStoreTestUtil.println("--- Benchmark scanBatch2 1Owner---");
+ String tableName = HgStoreTestUtil.TABLE_NAME;
+ HgStoreSession session = getStoreSession();
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 300000;
+ byte[] owner = "Owner".getBytes();
+ Map data =
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt, key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+ HgStoreTestUtil.println("-- Starting scan --");
+ MetricX metrics = MetricX.ofStart();
+ //HgStoreTestUtil.println(session.scanIterator(tableName));
+ long t = System.currentTimeMillis();
+ int count = 0;
+ {
+ List keys = new ArrayList<>();
+ keys.add(HgStoreTestUtil.toOwnerKey(owner, keyName));
+
+ KvCloseableIterator> iterators =
+ session.scanBatch2(HgScanQuery.prefixIteratorOf(tableName, keys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder().setScanType(0x40).setSkipDegree(1)
+ .build());
+ //KvCloseableIterator> iterators = session.scanBatch2(HgScanQuery
+ // .tableOf(tableName));
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+// while (iterator.hasNext()){
+// System.out.println(new String(iterator.next().key()));
+// }
+ count += HgStoreTestUtil.amountOf(iterator);
+ // log.info("{} - {}", new String(iterator.key()), iterator.value());
+ }
+ keys.clear();
+ iterators.close();
+ iterators = null;
+ }
+ log.info("time is {}", System.currentTimeMillis() - t);
+ metrics.end();
+ log.info("*************************************************");
+ log.info("*********** Batch Scan Completed **************");
+ log.info("Total : {} (sec)", metrics.past() / 1000);
+ log.info(" Sum : {} (sec)", MetricX.getIteratorWait() / 1000);
+ log.info(" Amt : {} (scans).", MetricX.getIteratorCount());
+ log.info(" Avg : {} (ms)", MetricX.getIteratorWaitAvg());
+ log.info(" Max : {} (ms)", MetricX.getIteratorWaitMax());
+ log.info(" Fail : {} (times)", metrics.getFailureCount());
+ log.info(" Page : {} (KVs)", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info(" size is {}", count);
+ log.info("*************************************************");
+
+
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java
new file mode 100644
index 0000000000..9a63ce74ff
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java
@@ -0,0 +1,1125 @@
+/*
+ * 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.hugegraph.store;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.ALL_PARTITION_OWNER;
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import org.apache.hugegraph.pd.common.PartitionUtils;
+import org.apache.hugegraph.store.client.HgStoreNodeManager;
+import org.apache.hugegraph.store.client.util.ExecutorPool;
+import org.apache.hugegraph.store.client.util.HgStoreClientConfig;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.client.util.MetricX;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class HgSessionManagerTest {
+ private static final Map leaderMap = new ConcurrentHashMap<>();
+ private static final Map storeMap = new ConcurrentHashMap<>();
+
+ private static final ExecutorService pool = Executors.newFixedThreadPool(100,
+ ExecutorPool.newThreadFactory(
+ "unit-test"));
+
+ private static final int partitionCount = 10;
+ // 需要与 store 的 application.yml 的 fake-pd.partition-count 保持一致
+
+ //private static String[] storeAddress = {"127.0.0.1:8500"};
+ private static final String[] storeAddress =
+ {"127.0.0.1:8501", "127.0.0.1:8502", "127.0.0.1:8503"};
+
+ private static final int PARTITION_LENGTH = getPartitionLength();
+
+ private static int getPartitionLength() {
+ return PartitionUtils.MAX_VALUE /
+ (partitionCount == 0 ? storeAddress.length : partitionCount) + 1;
+ }
+
+ @BeforeClass
+ public static void init() {
+ for (String address : storeAddress) {
+ storeMap.put((long) address.hashCode(), address);
+ }
+ for (int i = 0; i < partitionCount; i++) {
+ leaderMap.put(i, storeMap.keySet().iterator().next());
+ }
+
+ HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ nodeManager.setNodePartitioner((builder, graphName, startKey, endKey) -> {
+ int startCode = PartitionUtils.calcHashcode(startKey);
+ int endCode = PartitionUtils.calcHashcode(endKey);
+ if (ALL_PARTITION_OWNER == startKey) {
+ storeMap.forEach((k, v) -> {
+ builder.add(k, -1);
+ });
+ } else if (endKey == HgStoreClientConst.EMPTY_BYTES || startKey == endKey ||
+ Arrays.equals(startKey, endKey)) {
+ //log.info("leader-> {}",leaderMap.get(startCode / PARTITION_LENGTH));
+ builder.add(leaderMap.get(startCode / PARTITION_LENGTH), startCode);
+ } else {
+ Assert.fail("OwnerKey 转成 HashCode 后已经无序了,按照 OwnerKey 范围查询没意义");
+ builder.add(leaderMap.get(startCode / PARTITION_LENGTH), startCode);
+ builder.add(leaderMap.get(endCode / PARTITION_LENGTH), endCode);
+ }
+ return 0;
+ });
+ nodeManager.setNodeProvider((graphName, nodeId) -> {
+ // System.out.println("HgStoreNodeProvider apply " + graphName + " " + nodeId +
+ // " " + storeMap.get(nodeId));
+ return nodeManager.getNodeBuilder().setNodeId(nodeId)
+ .setAddress(storeMap.get(nodeId)).build();
+ });
+ nodeManager.setNodeNotifier((graphName, storeNotice) -> {
+ System.out.println("recv node notifier " + storeNotice);
+ if (storeNotice.getPartitionLeaders().size() > 0) {
+ leaderMap.putAll(storeNotice.getPartitionLeaders());
+ System.out.println("leader changed ");
+ leaderMap.forEach((k, v) -> {
+ System.out.print(" " + k + " " + v + ",");
+ });
+ System.out.println();
+ }
+ return 0;
+ });
+ }
+
+ protected static HgStoreSession getStoreSession() {
+ return HgSessionManager.getInstance().openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ protected static HgStoreSession getStoreSession(String graph) {
+ return HgSessionManager.getInstance().openSession(graph);
+ }
+
+ @Test
+ public void put_get() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession();
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ //HgOwnerKey key = toAllNodeKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(HgStoreTestUtil.TABLE_NAME, key, value));
+ Assert.assertEquals(HgStoreTestUtil.toStr(value), HgStoreTestUtil.toStr(session.get(
+ HgStoreTestUtil.TABLE_NAME, key)));
+ }
+
+ @Test
+ public void batchPrefix() {
+ System.out.println("--- test batchGet ---");
+ HgStoreSession session = getStoreSession();
+ String keyPrefix = "UNIT-BATCH-GET";
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix);
+ List keyList =
+ map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList());
+
+ Map keyMap = new HashMap<>();
+ map.entrySet().forEach(e -> {
+ keyMap.put(Arrays.toString(e.getKey().getKey()), e.getValue());
+ });
+
+ //printOwner(keyList);
+ HgKvIterator iterator = session.batchPrefix(HgStoreTestUtil.TABLE_NAME, keyList);
+ int amount = HgStoreTestUtil.println(iterator);
+ Assert.assertEquals(amount, keyList.size());
+/*
+
+ println("--- batch-get result ---");
+ iterator = session.batchGet(TABLE_NAME, keyList);
+ while(iterator.hasNext()){
+ HgKvEntry kv=iterator.next();
+ Assert.assertEquals(true,keyMap.containsKey(Arrays.toString(kv.key())));
+ }
+*/
+
+ }
+
+ @Test
+ //CAUTION: ONLY FOR LONG!
+ //注意:目前只可以对 long 类型 value 进行 Merge 操作。
+ public void merge() {
+ System.out.println("--- test merge (1+1=2)---");
+ HgStoreSession session = getStoreSession();
+ String mergeKey = "merge-key";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(mergeKey);
+ byte[] value = HgStoreTestUtil.toBytes(1L);
+
+ System.out.println("- put " + mergeKey + ":1 -");
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ System.out.println("- merge " + mergeKey + ":1 -");
+ session.merge(HgStoreTestUtil.TABLE_NAME, key, value);
+ long res = HgStoreTestUtil.toLong(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.printf("after merge " + mergeKey + "=%s%n", res);
+ Assert.assertEquals(2L, res);
+
+ String putStr = "19";
+ session.put(HgStoreTestUtil.TABLE_NAME, key, HgStoreTestUtil.toBytes(putStr));
+ byte[] b1 = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ Assert.assertEquals(putStr, HgStoreTestUtil.toStr(b1));
+ }
+
+ @Test
+ public void delete() {
+ System.out.println("--- test delete ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-key";
+ String delValue = "del-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put " + delKey + ": " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+ HgStoreTestUtil.println("- delete " + delKey);
+ session.delete(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println("- get " + delKey + ": " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(EMPTY_BYTES, value);
+ }
+
+ // @Test
+ public void deleteSingle() {
+ System.out.println("--- test deleteSingle ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-single-key";
+ String delValue = "del-single-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put [" + delKey + "] = " + delValue);
+ session.put(HgStoreTestUtil.TABLE_NAME, key, value);
+
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- before del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(delValue, HgStoreTestUtil.toStr(value));
+
+ HgStoreTestUtil.println("- delete-single : [" + delKey + "]");
+ session.deleteSingle(HgStoreTestUtil.TABLE_NAME, key);
+ value = session.get(HgStoreTestUtil.TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- after del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals("", HgStoreTestUtil.toStr(value));
+
+ }
+
+ // @Test
+ public void deleteRange() {
+ HgStoreTestUtil.println("--- test deleteRange ---");
+ HgStoreSession session = getStoreSession();
+
+ String rangePrefix = "DEL-RANGE-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, rangePrefix, 10,
+ key -> HgStoreTestUtil.toOwnerKey(owner, key)
+ );
+
+ HgOwnerKey startKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-00");
+ HgOwnerKey endKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-05");
+
+ Assert.assertTrue(session.deleteRange(HgStoreTestUtil.TABLE_NAME, startKey, endKey));
+
+ HgStoreTestUtil.println("- after delete range from ["
+ + HgStoreTestUtil.toStr(startKey.getKey()) + "] to ["
+ + HgStoreTestUtil.toStr(endKey.getKey()) + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-" +
+ HgStoreTestUtil.padLeftZeros(
+ String.valueOf(i), 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ HgStoreTestUtil.println(
+ "- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+
+ // TODO: [start,end)?
+ if (i < 5) {
+ Assert.assertEquals("", value);
+ } else {
+ //println(value);
+ Assert.assertNotEquals("", value);
+ }
+ }
+
+ }
+
+ // @Test
+ public void deletePrefix() {
+ System.out.println("--- test deletePrefix ---");
+ HgStoreSession session = getStoreSession();
+
+ String prefixStr = "DEL-PREFIX-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(session, HgStoreTestUtil.TABLE_NAME, prefixStr, 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ //printOwner(map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
+
+ HgOwnerKey prefix = HgStoreTestUtil.toOwnerKey(owner, prefixStr);
+
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+ session.deletePrefix(HgStoreTestUtil.TABLE_NAME, prefix);
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(
+ HgStoreTestUtil.TABLE_NAME, prefix)));
+
+ HgStoreTestUtil.println("- after delete by prefix:[" + prefixStr + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, prefixStr + HgStoreTestUtil.toSuffix(i, 2));
+ String value = HgStoreTestUtil.toStr(session.get(HgStoreTestUtil.TABLE_NAME, key));
+ System.out.println("- get [" + HgStoreTestUtil.toStr(key.getKey()) + "] = " + value);
+ Assert.assertEquals("", value);
+ }
+
+ }
+
+ // @Test
+ public void scan() {
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = "UNIT_SCAN_ITERATOR";
+ String keyName = "SCAN-ITER";
+ int keyAmt = 100;
+
+ HgStoreSession session = getStoreSession();
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 10)) <
+ 10) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ // println("-- test scan all --");
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 10 == 0) {
+ // println(entry);
+ }
+ if (count >= max) break;
+ }
+ iterator.close();
+ Assert.assertEquals(keyAmt, count);
+
+ // println("-- test 0 element --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey("__SCAN-001"),
+ HgStoreTestUtil.toAllPartitionKey("__SCAN-100"), 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ // println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+ iterator.close();
+
+ // println("-- test limit 1 to 10 --");
+ for (int i = 1; i <= 10; i++) {
+ // println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"),
+ limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ // println(entry);
+ }
+ iterator.close();
+ Assert.assertEquals(limit, count);
+ }
+
+ // println("-- test limit 1 to 10 not enough --");
+ for (int i = 1; i <= 10; i++) {
+ // println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-001")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-005"), limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ // println(entry);
+ }
+ iterator.close();
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+
+ }
+
+ // println("-- test limit 0 (no limit) --");
+ limit = 0;
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-2"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 10 == 0) {
+ // println(entry);
+ }
+ if (count >= max) break;
+ }
+ iterator.close();
+ Assert.assertEquals(keyAmt, count);
+
+ // println("-- test scan prefix --");
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 10 == 0) {
+ // println(entry);
+ }
+ if (count >= max) break;
+ }
+ iterator.close();
+ Assert.assertEquals(keyAmt, count);
+
+ // println("-- test scan via hash code --");
+ iterator = session.scanIterator(tableName, 0, 65535, HgKvStore.SCAN_HASHCODE, EMPTY_BYTES);
+ count = 0;
+
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 10 == 0) {
+ // println(entry);
+ }
+ if (count >= max) break;
+ }
+ iterator.close();
+ Assert.assertEquals(keyAmt, count);
+
+ // println("-- test range limit scan type --");
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey("WWWWWWW")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+ iterator.close();
+ // println("-- test range limit scan type -session.scanIterator over--");
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(iterator));
+ // println("-- test range limit scan type -session.assertEquals over--");
+
+ // println("-- test range limit scan type -100");
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-100")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+
+ // println("-- test range limit scan type -100 over");
+ Assert.assertEquals(1, HgStoreTestUtil.amountOf(iterator));
+ // println("-- test range limit scan type -100 assertEquals 1");
+
+ // println("-- test range limit scan type -51 ");
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-051")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ );
+
+ // println("-- test range limit scan type -51 over");
+ //HgStoreTestUtil.println(iterator);
+ Assert.assertEquals(50, HgStoreTestUtil.amountOf(iterator));
+ // println("-- test range limit scan type -51 assertEquals");
+ //TODO: add more...
+ HgStoreTestUtil.println("-- test scanIterator end");
+ }
+
+ // @Test
+ public void scan_close() {
+ /*************** test scan close **************/
+ HgStoreTestUtil.println("--- test scan close ---");
+ String tableName = "UNIT_ITER_CLOSE";
+ String keyName = "UNIT_ITER_CLOSE";
+
+ int amount = 1_000_000;
+ HgStoreSession session = getStoreSession();
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ HgKvIterator iterator = null;
+
+ /* server over, all -> close */
+ iterator = session.scanIterator(tableName);
+ Assert.assertEquals(amount, HgStoreTestUtil.amountOf(iterator));
+
+ /* server over, one page, all -> close */
+ iterator = session.scanIterator(tableName, 100_000);
+ Assert.assertEquals(100_000, HgStoreTestUtil.amountOf(iterator));
+
+ /* server over, two page, all -> close */
+ iterator = session.scanIterator(tableName, 200_000);
+ Assert.assertEquals(200_000, HgStoreTestUtil.amountOf(iterator));
+
+ /* server not over, enough -> close */
+ iterator = session.scanIterator(tableName);
+ iterator.next();
+ iterator.close();
+
+ /* server not over, one page, enough -> close */
+ iterator = session.scanIterator(tableName, 100_000);
+ iterator.next();
+ iterator.close();
+
+ /* server not over, two page, enough -> close */
+ iterator = session.scanIterator(tableName, 200_000);
+ iterator.next();
+ iterator.close();
+
+ /* server not over, enough -> close */
+ iterator = session.scanIterator(tableName);
+ iterator.next();
+ iterator.close();
+ iterator = session.scanIterator(tableName);
+ for (int i = 0; iterator.hasNext() && i < 500_000; i++) {
+ iterator.next();
+ }
+ iterator.close();
+
+ /* server timeout, enough -> close */
+ iterator = session.scanIterator(tableName);
+ iterator.next();
+ // HgStoreTestUtil.sleeping(11000);
+
+ try {
+ HgStoreTestUtil.amountOf(iterator);
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- passed server waiting timeout --");
+ }
+
+ iterator.close();
+
+ }
+
+ // @Test
+ public void paging() {
+ HgStoreTestUtil.println("--- test scanIterator_range ---");
+ String graph = "UNIT/paging";
+ String tableName = "UNIT_SCAN_PAGING";
+ String keyName = "SCAN-PAGING";
+ int keyAmt = 100;
+ HgStoreSession session = getStoreSession(graph);
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ count = 0;
+
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-000")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+ //HgStoreTestUtil.println(iterator);
+ // Assert.assertEquals(100, HgStoreTestUtil.amountOf(iterator));
+ List positionList = new LinkedList<>();
+ while (iterator.hasNext()) {
+ HgStoreTestUtil.print((count++) + " ");
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.print(entry);
+ HgStoreTestUtil.print(" " + Arrays.toString(iterator.position()) + "\n");
+ positionList.add(iterator.position());
+ if (count >= max) break;
+ }
+
+
+ iterator = session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-000")
+ , HgStoreClientConst.EMPTY_OWNER_KEY
+ , 0, HgKvStore.SCAN_ANY, EMPTY_BYTES
+ );
+
+ byte[] position = positionList.get(50);
+ HgStoreTestUtil.println("seek: " + Arrays.toString(position));
+ iterator.seek(position);
+ //println("amt after seek: "+HgStoreTestUtil.println(iterator));
+ Assert.assertEquals(50, HgStoreTestUtil.amountOf(iterator));
+
+ }
+
+ @Test
+ public void scanBatch() {
+ HgStoreTestUtil.println("--- test scanBatch ---");
+ String tableName = "UNIT_SCAN_BATCH_1";
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 10_000;
+
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName),
+ keyAmt)) < keyAmt) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ List> iterators = null;
+ List prefixes = null;
+
+ List startList = Arrays.asList(
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-001")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-003")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-005")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-007")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-009")
+ );
+
+ List endList = Arrays.asList(
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-002")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-004")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-006")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-008")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-010")
+ );
+
+ List prefixList = Arrays.asList(
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-001")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-002")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-003")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-004")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-005")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-006")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-007")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-008")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-009")
+ );
+
+ HgStoreTestUtil.println("-- test scan-batch all --");
+
+ HgScanQuery scanQuery = HgScanQuery.tableOf(tableName);
+ iterators = session.scanBatch(scanQuery);
+ Assert.assertEquals(3, iterators.size());
+
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.println(iterators));
+
+ HgStoreTestUtil.println("-- test scan-batch prefix --");
+
+
+ iterators = session.scanBatch(
+ HgScanQuery.prefixOf(tableName, prefixList)
+ );
+ Assert.assertEquals(3, iterators.size());
+ Assert.assertEquals(900,
+ iterators.parallelStream().mapToInt(e -> HgStoreTestUtil.amountOf(e))
+ .sum()
+ );
+
+ HgStoreTestUtil.println("-- test scan-batch range --");
+
+ iterators = session.scanBatch(HgScanQuery.rangeOf(tableName, startList, endList));
+ Assert.assertEquals(3, iterators.size());
+ Assert.assertEquals(
+ HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-001")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-010")
+ )
+ )
+ ,
+ iterators.parallelStream().mapToInt(e -> HgStoreTestUtil.amountOf(e)).sum()
+ );
+
+ HgStoreTestUtil.println("-- test scan-batch limit --");
+
+ int limit = 1;
+ iterators = session.scanBatch(
+ HgScanQuery.rangeOf(tableName, startList, endList)
+ .builder()
+ .setLimit(limit)
+ .build()
+ );
+
+ //HgStoreTestUtil.println(iterators);
+ Assert.assertEquals(iterators.size() * limit,
+ iterators.parallelStream().mapToInt(e -> HgStoreTestUtil.amountOf(e))
+ .sum()
+ );
+
+ HgStoreTestUtil.println("-- test scan-batch multi-table --");
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator("g+oe", HgStoreTestUtil.toAllPartitionKey(keyName), keyAmt)) <
+ keyAmt) {
+ HgStoreTestUtil.batchPut(session, "g+oe", keyName, keyAmt);
+ HgStoreTestUtil.batchPut(session, "g+ie", keyName, keyAmt);
+ }
+
+ prefixes = Collections.singletonList(HgStoreTestUtil.toAllPartitionKey(keyName));
+
+ tableName = "g+oe,g+ie";
+ iterators = session.scanBatch(
+ HgScanQuery.prefixOf(tableName, prefixes)
+ );
+
+ //HgStoreTestUtil.println(iterators);
+ Assert.assertEquals(keyAmt * 2, HgStoreTestUtil.amountIn(iterators));
+ iterators = session.scanBatch(
+ HgScanQuery.prefixOf(tableName, prefixList)
+ );
+ Assert.assertEquals(900 * 2, HgStoreTestUtil.amountIn(iterators));
+
+ HgStoreTestUtil.println("-- test scan-batch per-key-limit --");
+
+ tableName = "PER_KEY_LIMIT_TABLE";
+ keyName = "PER_KEY_LIMIT";
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName),
+ keyAmt)) < keyAmt) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+ prefixes = Arrays.asList(
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-01")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-02")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-03")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-04")
+ , HgStoreTestUtil.toAllPartitionKey(keyName + "-05")
+ );
+
+ iterators = session.scanBatch(
+ HgScanQuery.prefixOf(tableName, prefixes).builder().setPerKeyLimit(1).build()
+ );
+ //HgStoreTestUtil.println(iterators);
+ Assert.assertEquals(prefixes.size() * 3, HgStoreTestUtil.amountIn(iterators));
+
+ }
+
+ // @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String graph = "graph_truncate";
+ String tableName = "UNIT_TRUNCATE_1";
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ String tableName2 = "UNIT_TRUNCATE_2";
+ HgStoreTestUtil.batchPut(session, tableName2, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+ }
+
+ // @Test
+ public void handle_table() {
+ HgStoreTestUtil.println("--- test table ---");
+
+ String tableName = "UNIT_TABLE_" + System.currentTimeMillis();
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+ HgStoreSession session = getStoreSession();
+
+ HgStoreTestUtil.println("-- test createTable --");
+ session.createTable(tableName);
+ Assert.assertTrue(session.existsTable(tableName));
+
+ HgStoreTestUtil.println("-- test deleteTable --");
+ session.put(tableName, key, value);
+ Assert.assertEquals(HgStoreTestUtil.toStr(value),
+ HgStoreTestUtil.toStr(session.get(tableName, key)));
+ session.deleteTable(tableName);
+ Assert.assertNotEquals(HgStoreTestUtil.toStr(value),
+ HgStoreTestUtil.toStr(session.get(tableName, key)));
+ Assert.assertTrue(session.existsTable(tableName));
+
+
+ HgStoreTestUtil.println("-- test dropTable --");
+ Assert.assertTrue(session.dropTable(tableName));
+ Assert.assertFalse(session.existsTable(tableName));
+
+
+ HgStoreTestUtil.println("-- test existsTable --");
+ Assert.assertFalse(session.existsTable(tableName));
+
+ }
+
+ // @Test
+ public void tx() {
+ HgStoreTestUtil.println("--- test tx ---");
+ HgStoreSession session = getStoreSession();
+ String tableName = "UNIT_TABLE_TX";
+ String keyPrefix = "TX";
+ int keyAmt = 100;
+
+ HgStoreTestUtil.println("-- unsupported tx operation --");
+ HgStoreTestUtil.println("- tx deleteTable -");
+ HgStoreTestUtil.batchPut(session, tableName, keyPrefix, keyAmt);
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ session.beginTx();
+ session.deleteTable(tableName);
+ session.commit();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ HgStoreTestUtil.println("- tx dropTable -");
+ HgStoreTestUtil.batchPut(session, tableName, keyPrefix, keyAmt);
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ session.beginTx();
+ session.dropTable(tableName);
+ session.commit();
+ Assert.assertFalse(session.existsTable(tableName));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ HgStoreTestUtil.println("- tx truncate -");
+ HgStoreTestUtil.batchPut(session, tableName, keyPrefix, keyAmt);
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ session.beginTx();
+ session.truncate();
+ session.commit();
+ Assert.assertFalse(session.existsTable(tableName));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ //TODO : add others
+ }
+
+ //// @Test
+ public void scanIterator_WithNonePartition() {
+ HgStoreTestUtil.println("--- test scanIterator with none partition ---");
+ int count = 0;
+ HgStoreSession session = getStoreSession();
+
+ for (int i = 0; i < 100; i++) {
+ HgKvIterator iterator = session.scanIterator("XXXXXXXX");
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ }
+
+ Assert.assertEquals(0, count);
+
+ }
+
+ //// @Test
+ public void repeatedly_parallel_scan() {
+ MetricX metrics = MetricX.ofStart();
+ HgStoreTestUtil.repeatedlyTest(100, () -> parallel_scan());
+ metrics.end();
+
+ log.info("*************************************************");
+ log.info("************* Scanning Completed **************");
+ log.info("Total: {} sec.", metrics.past() / 1000);
+ log.info("Sum: {} sec.", MetricX.getIteratorWait() / 1000);
+ log.info("Amt: {} scans.", MetricX.getIteratorCount());
+ log.info("Avg: {} ms.", MetricX.getIteratorWaitAvg());
+ log.info("Max: {} ms.", MetricX.getIteratorWaitMax());
+ log.info("Fail: {} times.", metrics.getFailureCount());
+ log.info("Page: {}", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("*************************************************");
+
+ // runWaiting();
+ }
+
+ // @Test
+ public void parallel_scan() {
+ HgStoreTestUtil.println("--- test scanIterator in parallel ---");
+ HgStoreTestUtil.parallelTest(100, () -> {
+ this.scan();
+ }, t -> t.printStackTrace());
+ }
+
+ //// @Test
+ public void put_Benchmark() {
+ /*************** Put Benchmark **************/
+ String tableName = "UNIT_PUT_BENCHMARK";
+ String keyPrefix = "PUT-BENCHMARK";
+ int amount = 1_000_000;
+ HgStoreSession session = getStoreSession();
+
+ int length = String.valueOf(amount).length();
+
+ session.beginTx();
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < amount; i++) {
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(
+ keyPrefix + "-" + HgStoreTestUtil.padLeftZeros(String.valueOf(i), length));
+ byte[] value = HgStoreTestUtil.toBytes(keyPrefix + "-V-" + i);
+
+ session.put(tableName, key, value);
+
+ if ((i + 1) % 100_000 == 0) {
+ HgStoreTestUtil.println("---------- " + (i + 1) + " --------");
+ HgStoreTestUtil.println(
+ "Preparing took: " + (System.currentTimeMillis() - start) + " ms.");
+ session.commit();
+ HgStoreTestUtil.println(
+ "Committing took: " + (System.currentTimeMillis() - start) + " ms.");
+ start = System.currentTimeMillis();
+ session.beginTx();
+ }
+ }
+
+ if (session.isTx()) {
+ session.commit();
+ }
+
+ Assert.assertEquals(amount, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+
+ }
+
+ //// @Test
+ public void put_Benchmark_Parallel() {
+ int threadsAmount = 100;
+ CountDownLatch countDownLatch = new CountDownLatch(threadsAmount);
+
+ for (int j = 0; j < threadsAmount; j++) {
+ for (int i = 0; i < threadsAmount; i++) {
+ pool.submit(() -> {
+ this.put_Benchmark();
+ // this.scanIterator_WithNonePartition();
+ countDownLatch.countDown();
+ });
+ }
+ }
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ //// @Test
+ public void parallel_scanBatch() {
+ int threadsAmount = 50;
+ CountDownLatch countDownLatch = new CountDownLatch(threadsAmount);
+
+ for (int j = 0; j < threadsAmount; j++) {
+ for (int i = 0; i < threadsAmount; i++) {
+ pool.submit(() -> {
+ try {
+ this.scanBatch();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ countDownLatch.countDown();
+ }
+ });
+ }
+ }
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ //// @Test
+ public void benchmark_scanBatch() {
+ HgStoreTestUtil.println("--- Benchmark scanBatch ---");
+ String tableName = "Benchmark_SCAN_BATCH";
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 10_000_000;
+
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+ HgStoreTestUtil.println("-- Starting scan --");
+ // while (true) {
+
+ MetricX metrics = MetricX.ofStart();
+ //HgStoreTestUtil.println(session.scanIterator(tableName));
+ List> iterators = session.scanBatch(HgScanQuery.tableOf(tableName));
+ //HgStoreTestUtil.println(iterators);
+ //Assert.assertEquals(keyAmt, HgStoreTestUtil.amountIn(iterators));
+ HgStoreTestUtil.amountIn(iterators);
+ metrics.end();
+ log.info("*************************************************");
+ log.info("*********** Batch Scan Completed **************");
+ log.info("Total : {} (sec)", metrics.past() / 1000);
+ log.info(" Sum : {} (sec)", MetricX.getIteratorWait() / 1000);
+ log.info(" Amt : {} (scans).", MetricX.getIteratorCount());
+ log.info(" Avg : {} (ms)", MetricX.getIteratorWaitAvg());
+ log.info(" Max : {} (ms)", MetricX.getIteratorWaitMax());
+ log.info(" Fail : {} (times)", metrics.getFailureCount());
+ log.info(" Page : {} (KVs)", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("Iters : {}", iterators.size());
+ log.info("*************************************************");
+ HgStoreTestUtil.sleeping(100);
+
+ // }
+ }
+
+ //// @Test
+ public void benchmark_scan() {
+ /*************** test no limit, with 10 millions **************/
+ String tableName = "UNIT_HUGE";
+ String keyName = "SCAN-HUGE";
+ int amount = 10_000_000;
+ int max = 10_000_000;
+ HgStoreSession session = getStoreSession();
+
+ /*Initialization*/
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ MetricX metricX = MetricX.ofStart();
+
+ int count = 0;
+ HgKvIterator iterator = session.scanIterator(tableName);
+ //HgStoreTestUtil.println(iterator, e -> (e % (amount / 100) == 0));
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % (amount / 10) == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+
+ metricX.end();
+
+ log.info("*************************************************");
+ log.info("************* Benchmark Completed *************");
+ log.info("Keys: {}", count);
+ log.info("Waiting: {} ms.", MetricX.getIteratorWait());
+ log.info("Total: {} ms.", metricX.past());
+ log.info("Iterator: [{}]", iterator.getClass().getSimpleName());
+ log.info("Page: {}", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("*************************************************");
+
+ Assert.assertEquals(amount, count);
+ }
+
+
+ //// @Test
+ public void extreme_scan_close() {
+ /*************** test close **************/
+ String tableName = "UNIT_ITER_CLOSE_EXTREME";
+ String keyName = "UNIT_ITER_CLOSE_EXTREME";
+ int amount = 1_000_000;
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+ HgKvIterator iterator = null;
+ /* server not over, enough, extreme -> close */
+ for (int i = 0; i <= 10_000; i++) {
+ iterator = session.scanIterator(tableName);
+ iterator.next();
+ iterator.close();
+ HgStoreTestUtil.println("extreme loop: " + i);
+ }
+ HgStoreTestUtil.runWaiting();
+ }
+
+ //// @Test
+ public void parallel_scan_close() {
+ HgStoreTestUtil.parallelTest(10, () -> this.scan_close(), t -> t.printStackTrace());
+ }
+
+ //// @Test
+ public void repeat_parallel_scan_close() {
+ HgStoreTestUtil.repeatedlyTest(1000, () -> this.parallel_scan_close());
+ HgStoreTestUtil.runWaiting();
+ }
+
+ //// @Test
+ public void parallel_huge_scan() {
+ int threadsAmount = 3;
+ CountDownLatch countDownLatch = new CountDownLatch(threadsAmount);
+ ExecutorService poll = Executors.newFixedThreadPool(threadsAmount);
+
+ for (int i = 0; i < threadsAmount; i++) {
+ poll.submit(() -> {
+ this.benchmark_scan();
+ countDownLatch.countDown();
+ });
+ }
+
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java
new file mode 100644
index 0000000000..7115aaa65d
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.hugegraph.store;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.cmd.HgCmdClient;
+import org.apache.hugegraph.store.meta.Partition;
+import org.junit.Assert;
+
+import com.alipay.sofa.jraft.option.RpcOptions;
+
+public class PartitionEngineTest {
+
+ // @Test
+ public void test() {
+ String[] peers = new String[]{"1", "2", "6"};
+ String[] learners = new String[]{"3", "7"};
+ List oldPeers1 = Arrays.asList("1", "2", "3");
+ List oldLearner1 = Arrays.asList("4", "5");
+
+
+ List oldPeers =
+ oldPeers1.stream().map(peer -> peer).collect(Collectors.toList());
+ oldPeers.addAll(
+ oldLearner1.stream().map(peer -> peer).collect(Collectors.toList()));
+
+ List addedNodes = Arrays.stream(peers).filter(peer ->
+ !oldPeers.stream()
+ .map(e -> e)
+ .collect(
+ Collectors.toSet())
+ .contains(peer))
+ .collect(Collectors.toList());
+ addedNodes.addAll(Arrays.stream(learners).filter(peer ->
+ !oldPeers.stream()
+ .map(e -> e)
+ .collect(
+ Collectors.toSet())
+ .contains(peer))
+ .collect(Collectors.toList()));
+
+ List removedNodes = oldPeers.stream().filter(peer ->
+ !Arrays.stream(peers)
+ .map(e -> e).collect(
+ Collectors.toSet())
+ .contains(peer))
+ .collect(Collectors.toList());
+ removedNodes = removedNodes.stream().filter(peer ->
+ !Arrays.stream(learners).map(e -> e)
+ .collect(Collectors.toSet())
+ .contains(peer))
+ .collect(Collectors.toList());
+ List mixedPeer = oldPeers1.stream().filter(peer ->
+ Arrays.stream(learners)
+ .map(e -> e).collect(
+ Collectors.toSet())
+ .contains(peer))
+ .collect(Collectors.toList());
+
+ // 新增 6、7
+ Assert.assertEquals(2, addedNodes.size());
+ addedNodes.clear();
+ addedNodes.addAll(Arrays.asList(peers));
+ addedNodes.addAll(Arrays.asList(learners));
+ addedNodes.removeAll(oldPeers);
+ Assert.assertEquals(2, addedNodes.size());
+
+ addedNodes.forEach(s -> System.out.print(s + " "));
+ System.out.println();
+ // 删除 4,5
+ Assert.assertEquals(2, removedNodes.size());
+
+ removedNodes.clear();
+ removedNodes.addAll(oldPeers);
+ removedNodes.removeAll(Arrays.asList(peers));
+ removedNodes.removeAll(Arrays.asList(learners));
+ Assert.assertEquals(2, removedNodes.size());
+ removedNodes.forEach(s -> System.out.print(s + " "));
+ System.out.println();
+ // 交集 5
+ Assert.assertEquals(1, mixedPeer.size());
+ oldPeers1.removeAll(Arrays.asList(learners));
+ Assert.assertEquals(1, oldPeers1.size());
+ mixedPeer.forEach(s -> System.out.print(s + " "));
+
+ }
+
+
+ // @Test
+ public void testPartition() {
+ Partition p = new Partition();
+ p.setId(1);
+ List shards = new ArrayList<>();
+ shards.add(Metapb.Shard.newBuilder().build());
+ // p.setShardsList(shards);
+
+ Partition p2 = p.clone();
+ p.setId(2);
+ Assert.assertNotEquals(p2.getId(), p.getId());
+
+ }
+
+ // @Test
+ public void testUpdateShardsList() {
+ List curShards = new ArrayList<>();
+ curShards.add(Metapb.Shard.newBuilder().setStoreId(1001).setRole(Metapb.ShardRole.Follower)
+ .build());
+ curShards.add(Metapb.Shard.newBuilder().setStoreId(1002).setRole(Metapb.ShardRole.Leader)
+ .build());
+ curShards.add(Metapb.Shard.newBuilder().setStoreId(1003).setRole(Metapb.ShardRole.Follower)
+ .build());
+
+ List reqShards = new ArrayList<>();
+ reqShards.add(Metapb.Shard.newBuilder().setStoreId(1001).setRole(Metapb.ShardRole.Leader)
+ .build());
+ reqShards.add(Metapb.Shard.newBuilder().setStoreId(1002).setRole(Metapb.ShardRole.Leader)
+ .build());
+ reqShards.add(Metapb.Shard.newBuilder().setStoreId(1004).setRole(Metapb.ShardRole.Leader)
+ .build());
+
+
+ long leaderStoreId = 0;
+ for (Metapb.Shard shard : curShards) {
+ if (shard.getRole() == Metapb.ShardRole.Leader) {
+ leaderStoreId = shard.getStoreId();
+ break;
+ }
+ }
+
+ // remove
+ List shards = curShards.stream().filter(shard ->
+ reqShards.stream()
+ .map(Metapb.Shard::getStoreId)
+ .collect(
+ Collectors.toSet())
+ .contains(
+ shard.getStoreId()))
+ .collect(Collectors.toList());
+
+ // add
+ List addShards = reqShards.stream().filter(shard ->
+ !curShards.stream()
+ .map(Metapb.Shard::getStoreId)
+ .collect(
+ Collectors.toSet())
+ .contains(
+ shard.getStoreId()))
+ .collect(Collectors.toList());
+ shards.addAll(addShards);
+
+ // change leader
+ for (Metapb.Shard shard : shards) {
+ if (shard.getStoreId() == leaderStoreId) {
+ shard.toBuilder().setRole(Metapb.ShardRole.Leader).build();
+ } else {
+ shard.toBuilder().setRole(Metapb.ShardRole.Follower).build();
+ }
+ }
+
+ }
+
+ // @Test
+ public void testPriority() {
+ List oldPeers = new ArrayList<>();
+ oldPeers.add("127.0.0.1:8001::100");
+ oldPeers.add("127.0.0.1:8002::75");
+ oldPeers.add("127.0.0.1:8003::50");
+
+ List peers = new ArrayList<>();
+ peers.add("127.0.0.1:8001");
+ peers.add("127.0.0.1:8003::60");
+ peers.add("127.0.0.1:8004");
+
+ List priPeers = new ArrayList<>();
+ for (String peer : peers) {
+ if (peer.contains("::")) {
+ priPeers.add(peer);
+ System.out.println(peer);
+ } else {
+ boolean find = false;
+ for (String oldPeer : oldPeers) {
+ if (oldPeer.contains(peer + "::")) {
+ find = true;
+ priPeers.add(oldPeer);
+ System.out.println(oldPeer);
+ break;
+ }
+ }
+ if (!find) {
+ priPeers.add(peer);
+ System.out.println(peer);
+ }
+ }
+ }
+
+
+ }
+
+ // @Test
+ public void testRpcCall() throws ExecutionException, InterruptedException {
+ HgCmdClient client = new HgCmdClient();
+ client.init(new RpcOptions(), null);
+ ArrayList ps = new ArrayList<>();
+ Metapb.Partition p = Metapb.Partition.newBuilder()
+ .setGraphName("OK")
+ .setId(1)
+ // .addShards(Metapb.Shard.newBuilder().setStoreId
+ // (1).build())
+ .build();
+ ps.add(new Partition(p));
+ client.createRaftNode("127.0.0.1:8511", ps, status -> {
+ System.out.println(status);
+ }).get();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/UnitTestBase.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/UnitTestBase.java
new file mode 100644
index 0000000000..86532583e8
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/UnitTestBase.java
@@ -0,0 +1,101 @@
+/*
+ * 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.hugegraph.store;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hugegraph.rocksdb.access.RocksDBFactory;
+import org.apache.hugegraph.rocksdb.access.RocksDBOptions;
+import org.apache.hugegraph.rocksdb.access.RocksDBSession;
+import org.apache.hugegraph.store.business.BusinessHandler;
+import org.apache.hugegraph.store.business.BusinessHandlerImpl;
+import org.apache.hugegraph.store.meta.PartitionManager;
+import org.apache.hugegraph.store.options.HgStoreEngineOptions;
+import org.apache.hugegraph.store.options.RaftRocksdbOptions;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.apache.hugegraph.store.pd.PdProvider;
+
+public class UnitTestBase {
+
+ public final static RocksDBFactory factory = RocksDBFactory.getInstance();
+ public final static String DEFAULT_TEST_TABLE = "unknown";
+ private String dbPath;
+
+ private BusinessHandler handler;
+
+ public static boolean deleteDir(File dir) {
+ if (dir.isDirectory()) {
+ for (File file : dir.listFiles()) {
+ deleteDir(file);
+ }
+ }
+ return dir.delete();
+ }
+
+ public void initDB(String dbPath) {
+ this.dbPath = dbPath;
+ UnitTestBase.deleteDir(new File(dbPath));
+ Map configMap = new HashMap<>();
+ configMap.put("rocksdb.write_buffer_size", "1048576");
+ configMap.put("rocksdb.bloom_filter_bits_per_key", "10");
+
+ RaftRocksdbOptions.initRocksdbGlobalConfig(configMap);
+ BusinessHandlerImpl.initRocksdb(configMap, null);
+
+
+ }
+
+ protected BusinessHandler getBusinessHandler() {
+ if (handler == null) {
+ synchronized (this) {
+ if (handler == null) {
+ int partitionCount = 2;
+ HgStoreEngineOptions options = new HgStoreEngineOptions() {{
+ setDataPath(dbPath);
+ setFakePdOptions(new HgStoreEngineOptions.FakePdOptions() {{
+ setPartitionCount(partitionCount);
+ setPeersList("127.0.0.1");
+ setStoreList("127.0.0.1");
+
+ }});
+ }};
+
+ PdProvider pdProvider = new FakePdServiceProvider(options.getFakePdOptions());
+ PartitionManager partitionManager = new PartitionManager(pdProvider, options);
+ BusinessHandler handler = new BusinessHandlerImpl(partitionManager);
+ }
+ }
+ }
+
+ return handler;
+ }
+
+ public RocksDBSession getDBSession(String dbName) {
+ RocksDBSession session = factory.queryGraphDB(dbName);
+ if (session == null) {
+ session = factory.createGraphDB(dbPath, dbName);
+ }
+ return session;
+ }
+
+ public void close() {
+ handler.closeAll();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java
new file mode 100644
index 0000000000..be0c869969
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.hugegraph.store.client;
+
+import org.apache.hugegraph.pd.common.PDException;
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * 测试修改副本数
+ */
+public class ChangeShardNumTest extends HgStoreClientBase {
+
+ @Test
+ public void test3To1() throws PDException {
+ int number = 10000;
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "testKey", number);
+
+ try (HgKvIterator iterators = session.scanIterator(TABLE_NAME)) {
+// Assert.assertEquals(number, HgStoreTestUtil.amountOf(iterators));
+ }
+
+ Metapb.PDConfig pdConfig = pdClient.getPDConfig();
+ pdConfig = pdConfig.toBuilder().setShardCount(1).build();
+
+ pdClient.setPDConfig(pdConfig);
+ pdClient.balancePartition();
+ }
+
+ // @Test
+ public void test1To3() throws PDException {
+ int number = 10000;
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "testKey", number);
+
+ try (HgKvIterator iterators = session.scanIterator(TABLE_NAME)) {
+ Assert.assertEquals(number, HgStoreTestUtil.amountOf(iterators));
+ }
+
+ Metapb.PDConfig pdConfig = pdClient.getPDConfig();
+ pdConfig = pdConfig.toBuilder().setShardCount(3).build();
+
+ pdClient.setPDConfig(pdConfig);
+ pdClient.balancePartition();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ClientTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ClientTest.java
new file mode 100644
index 0000000000..e2c9fb1c2b
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ClientTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.hugegraph.store.client;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ClientTest {
+
+ @Test
+ public void testDemo() {
+ String s = "i am client";
+ log.info("UT:{}", s);
+ Assert.assertTrue(s.startsWith("i"));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgAssertTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgAssertTest.java
new file mode 100644
index 0000000000..ecd8bc0592
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgAssertTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.hugegraph.store.client;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hugegraph.store.client.util.HgAssert;
+import org.junit.Test;
+
+public class HgAssertTest {
+
+ @Test
+ public void testIsTrue1() {
+ try {
+ HgAssert.isTrue(false, "message");
+ } catch (Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+ }
+
+ @Test
+ public void testIsTrue2() {
+ try {
+ HgAssert.isTrue(false, () -> "message");
+ } catch (Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+ }
+
+ @Test
+ public void testIsFalse1() {
+ try {
+ HgAssert.isFalse(true, "message");
+ } catch (Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+ }
+
+ @Test
+ public void testIsFalse2() {
+ try {
+ HgAssert.isFalse(true, () -> "message");
+ } catch (Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+ }
+
+ @Test
+ public void testIsArgumentValid1() {
+ // Setup
+ // Run the test
+ HgAssert.isArgumentValid("content".getBytes(), "parameter");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsArgumentValid2() {
+ // Setup
+ // Run the test
+ HgAssert.isArgumentValid("str", "parameter");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsArgumentValid3() {
+ // Setup
+ // Run the test
+ HgAssert.isArgumentValid(List.of("value"), "parameter");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsArgumentNotNull() {
+ // Setup
+ // Run the test
+ HgAssert.isArgumentNotNull("obj", "parameter");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIstValid() {
+ // Setup
+ // Run the test
+ HgAssert.istValid("content".getBytes(), "message");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsValid() {
+ // Setup
+ // Run the test
+ HgAssert.isValid("str", "message");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsNotNull() {
+ // Setup
+ // Run the test
+ HgAssert.isNotNull("obj", "message");
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsContains1() {
+ assertTrue(HgAssert.isContains(new Object[]{"obj"}, "obj"));
+ }
+
+ @Test
+ public void testIsInvalid1() {
+ assertFalse(HgAssert.isInvalid("strs"));
+ }
+
+ @Test
+ public void testIsInvalid2() {
+ assertFalse(HgAssert.isInvalid("content".getBytes()));
+ }
+
+ @Test
+ public void testIsInvalid3() {
+ // Setup
+ final Map, ?> map = Map.ofEntries(Map.entry("value", "value"));
+ // Verify the results
+ assertFalse(HgAssert.isInvalid(map));
+ }
+
+ @Test
+ public void testIsInvalid4() {
+ assertFalse(HgAssert.isInvalid(List.of("value")));
+ }
+
+ @Test
+ public void testIsContains2() {
+ assertTrue(HgAssert.isContains(List.of("item"), "item"));
+ }
+
+ @Test
+ public void testIsNull() {
+ assertFalse(HgAssert.isNull("objs"));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgKvStoreTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgKvStoreTest.java
new file mode 100644
index 0000000000..6cbf9a7877
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgKvStoreTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.hugegraph.store.client;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toBytes;
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toOwnerKey;
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toStr;
+
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgOwnerKey;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HgKvStoreTest extends HgStoreClientBase {
+
+ @Test
+ public void truncateTest() {
+ System.out.println("--- test truncateTest ---");
+ HgStoreSession graph0 = storeClient.openSession("hugegraph0");
+ HgStoreSession graph1 = storeClient.openSession("hugegraph1");
+
+ graph0.truncate();
+ graph1.truncate();
+
+ for (int i = 0; i < 3; i++) {
+ HgOwnerKey key = toOwnerKey("owner-" + i, "ownerKey-" + i);
+ byte[] value0 = toBytes("g0 owner-" + i + ";ownerKey-" + i);
+ graph0.put(TABLE_NAME, key, value0);
+
+ byte[] value1 = toBytes("g1 owner-" + i + ";ownerKey-" + i);
+ graph1.put(TABLE_NAME, key, value1);
+ }
+
+ HgKvIterator iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+// log.info("key:{} value:{}", toStr(entry.key()), toStr(entry.value()));
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g0"));
+ }
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+// log.info("key:{} value:{}", toStr(entry.key()), toStr(entry.value()));
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+
+ graph0.truncate();
+ iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertFalse(iterator.hasNext());
+
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ // System.out.println("key:" + toStr(entry.key()) + " value:" + toStr(entry.value()));
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+ }
+
+ @Test
+ public void deleteTableTest() {
+ System.out.println("--- test deleteTableTest ---");
+ HgStoreSession graph0 = storeClient.openSession("hugegraph0");
+ HgStoreSession graph1 = storeClient.openSession("hugegraph1");
+ graph0.truncate();
+ graph1.truncate();
+
+ for (int i = 0; i < 2; i++) {
+ HgOwnerKey key = toOwnerKey("owner-" + i, "ownerKey-" + i);
+ byte[] value0 = toBytes("g0 owner-" + i + ";ownerKey-" + i);
+ graph0.put(TABLE_NAME, key, value0);
+
+ byte[] value1 = toBytes("g1 owner-" + i + ";ownerKey-" + i);
+ graph1.put(TABLE_NAME, key, value1);
+ }
+
+ HgKvIterator iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g0"));
+ }
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+
+ graph0.deleteTable(TABLE_NAME);
+ Assert.assertTrue(graph0.existsTable(TABLE_NAME));
+ iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertFalse(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ }
+
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+ }
+
+ @Test
+ public void dropTableTest() {
+ System.out.println("--- test dropTableTest ---");
+ HgStoreSession graph0 = storeClient.openSession("hugegraph0");
+ HgStoreSession graph1 = storeClient.openSession("hugegraph1");
+ graph0.truncate();
+ graph1.truncate();
+
+ for (int i = 0; i < 2; i++) {
+ HgOwnerKey key = toOwnerKey("owner-" + i, "ownerKey-" + i);
+ byte[] value0 = toBytes("g0 owner-" + i + ";ownerKey-" + i);
+ graph0.put(TABLE_NAME, key, value0);
+
+ byte[] value1 = toBytes("g1 owner-" + i + ";ownerKey-" + i);
+ graph1.put(TABLE_NAME, key, value1);
+ }
+
+ HgKvIterator iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g0"));
+ }
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+
+ graph0.dropTable(TABLE_NAME);
+ Assert.assertTrue(graph0.existsTable(TABLE_NAME));
+ iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertFalse(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ }
+
+ iterator = graph1.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g1"));
+ }
+ }
+
+ @Test
+ public void moveDataPathTest() {
+ System.out.println("--- test moveDataPathTest ---");
+ HgStoreSession graph0 = storeClient.openSession("hugegraph0");
+ graph0.truncate();
+
+ for (int i = 0; i < 2; i++) {
+ HgOwnerKey key = toOwnerKey("owner-" + i, "ownerKey-" + i);
+ byte[] value0 = toBytes("g0 owner-" + i + ";ownerKey-" + i);
+ graph0.put(TABLE_NAME, key, value0);
+ }
+
+ HgKvIterator iterator = graph0.scanIterator(TABLE_NAME);
+ Assert.assertTrue(iterator.hasNext());
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ Assert.assertEquals(0, toStr(entry.value()).indexOf("g0"));
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgPairTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgPairTest.java
new file mode 100644
index 0000000000..fd3ce3d51c
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgPairTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hugegraph.store.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.apache.hugegraph.store.term.Bits;
+import org.apache.hugegraph.store.term.HgPair;
+import org.apache.hugegraph.store.term.HgTriple;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HgPairTest {
+
+ private HgPair pair;
+ private HgTriple triple;
+
+ @Before
+ public void setUp() {
+ pair = new HgPair<>("key", "value");
+ triple = new HgTriple<>("x", "y", "z");
+ }
+
+ @Test
+ public void testPair() {
+ int hashCode = pair.hashCode();
+ pair.toString();
+ pair.setKey("key1");
+ pair.setValue("value1");
+ pair.getKey();
+ pair.getValue();
+ assertEquals(new HgPair<>("key1", "value1"), pair);
+ var pair2 = new HgPair<>();
+ pair2.setKey("key1");
+ pair2.hashCode();
+ assertNotEquals(pair2, pair);
+ triple.getZ();
+ triple.getX();
+ triple.getY();
+ triple.toString();
+ triple.hashCode();
+ triple.hashCode();
+ assertEquals(triple, new HgTriple<>("x", "y", "z"));
+ assertNotEquals(pair2, triple);
+ }
+
+ @Test
+ public void testBits() {
+ byte[] buf = new byte[4];
+ Bits.putInt(buf, 0, 3);
+ int i = Bits.getInt(buf, 0);
+ assertEquals(3, i);
+ buf = new byte[2];
+ Bits.putShort(buf, 0, 2);
+ int s = Bits.getShort(buf, 0);
+ assertEquals(2, s);
+ buf = new byte[4];
+ Bits.put(buf, 0, new byte[]{0, 0, 0, 66});
+ int toInt = Bits.toInt(buf);
+ assertEquals(66, toInt);
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java
new file mode 100644
index 0000000000..e52ae8d2d7
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java
@@ -0,0 +1,685 @@
+/*
+ * 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.hugegraph.store.client;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+import static org.apache.hugegraph.store.util.HgStoreTestUtil.batchPut;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgKvStore;
+import org.apache.hugegraph.store.HgOwnerKey;
+import org.apache.hugegraph.store.HgScanQuery;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.client.grpc.KvCloseableIterator;
+import org.apache.hugegraph.store.client.util.HgStoreClientConfig;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.client.util.MetricX;
+import org.apache.hugegraph.store.grpc.common.ScanOrderType;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HgSessionManagerRaftPDTest extends HgStoreClientBase {
+
+ public static final String GRAPH_NAME_X = "default/hugegraph/x";
+ public static final String GRAPH_NAME_Y = "default/hugegraph/y";
+ public static final String GRAPH_NAME_Z = "default/hugegraph/z";
+ public static final String TABLE_NAME_1 = "table1";
+ public static final String TABLE_NAME_2 = "table2";
+ public static final String TABLE_NAME_3 = "table3";
+
+ private HgStoreSession getStoreSession() {
+ return storeClient.openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private HgStoreSession getStoreSession(String graph) {
+ return storeClient.openSession(graph);
+ }
+
+ @Test
+ public void putGet() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession(HgStoreTestUtil.GRAPH_NAME);
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ long stime = System.currentTimeMillis();
+ batchPut(session, TABLE_NAME, "BATCH-PUT-TEST", 30000);
+ System.out.println("Time is " + (System.currentTimeMillis() - stime));
+ }
+
+ public void putGet2() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession("testGraph");
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY");
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+ long stime = System.currentTimeMillis();
+ HgStoreTestUtil.batchPut(session, "testTable", "BATCH-PUT-TEST", 30000);
+ System.out.println("Time is " + (System.currentTimeMillis() - stime));
+ }
+
+ @Test
+ public void scanPartition() {
+ HgStoreTestUtil.println("--- test scanPartition ---");
+
+ HgStoreSession session = getStoreSession();
+
+ Iterator iterator =
+ session.scanIterator(TABLE_NAME, 0, 65535, HgKvStore.SCAN_HASHCODE, EMPTY_BYTES);
+ System.out.println(HgStoreTestUtil.amountOf(iterator));
+ }
+
+ @Test
+ public void check() {
+ System.out.println("--- test check ---");
+
+ HgStoreSession session = getStoreSession();
+ HgKvIterator iterator = session.scanIterator(TABLE_NAME);
+ int count = 0;
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ }
+ System.out.println(count);
+ }
+
+ @Test
+ public void putGetUnique() {
+ System.out.println("--- test put & get ---");
+
+ HgStoreSession session = getStoreSession();
+
+ // add timestamp into key to avoid key duplication
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey("FOR-PUT-KEY-" + timestamp);
+ byte[] value = HgStoreTestUtil.toBytes("FOR-PUT-VALUE");
+
+ Assert.assertTrue(session.put(TABLE_NAME, key, value));
+
+ Assert.assertEquals(
+ HgStoreTestUtil.toStr(value), HgStoreTestUtil.toStr(session.get(TABLE_NAME, key)));
+ }
+
+ @Test
+ public void testBatchPutExt() throws IOException {
+ System.out.println("--- test batchPut ---");
+ HgStoreSession session = getStoreSession();
+ session.truncate();
+ String keyPrefix = "BATCH-GET-UNIT";
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix, 10);
+
+ File outputFile = new File("tmp/batch_put_list");
+ if (outputFile.exists()) {
+ FileUtils.forceDelete(outputFile);
+ }
+ FileUtils.forceMkdir(new File("tmp/"));
+
+ ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(outputFile));
+ oo.writeObject(map);
+ oo.close();
+ System.out.printf("%d entries have be put into graph %s\n", map.size(),
+ HgStoreTestUtil.GRAPH_NAME);
+
+ int count = 0;
+ HgKvIterator iterator = null;
+ iterator = session.scanIterator(TABLE_NAME);
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ }
+ Assert.assertEquals(10, count);
+ }
+
+ // @Test
+ public void testBatchGetExt() throws IOException, ClassNotFoundException {
+ File outputFile = new File("tmp/batch_put_list");
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(outputFile));
+ Map map = (Map) ois.readObject();
+ ois.close();
+ System.out.printf("%d entries get from %s\n", map.size(), outputFile.getPath());
+
+ HgStoreSession session = getStoreSession();
+ List keyList =
+ map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList());
+ List resList = session.batchGetOwner(TABLE_NAME, keyList);
+
+ Assert.assertTrue(
+ (resList.stream().map(e -> map.containsKey(HgStoreTestUtil.toOwnerKey(e.key())))
+ .allMatch(Boolean::booleanValue)));
+ }
+
+ @Test
+ public void testBatchPutUniqueExt() throws IOException {
+ System.out.println("--- test batchPut ---");
+ HgStoreSession session = getStoreSession();
+
+ // add timestamp into key to avoid key duplication
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+
+ String keyPrefix = "BATCH-GET-UNIT-" + timestamp;
+
+ Map map = HgStoreTestUtil.batchPut(session, keyPrefix, 30);
+
+ File outputFile = new File("tmp/batch_put_list");
+ if (outputFile.exists()) {
+ FileUtils.forceDelete(outputFile);
+ }
+ FileUtils.forceMkdir(new File("tmp/"));
+
+ ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(outputFile));
+ oo.writeObject(map);
+ oo.close();
+ System.out.printf("%d entries have be put into graph %s\n", map.size(),
+ HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ @Test
+ public void testBatchPutMultiGraph() throws IOException {
+ System.out.println("--- test testBatchPutMultiGraph ---");
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("HHmmss");
+ String timestamp = formatter.format(date);
+ HgStoreSession session1 = getStoreSession(GRAPH_NAME_X);
+ HgStoreSession session2 = getStoreSession(GRAPH_NAME_Y);
+ HgStoreSession session3 = getStoreSession(GRAPH_NAME_Z);
+ String keyPrefix1 = "BATCH-PUT-UNIT-X-" + timestamp;
+ String keyPrefix2 = "BATCH-PUT-UNIT-Y-" + timestamp;
+ String keyPrefix3 = "BATCH-PUT-UNIT-Z-" + timestamp;
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_1, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_2, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session1, TABLE_NAME_3, keyPrefix1, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_1, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_2, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session2, TABLE_NAME_3, keyPrefix2, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_1, keyPrefix3, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_2, keyPrefix3, 1000);
+ HgStoreTestUtil.batchPut(session3, TABLE_NAME_3, keyPrefix3, 1000);
+ }
+
+ // @Test
+ // CAUTION: ONLY FOR LONG!
+ // 注意:目前只可以对 long 类型 value 进行 Merge 操作。
+ public void merge() {
+ System.out.println("--- test merge (1+1=2)---");
+ HgStoreSession session = getStoreSession();
+ String mergeKey = "merge-key";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(mergeKey);
+ byte[] value = HgStoreTestUtil.toBytes(1L);
+
+ System.out.println("- put " + mergeKey + ":1 -");
+ session.put(TABLE_NAME, key, value);
+ System.out.println("- merge " + mergeKey + ":1 -");
+ session.merge(TABLE_NAME, key, value);
+ long res = HgStoreTestUtil.toLong(session.get(TABLE_NAME, key));
+ System.out.printf("after merge " + mergeKey + "=%s%n", res);
+ Assert.assertEquals(2L, res);
+
+ String putStr = "19";
+ session.put(TABLE_NAME, key, HgStoreTestUtil.toBytes(putStr));
+ byte[] b1 = session.get(TABLE_NAME, key);
+ Assert.assertEquals(putStr, HgStoreTestUtil.toStr(b1));
+ }
+
+ @Test
+ public void delete() {
+ System.out.println("--- test delete ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-key";
+ String delValue = "del-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ HgStoreTestUtil.println("- put " + delKey + ": " + delValue);
+ session.put(TABLE_NAME, key, value);
+ HgStoreTestUtil.println("- delete " + delKey);
+ session.delete(TABLE_NAME, key);
+ value = session.get(TABLE_NAME, key);
+ HgStoreTestUtil.println("- get " + delKey + ": " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals(EMPTY_BYTES, value);
+ }
+
+ @Test
+ public void deleteSingle() {
+ System.out.println("--- test deleteSingle ---");
+ HgStoreSession session = getStoreSession();
+
+ String delKey = "del-single-key";
+ String delValue = "del-single-value";
+ HgOwnerKey key = HgStoreTestUtil.toOwnerKey(delKey);
+ byte[] value = HgStoreTestUtil.toBytes(delValue);
+
+ session.put(TABLE_NAME, key, value);
+ value = session.get(TABLE_NAME, key);
+ Assert.assertEquals(delValue, HgStoreTestUtil.toStr(value));
+
+ HgStoreTestUtil.println("- delete-single : [" + delKey + "]");
+ session.deleteSingle(TABLE_NAME, key);
+ value = session.get(TABLE_NAME, key);
+ HgStoreTestUtil.println(
+ "- after del, get [" + delKey + "] = " + HgStoreTestUtil.toStr(value));
+ Assert.assertEquals("", HgStoreTestUtil.toStr(value));
+ }
+
+ @Test
+ public void deleteRange() {
+ HgStoreTestUtil.println("--- test deleteRange ---");
+ HgStoreSession session = getStoreSession();
+
+ String rangePrefix = "DEL-RANGE-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(
+ session,
+ TABLE_NAME,
+ rangePrefix,
+ 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ HgOwnerKey startKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-00");
+ HgOwnerKey endKey = HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-05");
+
+ Assert.assertTrue(session.deleteRange(TABLE_NAME, startKey, endKey));
+
+ HgStoreTestUtil.println(
+ "- after delete range from [" + HgStoreTestUtil.toStr(startKey.getKey()) +
+ "] to [" +
+ HgStoreTestUtil.toStr(endKey.getKey()) + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, rangePrefix + "-" +
+ HgStoreTestUtil.padLeftZeros(
+ String.valueOf(i), 2));
+ String value = HgStoreTestUtil.toStr(session.get(TABLE_NAME, key));
+
+ // TODO: [start,end)?
+ if (i < 5) {
+ Assert.assertEquals("", value);
+ } else {
+ // println(value);
+ Assert.assertNotEquals("", value);
+ }
+ }
+ }
+
+ @Test
+ public void deletePrefix() {
+ System.out.println("--- test deletePrefix ---");
+ HgStoreSession session = getStoreSession();
+
+ String prefixStr = "DEL-PREFIX-KEY";
+ String owner = "batch-delete-owner";
+ Map map =
+ HgStoreTestUtil.batchPut(
+ session,
+ TABLE_NAME,
+ prefixStr,
+ 10,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+
+ // printOwner(map.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
+
+ HgOwnerKey prefix = HgStoreTestUtil.toOwnerKey(owner, prefixStr);
+
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(session.scanIterator(TABLE_NAME, prefix)));
+ session.deletePrefix(TABLE_NAME, prefix);
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(TABLE_NAME, prefix)));
+
+ HgStoreTestUtil.println("- after delete by prefix:[" + prefixStr + "]");
+
+ for (int i = 0; i < 10; i++) {
+ HgOwnerKey key =
+ HgStoreTestUtil.toOwnerKey(owner, prefixStr + HgStoreTestUtil.toSuffix(i, 2));
+ String value = HgStoreTestUtil.toStr(session.get(TABLE_NAME, key));
+ Assert.assertEquals("", value);
+ }
+ }
+
+ // @Test
+ // TODO: this test's result is unstable
+ public void scanIterator() {
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = TABLE_NAME;
+ String keyName = "SCAN-ITER";
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 10000);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ HgStoreTestUtil.println("-- test 0 element --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey("__SCAN-001"),
+ HgStoreTestUtil.toAllPartitionKey("__SCAN-100"), 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+
+ for (int i = 1; i <= 10; i++) {
+ limit = i;
+ iterator =
+ session.scanIterator(
+ tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"), limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ }
+ Assert.assertEquals(limit, count);
+ }
+
+ for (int i = 1; i <= 10; i++) {
+ limit = i;
+ iterator =
+ session.scanIterator(
+ tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-00001"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-00005"), limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ }
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+ }
+
+ limit = 0;
+ iterator =
+ session.scanIterator(
+ tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-0"),
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-1"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count >= max) {
+ break;
+ }
+ }
+ Assert.assertEquals(10000, count);
+
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry ignore = iterator.next();
+ if (count >= max) {
+ break;
+ }
+ }
+ Assert.assertEquals(10000, count);
+
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName + "-01"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count >= max) {
+ break;
+ }
+ }
+ Assert.assertEquals(1000, count);
+ }
+
+ @Test
+ public void paging() {
+ HgStoreTestUtil.println("--- test scanIterator_range ---");
+ String graph = "UNIT/paging";
+ String tableName = TABLE_NAME;
+ String keyName = "SCAN-PAGING";
+ int keyAmt = 100;
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ count = 0;
+
+ iterator =
+ session.scanIterator(
+ tableName,
+ HgStoreTestUtil.toAllPartitionKey(keyName + "-000"),
+ HgStoreClientConst.EMPTY_OWNER_KEY,
+ 0,
+ HgKvStore.SCAN_ANY,
+ EMPTY_BYTES);
+ List positionList = new LinkedList<>();
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ positionList.add(iterator.position());
+ if (count >= max) {
+ break;
+ }
+ }
+
+ iterator = session.scanIterator(tableName, 100);
+
+ byte[] position = positionList.get(50);
+ HgStoreTestUtil.println("seek: " + Arrays.toString(position));
+ iterator.seek(position);
+ HgStoreTestUtil.println(iterator);
+ // Assert.assertEquals(50, HgStoreTestUtil.amountOf(iterator));
+
+ }
+
+ @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String graph = "graph_truncate";
+ String tableName = TABLE_NAME;
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession(graph);
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ }
+
+ // @Test
+ public void scanIteratorHuge() {
+ /*************** test no limit, with 10 millions **************/
+ String tableName = TABLE_NAME;
+ String keyName = "SCAN-HUGE";
+ int amount = 10_000_000;
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 10)) <
+ 10) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, amount);
+ }
+
+ int count = 0;
+ HgKvIterator iterator = session.scanIterator(tableName);
+
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ }
+
+ Assert.assertEquals(amount, count);
+ }
+
+ @Test
+ public void scanTable() {
+ HgStoreSession session = getStoreSession("DEFAULT/hg1/g");
+ HgStoreTestUtil.println(session.scanIterator("g+v", 10));
+ }
+
+ @Test
+ public void testDelGraph() {
+ HgStoreSession session = getStoreSession();
+ session.deleteGraph(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ // TODO: need figure out
+ // @Test
+ public void benchmarkScanBatch() {
+ HgStoreTestUtil.println("--- Benchmark scanBatch ---");
+ String tableName = TABLE_NAME;
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 30001;
+
+ HgStoreSession session = getStoreSession();
+
+ if (HgStoreTestUtil.amountOf(
+ session.scanIterator(tableName, HgStoreTestUtil.toAllPartitionKey(keyName), 1)) <
+ 1) {
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ }
+ HgStoreTestUtil.println("-- Starting scan --");
+ List> iterators = session.scanBatch(HgScanQuery.tableOf(tableName));
+ Assert.assertEquals(keyAmt, HgStoreTestUtil.amountIn(iterators));
+ }
+
+ @Test
+ public void benchmarkScanBatch2() throws IOException {
+ HgStoreTestUtil.println("--- Benchmark scanBatch2 ---");
+ String tableName = TABLE_NAME;
+ HgStoreSession session = getStoreSession();
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 300;
+ Map data =
+ HgStoreTestUtil.batchPut(session, tableName, keyName, keyAmt);
+ HgStoreTestUtil.println("-- Starting scan --");
+ MetricX metrics = MetricX.ofStart();
+ // HgStoreTestUtil.println(session.scanIterator(tableName));
+ long t = System.currentTimeMillis();
+ int count = 0;
+ List keys = new ArrayList<>();
+ data.forEach((k, v) -> keys.add(k));
+ KvCloseableIterator> iterators =
+ session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(tableName, keys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder()
+ .setScanType(0x40)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ keys.clear();
+ iterators.close();
+ }
+
+ @Test
+ public void benchmarkScanBatchSkipDegree() throws IOException {
+ HgStoreTestUtil.println("--- Benchmark scanBatch2 1Owner---");
+ String tableName = TABLE_NAME;
+ HgStoreSession session = getStoreSession();
+ String keyName = "SCAN-BATCH";
+ int keyAmt = 300;
+ byte[] owner = "Owner".getBytes();
+ Map data =
+ HgStoreTestUtil.batchPut(
+ session,
+ tableName,
+ keyName,
+ keyAmt,
+ key -> {
+ return HgStoreTestUtil.toOwnerKey(owner, key);
+ });
+ HgStoreTestUtil.println("-- Starting scan --");
+ MetricX metrics = MetricX.ofStart();
+ long t = System.currentTimeMillis();
+ int count = 0;
+
+ List keys = new ArrayList<>();
+ keys.add(HgStoreTestUtil.toOwnerKey(owner, keyName));
+
+ KvCloseableIterator> iterators =
+ session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(tableName, keys.iterator(),
+ ScanOrderType.ORDER_NONE)
+ .builder()
+ .setScanType(0x40)
+ .setSkipDegree(1)
+ .build());
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ count += HgStoreTestUtil.amountOf(iterator);
+ }
+ keys.clear();
+ iterators.close();
+ iterators = null;
+
+ HgStoreTestUtil.println("time is " + (System.currentTimeMillis() - t));
+ metrics.end();
+ HgStoreTestUtil.println("*************************************************");
+ HgStoreTestUtil.println("*********** Batch Scan Completed **************");
+ HgStoreTestUtil.println("Total : " + (metrics.past() / 1000) + " (sec)");
+ HgStoreTestUtil.println(" Sum : " + (MetricX.getIteratorWait() / 1000) + " (sec)");
+ HgStoreTestUtil.println(" Amt : " + MetricX.getIteratorCount() + " (scans).");
+ HgStoreTestUtil.println(" Avg : " + MetricX.getIteratorWaitAvg() + " (ms)");
+ HgStoreTestUtil.println(" Max : " + MetricX.getIteratorWaitMax() + " (ms)");
+ HgStoreTestUtil.println(" Fail : " + metrics.getFailureCount() + " (times)");
+ HgStoreTestUtil.println(
+ " Page : " + HgStoreClientConfig.of().getNetKvScannerPageSize() + " (KVs)");
+ HgStoreTestUtil.println(" size is " + count);
+ HgStoreTestUtil.println("*************************************************");
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientBase.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientBase.java
new file mode 100644
index 0000000000..18d393f9c9
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientBase.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hugegraph.store.client;
+
+import org.apache.hugegraph.pd.client.PDClient;
+import org.apache.hugegraph.pd.client.PDConfig;
+import org.apache.hugegraph.store.HgStoreClient;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.junit.After;
+import org.junit.Before;
+
+public class HgStoreClientBase {
+
+ protected static String GRAPH_NAME = "testGraphName";
+ protected static String TABLE_NAME = UnitTestBase.DEFAULT_TEST_TABLE;
+ private static final String PD_ADDRESS = "127.0.0.1:8686";
+ protected HgStoreClient storeClient;
+ protected PDClient pdClient;
+
+ @Before
+ public void setup() throws Exception {
+ storeClient = HgStoreClient.create(PDConfig.of(PD_ADDRESS)
+ .setEnableCache(true));
+ pdClient = storeClient.getPdClient();
+
+ HgStoreSession session = storeClient.openSession(TABLE_NAME);
+ session.dropTable(TABLE_NAME);
+ session.truncate();
+ }
+
+ @After
+ public void teardown() {
+ // pass
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientTest.java
new file mode 100644
index 0000000000..82bc2f7eae
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreClientTest.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.hugegraph.store.client;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientConst.ALL_PARTITION_OWNER;
+
+import java.util.List;
+
+import org.apache.hugegraph.pd.common.PDException;
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgKvStore;
+import org.apache.hugegraph.store.HgOwnerKey;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HgStoreClientTest extends HgStoreClientBase {
+
+ public static final byte[] EMPTY_BYTES = new byte[0];
+
+ @Test
+ public void testPutData() {
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ long start = System.currentTimeMillis();
+ int loop = 100000;
+ session.truncate();
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "testKey", loop);
+
+ System.out.println("Time is " + (System.currentTimeMillis() - start));
+ try (HgKvIterator iterator = session.scanIterator(TABLE_NAME)) {
+ Assert.assertEquals(loop, HgStoreTestUtil.amountOf(iterator));
+ }
+ }
+
+ @Test
+ public void testPutData2() {
+ String GRAPH_NAME = "testGRAPH_NAME2";
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ long start = System.currentTimeMillis();
+ int loop = 100000;
+ session.truncate();
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "testKey", loop);
+
+ System.out.println("Time is " + (System.currentTimeMillis() - start));
+ try (HgKvIterator iterator = session.scanIterator(TABLE_NAME)) {
+ Assert.assertEquals(loop, HgStoreTestUtil.amountOf(iterator));
+ }
+ }
+
+ @Test
+ public void testScan() throws PDException {
+
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "testKey", 12);
+
+ int count = 0;
+ byte[] position = null;
+ try (HgKvIterator iterator = session.scanIterator(TABLE_NAME)) {
+ while (iterator.hasNext()) {
+ iterator.next();
+ position = iterator.position();
+ dumpPosition(position);
+ if (++count > 5) {
+ break;
+ }
+ }
+ }
+
+ System.out.println("--------------------------------");
+ try (HgKvIterator iterator = session.scanIterator(TABLE_NAME)) {
+ iterator.seek(position);
+ while (iterator.hasNext()) {
+ iterator.next();
+ dumpPosition(iterator.position());
+ }
+ }
+
+ System.out.println("--------------------------------");
+
+ byte[] start = new byte[]{0x0};
+ byte[] end = new byte[]{-1};
+ try (HgKvIterator iterator = session.scanIterator(TABLE_NAME,
+ HgOwnerKey.of(
+ ALL_PARTITION_OWNER,
+ start),
+ HgOwnerKey.of(
+ ALL_PARTITION_OWNER,
+ end))) {
+ iterator.seek(position);
+ while (iterator.hasNext()) {
+ iterator.next();
+ dumpPosition(iterator.position());
+ }
+ }
+ }
+
+ public void dumpPosition(byte[] b) {
+ byte[] buf = new byte[Long.BYTES];
+ System.arraycopy(b, 0, buf, 0, Long.BYTES);
+ // long storeId = HgStoreTestUtil.toLong(buf);
+ buf = new byte[Integer.BYTES];
+ System.arraycopy(b, Long.BYTES, buf, 0, Integer.BYTES);
+ // int partId = HgStoreTestUtil.toInt(buf);
+ // String key = new String(b);
+
+ // System.out.println(" " + storeId + ", " + partId + ", " + key);
+ }
+
+ // @Test
+ // TODO: unstable
+ public void testDeleteData() {
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ int ownerCode = 1;
+ HgStoreTestUtil.batchPut(session, TABLE_NAME, "T", 10, (key) -> {
+ return HgStoreTestUtil.toOwnerKey(ownerCode, key);
+ }
+ );
+ try (HgKvIterator iterators = session.scanIterator(TABLE_NAME)) {
+// while (iterators.hasNext()){
+// System.out.println(new String(iterators.next().key()));
+// }
+ Assert.assertEquals(10, HgStoreTestUtil.amountOf(iterators));
+ }
+ session.beginTx();
+ session.deletePrefix(TABLE_NAME, HgStoreTestUtil.toOwnerKey(ownerCode, "T"));
+ session.commit();
+
+ System.out.println("=================================");
+ try (HgKvIterator iterators = session.scanIterator(TABLE_NAME)) {
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(iterators));
+// while (iterators.hasNext()){
+// System.out.println(new String(iterators.next().key()));
+// }
+ }
+ }
+
+ // @Test
+ // TODO: unstable
+ public void testDropTable() throws PDException {
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+
+ String table1 = TABLE_NAME;
+ session.createTable(table1);
+ HgStoreTestUtil.batchPut(session, table1, "testKey", 1000);
+
+ try (HgKvIterator iterators = session.scanIterator(table1)) {
+ Assert.assertEquals(1000, HgStoreTestUtil.amountOf(iterators));
+ }
+
+ session.dropTable(table1);
+ try (HgKvIterator iterators = session.scanIterator(table1)) {
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(iterators));
+ }
+
+ deleteGraph(GRAPH_NAME);
+ }
+
+ public void deleteGraph(String GRAPH_NAME) throws PDException {
+ HgStoreSession session = storeClient.openSession(GRAPH_NAME);
+ session.deleteGraph(GRAPH_NAME);
+ pdClient.delGraph(GRAPH_NAME);
+
+ Metapb.Graph graph = null;
+ try {
+ graph = pdClient.getGraph(GRAPH_NAME);
+ } catch (PDException e) {
+ Assert.assertEquals(103, e.getErrorCode());
+ }
+ Assert.assertNull(graph);
+ }
+
+ @Test
+ public void testScanPartition() throws PDException {
+ // testPutData();
+ List partitions = pdClient.getPartitions(0, "DEFAULT/hugegraph/g");
+ HgStoreSession session = storeClient.openSession("DEFAULT/hugegraph/g");
+ for (Metapb.Partition partition : partitions) {
+ try (HgKvIterator iterators = session.scanIterator("g+v",
+ (int) (partition.getStartKey()),
+ (int) (partition.getEndKey()),
+ HgKvStore.SCAN_HASHCODE,
+ EMPTY_BYTES)) {
+
+ System.out.println(
+ " " + partition.getId() + " " + HgStoreTestUtil.amountOf(iterators));
+ }
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeSessionTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeSessionTest.java
new file mode 100644
index 0000000000..25151e4c84
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeSessionTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.hugegraph.store.client;
+
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+
+/**
+ * created on 2021/10/12
+ */
+public class HgStoreNodeSessionTest {
+
+ private static final HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ private static HgStoreNode node;
+
+ // @BeforeClass
+ public static void init() {
+ node = nodeManager.addNode(HgStoreTestUtil.GRAPH_NAME,
+ nodeManager.getNodeBuilder().setAddress("localhost:9080")
+ .build());
+ }
+
+ private static HgStoreSession getStoreSession() {
+ return node.openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private HgStoreNode getOneNode() {
+ return node;
+ }
+
+ // @Test
+ public void truncate() {
+ HgStoreTestUtil.println("--- test truncate ---");
+ String tableName = "UNIT_TRUNCATE_1";
+ String keyName = "KEY_TRUNCATE";
+
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+
+ String tableName2 = "UNIT_TRUNCATE_2";
+ HgStoreTestUtil.batchPut(session, tableName2, keyName, 100);
+ Assert.assertEquals(100, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+
+ session.truncate();
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName)));
+ Assert.assertEquals(0, HgStoreTestUtil.amountOf(session.scanIterator(tableName2)));
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStateTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStateTest.java
new file mode 100644
index 0000000000..f1bb94c333
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStateTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.hugegraph.store.client;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Test;
+
+public class HgStoreNodeStateTest {
+ private static final HgStoreNodeManager NODE_MANAGER = HgStoreNodeManager.getInstance();
+ static int nodeNumber = 0;
+
+ static {
+ registerNode(HgStoreTestUtil.GRAPH_NAME, Long.valueOf(nodeNumber++), "localhost:9180");
+ registerNode(HgStoreTestUtil.GRAPH_NAME, Long.valueOf(nodeNumber++), "localhost:9280");
+ registerNode(HgStoreTestUtil.GRAPH_NAME, Long.valueOf(nodeNumber++), "localhost:9380");
+ }
+
+ private static void registerNode(String graphName, Long nodeId, String address) {
+ NODE_MANAGER.addNode(graphName,
+ NODE_MANAGER.getNodeBuilder().setNodeId(nodeId).setAddress(address)
+ .build());
+ }
+
+
+ @Test
+ public void isNodeHealthy() {
+ AtomicInteger count = new AtomicInteger(0);
+
+ for (int i = 0; i < 100; i++) {
+ NODE_MANAGER.getStoreNodes(HgStoreTestUtil.GRAPH_NAME)
+ .stream().map(
+ node -> {
+ System.out.println(node.getNodeId() + " " + node.getAddress()
+ + "is healthy: " + node.isHealthy());
+ return node.isHealthy();
+ }
+ ).count();
+
+ Thread.yield();
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStreamTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStreamTest.java
new file mode 100644
index 0000000000..aeee3da6b7
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgStoreNodeStreamTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.hugegraph.store.client;
+
+import static org.apache.hugegraph.store.util.HgStoreTestUtil.GRAPH_NAME;
+import static org.apache.hugegraph.store.util.HgStoreTestUtil.batchPut;
+import static org.apache.hugegraph.store.util.HgStoreTestUtil.println;
+import static org.apache.hugegraph.store.util.HgStoreTestUtil.toOwnerKey;
+
+import java.util.NoSuchElementException;
+
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.client.HgStoreNode;
+import org.apache.hugegraph.store.client.HgStoreNodeManager;
+import org.apache.hugegraph.store.util.HgStoreTestUtil;
+import org.junit.Assert;
+
+/**
+ * created on 2021/10/12
+ */
+public class HgStoreNodeStreamTest {
+ private static final HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ private static HgStoreNode node;
+
+ // @BeforeClass
+ public static void init() {
+ node = nodeManager.addNode(HgStoreTestUtil.GRAPH_NAME,
+ nodeManager.getNodeBuilder().setAddress("localhost:9080")
+ .build());
+ }
+
+ private static HgStoreSession getStoreSession() {
+ return node.openSession(HgStoreTestUtil.GRAPH_NAME);
+ }
+
+ private HgStoreNode getOneNode() {
+ return node;
+ }
+
+ // @Test
+ public void scanIterator() {
+
+ HgStoreTestUtil.println("--- test scanIterator ---");
+ String tableName = "UNIT_SCAN";
+ String keyName = "SCAN-ITER";
+ HgStoreSession session = getStoreSession();
+ HgStoreTestUtil.batchPut(session, tableName, keyName, 10000);
+ int count = 0;
+ int limit = 0;
+ int max = 99999;
+ HgKvIterator iterator = null;
+
+ HgStoreTestUtil.println("-- test 0 element --");
+ iterator =
+ session.scanIterator(tableName, HgStoreTestUtil.toOwnerKey("__SCAN-001"), HgStoreTestUtil.toOwnerKey("__SCAN-100"),
+ 0);
+ Assert.assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ Assert.fail();
+ } catch (Throwable t) {
+ HgStoreTestUtil.println("-- test NoSuchElementException --");
+ Assert.assertTrue(t instanceof NoSuchElementException);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toOwnerKey(keyName + "-0"),
+ HgStoreTestUtil.toOwnerKey(keyName + "-1"), limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ Assert.assertEquals(limit, count);
+ }
+
+ HgStoreTestUtil.println("-- test limit 1 to 10 not enough --");
+ for (int i = 1; i <= 10; i++) {
+ HgStoreTestUtil.println("- limit " + i + " -");
+ limit = i;
+ iterator = session.scanIterator(tableName,
+ HgStoreTestUtil.toOwnerKey(keyName + "-00001"),
+ HgStoreTestUtil.toOwnerKey(keyName + "-00005"), limit);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ HgStoreTestUtil.println(entry);
+ }
+ if (i <= 5) {
+ Assert.assertEquals(limit, count);
+ } else {
+ Assert.assertEquals(5, count);
+ }
+
+ }
+
+ HgStoreTestUtil.println("-- test limit 0 (no limit) --");
+ limit = 0;
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toOwnerKey(keyName + "-0"),
+ HgStoreTestUtil.toOwnerKey(keyName + "-1"), limit);
+
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 1000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan all --");
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(10000, count);
+
+ HgStoreTestUtil.println("-- test scan prefix --");
+ iterator = session.scanIterator(tableName, HgStoreTestUtil.toOwnerKey(keyName + "-01"));
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ if (count >= max) break;
+ }
+ Assert.assertEquals(1000, count);
+
+ }
+
+ //// @Test
+ public void scanIteratorBenchmark() {
+ /*************** test no limit, with 10 millions **************/
+ String tableName = "UNIT_HUGE";
+ String keyName = "SCAN-HUGE";
+ HgStoreSession session = getStoreSession();
+ //batchPut(session,tableName, keyName, 10000000);
+ int count = 0;
+ int limit = 0;
+ HgKvIterator iterator = null;
+
+ limit = 0;
+ iterator = session.scanIterator(tableName);
+ count = 0;
+ while (iterator.hasNext()) {
+ count++;
+ HgKvEntry entry = iterator.next();
+ if (count % 100000 == 0) {
+ HgStoreTestUtil.println(entry);
+ }
+ }
+
+ Assert.assertEquals(10000000, count);
+
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/graph/GraphStoreClientTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/graph/GraphStoreClientTest.java
new file mode 100644
index 0000000000..4514ef676e
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/graph/GraphStoreClientTest.java
@@ -0,0 +1,182 @@
+/*
+ * 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.hugegraph.store.client.graph;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hugegraph.store.grpc.GraphStoreGrpc;
+import org.apache.hugegraph.store.grpc.GraphStoreGrpc.GraphStoreStub;
+import org.apache.hugegraph.store.grpc.Graphpb.ScanPartitionRequest;
+import org.apache.hugegraph.store.grpc.Graphpb.ScanPartitionRequest.Reply;
+import org.apache.hugegraph.store.grpc.Graphpb.ScanResponse;
+import org.junit.Test;
+
+import com.google.protobuf.util.JsonFormat;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.stub.StreamObserver;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class GraphStoreClientTest {
+
+ private final AtomicInteger sum = new AtomicInteger();
+ ConcurrentHashMap> observers =
+ new ConcurrentHashMap<>();
+
+ @Test
+ public void getData() {
+ long start = System.currentTimeMillis();
+ String[] addresses = new String[]{"10.14.139.71:8500",
+ "10.14.139.70:8500",
+ "10.14.139.69:8500"};
+ Arrays.stream(addresses).parallel().forEach(address -> {
+ int size = 72;
+ CountDownLatch latch = new CountDownLatch(size);
+
+ for (int i = 0; i < size; i++) {
+ int finalI = i;
+ new Thread(() -> getData(finalI, latch, address)).start();
+ }
+ try {
+ latch.await();
+
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ long end = System.currentTimeMillis();
+ System.out.println(
+ "all rows are: " + sum.get() + ", end: " + (end - start));
+ }
+
+ public void getData(int pId, CountDownLatch latch, String address) {
+ try {
+ ScanPartitionRequest.Builder builder =
+ ScanPartitionRequest.newBuilder();
+ ScanPartitionRequest.Request.Builder srb =
+ ScanPartitionRequest.Request.newBuilder();
+ ArrayList properties = new ArrayList<>() {{
+ add(2L);
+ add(3L);
+ }};
+ ScanPartitionRequest.Request request =
+ srb.setGraphName("DEFAULT/hugegraph0/g")
+ .setScanType(
+ ScanPartitionRequest.ScanType.SCAN_VERTEX).setBoundary(0x10)
+ // .addAllProperties(properties)
+ // .setCondition("element.id().asString().equals
+ // ('1:marko1')")
+ .setPartitionId(pId).build();
+ ManagedChannel c =
+ ManagedChannelBuilder.forTarget(address)
+ .usePlaintext().build();
+ int maxSize = 1024 * 1024 * 1024;
+ GraphStoreStub stub;
+ stub = GraphStoreGrpc.newStub(c)
+ .withMaxInboundMessageSize(maxSize)
+ .withMaxOutboundMessageSize(maxSize);
+
+ AtomicInteger count = new AtomicInteger();
+ long start = System.currentTimeMillis();
+ long id = Thread.currentThread().getId();
+ StreamObserver ro =
+ new StreamObserver() {
+ @Override
+ public void onNext(ScanResponse value) {
+ try {
+ int edgeSize = value.getEdgeCount();
+ int vertexSize = value.getVertexCount();
+ if (request.getScanType().equals(
+ ScanPartitionRequest.ScanType.SCAN_VERTEX)) {
+ count.getAndAdd(vertexSize);
+ } else {
+ count.getAndAdd(edgeSize);
+ }
+ String print = JsonFormat.printer().print
+ (value);
+ System.out.println(print);
+ ScanPartitionRequest.Builder builder =
+ ScanPartitionRequest.newBuilder();
+ builder.setScanRequest(request);
+ Reply.Builder reply = Reply.newBuilder();
+ reply.setSeqNo(1);
+ builder.setReplyRequest(reply);
+ observers.get(id).onNext(builder.build());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ System.out.println(t);
+ latch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ long time = System.currentTimeMillis() - start;
+ System.out.println(
+ "scan id :" + pId + ", complete: " +
+ count.get() + ",time: " + time);
+ sum.addAndGet(count.get());
+ latch.countDown();
+ }
+ };
+ StreamObserver observer =
+ stub.scanPartition(ro);
+ observers.put(id, observer);
+ builder.setScanRequest(request);
+ observer.onNext(builder.build());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @Test
+ public void getDataSingle() {
+ CountDownLatch latch = new CountDownLatch(1);
+ new Thread(() -> getData(58, latch, "10.14.139.71:8500")).start();
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("all rows are: " + sum.get());
+ }
+
+ @Test
+ public void getNativeDataSingle() {
+ CountDownLatch latch = new CountDownLatch(1);
+ new Thread(() -> getData(0, latch, "127.0.0.1:8500")).start();
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("all rows are: " + sum.get());
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BaseCommonTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BaseCommonTest.java
index 0067b11ae7..7508ec4d5e 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BaseCommonTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BaseCommonTest.java
@@ -21,7 +21,6 @@
import org.junit.BeforeClass;
public class BaseCommonTest {
-
@BeforeClass
public static void beforeClass() throws Exception {
}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BitsTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BitsTest.java
index afa1f2baba..a665b4d764 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BitsTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/BitsTest.java
@@ -22,7 +22,6 @@
// import org.junit.Test;
public class BitsTest {
-
// @Test
public void test() {
for (int i = 0; i < Integer.MAX_VALUE; i = i + 10) {
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/ByteBufferAllocatorTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/ByteBufferAllocatorTest.java
index 0faf3457c7..90aae3a2e8 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/ByteBufferAllocatorTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/ByteBufferAllocatorTest.java
@@ -27,7 +27,6 @@
@Slf4j
public class ByteBufferAllocatorTest extends BaseCommonTest {
-
@Test
public void getAndReleaseTest() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(2);
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/CommonSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/CommonSuiteTest.java
index 092cc804fe..2ef65cf3b0 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/CommonSuiteTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/common/CommonSuiteTest.java
@@ -30,5 +30,4 @@
@Slf4j
public class CommonSuiteTest {
-
}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/BaseCoreTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/BaseCoreTest.java
new file mode 100644
index 0000000000..3ecbb1da73
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/BaseCoreTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hugegraph.store.core;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.BeforeClass;
+
+
+public class BaseCoreTest {
+
+ @BeforeClass
+ public static void setup() throws Exception {
+
+ }
+
+ public static void deleteDirectory(File dir) {
+ try {
+ FileUtils.deleteDirectory(dir);
+ } catch (IOException e) {
+ System.out.printf("Failed to start ....,%s%n", e.getMessage());
+ }
+ }
+
+ @After
+ public void teardown() throws Exception {
+ // pass
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java
new file mode 100644
index 0000000000..9781b06a7b
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hugegraph.store.core;
+
+import lombok.extern.slf4j.Slf4j;
+
+// TODO: uncomment it until all test can run free.
+//@RunWith(Suite.class)
+//@Suite.SuiteClasses({
+// HgCmdClientTest.class,
+// HgSnapshotHandlerTest.class,
+// RaftUtilsTest.class,
+// RaftOperationTest.class,
+// UnsafeUtilTest.class,
+// CopyOnWriteCacheTest.class,
+// MetricServiceTest.class,
+// TaskManagerTest.class,
+// CleanTaskTest.class,
+// MetadataKeyHelperTest.class,
+// HgStoreEngineTest.class,
+// PartitionEngineTest.class,
+// PartitionManagerTest.class,
+// PartitionMetaStoreWrapperTest.class,
+// ZipUtilsTest.class,
+// MiscUtilClassTest.class,
+// PartitionInstructionProcessorTest.class,
+// // 尽量放到最后
+// HgBusinessImplTest.class
+//})
+
+@Slf4j
+public class CoreSuiteTest {
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreTest.java
new file mode 100644
index 0000000000..6af95dac56
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.hugegraph.store.core;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class CoreTest {
+
+ @Test
+ public void testDemo() {
+ String s = "i am core";
+ log.info("UT:{}", s);
+ Assert.assertTrue(s.startsWith("i"));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgBusinessImplTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgBusinessImplTest.java
new file mode 100644
index 0000000000..d30e37e8a3
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgBusinessImplTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.hugegraph.store.core;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hugegraph.rocksdb.access.RocksDBFactory;
+import org.apache.hugegraph.rocksdb.access.RocksDBSession;
+import org.apache.hugegraph.rocksdb.access.ScanIterator;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.hugegraph.store.business.BusinessHandler;
+import org.apache.hugegraph.util.Bytes;
+import org.junit.Assert;
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+
+@Slf4j
+public class HgBusinessImplTest extends StoreEngineTestBase {
+
+ public static final String TABLE_NAME = UnitTestBase.DEFAULT_TEST_TABLE;
+ public BusinessHandler getBusinessHandler() {
+ return getStoreEngine().getBusinessHandler();
+ }
+
+ @Test
+ public void testPut() throws InterruptedException {
+
+ String graph1 = "testPut-graph1";
+ String graph2 = "testPut-graph2";
+
+ createPartitionEngine(0, graph1);
+ createPartitionEngine(0, graph2);
+
+ BusinessHandler handler = getBusinessHandler();
+ handler.doPut(graph1, 0, TABLE_NAME, "key1".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xF, TABLE_NAME, "key2".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xFF, TABLE_NAME, "key3".getBytes(), "value1".getBytes());
+ handler.doPut(graph1, 0xFFF, TABLE_NAME, "key4".getBytes(), "value1".getBytes());
+
+ handler.doPut(graph2, 0, TABLE_NAME, "key21".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xF, TABLE_NAME, "key22".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xFF, TABLE_NAME, "key23".getBytes(), "value1".getBytes());
+ handler.doPut(graph2, 0xFFF, TABLE_NAME, "key24".getBytes(), "value1".getBytes());
+
+ System.out.println("--------------------dump all -------");
+ dump(handler, graph1, 0);
+ System.out.println("--------------------dump scan 0 0xff -------");
+ ScanIterator iterator = handler.scan(graph1, TABLE_NAME, 0, 0xff);
+ int count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(2, count);
+
+ System.out.println("--------------------dump scan prefix -------");
+ iterator = handler.scanPrefix(graph1, 0, TABLE_NAME, "key".getBytes());
+
+ count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(4, count);
+ System.out.println("--------------------dump scan range key1 key4 -------");
+ iterator = handler.scan(graph1, 0, TABLE_NAME, "key1".getBytes(), "key4".getBytes(),
+ ScanIterator.Trait.SCAN_LT_END);
+ count = 0;
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn entry = iterator.next();
+ System.out.println(new String(entry.name) + " -- " + Bytes.toHex(entry.name));
+ count++;
+ }
+
+ Assert.assertEquals(3, count);
+ boolean cleanResult = handler.cleanPartition(graph1, 0);
+ Assert.assertTrue(cleanResult);
+ Thread.sleep(2000);
+
+ handler.closeAll();
+ }
+
+ @Test
+ public void testLoadSnapshot() throws InterruptedException {
+
+ String graph1 = "LoadSnapshot-graph1";
+ createPartitionEngine(0, graph1);
+ BusinessHandler handler = getBusinessHandler();
+
+ for (int i = 0; i < 256; i++) {
+ handler.doPut(graph1, i, TABLE_NAME, ("key" + i).getBytes(), "value1".getBytes());
+ }
+ ScanIterator iterator = handler.scanAll(graph1, TABLE_NAME);
+
+ System.out.println(iterator.count());
+
+ String snapshotPath;
+ try (RocksDBSession session = handler.getSession(0)) {
+ snapshotPath = session.getDbPath();
+ }
+
+ handler.closeAll();
+
+ System.out.println("start loadSnapshot");
+ handler.loadSnapshot(snapshotPath, graph1, 0, 10);
+ iterator = handler.scanAll(graph1, TABLE_NAME);
+ Assert.assertEquals(255, iterator.count());
+ try (RocksDBSession session = handler.getSession(0)) {
+ System.out.println(session.getDbPath());
+ }
+
+ CountDownLatch latch = new CountDownLatch(1);
+ RocksDBFactory.getInstance()
+ .addRocksdbChangedListener(new RocksDBFactory.RocksdbChangedListener() {
+ @Override
+ public void onCompacted(String dbName) {
+ RocksDBFactory.RocksdbChangedListener.super.onCompacted(dbName);
+ }
+
+ @Override
+ public void onDBDeleteBegin(String dbName, String filePath) {
+ RocksDBFactory.RocksdbChangedListener.super.onDBDeleteBegin(dbName,
+ filePath);
+ }
+
+ @Override
+ public void onDBDeleted(String dbName, String filePath) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onDBSessionReleased(RocksDBSession dbSession) {
+ RocksDBFactory.RocksdbChangedListener.super.onDBSessionReleased(
+ dbSession);
+ }
+ });
+
+ latch.await(1, TimeUnit.SECONDS);
+
+ }
+
+ public void dump(BusinessHandler handler, String graph, int partId) {
+ ScanIterator cfIterator = handler.scanRaw(graph, partId, 0);
+ while (cfIterator.hasNext()) {
+ try (ScanIterator iterator = cfIterator.next()) {
+ byte[] cfName = cfIterator.position();
+ System.out.println(graph + "-" + partId + "-" + new String(cfName) + "--------");
+ while (iterator.hasNext()) {
+ RocksDBSession.BackendColumn col = iterator.next();
+ System.out.println(new String(col.name) + " -- " + Bytes.toHex(col.name));
+ }
+ }
+ }
+ cfIterator.close();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java
new file mode 100644
index 0000000000..d31e01724a
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java
@@ -0,0 +1,359 @@
+/*
+ * 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.hugegraph.store.core;
+
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toIntBytes;
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toOwnerKey;
+import static org.apache.hugegraph.store.client.util.HgStoreClientUtil.toStr;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.hugegraph.pd.client.PDClient;
+import org.apache.hugegraph.pd.client.PDConfig;
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgOwnerKey;
+import org.apache.hugegraph.store.HgStoreClient;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.hugegraph.store.cmd.BatchPutRequest;
+import org.apache.hugegraph.store.cmd.BatchPutResponse;
+import org.apache.hugegraph.store.cmd.CleanDataRequest;
+import org.apache.hugegraph.store.cmd.CleanDataResponse;
+import org.apache.hugegraph.store.cmd.HgCmdClient;
+import org.apache.hugegraph.store.meta.Store;
+import org.apache.hugegraph.store.pd.DefaultPdProvider;
+import org.apache.hugegraph.store.pd.PdProvider;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.alipay.sofa.jraft.JRaftUtils;
+import com.alipay.sofa.jraft.option.RpcOptions;
+import com.alipay.sofa.jraft.util.Endpoint;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class HgCmdClientTest {
+
+ private static AtomicLong id;
+ private final String pdAddress = "127.0.0.1:8686";
+ private final String graphName = "hugegraph";
+ private final String tableName = UnitTestBase.DEFAULT_TEST_TABLE;
+ private PdProvider pdProvider;
+ private HgCmdClient hgCmdClient;
+ private HgStoreClient storeClient;
+ private PDClient pdClient;
+
+ public static String getMd5(String txt) {
+ String rs = "";
+ String[] hexDigits =
+ {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+ byte[] b = messageDigest.digest(txt.getBytes());
+ StringBuffer resultSb = new StringBuffer();
+ for (int i = 0; i < b.length; i++) {
+ int n = b[i];
+ if (n < 0) {
+ n = 256 + n;
+ }
+ int d1 = n / 16;
+ int d2 = n % 16;
+ resultSb.append(hexDigits[d1] + hexDigits[d2]);
+ }
+ rs = resultSb.toString();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return rs;
+ }
+
+ public static Long getId() {
+ // 如果需要更长 或者更大冗余空间,只需要 time * 10^n 即可
+ // 当前可保证 1 毫秒 生成 10000 条不重复
+ Long time = Long.valueOf(new SimpleDateFormat("HHmmssSSS").format(new Date())) * 10000 +
+ (long) (Math.random() * 100);
+// Long time = Long.valueOf(new SimpleDateFormat("MMddhhmmssSSS").format(new Date())
+// .toString());
+// System.out.println(time);
+ if (id == null) {
+ id = new AtomicLong(time);
+ return id.get();
+ }
+ if (time <= id.get()) {
+ id.addAndGet(1);
+ } else {
+ id = new AtomicLong(time);
+ }
+ return id.get();
+ }
+
+ @Test
+ public void testGetStoreInfo() {
+
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), null);
+
+ Store response = hgCmdClient.getStoreInfo(pdAddress);
+
+ }
+
+ // @Test
+ public void testBatchPut() {
+
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), new HgCmdClient.PartitionAgent() {
+ @Override
+ public Endpoint getPartitionLeader(String graphName, int partitionId) {
+ Metapb.Shard shard = pdProvider.getPartitionLeader(graphName, partitionId);
+ return JRaftUtils.getEndPoint(
+ pdProvider.getStoreByID(shard.getStoreId()).getRaftAddress());
+ }
+ });
+
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddress)
+ .setEnableCache(true));
+ HgStoreSession session = storeClient.openSession(graphName);
+ pdClient = storeClient.getPdClient();
+ session.createTable(tableName);
+ String createGraph = "create_graph";
+ HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
+ // 需要写数据,才会创建图
+ session.put(tableName,
+ hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
+ Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
+
+ Integer partId = 0;
+ String key = "key-1";
+ List kvs = new LinkedList<>();
+ int x = 0;
+ for (int i = 1; i <= 3; i++) {
+ key = "key-" + i;
+ BatchPutRequest.KV kv = BatchPutRequest.KV.of(tableName, 1,
+ key.getBytes(StandardCharsets.UTF_8),
+ key.getBytes(StandardCharsets.UTF_8));
+ kvs.add(kv);
+
+ BatchPutRequest request = new BatchPutRequest();
+ request.setGraphName(graphName);
+ request.setPartitionId(partId);
+ request.setEntries(kvs);
+
+ try {
+ BatchPutResponse response = hgCmdClient.batchPut(request);
+ if (response == null) {
+ log.error("response is null ");
+ } else if (response.getStatus() == null) {
+ log.error("response status is null");
+ }
+
+ log.info("response status:{} {}", response.getStatus(), i);
+
+ Assert.assertTrue(response.getStatus().isOK());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ HgKvIterator hgKvIterator = session.scanIterator(tableName);
+ Assert.assertTrue(hgKvIterator.hasNext());
+ boolean findKey = false;
+ while (hgKvIterator.hasNext()) {
+ HgKvEntry entry = hgKvIterator.next();
+ if (toStr(entry.key()).equals(key) && toStr(entry.value()).equals(key)) {
+ log.info("key={} value={}", toStr(entry.key()), toStr(entry.value()));
+ findKey = true;
+ }
+ }
+ Assert.assertTrue(findKey);
+ }
+
+ // @Test
+ public void testCleanData() {
+
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), new HgCmdClient.PartitionAgent() {
+ @Override
+ public Endpoint getPartitionLeader(String graphName, int partitionId) {
+ Metapb.Shard shard = pdProvider.getPartitionLeader(graphName, partitionId);
+ return JRaftUtils.getEndPoint(
+ pdProvider.getStoreByID(shard.getStoreId()).getRaftAddress());
+ }
+ });
+
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddress)
+ .setEnableCache(true));
+ HgStoreSession session = storeClient.openSession(graphName);
+ pdClient = storeClient.getPdClient();
+ session.createTable(tableName);
+ String createGraph = "create_graph";
+ HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
+ // 需要写数据,才会创建图
+ session.put(tableName,
+ hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
+ Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
+
+ Integer partId = 0;
+
+ Metapb.Partition pt = Metapb.Partition.newBuilder().build();
+ CleanDataRequest request = new CleanDataRequest();
+ request.setGraphName(graphName);
+ request.setPartitionId(partId);
+
+ try {
+ CleanDataResponse response = hgCmdClient.cleanData(request);
+ if (response == null) {
+ log.error("response is null ");
+ } else if (response.getStatus() == null) {
+ log.error("response status is null");
+ }
+
+ log.info("response status:{} ", response.getStatus());
+
+ Assert.assertTrue(response.getStatus().isOK());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // @Test
+ // TODO: partition not local
+ public void testUpdatePartitionLeader() {
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), new HgCmdClient.PartitionAgent() {
+ @Override
+ public Endpoint getPartitionLeader(String graphName, int partitionId) {
+ Metapb.Shard shard = pdProvider.getPartitionLeader(graphName, partitionId);
+ return JRaftUtils.getEndPoint(
+ pdProvider.getStoreByID(shard.getStoreId()).getRaftAddress());
+ }
+ });
+
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddress)
+ .setEnableCache(true));
+ HgStoreSession session = storeClient.openSession(graphName);
+ pdClient = storeClient.getPdClient();
+ session.createTable(tableName);
+ String createGraph = "create_graph";
+ HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
+ // 需要写数据,才会创建图
+ session.put(tableName,
+ hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
+ Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
+
+ }
+
+ // @Test
+ // TODO: partition not local
+ public void testData() {
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), new HgCmdClient.PartitionAgent() {
+ @Override
+ public Endpoint getPartitionLeader(String graphName, int partitionId) {
+ Metapb.Shard shard = pdProvider.getPartitionLeader(graphName, partitionId);
+ return JRaftUtils.getEndPoint(
+ pdProvider.getStoreByID(shard.getStoreId()).getRaftAddress());
+ }
+ });
+
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddress)
+ .setEnableCache(true));
+ HgStoreSession session = storeClient.openSession("hugegraphtest");
+ pdClient = storeClient.getPdClient();
+ session.truncate();
+
+ int loop = 3;
+
+ for (int i = 0; i < loop; i++) {
+ HgOwnerKey hgOwnerKey = toOwnerKey(i + "owner:" + i, i + "k:" + i);
+ session.put(tableName, hgOwnerKey, toIntBytes(i));
+ }
+
+ try {
+ HgKvIterator iterable = session.scanIterator(tableName);
+ int x = 0;
+ while (iterable.hasNext()) {
+ HgKvEntry entry = iterable.next();
+ log.info("data:{}-{}", toStr(entry.key()), entry.value());
+ x++;
+ }
+ log.info("x={}", x);
+ Assert.assertEquals(x, loop);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // @Test
+ // TODO: partition not local
+ public void testCompressionData() {
+
+ hgCmdClient = new HgCmdClient();
+ pdProvider = new DefaultPdProvider(pdAddress);
+ hgCmdClient.init(new RpcOptions(), new HgCmdClient.PartitionAgent() {
+ @Override
+ public Endpoint getPartitionLeader(String graphName, int partitionId) {
+ Metapb.Shard shard = pdProvider.getPartitionLeader(graphName, partitionId);
+ return JRaftUtils.getEndPoint(
+ pdProvider.getStoreByID(shard.getStoreId()).getRaftAddress());
+ }
+ });
+
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddress)
+ .setEnableCache(true));
+ HgStoreSession session = storeClient.openSession("hugegraphtest");
+ pdClient = storeClient.getPdClient();
+ session.truncate();
+
+ int loop = 10;
+
+ for (int i = 0; i < loop; i++) {
+ String key = "d41d8cd98f00b204e9800998ecf8427e" + getMd5("a" + i) + getId();
+ String value = "10000" + getId() + getId();
+ HgOwnerKey hgOwnerKey = toOwnerKey("d41d8cd98f00b204e9800998ecf8427e", key);
+ session.put(tableName, hgOwnerKey, value.getBytes());
+ }
+
+ try {
+ HgKvIterator iterable = session.scanIterator(tableName);
+ int x = 0;
+ while (iterable.hasNext()) {
+ HgKvEntry entry = iterable.next();
+ x++;
+ }
+ log.info("x={}", x);
+ Assert.assertEquals(x, loop);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/MetricServiceTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/MetricServiceTest.java
new file mode 100644
index 0000000000..bc7ff64021
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/MetricServiceTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hugegraph.store.core;
+
+import java.util.Map;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgStoreEngine;
+import org.apache.hugegraph.store.metric.HgMetricService;
+import org.apache.hugegraph.store.metric.SystemMetricService;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MetricServiceTest {
+
+ private SystemMetricService service;
+ private HgMetricService hgService;
+
+ @Before
+ public void setUp() {
+ service = new SystemMetricService();
+ HgStoreEngine instance = HgStoreEngine.getInstance();
+ service.setStoreEngine(instance);
+ hgService = HgMetricService.getInstance().setHgStoreEngine(instance);
+ }
+
+ @Test
+ public void testGetStorageEngine() {
+ HgStoreEngine result = service.getStorageEngine();
+ }
+
+ @Test
+ public void testGetSystemMetrics() {
+ try {
+ Map systemMetrics = service.getSystemMetrics();
+ Thread.sleep(1000);
+ systemMetrics = service.getSystemMetrics();
+ } catch (Exception e) {
+
+ }
+ }
+
+ @Test
+ public void testGetHgMetrics() {
+ // Setup
+ Metapb.StoreStats.Builder systemMetrics = hgService.getMetrics();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java
new file mode 100644
index 0000000000..267b5a566d
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java
@@ -0,0 +1,138 @@
+/*
+ * 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.hugegraph.store.core;
+
+import java.io.File;
+import java.util.HashMap;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgStoreEngine;
+import org.apache.hugegraph.store.PartitionEngine;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.hugegraph.store.business.DefaultDataMover;
+import org.apache.hugegraph.store.meta.Partition;
+import org.apache.hugegraph.store.meta.ShardGroup;
+import org.apache.hugegraph.store.options.HgStoreEngineOptions;
+import org.apache.hugegraph.store.options.RaftRocksdbOptions;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import com.alipay.sofa.jraft.util.StorageOptionsFactory;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 使用 FakePd 和 FakePdOptions,初始化 HgStoreEngine,该类的各项 get 函数可用
+ */
+@Slf4j
+public class StoreEngineTestBase {
+
+ private static final String DB_PATH = "/tmp/junit";
+ private static int initCount = 0;
+
+ @BeforeClass
+ public static void initEngine() {
+ UnitTestBase.deleteDir(new File(DB_PATH));
+
+ HgStoreEngineOptions options = new HgStoreEngineOptions();
+ options.setDataPath(DB_PATH);
+ options.setRaftPath(DB_PATH);
+ options.setFakePD(true);
+ options.setRocksdbConfig(new HashMap<>() {{
+ put("rocksdb.write_buffer_size", "1048576");
+ }});
+ options.setGrpcAddress("127.0.0.1:6511");
+ options.setRaftAddress("127.0.0.1:6510");
+ options.setDataTransfer(new DefaultDataMover());
+
+ options.setFakePdOptions(new HgStoreEngineOptions.FakePdOptions() {{
+ setStoreList("127.0.0.1");
+ setPeersList("127.0.0.1");
+ setPartitionCount(1);
+ setShardCount(1);
+ }});
+
+ if (initCount == 0) {
+ StorageOptionsFactory.releaseAllOptions();
+ RaftRocksdbOptions.initRocksdbGlobalConfig(options.getRocksdbConfig());
+ initCount++;
+ }
+ HgStoreEngine.getInstance().init(options);
+ }
+
+ public static Partition getPartition(int partitionId) {
+ return getPartition(partitionId, "graph0");
+ }
+
+ public static Partition getPartition(int partitionId, String graphName) {
+ Partition partition = new Partition();
+ partition.setId(partitionId);
+ partition.setGraphName(graphName);
+ partition.setStartKey(0);
+ partition.setEndKey(65535);
+ partition.setWorkState(Metapb.PartitionState.PState_Normal);
+ partition.setVersion(1);
+ return partition;
+ }
+
+ /**
+ * 创建 分区为 0 的 partition engine. 该分区 1 个 shard,为 leader, graph name: graph0
+ *
+ * @return
+ */
+ public static PartitionEngine createPartitionEngine(int partitionId) {
+ return createPartitionEngine(partitionId, "graph0");
+ }
+
+ public static PartitionEngine createPartitionEngine(int partitionId, String graphName) {
+ Metapb.Shard shard = Metapb.Shard.newBuilder()
+ .setStoreId(FakePdServiceProvider.makeStoreId(
+ "127.0.0.1:6511"))
+ .setRole(Metapb.ShardRole.Leader)
+ .build();
+
+ Metapb.ShardGroup shardGroup = Metapb.ShardGroup.newBuilder()
+ .setId(partitionId)
+ .setConfVer(1)
+ .setVersion(1)
+ .setState(
+ Metapb.PartitionState.PState_Normal)
+ .addShards(shard)
+ .build();
+
+ getStoreEngine().getPartitionManager().updateShardGroup(ShardGroup.from(shardGroup));
+
+ var engine = getStoreEngine().createPartitionEngine(getPartition(partitionId, graphName));
+ engine.waitForLeader(2000);
+ return engine;
+ }
+
+ public static HgStoreEngine getStoreEngine() {
+ return HgStoreEngine.getInstance();
+ }
+
+ @AfterClass
+ public static void shutDownEngine() {
+ try {
+ HgStoreEngine.getInstance().shutdown();
+ } catch (Exception e) {
+ log.error("shut down engine error: {}", e.getMessage());
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/HgStoreStateMachineTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/HgStoreStateMachineTest.java
new file mode 100644
index 0000000000..752a17ea59
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/HgStoreStateMachineTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.hugegraph.store.core.raft;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hugegraph.store.raft.HgStoreStateMachine;
+import org.apache.hugegraph.store.raft.RaftClosure;
+import org.apache.hugegraph.store.raft.RaftOperation;
+import org.apache.hugegraph.store.raft.RaftStateListener;
+import org.apache.hugegraph.store.raft.RaftTaskHandler;
+import org.apache.hugegraph.store.snapshot.HgSnapshotHandler;
+import org.apache.hugegraph.store.util.HgStoreException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import com.alipay.sofa.jraft.Closure;
+import com.alipay.sofa.jraft.Iterator;
+import com.alipay.sofa.jraft.Status;
+import com.alipay.sofa.jraft.conf.Configuration;
+import com.alipay.sofa.jraft.entity.LeaderChangeContext;
+import com.alipay.sofa.jraft.entity.PeerId;
+import com.alipay.sofa.jraft.entity.Task;
+import com.alipay.sofa.jraft.error.RaftError;
+import com.alipay.sofa.jraft.error.RaftException;
+
+@RunWith(MockitoJUnitRunner.class)
+public class HgStoreStateMachineTest {
+
+ @Mock
+ private HgSnapshotHandler mockSnapshotHandler;
+
+ private HgStoreStateMachine hgStoreStateMachineUnderTest;
+
+ @Before
+ public void setUp() {
+ hgStoreStateMachineUnderTest = new HgStoreStateMachine(0, mockSnapshotHandler);
+ }
+
+ @Test
+ public void testAddTaskHandler() {
+ // Setup
+ final RaftTaskHandler handler = new RaftTaskHandler() {
+ @Override
+ public boolean invoke(int groupId, byte[] request, RaftClosure response) throws
+ HgStoreException {
+ return false;
+ }
+
+ @Override
+ public boolean invoke(int groupId, byte methodId, Object req, RaftClosure response)
+ throws HgStoreException {
+ return false;
+ }
+ };
+
+ // Run the test
+ hgStoreStateMachineUnderTest.addTaskHandler(handler);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testAddStateListener() {
+ // Setup
+ final RaftStateListener mockListener = new RaftStateListener() {
+ @Override
+ public void onLeaderStart(long newTerm) {
+
+ }
+
+ @Override
+ public void onError(RaftException e) {
+
+ }
+ };
+
+ // Run the test
+ hgStoreStateMachineUnderTest.addStateListener(mockListener);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testIsLeader() {
+ // Setup
+ // Run the test
+ final boolean result = hgStoreStateMachineUnderTest.isLeader();
+
+ // Verify the results
+ assertFalse(result);
+ }
+
+ @Test
+ public void testOnApply() {
+ RaftOperation op = RaftOperation.create((byte) 0b0);
+ final Task task = new Task();
+ task.setData(ByteBuffer.wrap(op.getValues()));
+ task.setDone(new HgStoreStateMachine.RaftClosureAdapter(op, closure -> {
+
+ }));
+
+ List tasks = new ArrayList<>();
+ tasks.add(task);
+ // Setup
+ final Iterator inter = new Iterator() {
+ final java.util.Iterator iterator = tasks.iterator();
+ Task task;
+
+ @Override
+ public ByteBuffer getData() {
+ return task.getData();
+ }
+
+ @Override
+ public long getIndex() {
+ return 0;
+ }
+
+ @Override
+ public long getTerm() {
+ return 0;
+ }
+
+ @Override
+ public Closure done() {
+ return null;
+ }
+
+ @Override
+ public void setErrorAndRollback(long ntail, Status st) {
+
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public ByteBuffer next() {
+ task = iterator.next();
+ return task.getData();
+ }
+ };
+
+ // Run the test
+ hgStoreStateMachineUnderTest.onApply(inter);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testGetLeaderTerm() {
+ // Setup
+ // Run the test
+ final long result = hgStoreStateMachineUnderTest.getLeaderTerm();
+
+ // Verify the results
+ assertEquals(-1L, result);
+ }
+
+
+ @Test
+ public void testOnLeaderStart() {
+ // Setup
+ // Run the test
+ hgStoreStateMachineUnderTest.onLeaderStart(0L);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testOnLeaderStop() {
+ // Setup
+ final Status status = new Status(RaftError.UNKNOWN, "fmt", "args");
+
+ // Run the test
+ hgStoreStateMachineUnderTest.onLeaderStop(status);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testOnStartFollowing() {
+ // TODO: uncomment later (jraft)
+// // Setup
+// final LeaderChangeContext ctx =
+// new LeaderChangeContext(new PeerId("ip", 0, 0, 0), "groupId", 0L,
+// new Status(RaftError.UNKNOWN, "fmt", "args"));
+//
+// // Run the test
+// hgStoreStateMachineUnderTest.onStartFollowing(ctx);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testOnStopFollowing() {
+ // TODO: uncomment later (jraft)
+// // Setup
+// final LeaderChangeContext ctx =
+// new LeaderChangeContext(new PeerId("ip", 0, 0, 0), "groupId", 0L,
+// new Status(RaftError.UNKNOWN, "fmt", "args"));
+//
+// // Run the test
+// hgStoreStateMachineUnderTest.onStopFollowing(ctx);
+
+ // Verify the results
+ }
+
+ @Test
+ public void testOnConfigurationCommitted() {
+ // Setup
+ final Configuration conf = new Configuration(List.of(new PeerId("ip", 0, 0, 0)),
+ List.of(new PeerId("ip", 0, 0, 0)));
+
+ // Run the test
+ hgStoreStateMachineUnderTest.onConfigurationCommitted(conf);
+
+ // Verify the results
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/MockStateMachine.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/MockStateMachine.java
new file mode 100644
index 0000000000..2af5c683c9
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/MockStateMachine.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hugegraph.store.core.raft;
+
+import com.alipay.sofa.jraft.Iterator;
+import com.alipay.sofa.jraft.core.StateMachineAdapter;
+
+public class MockStateMachine extends StateMachineAdapter {
+ @Override
+ public void onApply(Iterator iter) {
+ while (iter.hasNext()) {
+ iter.next();
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftOperationTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftOperationTest.java
new file mode 100644
index 0000000000..586c2d8c10
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftOperationTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.hugegraph.store.core.raft;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.raft.RaftOperation;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.protobuf.GeneratedMessageV3;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+public class RaftOperationTest {
+
+ private RaftOperation raftOperationUnderTest;
+
+ @Before
+ public void setUp() {
+ raftOperationUnderTest = new RaftOperation();
+ }
+
+
+ @Test
+ public void testCreate1() {
+ // Run the test
+ final RaftOperation result = RaftOperation.create((byte) 0b0);
+ assertEquals(null, result.getReq());
+ assertEquals((byte) 0b0, result.getOp());
+ }
+
+ @Test
+ public void testCreate2() {
+ // Run the test
+ final RaftOperation result = RaftOperation.create((byte) 0b0, "content".getBytes(), "req");
+ assertArrayEquals("content".getBytes(), result.getValues());
+ assertEquals("req", result.getReq());
+ assertEquals((byte) 0b0, result.getOp());
+ }
+
+ @Test
+ public void testCreate3() {
+ // Run the test
+ final RaftOperation result = RaftOperation.create((byte) 0b0, "req");
+ assertEquals("req", result.getReq());
+ assertEquals((byte) 0b0, result.getOp());
+ }
+
+ @Test
+ public void testCreate4() throws Exception {
+ // Setup
+ final GeneratedMessageV3 req = Metapb.Graph.newBuilder().setGraphName("name").build();
+
+ // Run the test
+ final RaftOperation result = RaftOperation.create((byte) 0b0, req);
+ assertEquals((byte) 0b0, result.getOp());
+
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftUtilsTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftUtilsTest.java
new file mode 100644
index 0000000000..9f8b72b3b1
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/raft/RaftUtilsTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.hugegraph.store.core.raft;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.hugegraph.store.raft.util.RaftUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.alipay.sofa.jraft.Node;
+import com.alipay.sofa.jraft.NodeManager;
+import com.alipay.sofa.jraft.conf.Configuration;
+import com.alipay.sofa.jraft.core.NodeImpl;
+import com.alipay.sofa.jraft.entity.PeerId;
+import com.alipay.sofa.jraft.option.NodeOptions;
+import com.alipay.sofa.jraft.util.Endpoint;
+
+public class RaftUtilsTest {
+ final String ip = "127.0.0.1";
+ final int port = 12456;
+ final String dataPath = "tmp/raftUtils";
+
+ @Before
+ public void setUp() {
+
+ UnitTestBase.deleteDir(new File(dataPath));
+ new File(dataPath).mkdirs();
+ }
+
+ @Test
+ public void testGetAllEndpoints1() throws InterruptedException {
+ final Endpoint addr = new Endpoint(ip, port);
+ final PeerId peer = new PeerId(addr, 0);
+ NodeManager.getInstance().addAddress(addr);
+ final NodeOptions nodeOptions = new NodeOptions();
+ nodeOptions.setFsm(new MockStateMachine());
+ nodeOptions.setLogUri(this.dataPath + File.separator + "log");
+ nodeOptions.setRaftMetaUri(this.dataPath + File.separator + "meta");
+ nodeOptions.setSnapshotUri(this.dataPath + File.separator + "snapshot");
+ nodeOptions.setInitialConf(new Configuration(Collections.singletonList(peer)));
+ final Node node = new NodeImpl("unittest", new PeerId(addr, 0));
+ assertTrue(node.init(nodeOptions));
+ node.isLeader(true);
+
+ // Run the test
+ final List result = RaftUtils.getAllEndpoints(node);
+ // Verify the results
+ assertEquals(1, result.size());
+ node.shutdown();
+ node.join();
+
+ }
+
+ @Test
+ public void testGetAllEndpoints2() {
+ final Endpoint addr = new Endpoint(ip, port);
+ final PeerId peer = new PeerId(addr, 0);
+
+ Configuration conf = new Configuration(Collections.singletonList(peer));
+ // Run the test
+ final List result = RaftUtils.getAllEndpoints(conf);
+
+ // Verify the results
+ assertEquals(1, result.size());
+ }
+
+ @Test
+ public void testGetPeerEndpoints1() throws InterruptedException {
+ final Endpoint addr = new Endpoint(ip, port);
+ final PeerId peer = new PeerId(addr, 0);
+ NodeManager.getInstance().addAddress(addr);
+ final NodeOptions nodeOptions = new NodeOptions();
+ nodeOptions.setFsm(new MockStateMachine());
+ nodeOptions.setLogUri(this.dataPath + File.separator + "log");
+ nodeOptions.setRaftMetaUri(this.dataPath + File.separator + "meta");
+ nodeOptions.setSnapshotUri(this.dataPath + File.separator + "snapshot");
+ nodeOptions.setInitialConf(new Configuration(Collections.singletonList(peer)));
+ final Node node = new NodeImpl("unittest", new PeerId(addr, 0));
+ assertTrue(node.init(nodeOptions));
+ node.isLeader(true);
+
+
+ // Run the test
+ final List result = RaftUtils.getPeerEndpoints(node);
+ // Verify the results
+ assertEquals(1, result.size());
+ node.shutdown();
+ node.join();
+ }
+
+ @Test
+ public void testGetPeerEndpoints2() {
+ // Setup
+ final Configuration conf = new Configuration(List.of(new PeerId("ip", 0, 0, 0)),
+ List.of(new PeerId("ip", 0, 0, 0)));
+
+ // Run the test
+ final List result = RaftUtils.getPeerEndpoints(conf);
+
+ // Verify the results
+ assertEquals(1, result.size());
+ }
+
+ @Test
+ public void testGetLearnerEndpoints1() throws InterruptedException {
+ // Setup
+ final Endpoint addr = new Endpoint(ip, port);
+ final PeerId peer = new PeerId(addr, 0);
+ final PeerId peer2 = new PeerId(new Endpoint(ip, 13456), 0);
+ NodeManager.getInstance().addAddress(addr);
+ final NodeOptions nodeOptions = new NodeOptions();
+ nodeOptions.setFsm(new MockStateMachine());
+ nodeOptions.setLogUri(this.dataPath + File.separator + "log");
+ nodeOptions.setRaftMetaUri(this.dataPath + File.separator + "meta");
+ nodeOptions.setSnapshotUri(this.dataPath + File.separator + "snapshot");
+ nodeOptions.setInitialConf(new Configuration(Collections.singletonList(peer),
+ Collections.singletonList(peer2)));
+ final Node node = new NodeImpl("unittest", new PeerId(addr, 0));
+ assertTrue(node.init(nodeOptions));
+ node.isLeader(true);
+ // Run the test
+ final List result = RaftUtils.getLearnerEndpoints(node);
+
+ // Verify the results
+ assertEquals(1, result.size());
+ node.shutdown();
+ node.join();
+ }
+
+ @Test
+ public void testGetLearnerEndpoints2() {
+ // Setup
+ final Configuration conf = new Configuration(List.of(new PeerId("ip", 0, 0, 0)),
+ List.of(new PeerId("ip", 0, 0, 0)));
+
+ // Run the test
+ final List result = RaftUtils.getLearnerEndpoints(conf);
+
+ // Verify the results
+ assertEquals(1, result.size());
+ }
+
+ @Test
+ public void testConfigurationEquals() {
+ // Setup
+ final Configuration oldConf = new Configuration(List.of(new PeerId("ip", 0, 0, 0)),
+ List.of(new PeerId("ip", 0, 0, 0)));
+ final Configuration newConf = new Configuration(List.of(new PeerId("ip", 0, 0, 0)),
+ List.of(new PeerId("ip", 0, 0, 0)));
+
+ // Run the test
+ final boolean result = RaftUtils.configurationEquals(oldConf, newConf);
+
+ // Verify the results
+ assertTrue(result);
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/snapshot/HgSnapshotHandlerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/snapshot/HgSnapshotHandlerTest.java
new file mode 100644
index 0000000000..ff5ef24acf
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/snapshot/HgSnapshotHandlerTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.hugegraph.store.core.snapshot;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.meta.Partition;
+import org.apache.hugegraph.store.snapshot.HgSnapshotHandler;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.alipay.sofa.jraft.entity.RaftOutter;
+import com.alipay.sofa.jraft.storage.snapshot.SnapshotReader;
+import com.alipay.sofa.jraft.storage.snapshot.SnapshotWriter;
+import com.google.protobuf.Message;
+
+
+public class HgSnapshotHandlerTest extends StoreEngineTestBase {
+
+ private static HgSnapshotHandler hgSnapshotHandlerUnderTest;
+
+ @Before
+ public void setUp() throws IOException {
+ hgSnapshotHandlerUnderTest = new HgSnapshotHandler(createPartitionEngine(0));
+ FileUtils.forceMkdir(new File("/tmp/snapshot"));
+ FileUtils.forceMkdir(new File("/tmp/snapshot/data"));
+ }
+
+ @Test
+ public void testGetPartitions() {
+ // Run the test
+ final Map result = hgSnapshotHandlerUnderTest.getPartitions();
+ // Verify the results
+ assertEquals(1, result.size());
+ }
+
+ @Test
+ public void testOnSnapshotSaveAndLoad() {
+ String path = "/tmp/snapshot";
+ // Setup
+ final SnapshotWriter writer = new SnapshotWriter() {
+ @Override
+ public boolean saveMeta(RaftOutter.SnapshotMeta meta) {
+ return false;
+ }
+
+ @Override
+ public boolean addFile(String fileName, Message fileMeta) {
+ return false;
+ }
+
+ @Override
+ public boolean removeFile(String fileName) {
+ return false;
+ }
+
+ @Override
+ public void close(boolean keepDataOnError) throws IOException {
+
+ }
+
+ @Override
+ public boolean init(Void opts) {
+ return false;
+ }
+
+ @Override
+ public void shutdown() {
+
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public Set listFiles() {
+ return null;
+ }
+
+ @Override
+ public Message getFileMeta(String fileName) {
+ return null;
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+ };
+
+ // Run the test
+ hgSnapshotHandlerUnderTest.onSnapshotSave(writer);
+
+ // Verify the results
+
+ // Setup
+ final SnapshotReader reader = new SnapshotReader() {
+ final String path = "/tmp/snapshot";
+
+ @Override
+ public RaftOutter.SnapshotMeta load() {
+ return null;
+ }
+
+ @Override
+ public String generateURIForCopy() {
+ return null;
+ }
+
+ @Override
+ public boolean init(Void opts) {
+ return false;
+ }
+
+ @Override
+ public void shutdown() {
+
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public Set listFiles() {
+ return null;
+ }
+
+ @Override
+ public Message getFileMeta(String fileName) {
+ return null;
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+ };
+
+ // Run the test
+ hgSnapshotHandlerUnderTest.onSnapshotLoad(reader, 0L);
+ }
+
+
+ @Test
+ public void testTrimStartPath() {
+ assertEquals("str", HgSnapshotHandler.trimStartPath("str", "prefix"));
+ }
+
+ @Test
+ public void testFindFileList() {
+ // Setup
+ final File dir = new File("filename.txt");
+ final File rootDir = new File("filename.txt");
+
+ // Run the test
+ HgSnapshotHandler.findFileList(dir, rootDir, List.of("value"));
+
+ // Verify the results
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/HgStoreEngineTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/HgStoreEngineTest.java
new file mode 100644
index 0000000000..0bc54d4700
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/HgStoreEngineTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.hugegraph.store.core.store;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.HgStoreEngine;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.apache.hugegraph.testutil.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HgStoreEngineTest extends StoreEngineTestBase {
+
+ private HgStoreEngine engine;
+
+ @Before
+ public void setup() {
+ engine = HgStoreEngine.getInstance();
+ }
+
+ @Test
+ public void testGetInstance() {
+ assertNotNull(HgStoreEngine.getInstance());
+ }
+
+ // @Test
+ // TODO: npe and not leader
+ public void testStateChanged() {
+ createPartitionEngine(0);
+ var storeId = FakePdServiceProvider.makeStoreId("127.0.0.1:6511");
+ var store = engine.getPartitionManager().getStore(storeId);
+ engine.stateChanged(store, Metapb.StoreState.Offline, Metapb.StoreState.Up);
+ assertEquals(engine.getPartitionEngines().size(), 1);
+ }
+
+ @Test
+ public void testCreatePartitionEngine() {
+ var partition = getPartition(0);
+ assertNotNull(engine.createPartitionEngine(partition));
+ }
+
+ @Test
+ public void testCreatePartitionGroups() {
+ var partition = getPartition(0);
+ engine.createPartitionGroups(partition);
+ }
+
+ @Test
+ public void testDestroyPartitionEngine() {
+ createPartitionEngine(16);
+ engine.destroyPartitionEngine(16, List.of("graph0"));
+ // assertEquals(engine.getPartitionEngines().size(), 0);
+ }
+
+ @Test
+ public void testDeletePartition() {
+ createPartitionEngine(0);
+ engine.deletePartition(0, "graph0");
+ // TODO: check logic
+ assertEquals(engine.getPartitionEngines().size(), 1);
+ }
+
+ @Test
+ public void testGetLeaderPartition() throws InterruptedException {
+ createPartitionEngine(0);
+ assertEquals(engine.getLeaderPartition().size(), 1);
+ }
+
+ @Test
+ public void testGetAlivePeers() throws InterruptedException {
+ createPartitionEngine(0);
+ assertEquals(engine.getAlivePeers(0).size(), 1);
+ }
+
+ @Test
+ public void testGetLeaderTerm() {
+ createPartitionEngine(0);
+ // no vote
+ assertEquals(engine.getLeaderTerm(0), -1);
+ }
+
+ @Test
+ public void testGetCommittedIndex() throws InterruptedException {
+ createPartitionEngine(0);
+ // write something background
+ Assert.assertTrue(engine.getCommittedIndex(0) > 0);
+ }
+
+ @Test
+ public void testGetRaftRpcServer() {
+ assertNotNull(engine.getRaftRpcServer());
+ }
+
+ @Test
+ public void testGetPartitionManager() {
+ assertNotNull(engine.getPartitionManager());
+ }
+
+ @Test
+ public void testGetDataMover() {
+ assertNotNull(engine.getDataMover());
+ }
+
+ @Test
+ public void testGetPdProvider() {
+ assertNotNull(engine.getPdProvider());
+ }
+
+ @Test
+ public void testGetCmdClient() {
+ assertNotNull(engine.getHgCmdClient());
+ }
+
+ @Test
+ public void testGetHeartbeatService() {
+ assertNotNull(engine.getHeartbeatService());
+ }
+
+ @Test
+ public void testIsClusterReady() throws InterruptedException {
+ // wait heart beat
+ Thread.sleep(2000);
+ assertNotNull(engine.isClusterReady());
+ }
+
+ @Test
+ public void testGetDataLocations() {
+ assertEquals(engine.getDataLocations().size(), 1);
+ }
+
+ @Test
+ public void testGetPartitionEngine() {
+ createPartitionEngine(0);
+ assertNotNull(engine.getPartitionEngine(0));
+ }
+
+ @Test
+ public void testGetPartitionEngines() {
+ createPartitionEngine(0);
+ assertEquals(engine.getPartitionEngines().size(), 1);
+ }
+
+ @Test
+ public void testGetNodeMetrics() {
+ assertNotNull(engine.getNodeMetrics());
+ }
+
+ @Test
+ public void testGetRaftGroupCount() {
+ createPartitionEngine(0);
+ assertEquals(engine.getRaftGroupCount(), 1);
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionEngineTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionEngineTest.java
new file mode 100644
index 0000000000..02ff99259a
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionEngineTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.hugegraph.store.core.store;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.hugegraph.store.PartitionEngine;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PartitionEngineTest extends StoreEngineTestBase {
+
+ PartitionEngine engine;
+
+ @Before
+ public void setup() {
+ engine = createPartitionEngine(0);
+ }
+
+ @Test
+ public void testHasPartition() {
+ assertTrue(engine.hasPartition("graph0"));
+ }
+
+ @Test
+ public void testGetGroupId() {
+ assertEquals(engine.getGroupId().intValue(), 0);
+ }
+
+ @Test
+ public void testGetShardGroup() {
+ assertEquals(engine.getShardGroup().getShards().size(), 1);
+ }
+
+ @Test
+ public void testIsLeader() {
+ System.out.println(engine.isLeader());
+ }
+
+ @Test
+ public void testGetLeader() {
+ assertEquals(engine.getLeader().toString(), engine.getOptions().getRaftAddress());
+ }
+
+ @Test
+ public void testGetAlivePeers() {
+ try {
+ System.out.println(engine.getAlivePeers().size());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetRaftNode() {
+ assertNotNull(engine.getRaftNode());
+ }
+
+ @Test
+ public void testGetPartitions() {
+ assertEquals(engine.getPartitions().get("graph0").getId(), 0);
+ }
+
+ @Test
+ public void testGetPartition() {
+ assertEquals(engine.getPartition("graph0").getId(), 0);
+ }
+
+ @Test
+ public void testGetCommittedIndex() throws InterruptedException {
+ Thread.sleep(1000);
+ System.out.println(engine.getCommittedIndex());
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionInstructionProcessorTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionInstructionProcessorTest.java
new file mode 100644
index 0000000000..7a0aae85de
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/PartitionInstructionProcessorTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.hugegraph.store.core.store;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.pd.grpc.pulse.DbCompaction;
+import org.apache.hugegraph.pd.grpc.pulse.SplitPartition;
+import org.apache.hugegraph.pd.grpc.pulse.TransferLeader;
+import org.apache.hugegraph.store.PartitionInstructionProcessor;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PartitionInstructionProcessorTest extends StoreEngineTestBase {
+
+ PartitionInstructionProcessor processor;
+
+ @Before
+ public void init() {
+ processor = new PartitionInstructionProcessor(getStoreEngine());
+ }
+
+ @Test
+ public void testTransferLeader() {
+ var engine = createPartitionEngine(0);
+ engine.waitForLeader(1000);
+ var shard = Metapb.Shard.newBuilder()
+ .setStoreId(FakePdServiceProvider.makeStoreId("127.0.0.1:6511"))
+ .setRole(Metapb.ShardRole.Leader)
+ .build();
+
+ TransferLeader trans = TransferLeader.newBuilder()
+ .setShard(shard)
+ .build();
+ processor.onTransferLeader(1, getPartition(0), trans, integer -> {
+ assertEquals(0, integer.intValue());
+ });
+ }
+
+ @Test
+ public void testDbCompaction() throws InterruptedException {
+ var engine = createPartitionEngine(0);
+ engine.waitForLeader(1000);
+ DbCompaction dbCompaction = DbCompaction.newBuilder()
+ .setTableName("test")
+ .build();
+ processor.onDbCompaction(2, getPartition(0), dbCompaction, integer -> {
+ assertEquals(0, integer.intValue());
+ });
+
+ Thread.sleep(2000);
+ }
+
+ @Test
+ public void testSplitPartition() throws InterruptedException {
+ var engine = createPartitionEngine(0);
+ engine.waitForLeader(1000);
+
+ var partition = getPartition(0);
+ System.out.println(partition);
+
+ List list = new ArrayList<>();
+ list.add(Metapb.Partition.newBuilder(partition.getProtoObj())
+ .setStartKey(0)
+ .setEndKey(20000)
+ .build());
+ list.add(Metapb.Partition.newBuilder(partition.getProtoObj())
+ .setStartKey(20000)
+ .setEndKey(65535)
+ .setId(1).build());
+
+ SplitPartition splitPartition = SplitPartition.newBuilder()
+ .addAllNewPartition(list)
+ .build();
+
+ processor.onSplitPartition(3, partition, splitPartition, integer -> {
+ assertEquals(0, integer.intValue());
+ });
+
+ Thread.sleep(2000);
+ System.out.println(getStoreEngine().getPartitionEngines());
+ }
+
+ @Test
+ public void testChangeShard() {
+
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/MetadataKeyHelperTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/MetadataKeyHelperTest.java
new file mode 100644
index 0000000000..768d0370fa
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/MetadataKeyHelperTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.hugegraph.store.core.store.meta;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import org.apache.hugegraph.store.meta.MetadataKeyHelper;
+import org.junit.Test;
+
+public class MetadataKeyHelperTest {
+
+ @Test
+ public void testKey() {
+ assertArrayEquals("HUGEGRAPH/TASK/".getBytes(), MetadataKeyHelper.getTaskPrefix());
+ assertArrayEquals("HUGEGRAPH/TASK/0/".getBytes(), MetadataKeyHelper.getTaskPrefix(0));
+ assertArrayEquals("HUGEGRAPH/TASK_DONE/0000000000000000".getBytes(),
+ MetadataKeyHelper.getDoneTaskKey(0));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/PartitionManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/PartitionManagerTest.java
new file mode 100644
index 0000000000..0cdee7333a
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/PartitionManagerTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.hugegraph.store.core.store.meta;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hugegraph.pd.common.PDException;
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.cmd.UpdatePartitionRequest;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.meta.Graph;
+import org.apache.hugegraph.store.meta.GraphManager;
+import org.apache.hugegraph.store.meta.PartitionManager;
+import org.apache.hugegraph.store.pd.FakePdServiceProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PartitionManagerTest extends StoreEngineTestBase {
+
+ private PartitionManager manager;
+
+ @Before
+ public void setup() {
+ manager = getStoreEngine().getPartitionManager();
+ }
+
+ @Test
+ public void testGetDeletedFileManager() {
+ assertNotNull(manager.getDeletedFileManager());
+ }
+
+ @Test
+ public void testGetPdProvider() {
+ assertEquals(manager.getPdProvider().getClass(), FakePdServiceProvider.class);
+ }
+
+ @Test
+ public void testGetStoreMetadata() {
+ assertNotNull(manager.getStoreMetadata());
+ }
+
+ @Test
+ public void testSetStore() {
+ var storeId = FakePdServiceProvider.makeStoreId("127.0.0.1:6511");
+ var store = manager.getStore(storeId);
+ manager.setStore(store);
+ var store2 = manager.getStoreMetadata().getStore();
+
+ assertEquals(store.getId(), store2.getId());
+ }
+
+ @Test
+ public void testUpdatePartition() {
+ var partition = getPartition(5);
+ manager.updatePartition(partition.getProtoObj(), true);
+
+ var partition2 = manager.findPartition("graph0", 5);
+ assertEquals(partition.getGraphName(), partition2.getGraphName());
+
+ var partition3 = manager.loadPartitionFromSnapshot(partition2);
+ assertEquals(partition3.getGraphName(), partition2.getGraphName());
+ }
+
+ @Test
+ public void testChangeState() {
+ createPartitionEngine(4);
+ var partition = getPartition(4);
+ manager.changeState(partition, Metapb.PartitionState.PState_Offline);
+ var partition2 = manager.findPartition("graph0", 4);
+ assertEquals(partition2.getWorkState(), Metapb.PartitionState.PState_Offline);
+ }
+
+ @Test
+ public void testChangeKeyRange() {
+ createPartitionEngine(4);
+ var partition = getPartition(4);
+ manager.changeKeyRange(partition, 1000, 2000);
+
+ var partition2 = manager.findPartition("graph0", 4);
+ assertEquals(partition2.getStartKey(), 1000);
+ assertEquals(partition2.getEndKey(), 2000);
+ }
+
+
+ @Test
+ public void testUpdatePartitionRangeOrState() {
+ createPartitionEngine(4);
+ UpdatePartitionRequest request = new UpdatePartitionRequest();
+ request.setPartitionId(4);
+ request.setGraphName("graph0");
+ request.setStartKey(2000);
+ request.setEndKey(3000);
+ request.setWorkState(Metapb.PartitionState.PState_Offline);
+ manager.updatePartitionRangeOrState(request);
+
+ var partition = manager.findPartition("graph0", 4);
+ assertEquals(partition.getStartKey(), 2000);
+ assertEquals(partition.getEndKey(), 3000);
+ assertEquals(partition.getWorkState(), Metapb.PartitionState.PState_Offline);
+ }
+
+ @Test
+ public void testGetLeaderPartitionIds() {
+ createPartitionEngine(0);
+ createPartitionEngine(4);
+ createPartitionEngine(5);
+ System.out.println(manager.getLeaderPartitionIds("graph0"));
+ assertEquals(manager.getLeaderPartitionIds("graph0").size(), 3);
+ }
+
+ @Test
+ public void testisLocal() {
+ createPartitionEngine(0);
+ assertTrue(manager.isLocalPartition(0));
+ assertTrue(manager.isLocalPartition(getPartition(0)));
+ assertTrue(manager.isLocalStore(manager.getStore()));
+ }
+
+ @Test
+ public void testUploadToPd() throws PDException {
+ createPartitionEngine(0);
+ var partition = manager.findPartition("graph0", 0);
+ var list = new ArrayList();
+ list.add(partition.getProtoObj());
+ // fake pd, return nothing
+ assertEquals(1, manager.updatePartitionToPD(list).size());
+
+ manager.reportTask(null);
+
+ var partitions = manager.changePartitionToOnLine(list);
+ assertSame(partitions.get(0).getState(), Metapb.PartitionState.PState_Normal);
+ // fake pd
+ // TODO: uncomment it until fix it
+ // assertNotNull(manager.findPartition("graph0", 1000));
+
+ }
+
+ @Test
+ public void testShards2Peers() {
+ var storeId = FakePdServiceProvider.makeStoreId("127.0.0.1:6511");
+ Metapb.Shard shard = Metapb.Shard.newBuilder()
+ .setStoreId(storeId)
+ .setRole(Metapb.ShardRole.Leader)
+ .build();
+
+ List list = new ArrayList<>();
+ list.add(shard);
+
+ var peers = manager.shards2Peers(list);
+ assertEquals("127.0.0.1:6510", peers.get(0));
+ }
+
+ @Test
+ public void testLoad() {
+ createPartitionEngine(0);
+ var graphManager = new GraphManager(manager.getOptions(), manager.getPdProvider());
+ var graph = Metapb.Graph.newBuilder()
+ .setGraphName("graph0")
+ .setPartitionCount(12)
+ .build();
+ graphManager.updateGraph(new Graph(graph));
+
+ manager.load();
+ assertNotNull(manager.getLeaderPartitionIds("graph0"));
+ }
+
+ @Test
+ public void testSyncPartitionsFromPD() throws PDException {
+ createPartitionEngine(0);
+ // from fake pd
+ manager.syncPartitionsFromPD(partition -> {
+ });
+
+ assertTrue(manager.getPartitions().isEmpty());
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/TaskManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/TaskManagerTest.java
new file mode 100644
index 0000000000..ac4b44f537
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/TaskManagerTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.hugegraph.store.core.store.meta;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.hugegraph.pd.grpc.MetaTask;
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.meta.TaskManager;
+import org.apache.hugegraph.store.meta.asynctask.AsyncTaskState;
+import org.apache.hugegraph.store.meta.asynctask.CleanTask;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TaskManagerTest extends StoreEngineTestBase {
+
+ private TaskManager manager;
+
+ @Before
+ public void setup() {
+ createPartitionEngine(0, "graph0");
+ manager = getStoreEngine().getPartitionEngine(0).getTaskManager();
+ }
+
+ @Test
+ public void testAsyncTaskReadAndWrite() {
+ var task1 = new CleanTask(0, "graph0", AsyncTaskState.START, null);
+ var task2 = new CleanTask(0, "graph0", AsyncTaskState.FAILED, null);
+ var task3 = new CleanTask(0, "graph0", AsyncTaskState.SUCCESS, null);
+ var task4 = new CleanTask(0, "graph0", AsyncTaskState.FAILED, null);
+
+ manager.putAsyncTask(task1);
+ manager.putAsyncTask(task2);
+ manager.putAsyncTask(task3);
+ manager.putAsyncTask(task4);
+
+ var list = manager.scanAsyncTasks(0, "graph0");
+ assertEquals(list.size(), 4);
+
+ var newTask1 = (CleanTask) manager.getOneAsyncTask(0, "graph0", task1.getId());
+ assertEquals(task1.getState(), newTask1.getState());
+ assertEquals(task1.getType(), newTask1.getType());
+
+ manager.updateAsyncTaskState(0, "graph0", task4.getId(), AsyncTaskState.SUCCESS);
+ var newTask4 = (CleanTask) manager.getOneAsyncTask(0, "graph0", task4.getId());
+ assertEquals(newTask4.getState(), AsyncTaskState.SUCCESS);
+
+ assertNull(manager.getOneAsyncTask(1, "graph0", ""));
+ }
+
+ @Test
+ public void testTaskOp() {
+ MetaTask.Task task1 = MetaTask.Task.newBuilder()
+ .setId(1)
+ .setState(MetaTask.TaskState.Task_Ready)
+ .setType(MetaTask.TaskType.Split_Partition)
+ .setPartition(Metapb.Partition.newBuilder()
+ .setGraphName("graph0")
+ .setId(0).build())
+ .build();
+
+ manager.updateTask(task1);
+ assertTrue(manager.taskExists(task1));
+ assertFalse(manager.taskExists(0, "graph0",
+ MetaTask.TaskType.Split_Partition.name()));
+ assertFalse(manager.partitionTaskRepeat(0, "graph0",
+ MetaTask.TaskType.Split_Partition.name()));
+
+ MetaTask.Task task2 = MetaTask.Task.newBuilder(task1).setId(2).build();
+ manager.updateTask(task2);
+
+ assertTrue(manager.taskExists(0, "graph0",
+ MetaTask.TaskType.Split_Partition.name()));
+ assertTrue(manager.partitionTaskRepeat(0, "graph0",
+ MetaTask.TaskType.Split_Partition.name()));
+
+ MetaTask.Task task3 = MetaTask.Task.newBuilder(task1)
+ .setId(3)
+ .setState(MetaTask.TaskState.Task_Success)
+ .setPartition(
+ Metapb.Partition.newBuilder(task1.getPartition())
+ .setGraphName("graph1")
+ .setId(1)
+ .build())
+ .build();
+ manager.updateTask(task3);
+ assertFalse(manager.taskExists(task3));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/asynctask/CleanTaskTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/asynctask/CleanTaskTest.java
new file mode 100644
index 0000000000..816c4ccdd3
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/meta/asynctask/CleanTaskTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hugegraph.store.core.store.meta.asynctask;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.hugegraph.store.meta.asynctask.AbstractAsyncTask;
+import org.apache.hugegraph.store.meta.asynctask.AsyncTask;
+import org.apache.hugegraph.store.meta.asynctask.AsyncTaskState;
+import org.apache.hugegraph.store.meta.asynctask.CleanTask;
+import org.junit.Test;
+
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+
+public class CleanTaskTest extends StoreEngineTestBase {
+
+ @Test
+ public void testSerialize() {
+ CleanTask task = new CleanTask(0, "graph0", AsyncTaskState.SUCCESS, null);
+ byte[] bytes = task.toBytes();
+
+ AsyncTask task2 = AbstractAsyncTask.fromBytes(bytes);
+ assertEquals(CleanTask.class, task2.getClass());
+ System.out.println(task2);
+
+ createPartitionEngine(0);
+
+ CleanTask task3 = new CleanTask(0, "graph0", AsyncTaskState.START, null);
+ CleanTask task4 = new CleanTask(0, "graph0", AsyncTaskState.FAILED, null);
+ task3.handleTask();
+ task4.handleTask();
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/MiscUtilClassTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/MiscUtilClassTest.java
new file mode 100644
index 0000000000..0102dcd9c5
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/MiscUtilClassTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.hugegraph.store.core.store.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hugegraph.store.util.Asserts;
+import org.apache.hugegraph.store.util.HgRaftError;
+import org.apache.hugegraph.store.util.HgStoreException;
+import org.apache.hugegraph.store.util.ManualResetEvent;
+import org.junit.Test;
+
+import com.alipay.sofa.jraft.Status;
+
+public class MiscUtilClassTest {
+
+ @Test
+ public void testHgRaftError() {
+ HgRaftError error = HgRaftError.forNumber(0);
+ assertEquals(0, error.getNumber());
+ assertEquals("OK", error.getMsg());
+ assertEquals(Status.OK().getCode(), error.toStatus().getCode());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testAsserts() {
+ assertTrue(Asserts.isInvalid(null));
+ assertTrue(Asserts.isInvalid());
+ assertTrue(Asserts.isInvalid(null));
+ assertTrue(Asserts.isInvalid(""));
+ assertFalse(Asserts.isInvalid("a"));
+
+ Asserts.isNonNull(null);
+ Asserts.isNonNull(null, "msg");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAsserts2() {
+ Asserts.isTrue(false, "");
+ Asserts.isFalse(true, "");
+ Asserts.isTrue(true, null);
+ }
+
+ @Test
+ public void testHgStoreException() {
+ var exception = new HgStoreException();
+ assertEquals(0, exception.getCode());
+ exception = new HgStoreException("invalid");
+ assertEquals(1000, exception.getCode());
+ exception = new HgStoreException(1000, "invalid");
+ assertEquals(1000, exception.getCode());
+ exception = new HgStoreException(1000, new Throwable());
+ assertEquals(1000, exception.getCode());
+ exception = new HgStoreException("invalid", new Throwable());
+ assertEquals(1000, exception.getCode());
+ exception = new HgStoreException(1000, "%s", "invalid");
+ assertEquals(1000, exception.getCode());
+ }
+
+ @Test
+ public void testManualResetEvent() throws InterruptedException {
+ ManualResetEvent event = new ManualResetEvent(false);
+ assertFalse(event.isSignalled());
+ event.set();
+ assertTrue(event.isSignalled());
+ event.reset();
+ assertFalse(event.waitOne(1, TimeUnit.SECONDS));
+ event.set();
+ event.waitOne();
+ assertTrue(event.isSignalled());
+ }
+
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/PartitionMetaStoreWrapperTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/PartitionMetaStoreWrapperTest.java
new file mode 100644
index 0000000000..c15ddfeff0
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/PartitionMetaStoreWrapperTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.hugegraph.store.core.store.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.hugegraph.pd.grpc.Metapb;
+import org.apache.hugegraph.store.core.StoreEngineTestBase;
+import org.apache.hugegraph.store.meta.MetadataKeyHelper;
+import org.apache.hugegraph.store.util.PartitionMetaStoreWrapper;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PartitionMetaStoreWrapperTest extends StoreEngineTestBase {
+
+ private PartitionMetaStoreWrapper wrapper;
+
+ private Metapb.Partition partition;
+
+ public static void putToDb(Metapb.Partition partition, PartitionMetaStoreWrapper wrapper) {
+ byte[] key = MetadataKeyHelper.getPartitionKey(partition.getGraphName(), partition.getId());
+ wrapper.put(partition.getId(), key, partition.toByteArray());
+ }
+
+ @Before
+ public void setup() {
+ wrapper = new PartitionMetaStoreWrapper();
+ partition = Metapb.Partition.newBuilder()
+ .setId(1)
+ .setGraphName("graph0")
+ .setStartKey(0L)
+ .setEndKey(65535L)
+ .build();
+ }
+
+ @Test
+ public void testGet() {
+ putToDb(partition, wrapper);
+ byte[] key = MetadataKeyHelper.getPartitionKey(partition.getGraphName(), partition.getId());
+ assertEquals(partition, wrapper.get(1, key, Metapb.Partition.parser()));
+ byte[] key2 = MetadataKeyHelper.getPartitionKey("not_exists", partition.getId());
+ assertNull(wrapper.get(1, key2, Metapb.Partition.parser()));
+ }
+
+ @Test
+ public void testPut() {
+ putToDb(partition, wrapper);
+ byte[] key = MetadataKeyHelper.getPartitionKey(partition.getGraphName(), partition.getId());
+ var list = wrapper.scan(partition.getId(), Metapb.Partition.parser(), key);
+ assertEquals(list.size(), 1);
+ assertEquals(list.get(0).getGraphName(), partition.getGraphName());
+ }
+
+ @Test
+ public void testDelete() {
+ putToDb(partition, wrapper);
+ byte[] key = MetadataKeyHelper.getPartitionKey(partition.getGraphName(), partition.getId());
+ wrapper.delete(partition.getId(), key);
+ var list = wrapper.scan(partition.getId(), Metapb.Partition.parser(), key);
+ assertEquals(list.size(), 0);
+ }
+
+ @Test
+ public void testScan() {
+ putToDb(partition, wrapper);
+ byte[] key = MetadataKeyHelper.getPartitionKey(partition.getGraphName(), partition.getId());
+ var list = wrapper.scan(partition.getId(), Metapb.Partition.parser(), key);
+ assertEquals(list.size(), 1);
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/ZipUtilsTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/ZipUtilsTest.java
new file mode 100644
index 0000000000..1435c349ca
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/store/util/ZipUtilsTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.hugegraph.store.core.store.util;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.zip.CRC32;
+
+import org.apache.hugegraph.rocksdb.access.util.ZipUtils;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.logging.log4j.core.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ZipUtilsTest {
+
+ private static final String ZIP_TEST_PATH = "/tmp/zip_util_test";
+
+ @Before
+ public void init() throws IOException {
+ UnitTestBase.deleteDir(new File(ZIP_TEST_PATH));
+ FileUtils.mkdir(new File(ZIP_TEST_PATH), true);
+ FileUtils.mkdir(new File(ZIP_TEST_PATH + "/input"), true);
+ FileUtils.mkdir(new File(ZIP_TEST_PATH + "/output"), true);
+ Files.createFile(Paths.get(ZIP_TEST_PATH + "/input/foo.txt"));
+ }
+
+ @Test
+ public void testZip() throws IOException {
+ ZipUtils.compress(ZIP_TEST_PATH, "input", ZIP_TEST_PATH + "/foo.zip", new CRC32());
+ ZipUtils.decompress(ZIP_TEST_PATH + "/foo.zip", ZIP_TEST_PATH + "/output", new CRC32());
+ assertTrue(Files.exists(Paths.get(ZIP_TEST_PATH + "/output/input/foo.txt")));
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphIDManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphIDManagerTest.java
new file mode 100644
index 0000000000..60bb542a9b
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphIDManagerTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hugegraph.store.meta;
+
+import java.io.File;
+
+import org.apache.hugegraph.pd.common.PDException;
+import org.apache.hugegraph.rocksdb.access.RocksDBSession;
+import org.apache.hugegraph.store.UnitTestBase;
+import org.apache.hugegraph.store.meta.base.DBSessionBuilder;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GraphIDManagerTest extends UnitTestBase {
+ @Before
+ public void init() {
+ String dbPath = "/tmp/junit";
+ UnitTestBase.deleteDir(new File(dbPath));
+ super.initDB(dbPath);
+ }
+
+ @Test
+ public void test() throws PDException {
+ GraphIdManager.maxGraphID = 64;
+ int max = GraphIdManager.maxGraphID;
+ try (RocksDBSession session = getDBSession("test")) {
+ GraphIdManager gid = new GraphIdManager(new DBSessionBuilder() {
+ @Override
+ public RocksDBSession getSession(int partId) {
+ return session.clone();
+ }
+ }, 0);
+ for (int i = 0; i < max; i++) {
+ Assert.assertEquals(i, gid.getCId("Test", max));
+ }
+
+ Assert.assertEquals(-1, gid.getCId("Test", max));
+
+ gid.delCId("Test", 3);
+ Assert.assertEquals(3, gid.getCId("Test", max));
+ Assert.assertEquals(-1, gid.getCId("Test", max));
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < GraphIdManager.maxGraphID; i++) {
+ long id = gid.getGraphId("g" + i);
+ Assert.assertEquals(i, id);
+ }
+ System.out.println("time is " + (System.currentTimeMillis() - start));
+ {
+ gid.releaseGraphId("g" + 10);
+ long id = gid.getGraphId("g" + 10);
+ Assert.assertEquals(10, id);
+ }
+ start = System.currentTimeMillis();
+ for (int i = 0; i < GraphIdManager.maxGraphID; i++) {
+ long id = gid.releaseGraphId("g" + i);
+ Assert.assertEquals(i, id);
+ }
+ System.out.println("time is " + (System.currentTimeMillis() - start));
+ start = System.currentTimeMillis();
+ for (int i = 0; i < GraphIdManager.maxGraphID; i++) {
+ long id = gid.getCId(GraphIdManager.GRAPH_ID_PREFIX, GraphIdManager.maxGraphID);
+ // long id = gid.getGraphId("g" + i);
+ Assert.assertTrue(id >= 0);
+ }
+ System.out.println("time is " + (System.currentTimeMillis() - start));
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphManagerTest.java
new file mode 100644
index 0000000000..8777700afe
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/meta/GraphManagerTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.hugegraph.store.meta;
+
+
+import org.junit.Assert;
+// import org.junit.Test;
+
+public class GraphManagerTest {
+ // @Test
+ public void testCloneGraph() {
+ Graph graph = new Graph();
+ graph.setGraphName("test1");
+
+
+ Graph graph1 = graph.clone();
+
+ Assert.assertNotSame(graph, graph1);
+
+ Assert.assertEquals(graph.getGraphName(), graph1.getGraphName());
+ graph1.setGraphName("test4");
+
+
+ Assert.assertNotEquals(graph.getGraphName(), graph1.getGraphName());
+
+ Assert.assertEquals(graph.getGraphName(), "test1");
+
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/BytesCarrierTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/BytesCarrierTest.java
new file mode 100644
index 0000000000..30142756c0
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/BytesCarrierTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hugegraph.store.raftcore;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.junit.Test;
+
+import com.google.protobuf.BytesCarrier;
+
+public class BytesCarrierTest {
+
+ @Test
+ public void testWrite() throws IOException {
+ byte[] bytes = new byte[]{10, 20, 30};
+ BytesCarrier carrier = new BytesCarrier();
+
+ // not valid
+ carrier.write((byte) 1);
+ assertNull(carrier.getValue());
+ assertFalse(carrier.isValid());
+
+ // not valid
+ ByteBuffer buffer = ByteBuffer.allocate(10);
+ carrier.write(buffer);
+ assertNull(carrier.getValue());
+
+ // not valid
+ carrier.writeLazy(buffer);
+ assertNull(carrier.getValue());
+
+ // ok, write done
+ carrier.write(bytes, 0, bytes.length);
+ assertNotNull(carrier.getValue());
+ assertTrue(carrier.isValid());
+
+ // has data
+ carrier.writeLazy(bytes, 0, bytes.length);
+ assertFalse(carrier.isValid());
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/RaftSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/RaftSuiteTest.java
new file mode 100644
index 0000000000..f3b1f31d29
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/RaftSuiteTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hugegraph.store.raftcore;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BytesCarrierTest.class,
+ ZeroByteStringHelperTest.class
+})
+public class RaftSuiteTest {
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/ZeroByteStringHelperTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/ZeroByteStringHelperTest.java
new file mode 100644
index 0000000000..9d702e3ff7
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/raftcore/ZeroByteStringHelperTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.hugegraph.store.raftcore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.junit.Test;
+
+import com.google.protobuf.ZeroByteStringHelper;
+
+public class ZeroByteStringHelperTest {
+
+ private static final String STR = "hello word!";
+
+ @Test
+ public void testWrap() {
+ byte[] b1 = new byte[]{10, 20, 30};
+ byte[] b2 = new byte[]{40, 50};
+
+ var h1 = ZeroByteStringHelper.wrap(b1);
+ var h2 = ZeroByteStringHelper.wrap(b2, 0, b2.length);
+
+ ByteBuffer buffer = ByteBuffer.allocate(5);
+ buffer.put(b1);
+ buffer.put(b2);
+ var h3 = ZeroByteStringHelper.wrap(buffer);
+ assertEquals(h3.isEmpty(), true);
+ var h4 = ZeroByteStringHelper.concatenate(h1, h2);
+ assertTrue(Arrays.equals(ZeroByteStringHelper.getByteArray(h4), buffer.array()));
+ }
+
+ @Test
+ public void testConcatenate() {
+ byte[] b1 = new byte[]{10, 20, 30};
+ byte[] b2 = new byte[]{40, 50};
+ ByteBuffer buffer1 = ByteBuffer.allocate(5);
+ buffer1.put(b1);
+
+ ByteBuffer buffer2 = ByteBuffer.allocate(5);
+ buffer1.put(b2);
+
+ var array = new ArrayList();
+ array.add(buffer1);
+ array.add(buffer2);
+
+ var bs = ZeroByteStringHelper.concatenate(array);
+ assertEquals(bs.toByteArray().length, 5);
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/BaseRocksDbTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/BaseRocksDbTest.java
new file mode 100644
index 0000000000..4fd36665e9
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/BaseRocksDbTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hugegraph.store.rocksdb;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.OptionSpace;
+import org.apache.hugegraph.rocksdb.access.RocksDBFactory;
+import org.apache.hugegraph.rocksdb.access.RocksDBOptions;
+import org.junit.After;
+import org.junit.BeforeClass;
+
+public class BaseRocksDbTest {
+ @BeforeClass
+ public static void init() {
+ OptionSpace.register("org/apache/hugegraph/store/rocksdb",
+ "org.apache.hugegraph.rocksdb.access.RocksDBOptions");
+ RocksDBOptions.instance();
+
+ Map configMap = new HashMap<>();
+ configMap.put("rocksdb.write_buffer_size", "1048576");
+ configMap.put("rocksdb.bloom_filter_bits_per_key", "10");
+
+ HugeConfig hConfig = new HugeConfig(configMap);
+ RocksDBFactory rFactory = RocksDBFactory.getInstance();
+ rFactory.setHugeConfig(hConfig);
+
+ }
+
+ @After
+ public void teardown() throws Exception {
+ // pass
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDBFactoryTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDBFactoryTest.java
new file mode 100644
index 0000000000..61931fac9c
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDBFactoryTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.hugegraph.store.rocksdb;
+
+import org.apache.hugegraph.rocksdb.access.RocksDBFactory;
+import org.apache.hugegraph.rocksdb.access.RocksDBSession;
+import org.apache.hugegraph.rocksdb.access.SessionOperator;
+import org.junit.Test;
+
+public class RocksDBFactoryTest extends BaseRocksDbTest {
+ @Test
+ public void testCreateSession() {
+ RocksDBFactory factory = RocksDBFactory.getInstance();
+ try (RocksDBSession dbSession = factory.createGraphDB("./tmp", "test1")) {
+ SessionOperator op = dbSession.sessionOp();
+ op.prepare();
+ try {
+ op.put("tbl", "k1".getBytes(), "v1".getBytes());
+ op.commit();
+ } catch (Exception e) {
+ op.rollback();
+ }
+
+ }
+ factory.destroyGraphDB("test1");
+ }
+
+ @Test
+ public void testTotalKeys() {
+ RocksDBFactory dbFactory = RocksDBFactory.getInstance();
+ System.out.println(dbFactory.getTotalSize());
+
+ System.out.println(dbFactory.getTotalKey().entrySet()
+ .stream().map(e -> e.getValue()).reduce(0L, Long::sum));
+ }
+
+ @Test
+ public void releaseAllGraphDB() {
+ System.out.println(RocksDBFactory.class);
+
+ RocksDBFactory rFactory = RocksDBFactory.getInstance();
+
+ if (rFactory.queryGraphDB("bj01") == null) {
+ rFactory.createGraphDB("./tmp", "bj01");
+ }
+
+ if (rFactory.queryGraphDB("bj02") == null) {
+ rFactory.createGraphDB("./tmp", "bj02");
+ }
+
+ if (rFactory.queryGraphDB("bj03") == null) {
+ rFactory.createGraphDB("./tmp", "bj03");
+ }
+
+ RocksDBSession dbSession = rFactory.queryGraphDB("bj01");
+
+ dbSession.checkTable("test");
+ SessionOperator sessionOp = dbSession.sessionOp();
+ sessionOp.prepare();
+
+ sessionOp.put("test", "hi".getBytes(), "byebye".getBytes());
+ sessionOp.commit();
+
+ rFactory.releaseAllGraphDB();
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDbSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDbSuiteTest.java
new file mode 100644
index 0000000000..59c1cd9986
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/rocksdb/RocksDbSuiteTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hugegraph.store.rocksdb;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import lombok.extern.slf4j.Slf4j;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ RocksDBFactoryTest.class
+})
+
+@Slf4j
+public class RocksDbSuiteTest {
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/BaseServerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/BaseServerTest.java
new file mode 100644
index 0000000000..ca0a8fd248
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/BaseServerTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.hugegraph.store.service;
+
+import org.junit.After;
+import org.junit.BeforeClass;
+
+public class BaseServerTest {
+ @BeforeClass
+ public static void init() {
+
+ }
+
+ @After
+ public void teardown() {
+ // pass
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/ServerSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/ServerSuiteTest.java
new file mode 100644
index 0000000000..00a58d490e
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/ServerSuiteTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hugegraph.store.service;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import lombok.extern.slf4j.Slf4j;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+})
+
+@Slf4j
+
+public class ServerSuiteTest {
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/SessionTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/SessionTest.java
new file mode 100644
index 0000000000..38449a106e
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/service/SessionTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hugegraph.store.service;
+
+import org.junit.Test;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SessionTest {
+ @Test
+ public void testQuota() {
+
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/CopyOnWriteCacheTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/CopyOnWriteCacheTest.java
new file mode 100644
index 0000000000..86d03fd534
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/CopyOnWriteCacheTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.hugegraph.store.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.Hessian2Output;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.hugegraph.store.util.CopyOnWriteCache;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CopyOnWriteCacheTest {
+
+ private CopyOnWriteCache writeCache;
+
+ @Before
+ public void setUp() {
+ writeCache = new CopyOnWriteCache<>(5000L);
+ }
+
+ @Test
+ public void testContainsKey() {
+ // Setup
+ // Run the test
+ writeCache.put("k", "v");
+ final boolean result = writeCache.containsKey("k");
+ Map extends String, ? extends String> allKeys =
+ Map.ofEntries(Map.entry("key1", "value1"));
+ writeCache.putAll(allKeys);
+ // Verify the results
+ assertTrue(result);
+ final Set> entries = writeCache.entrySet();
+ Set keySet = writeCache.keySet();
+ String val = writeCache.get("k");
+ boolean isEmpty = writeCache.isEmpty();
+ writeCache.size();
+ writeCache.values();
+ // Verify the results
+ assertFalse(isEmpty);
+ writeCache.remove("k");
+ writeCache.putIfAbsent("k", "v");
+ writeCache.replace("k", "original", "replacement");
+ writeCache.replace("k", "v");
+ writeCache.clear();
+ assertTrue(writeCache.isEmpty());
+ }
+
+ // @Test
+ public void testCache() throws InterruptedException {
+ Map cache = new CopyOnWriteCache<>(1000);
+ cache.put("1", "1");
+ Thread.sleep(2000);
+ Asserts.isTrue(!cache.containsKey("1"), "cache do not clear");
+ }
+
+ // @Test
+ public void test() {
+
+ byte[] bytes;
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+ long[] l = new long[]{1, 2};
+ Hessian2Output output = new Hessian2Output(bos);
+ output.writeObject(l);
+ output.flush();
+ bytes = bos.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
+ Hessian2Input input = new Hessian2Input(bis);
+ long[] obj = (long[]) input.readObject();
+ input.close();
+
+ for (long l : obj) {
+ System.out.println(l);
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/FutureClosureTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/FutureClosureTest.java
new file mode 100644
index 0000000000..1c06f97f26
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/FutureClosureTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.hugegraph.store.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.alipay.sofa.jraft.Status;
+
+public class FutureClosureTest {
+ @Test
+ public void test() {
+ FutureClosure closure = new FutureClosure();
+ new Thread(() -> {
+ try {
+ Thread.sleep(1000);
+ closure.run(Status.OK());
+ } catch (InterruptedException e) {
+ closure.run(new Status(-1, e.getMessage()));
+ }
+
+ }).start();
+
+ Assert.assertEquals(closure.get().getCode(), Status.OK().getCode());
+ Assert.assertEquals(closure.get().getCode(), Status.OK().getCode());
+ Assert.assertEquals(closure.get().getCode(), Status.OK().getCode());
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/HgStoreTestUtil.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/HgStoreTestUtil.java
new file mode 100644
index 0000000000..6a19a026b6
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/HgStoreTestUtil.java
@@ -0,0 +1,486 @@
+/*
+ * 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.hugegraph.store.util;
+
+import java.io.Closeable;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.apache.hugegraph.store.HgKvEntry;
+import org.apache.hugegraph.store.HgKvIterator;
+import org.apache.hugegraph.store.HgOwnerKey;
+import org.apache.hugegraph.store.HgStoreSession;
+import org.apache.hugegraph.store.client.util.HgStoreClientConst;
+import org.apache.hugegraph.store.client.util.MetricX;
+
+public class HgStoreTestUtil {
+ public static final String GRAPH_NAME = "default/hugegraph/g";
+ public static final String GRAPH_NAME2 = "default/hugegraph2/g";
+ public static final String TABLE_NAME = "unit-table";
+ public static final String TABLE_NAME2 = "unit-table-2";
+
+ public static Map batchPut(HgStoreSession session, String keyPrefix) {
+ return batchPut(session, keyPrefix, 100);
+ }
+
+ public static Map batchPut(HgStoreSession session, String keyPrefix,
+ int loop) {
+ return batchPut(session, TABLE_NAME, keyPrefix, loop);
+ }
+
+ public static Map batchPut(
+ HgStoreSession session, String tableName, String keyPrefix, int loop) {
+ return batchPut(session, tableName, keyPrefix, loop, 1, key -> toOwnerKey(key));
+ }
+
+ public static Map batchPut(
+ HgStoreSession session, String tableName, byte[] keyPrefix, int loop) {
+ return batchPut(session, tableName, keyPrefix, loop, 1,
+ (prefix, key) -> toOwnerKey(prefix, key));
+ }
+
+ public static Map batchPut(
+ HgStoreSession session, String tableName, String keyPrefix, int loop, int start) {
+ return batchPut(session, tableName, keyPrefix, loop, start, key -> toOwnerKey(key));
+ }
+
+ public static Map batchPut(
+ HgStoreSession session, String tableName, String keyPrefix, int loop,
+ Function f) {
+ return batchPut(session, tableName, keyPrefix, loop, 1, f);
+ }
+
+ public static Map batchPut(
+ HgStoreSession session,
+ String tableName,
+ String keyPrefix,
+ int loop,
+ int start,
+ Function f) {
+
+ Map res = new LinkedHashMap<>();
+
+ int length = String.valueOf(loop).length();
+
+ session.beginTx();
+ for (int i = start; i <= loop; i++) {
+
+ HgOwnerKey key = f.apply(keyPrefix + "-" + padLeftZeros(String.valueOf(i), length));
+
+ byte[] value = toBytes(keyPrefix + "-V-" + i);
+ res.put(key, value);
+ session.put(tableName, key, value);
+
+ if ((i + 1) % 10000 == 0) {
+ println("commit: " + (i + 1));
+ session.commit();
+ session.beginTx();
+ }
+ }
+ if (session.isTx()) {
+ session.commit();
+ }
+
+ return res;
+ }
+
+ public static Map batchPut(
+ HgStoreSession session,
+ String tableName,
+ byte[] keyPrefix,
+ int loop,
+ int start,
+ BiFunction f) {
+
+ Map res = new LinkedHashMap<>();
+
+ int length = String.valueOf(loop).length();
+
+ session.beginTx();
+ for (int i = start; i <= loop; i++) {
+
+ HgOwnerKey key = f.apply(keyPrefix, padLeftZeros(String.valueOf(i), length));
+
+ byte[] value = toBytes(keyPrefix + "-V-" + i);
+ res.put(key, value);
+ session.put(tableName, key, value);
+
+ if ((i + 1) % 10000 == 0) {
+ println("commit: " + (i + 1));
+ session.commit();
+ session.beginTx();
+ }
+ }
+ if (session.isTx()) {
+ session.commit();
+ }
+
+ return res;
+ }
+
+ /*---- common -----*/
+ public static void printOwner(List list) {
+ if (list == null) {
+ return;
+ }
+
+ for (HgOwnerKey entry : list) {
+ println(entry);
+ }
+ }
+
+ public static void printNum(List list, String title) {
+ if (list == null) {
+ return;
+ }
+
+ println(title + " size: " + list.size());
+ }
+
+ public static int println(Iterable> iterators) {
+ AtomicInteger counter = new AtomicInteger();
+ iterators.forEach(e -> counter.addAndGet(HgStoreTestUtil.println(e)));
+ return counter.get();
+ }
+
+ public static int println(HgKvIterator iterator) {
+ if (iterator == null) {
+ return 0;
+ }
+
+ AtomicInteger counter = new AtomicInteger();
+
+ while (iterator.hasNext()) {
+ counter.incrementAndGet();
+ print(iterator.next());
+ println(" " + Arrays.toString(iterator.position()));
+ }
+
+ iterator.close();
+
+ return counter.get();
+ }
+
+ public static void println(HgKvIterator iterator, Function mod) {
+ if (iterator == null) {
+ return;
+ }
+ int count = 0;
+
+ while (iterator.hasNext()) {
+ count++;
+ if (mod.apply(count)) {
+ print(iterator.next());
+ println(" " + Arrays.toString(iterator.position()));
+ }
+ }
+
+ iterator.close();
+ }
+
+ public static void println(List list) {
+ if (list == null) {
+ return;
+ }
+
+ for (HgKvEntry entry : list) {
+ println(entry);
+ }
+ }
+
+ public static void println(List list, int mod) {
+ if (list == null) {
+ return;
+ }
+
+ for (int i = 0; i < list.size(); i++) {
+ if (i % mod == 0) {
+ println(list.get(i));
+ }
+ }
+ }
+
+ public static void println(HgKvEntry kv) {
+ if (kv == null) {
+ System.out.println("null");
+ return;
+ }
+ println("[ " + kv.code() + " " + toStr(kv.key()) + " : " + toStr(kv.value()) + " ]");
+ }
+
+ public static void println(HgOwnerKey key) {
+ if (key == null) {
+ System.out.println("null");
+ return;
+ }
+ println("[ " + toInt(key.getOwner()) + " : " + toStr(key.getKey()) + " ]");
+ }
+
+ public static void println(String str) {
+ System.out.println(str);
+ }
+
+ public static void println(Number num) {
+ System.out.println(num);
+ }
+
+ public static void print(String str) {
+ System.out.print(str);
+ }
+
+ public static void print(HgKvEntry kv) {
+ if (kv == null) {
+ System.out.println("null");
+ return;
+ }
+ print("[ " + kv.code() + " " + toStr(kv.key()) + " : " + toStr(kv.value()) + " ]");
+ }
+
+ private static byte[] getOwner(String key) {
+ return getOwner(toBytes(key));
+ }
+
+ private static byte[] getOwner(byte[] key) {
+ return toBytes(Arrays.hashCode(key));
+ }
+
+ public static HgOwnerKey toAllPartitionKey(String key) {
+ return HgOwnerKey.of(HgStoreClientConst.ALL_PARTITION_OWNER, toBytes(key));
+ }
+
+ public static HgOwnerKey toAllPartitionKey(byte[] prefix, String key) {
+ return HgOwnerKey.of(HgStoreClientConst.ALL_PARTITION_OWNER, toBytes(prefix, key));
+ }
+
+ public static HgOwnerKey toAllPartitionKey(byte[] prefix) {
+ return HgOwnerKey.of(HgStoreClientConst.ALL_PARTITION_OWNER, prefix);
+ }
+
+ public static HgOwnerKey toOwnerKey(byte[] prefix, String key) {
+ byte[] newKey = toBytes(prefix, key);
+ return new HgOwnerKey(getOwner(newKey), newKey);
+ }
+
+ public static HgOwnerKey toOwnerKey(String key) {
+ return new HgOwnerKey(getOwner(key), toBytes(key));
+ }
+
+ public static HgOwnerKey toOwnerKey(byte[] key) {
+ return new HgOwnerKey(getOwner(key), key);
+ }
+
+ public static HgOwnerKey toOwnerKey(String owner, String key) {
+ return HgOwnerKey.of(toBytes(owner), toBytes(key));
+ }
+
+ public static HgOwnerKey toOwnerKey(int code, String key) {
+ return HgOwnerKey.of(code, toBytes(key));
+ }
+
+ public static String toStr(byte[] b) {
+ if (b == null) {
+ return "";
+ }
+ if (b.length == 0) {
+ return "";
+ }
+ return new String(b, StandardCharsets.UTF_8);
+ }
+
+ public static byte[] toBytes(byte[] prefix, String str) {
+ if (str == null) {
+ return null;
+ }
+ byte[] buf = str.getBytes(StandardCharsets.UTF_8);
+ byte[] res = new byte[buf.length + prefix.length];
+ System.arraycopy(prefix, 0, res, 0, prefix.length);
+ System.arraycopy(buf, 0, res, prefix.length, buf.length);
+ return res;
+ }
+
+ public static byte[] toBytes(String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.getBytes(StandardCharsets.UTF_8);
+ }
+
+ public static byte[] toBytes(long l) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+ buffer.putLong(l);
+ return buffer.array();
+ }
+
+ private static byte[] toBytes(final int i) {
+ ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
+ buffer.putInt(i);
+ return buffer.array();
+ }
+
+ public static long toLong(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+ buffer.put(bytes);
+ buffer.flip(); // need flip
+ return buffer.getLong();
+ }
+
+ public static int toInt(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
+ buffer.put(bytes);
+ buffer.flip(); // need flip
+ return buffer.getInt();
+ }
+
+ public static String padLeftZeros(String str, int n) {
+ return String.format("%1$" + n + "s", str).replace(' ', '0');
+ }
+
+ public static String toSuffix(int num, int length) {
+ return "-" + padLeftZeros(String.valueOf(num), length);
+ }
+
+ public static int amountOf(List list) {
+ if (list == null) {
+ return 0;
+ }
+ return list.size();
+ }
+
+ public static int amountOf(Iterator iterator) {
+ if (iterator == null) {
+ return 0;
+ }
+ int count = 0;
+ while (iterator.hasNext()) {
+ Object ignore = iterator.next();
+ ++count;
+ }
+ return count;
+ }
+
+ public static int oOMAmountOf(Iterator iterator) {
+ if (iterator == null) {
+ return 0;
+ }
+ int count = 0;
+ while (iterator.hasNext()) {
+ Object obj = iterator.next();
+ ++count;
+ if (count % 10000 == 0) {
+ println(count);
+ sleeping(10);
+ }
+ if (count % 100000 == 0) {
+ break;
+ }
+ }
+ if (iterator instanceof Closeable) {
+ try {
+ ((Closeable) iterator).close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return count;
+ }
+
+ public static int amountIn(List extends Iterator> iterators) {
+ return iterators.stream().map(e -> HgStoreTestUtil.amountOf(e)).reduce(0, Integer::sum);
+ }
+
+ public static void sleeping(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void parallelTest(int threads, Runnable runner,
+ Consumer throwableConsumer) {
+ int threadsAmount = threads;
+ CountDownLatch countDownLatch = new CountDownLatch(threadsAmount);
+ ExecutorService pool = new ThreadPoolExecutor(threadsAmount, threadsAmount + 20,
+ 200, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(1000));
+ for (int i = 0; i < threadsAmount; i++) {
+ pool.submit(
+ () -> {
+ try {
+ runner.run();
+ } catch (Throwable t) {
+ throwableConsumer.accept(t);
+ }
+ countDownLatch.countDown();
+ });
+ }
+
+ try {
+ countDownLatch.await();
+ pool.shutdown();
+
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void repeatedlyTest(int times, Runnable runner) {
+ MetricX metrics = MetricX.ofStart();
+
+ for (int j = 0; j < times; j++) {
+ try {
+ runner.run();
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ break;
+ } catch (Throwable t) {
+ metrics.countFail();
+ t.printStackTrace();
+ }
+ }
+ metrics.end();
+ System.out.println("*************************************************");
+ System.out.println("************* Repeatedly Test Completed **************");
+ System.out.println("Total: " + metrics.past() / 1000 + " sec.");
+ System.out.println("Repeated: " + times + " times.");
+ System.out.println("Fail: " + metrics.getFailureCount() + " times.");
+ System.out.println("*************************************************");
+ }
+
+ public static void runWaiting() {
+ while (true) {
+ sleeping(1000);
+ }
+ }
+}
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/UnsafeUtilTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/UnsafeUtilTest.java
new file mode 100644
index 0000000000..5e3c40c017
--- /dev/null
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/util/UnsafeUtilTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.hugegraph.store.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+
+import org.apache.hugegraph.store.util.UnsafeUtf8Util;
+import org.apache.hugegraph.store.util.UnsafeUtil;
+import org.junit.Test;
+
+import lombok.Data;
+import sun.misc.Unsafe;
+
+public class UnsafeUtilTest {
+
+
+ @Test
+ public void testHasUnsafe() {
+ assertTrue(UnsafeUtil.hasUnsafe());
+ }
+
+ @Test
+ public void testPutByte() {
+ UnsafeUtil.putByte("content".getBytes(), 0L, (byte) 99);
+ assertEquals((byte) 99, UnsafeUtil.getByte("content".getBytes(), 0L));
+ }
+
+ @Test
+ public void testMoveToString() {
+ assertEquals("a", UnsafeUtil.moveToString(new char[]{'a'}));
+ }
+
+ @Test
+ public void testEncodedLength() {
+ assertEquals(10, UnsafeUtf8Util.encodedLength("aa中文aa"));
+ }
+
+ @Test
+ public void testEncodeUtf8() {
+ assertEquals(10, UnsafeUtf8Util.encodeUtf8("aa中文aa", new byte[16], 0, 16));
+ }
+
+ @Test
+ public void testDecodeUtf8() {
+ assertEquals("co", UnsafeUtf8Util.decodeUtf8("content".getBytes(), 0, 2));
+ }
+
+ @Test
+ public void testUnsafeUtf8Util() {
+ String content = "content";
+ UnsafeUtf8Util.decodeUtf8(content.getBytes(), 0, content.length());
+ byte[] out = new byte[content.length()];
+ UnsafeUtf8Util.encodeUtf8(content, out, 0, content.length());
+ UnsafeUtf8Util.encodedLength(content);
+ }
+
+ @Test
+ public void testUnsafeAccessor() {
+ Unsafe unsafe = null;
+ long offset = 0;
+ try {
+ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ unsafe = (Unsafe) unsafeField.get(null);
+ UnsafeUtil.UnsafeAccessor acc = new UnsafeUtil.UnsafeAccessor(unsafe);
+ acc.getUnsafe();
+ TestObject to = new TestObject();
+ byte byteValue = 126;
+ offset = acc.objectFieldOffset(TestObject.class.getDeclaredField("b"));
+ acc.putByte(to, offset, byteValue);
+ byte b = acc.getByte(to, offset);
+ assertEquals(byteValue, b);
+ short shortValue = 1;
+ acc.putShort(to, offset, shortValue);
+ short shortResult = acc.getShort(to, offset);
+ assertEquals(shortValue, shortResult);
+ int intValue = 99;
+ acc.putInt(to, offset, intValue);
+ int i = acc.getInt(to, offset);
+ assertEquals(intValue, i);
+ long longValue = 11L;
+ acc.putLong(to, offset, longValue);
+ long l = acc.getLong(to, offset);
+ assertEquals(longValue, l);
+ acc.putBoolean(to, offset, false);
+ assertFalse(acc.getBoolean(to, offset));
+ float f = 1;
+ acc.putFloat(to, offset, f);
+ float v = acc.getFloat(to, offset);
+ assertEquals(f, v, 0.0);
+ double d = 2;
+ acc.putDouble(to, offset, d);
+ double v1 = acc.getDouble(to, offset);
+ assertEquals(d, v1, 0.0);
+ TestObject o1 = new TestObject();
+ acc.putObject(to, offset, o1);
+ Object o2 = acc.getObject(to, offset);
+ assertEquals(o1, o2);
+ offset = unsafe.allocateMemory(1024);
+ acc.putByte(offset, byteValue);
+ byte bResult = acc.getByte(offset);
+ assertEquals(byteValue, bResult);
+ acc.putShort(offset, shortValue);
+ short aShort1 = acc.getShort(offset);
+ assertEquals(aShort1, shortValue);
+ acc.putInt(offset, intValue);
+ assertEquals(acc.getInt(offset), intValue);
+ acc.putLong(offset, longValue);
+ assertEquals(acc.getLong(offset), longValue);
+ unsafe.freeMemory(offset);
+ offset = acc.objectFieldOffset(TestObject.class.getDeclaredField("b"));
+ acc.putByteVolatile(to, offset, byteValue);
+ b = acc.getByteVolatile(to, offset);
+ assertEquals(byteValue, b);
+ acc.putShortVolatile(to, offset, shortValue);
+ shortResult = acc.getShortVolatile(to, offset);
+ assertEquals(shortValue, shortResult);
+ acc.putIntVolatile(to, offset, intValue);
+ i = acc.getIntVolatile(to, offset);
+ assertEquals(intValue, i);
+ acc.putLongVolatile(to, offset, longValue);
+ l = acc.getLongVolatile(to, offset);
+ assertEquals(longValue, l);
+ acc.putBooleanVolatile(to, offset, false);
+ assertFalse(acc.getBooleanVolatile(to, offset));
+ acc.putFloatVolatile(to, offset, f);
+ v = acc.getFloatVolatile(to, offset);
+ assertEquals(f, v, 0.0);
+ acc.putDoubleVolatile(to, offset, d);
+ v1 = acc.getDoubleVolatile(to, offset);
+ assertEquals(d, v1, 0.0);
+ acc.putObjectVolatile(to, offset, o1);
+ o2 = acc.getObjectVolatile(to, offset);
+ assertEquals(o1, o2);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Data
+ private class TestObject {
+ private Object o;
+ private byte b;
+
+ public TestObject() {
+
+ }
+
+ public TestObject(Object o, byte b) {
+ this.o = o;
+ this.b = b;
+ }
+ }
+
+}
diff --git a/hugegraph-store/hg-store-test/src/main/resources/log4j2.xml b/hugegraph-store/hg-store-test/src/main/resources/log4j2.xml
index 0a3aae7b9d..c8fa4195f6 100644
--- a/hugegraph-store/hg-store-test/src/main/resources/log4j2.xml
+++ b/hugegraph-store/hg-store-test/src/main/resources/log4j2.xml
@@ -26,8 +26,8 @@
-
-
+
+
@@ -37,24 +37,24 @@
-
-
+
+
-
-
+
+
-
+
-
-
+
+
@@ -64,25 +64,25 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -91,11 +91,11 @@
-
+
-
-
+
+
diff --git a/hugegraph-store/pom.xml b/hugegraph-store/pom.xml
index be1bbfc7ff..0174de1aed 100644
--- a/hugegraph-store/pom.xml
+++ b/hugegraph-store/pom.xml
@@ -19,9 +19,7 @@
-
4.0.0
-
hugegraph-store
${revision}
pom
@@ -77,12 +75,11 @@
hg-store-core
${project.version}
-
-
-
-
-
-
+
+ org.apache.hugegraph
+ hg-store-transfer
+ ${project.version}
+
org.apache.logging.log4j
log4j-slf4j-impl
@@ -155,56 +152,55 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ store-client-test
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20
+
+
+ store-client-test
+
+ test
+
+ test
+
+
+
+
+
+
+
+ store-core-test
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20
+
+
+ store-core-test
+
+ test
+
+ test
+
+
+
+
+
+
store-common-test
@@ -229,77 +225,77 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ store-rocksdb-test
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20
+
+
+ sit -test
+
+ test
+
+ test
+
+
+
+
+
+
+
+ store-server-test
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20
+
+
+ store-server-test
+
+ test
+
+ test
+
+
+
+
+
+
+
+ store-raftcore-test
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20
+
+
+ store-raftcore-test
+
+ test
+
+ test
+
+
+
+
+
+