From 03b6d3761b31e6c1ca9b70bdcd3e25c59cfcb502 Mon Sep 17 00:00:00 2001
From: V_Galaxy <1904821183@qq.com>
Date: Sun, 23 Apr 2023 10:41:18 +0800
Subject: [PATCH 01/25] history merged until 2023.4.23
---
.gitignore | 53 +
.mvn/wrapper/MavenWrapperDownloader.java | 117 ++
.mvn/wrapper/maven-wrapper.properties | 2 +
README-dev.md | 38 +
README.md | 521 ++++++++
build-change.sh | 17 +
build-pre.sh | 87 ++
build.sh | 16 +
ci.yml | 26 +
conf/application-pd.yml | 17 +
deploy-release.sh | 8 +
deploy-snapshot.sh | 6 +
hg-store-cli/deploy-snapshot.sh | 5 +
hg-store-cli/pom.xml | 73 ++
.../baidu/hugegraph/store/cli/AppConfig.java | 40 +
.../store/cli/StoreConsoleApplication.java | 102 ++
.../store/cli/loader/HgThread2DB.java | 545 ++++++++
.../store/cli/scan/GrpcShardScanner.java | 156 +++
.../store/cli/scan/HgStoreCommitter.java | 68 +
.../store/cli/scan/HgStoreScanner.java | 203 +++
.../hugegraph/store/cli/util/HgCliUtil.java | 219 ++++
.../hugegraph/store/cli/util/HgMetricX.java | 48 +
.../src/main/resources/application.yml | 23 +
.../main/resources/hg-store-client.properties | 7 +
hg-store-cli/src/main/resources/log4j2.xml | 60 +
hg-store-client/deploy-snapshot.sh | 6 +
hg-store-client/pom.xml | 95 ++
.../com/baidu/hugegraph/store/HgKvEntry.java | 14 +
.../baidu/hugegraph/store/HgKvIterator.java | 17 +
.../hugegraph/store/HgKvOrderedIterator.java | 8 +
.../hugegraph/store/HgKvPagingIterator.java | 7 +
.../com/baidu/hugegraph/store/HgKvStore.java | 99 ++
.../com/baidu/hugegraph/store/HgOwnerKey.java | 127 ++
.../com/baidu/hugegraph/store/HgPageSize.java | 13 +
.../com/baidu/hugegraph/store/HgPrivate.java | 17 +
.../baidu/hugegraph/store/HgScanQuery.java | 305 +++++
.../com/baidu/hugegraph/store/HgSeekAble.java | 10 +
.../hugegraph/store/HgSessionManager.java | 38 +
.../hugegraph/store/HgSessionProvider.java | 11 +
.../baidu/hugegraph/store/HgStoreClient.java | 78 ++
.../baidu/hugegraph/store/HgStoreSession.java | 25 +
.../com/baidu/hugegraph/store/HgTkvEntry.java | 10 +
.../baidu/hugegraph/store/HgTokvEntry.java | 10 +
.../store/client/HgNodePartition.java | 75 ++
.../client/HgNodePartitionerBuilder.java | 50 +
.../hugegraph/store/client/HgPrivate.java | 20 +
.../hugegraph/store/client/HgStoreNode.java | 40 +
.../store/client/HgStoreNodeBuilder.java | 19 +
.../store/client/HgStoreNodeCandidates.java | 24 +
.../store/client/HgStoreNodeManager.java | 237 ++++
.../store/client/HgStoreNodeNotifier.java | 19 +
.../store/client/HgStoreNodePartitioner.java | 46 +
.../client/HgStoreNodePartitionerImpl.java | 177 +++
.../store/client/HgStoreNodeProvider.java | 16 +
.../store/client/HgStoreNodeSession.java | 24 +
.../hugegraph/store/client/HgStoreNotice.java | 82 ++
.../store/client/HgStoreService.java | 13 +
.../store/client/HgStoreSessionProvider.java | 19 +
.../store/client/HgTkvEntryImpl.java | 63 +
.../store/client/HgTokvEntryImpl.java | 62 +
.../store/client/MultiNodeSessionFactory.java | 39 +
.../baidu/hugegraph/store/client/NodeTkv.java | 99 ++
.../store/client/NodeTxExecutor.java | 401 ++++++
.../store/client/NodeTxSessionProxy.java | 837 ++++++++++++
.../store/client/SequencedIterator.java | 133 ++
.../store/client/ShiftWorkIteratorProxy.java | 144 +++
.../store/client/TopWorkIteratorProxy.java | 120 ++
.../store/client/grpc/AbstractGrpcClient.java | 126 ++
.../store/client/grpc/GrpcKvEntryImpl.java | 59 +
.../store/client/grpc/GrpcKvIteratorImpl.java | 141 ++
.../client/grpc/GrpcNodeHealthyClient.java | 76 ++
.../client/grpc/GrpcStoreNodeBuilder.java | 60 +
.../store/client/grpc/GrpcStoreNodeImpl.java | 74 ++
.../client/grpc/GrpcStoreNodeSessionImpl.java | 493 +++++++
.../client/grpc/GrpcStoreSessionClient.java | 123 ++
.../client/grpc/GrpcStoreStateClient.java | 60 +
.../client/grpc/GrpcStoreStreamClient.java | 192 +++
.../hugegraph/store/client/grpc/GrpcUtil.java | 132 ++
.../client/grpc/KvBatchOneShotScanner.java | 102 ++
.../store/client/grpc/KvBatchScanner.java | 378 ++++++
.../store/client/grpc/KvBatchScanner5.java | 413 ++++++
.../client/grpc/KvBatchScannerMerger.java | 310 +++++
.../store/client/grpc/KvBatchUtil.java | 128 ++
.../client/grpc/KvCloseableIterator.java | 11 +
.../store/client/grpc/KvListIterator.java | 31 +
.../store/client/grpc/KvOneShotScanner.java | 188 +++
.../store/client/grpc/KvPageScanner.java | 284 +++++
.../store/client/grpc/NotifyingExecutor.java | 229 ++++
.../hugegraph/store/client/grpc/ScanUtil.java | 40 +
.../store/client/grpc/SeekAbleIterator.java | 50 +
.../store/client/grpc/SwitchingExecutor.java | 33 +
.../store/client/type/HgNodeStatus.java | 26 +
.../client/type/HgStoreClientException.java | 30 +
.../hugegraph/store/client/util/Base58.java | 162 +++
.../store/client/util/ExecutorPool.java | 124 ++
.../hugegraph/store/client/util/HgAssert.java | 111 ++
.../store/client/util/HgBufferProxy.java | 143 +++
.../client/util/HgStoreClientConfig.java | 175 +++
.../store/client/util/HgStoreClientConst.java | 36 +
.../store/client/util/HgStoreClientUtil.java | 141 ++
.../hugegraph/store/client/util/HgUuid.java | 26 +
.../hugegraph/store/client/util/MetricX.java | 83 ++
.../store/client/util/PropertyUtil.java | 79 ++
.../main/resources/hg-store-client.properties | 6 +
hg-store-client/src/main/resources/log4j2.xml | 85 ++
.../HgSessionManagerOneRaftFakePDTest.java | 439 +++++++
.../store/HgSessionManagerRaftFakePDTest.java | 605 +++++++++
.../store/HgSessionManagerRaftPDTest.java | 912 +++++++++++++
.../hugegraph/store/HgSessionManagerTest.java | 1061 +++++++++++++++
.../hugegraph/store/client/HgKvStoreTest.java | 207 +++
.../store/client/HgStoreClientBase.java | 25 +
.../store/client/HgStoreClientTest.java | 188 +++
.../store/client/HgStoreNodeSessionTest.java | 50 +
.../store/client/HgStoreNodeStateTest.java | 49 +
.../store/client/HgStoreNodeStreamTest.java | 159 +++
.../hugegraph/store/common/BitsTest.java | 17 +
.../store/test/ChangeShardNumTest.java | 52 +
.../hugegraph/store/util/HgStoreTestUtil.java | 433 +++++++
hg-store-client/src/test/resources/log4j2.xml | 85 ++
.../src/test/resources/pd-server.yml | 54 +
.../.mvn/wrapper/MavenWrapperDownloader.java | 117 ++
.../.mvn/wrapper/maven-wrapper.properties | 2 +
hg-store-common/mvnw | 310 +++++
hg-store-common/mvnw.cmd | 182 +++
hg-store-common/pom.xml | 27 +
.../store/buffer/ByteBufferAllocator.java | 49 +
.../hugegraph/store/buffer/KVByteBuffer.java | 68 +
.../com/baidu/hugegraph/store/term/Bits.java | 46 +
.../baidu/hugegraph/store/term/HgPair.java | 106 ++
.../baidu/hugegraph/store/term/HgTriple.java | 56 +
hg-store-core/build.sh | 15 +
hg-store-core/pom.xml | 130 ++
.../hugegraph/store/HeartbeatService.java | 353 +++++
.../baidu/hugegraph/store/HgStoreEngine.java | 652 ++++++++++
.../hugegraph/store/HgStoreStateListener.java | 8 +
.../hugegraph/store/PartitionEngine.java | 1133 +++++++++++++++++
.../store/PartitionInstructionProcessor.java | 305 +++++
.../store/PartitionStateListener.java | 14 +
.../business/AbstractSelectIterator.java | 54 +
.../store/business/BusinessHandler.java | 198 +++
.../store/business/BusinessHandlerImpl.java | 866 +++++++++++++
.../hugegraph/store/business/DataMover.java | 56 +
.../store/business/DefaultDataMover.java | 240 ++++
.../store/business/FilterIterator.java | 104 ++
.../store/business/GraphStoreIterator.java | 338 +++++
.../store/business/InnerKeyCreator.java | 104 ++
.../store/business/InnerKeyFilter.java | 82 ++
.../business/MultiPartitionIterator.java | 177 +++
.../store/business/SelectIterator.java | 94 ++
.../hugegraph/store/cmd/BatchPutRequest.java | 32 +
.../hugegraph/store/cmd/BatchPutResponse.java | 4 +
.../hugegraph/store/cmd/CleanDataRequest.java | 51 +
.../store/cmd/CleanDataResponse.java | 4 +
.../store/cmd/CreateRaftRequest.java | 48 +
.../store/cmd/CreateRaftResponse.java | 4 +
.../store/cmd/DbCompactionRequest.java | 14 +
.../store/cmd/DbCompactionResponse.java | 4 +
.../store/cmd/DestroyRaftRequest.java | 19 +
.../store/cmd/DestroyRaftResponse.java | 5 +
.../store/cmd/FutureClosureAdapter.java | 29 +
.../store/cmd/GetStoreInfoRequest.java | 8 +
.../store/cmd/GetStoreInfoResponse.java | 24 +
.../baidu/hugegraph/store/cmd/HgCmdBase.java | 57 +
.../hugegraph/store/cmd/HgCmdClient.java | 237 ++++
.../hugegraph/store/cmd/HgCmdProcessor.java | 206 +++
.../store/cmd/UpdatePartitionRequest.java | 17 +
.../store/cmd/UpdatePartitionResponse.java | 4 +
.../store/meta/DeletedFileManager.java | 48 +
.../com/baidu/hugegraph/store/meta/Graph.java | 44 +
.../hugegraph/store/meta/GraphIdManager.java | 164 +++
.../hugegraph/store/meta/GraphManager.java | 66 +
.../store/meta/MetadataKeyHelper.java | 297 +++++
.../baidu/hugegraph/store/meta/Partition.java | 86 ++
.../store/meta/PartitionManager.java | 865 +++++++++++++
.../hugegraph/store/meta/PartitionRole.java | 64 +
.../hugegraph/store/meta/PartitionStats.java | 40 +
.../com/baidu/hugegraph/store/meta/Shard.java | 24 +
.../hugegraph/store/meta/ShardGroup.java | 99 ++
.../com/baidu/hugegraph/store/meta/Store.java | 83 ++
.../hugegraph/store/meta/StoreMetadata.java | 204 +++
.../hugegraph/store/meta/TaskManager.java | 128 ++
.../meta/asynctask/AbstractAsyncTask.java | 128 ++
.../store/meta/asynctask/AsyncTask.java | 36 +
.../store/meta/asynctask/AsyncTaskState.java | 5 +
.../store/meta/asynctask/CleanTask.java | 51 +
.../store/meta/base/DBSessionBuilder.java | 8 +
.../store/meta/base/GlobalMetaStore.java | 39 +
.../store/meta/base/MetaStoreBase.java | 153 +++
.../store/meta/base/PartitionMetaStore.java | 34 +
.../store/metric/HgMetricService.java | 170 +++
.../hugegraph/store/metric/HgStoreMetric.java | 27 +
.../store/metric/SystemMetricService.java | 407 ++++++
.../store/options/HgStoreEngineOptions.java | 122 ++
.../store/options/MetadataOptions.java | 9 +
.../store/options/PartitionEngineOptions.java | 31 +
.../store/options/RaftRocksdbOptions.java | 135 ++
.../hugegraph/store/pd/DefaultPdProvider.java | 409 ++++++
.../store/pd/FakePdServiceProvider.java | 239 ++++
.../pd/PartitionInstructionListener.java | 31 +
.../baidu/hugegraph/store/pd/PdProvider.java | 62 +
.../store/raft/HgStoreStateMachine.java | 234 ++++
.../hugegraph/store/raft/RaftClosure.java | 8 +
.../hugegraph/store/raft/RaftOperation.java | 110 ++
.../store/raft/RaftStateListener.java | 69 +
.../hugegraph/store/raft/RaftTaskHandler.java | 11 +
.../hugegraph/store/raft/util/RaftUtils.java | 65 +
.../store/snapshot/HgSnapshotHandler.java | 201 +++
.../baidu/hugegraph/store/util/Asserts.java | 45 +
.../store/util/CopyOnWriteCache.java | 126 ++
.../hugegraph/store/util/FutureClosure.java | 75 ++
.../hugegraph/store/util/HgRaftError.java | 53 +
.../hugegraph/store/util/HgStoreConst.java | 18 +
.../store/util/HgStoreException.java | 77 ++
.../baidu/hugegraph/store/util/IpUtil.java | 82 ++
.../baidu/hugegraph/store/util/Lifecycle.java | 18 +
.../store/util/ManualResetEvent.java | 75 ++
.../store/util/PartitionMetaStoreWrapper.java | 57 +
.../hugegraph/store/util/UnsafeUtf8Util.java | 297 +++++
.../hugegraph/store/util/UnsafeUtil.java | 317 +++++
.../baidu/hugegraph/store/util/Version.java | 36 +
.../baidu/hugegraph/store/util/ZipUtils.java | 64 +
.../hugegraph/store/HgBusinessImplTest.java | 191 +++
.../hugegraph/store/PartitionEngineTest.java | 185 +++
.../baidu/hugegraph/store/UnitTestBase.java | 82 ++
.../store/meta/GraphIDManagerTest.java | 68 +
.../store/meta/GraphManagerTest.java | 29 +
.../store/util/CopyOnWriteCacheTest.java | 49 +
.../store/util/FutureClosureTest.java | 26 +
hg-store-core/src/test/resources/log4j2.xml | 84 ++
hg-store-core/src/test/resources/version.txt | 1 +
hg-store-dist/pom.xml | 138 ++
.../assembly/descriptor/server-assembly.xml | 42 +
.../src/assembly/static/bin/libjemalloc.so | Bin 0 -> 5956008 bytes
.../static/bin/libjemalloc_aarch64.so | Bin 0 -> 6023520 bytes
.../static/bin/restart-hugegraph-store.sh | 15 +
.../static/bin/start-hugegraph-store.sh | 143 +++
.../static/bin/stop-hugegraph-store.sh | 32 +
hg-store-dist/src/assembly/static/bin/util.sh | 355 ++++++
.../assembly/static/conf/application-pd.yml | 17 +
.../src/assembly/static/conf/application.yml | 47 +
.../src/assembly/static/conf/log4j2.xml | 119 ++
hg-store-grpc/.gitignore | 1 +
hg-store-grpc/build.sh | 9 +
hg-store-grpc/pom.xml | 148 +++
.../store/grpc/stream/HgStoreStreamGrpc.java | 543 ++++++++
.../store/grpc/stream/HgStoreStreamProto.java | 61 +
.../hugegraph/store/grpc/stream/KvStream.java | 810 ++++++++++++
.../store/grpc/stream/KvStreamOrBuilder.java | 53 +
.../store/grpc/stream/store_stream.proto | 33 +
hg-store-grpc/src/main/proto/graphpb.proto | 121 ++
hg-store-grpc/src/main/proto/healthy.proto | 13 +
.../src/main/proto/store_common.proto | 96 ++
.../src/main/proto/store_session.proto | 116 ++
.../src/main/proto/store_state.proto | 56 +
.../src/main/proto/store_stream_meta.proto | 92 ++
hg-store-node/banner.txt | 5 +
hg-store-node/pom.xml | 152 +++
hg-store-node/src/assembly/static/bin/app.sh | 55 +
.../src/assembly/static/bin/hg-get-release.sh | 55 +
.../src/assembly/static/bin/hg-update.sh | 31 +
.../baidu/hugegraph/store/node/AppConfig.java | 220 ++++
.../hugegraph/store/node/AppShutdownHook.java | 42 +
.../store/node/StoreNodeApplication.java | 43 +
.../controller/HgStoreMetricsController.java | 49 +
.../controller/HgStoreStatusController.java | 76 ++
.../node/controller/HgTestController.java | 97 ++
.../store/node/controller/IndexAPI.java | 86 ++
.../store/node/controller/PartitionAPI.java | 215 ++++
.../store/node/entry/RestResult.java | 14 +
.../store/node/grpc/BatchGrpcClosure.java | 190 +++
.../store/node/grpc/BatchScanIterator.java | 141 ++
.../store/node/grpc/EmptyIterator.java | 39 +
.../store/node/grpc/FusingScanIterator.java | 102 ++
.../store/node/grpc/GRpcServerConfig.java | 29 +
.../store/node/grpc/GrpcClosure.java | 53 +
.../store/node/grpc/HgStoreNodeService.java | 208 +++
.../store/node/grpc/HgStoreNodeState.java | 40 +
.../store/node/grpc/HgStoreSessionImpl.java | 490 +++++++
.../store/node/grpc/HgStoreStateService.java | 42 +
.../store/node/grpc/HgStoreStateSubject.java | 55 +
.../store/node/grpc/HgStoreStreamImpl.java | 101 ++
.../store/node/grpc/HgStoreWrapperEx.java | 112 ++
.../store/node/grpc/ParallelScanIterator.java | 365 ++++++
.../store/node/grpc/QueryCondition.java | 22 +
.../node/grpc/ScanBatchOneShotResponse.java | 84 ++
.../store/node/grpc/ScanBatchResponse.java | 251 ++++
.../store/node/grpc/ScanBatchResponse3.java | 376 ++++++
.../node/grpc/ScanBatchResponseFactory.java | 45 +
.../store/node/grpc/ScanOneShotResponse.java | 78 ++
.../hugegraph/store/node/grpc/ScanQuery.java | 87 ++
.../store/node/grpc/ScanQueryProducer.java | 239 ++++
.../store/node/grpc/ScanStreamResponse.java | 238 ++++
.../hugegraph/store/node/grpc/ScanUtil.java | 286 +++++
.../store/node/grpc/scan/GraphStoreImpl.java | 69 +
.../node/grpc/scan/ScanResponseObserver.java | 253 ++++
.../node/listener/ContextClosedListener.java | 40 +
.../node/listener/PdConfigureListener.java | 193 +++
.../store/node/metrics/DriveMetrics.java | 39 +
.../store/node/metrics/GRpcExMetrics.java | 73 ++
.../store/node/metrics/JRaftMetrics.java | 278 ++++
.../store/node/metrics/MetricsConfig.java | 30 +
.../store/node/metrics/MetricsUtil.java | 49 +
.../store/node/metrics/ProcfsEntry.java | 62 +
.../store/node/metrics/ProcfsMetrics.java | 49 +
.../store/node/metrics/ProcfsReader.java | 141 ++
.../store/node/metrics/ProcfsSmaps.java | 109 ++
.../store/node/metrics/RocksDBMetrics.java | 357 ++++++
.../node/metrics/RocksDBMetricsConst.java | 148 +++
.../store/node/metrics/StoreMetrics.java | 93 ++
.../store/node/metrics/SystemMetrics.java | 138 ++
.../store/node/model/HgNodeStatus.java | 55 +
.../hugegraph/store/node/util/Base58.java | 162 +++
.../baidu/hugegraph/store/node/util/Err.java | 23 +
.../hugegraph/store/node/util/HgAssert.java | 119 ++
.../store/node/util/HgBufferProxy.java | 156 +++
.../hugegraph/store/node/util/HgChannel.java | 132 ++
.../store/node/util/HgExecutorUtil.java | 79 ++
.../hugegraph/store/node/util/HgGrpc.java | 107 ++
.../store/node/util/HgRegexUtil.java | 69 +
.../store/node/util/HgStoreConst.java | 21 +
.../store/node/util/HgStoreNodeUtil.java | 60 +
.../store/node/util/PropertyUtil.java | 77 ++
.../hugegraph/store/node/util/Result.java | 22 +
.../hugegraph/store/node/util/TkEntry.java | 48 +
.../src/main/resources/application-pd.yml | 21 +
.../src/main/resources/application.yml | 34 +
hg-store-node/src/main/resources/banner.txt | 6 +
.../src/main/resources/log4j2-dev.xml | 126 ++
hg-store-node/src/main/resources/version.txt | 1 +
.../store/boot/StoreNodeServer00.java | 32 +
.../store/boot/StoreNodeServer01.java | 35 +
.../store/boot/StoreNodeServer02.java | 35 +
.../store/boot/StoreNodeServer03.java | 35 +
.../store/boot/StoreNodeServer04.java | 23 +
.../store/boot/StoreNodeServer05.java | 23 +
.../store/boot/StoreNodeServer06.java | 23 +
.../store/node/HgStoreNodeServiceTest.java | 55 +
.../store/node/metrics/JraftMetricsTest.java | 44 +
.../src/test/resources/application-pd.yml | 11 +
.../test/resources/application-server00.yml | 56 +
.../test/resources/application-server01.yml | 53 +
.../test/resources/application-server02.yml | 52 +
.../test/resources/application-server03.yml | 54 +
.../test/resources/application-server04.yml | 51 +
.../test/resources/application-server05.yml | 53 +
.../test/resources/application-server06.yml | 53 +
.../src/test/resources/log4j2-dev.xml | 122 ++
hg-store-rocksdb/pom.xml | 70 +
.../rocksdb/access/DBSnapshotMeta.java | 39 +
.../rocksdb/access/DBStoreException.java | 46 +
.../rocksdb/access/RocksDBFactory.java | 296 +++++
.../rocksdb/access/RocksDBOptions.java | 461 +++++++
.../rocksdb/access/RocksDBScanIterator.java | 217 ++++
.../rocksdb/access/RocksDBSession.java | 1029 +++++++++++++++
.../rocksdb/access/ScanIterator.java | 32 +
.../rocksdb/access/SessionOperator.java | 51 +
.../rocksdb/access/SessionOperatorImpl.java | 395 ++++++
.../rocksdb/access/util/Asserts.java | 26 +
.../hugegraph/rocksdb/access/util/CRC64.java | 106 ++
.../rocksdb/access/util/ZipUtils.java | 113 ++
.../src/main/java/place-holder.txt | 0
.../rocksdb/access/RocksDBFactoryTest.java | 84 ++
.../rocksdb/access/RocksDBSessionTest.java | 458 +++++++
.../hugegraph/rocksdb/access/RocksdbDump.java | 42 +
.../rocksdb/access/SnapshotManagerTest.java | 413 ++++++
.../src/test/java/place-holder.txt | 0
.../src/test/resources/hugegraph-2.properties | 15 +
.../src/test/resources/hugegraph.properties | 15 +
.../src/test/resources/log4j2.xml | 13 +
hg-store-test/pom.xml | 328 +++++
.../src/main/java/client/BaseClientTest.java | 31 +
.../main/java/client/ChangeShardNumTest.java | 49 +
.../src/main/java/client/ClientSuiteTest.java | 23 +
.../src/main/java/client/ClientTest.java | 21 +
.../src/main/java/client/HgAssertTest.java | 153 +++
.../src/main/java/client/HgKvStoreTest.java | 174 +++
.../src/main/java/client/HgPairTest.java | 62 +
.../client/HgSessionManagerRaftPDTest.java | 671 ++++++++++
.../main/java/client/HgStoreClientTest.java | 184 +++
.../java/client/HgStoreNodeStateTest.java | 41 +
.../client/graph/GraphStoreClientTest.java | 167 +++
.../src/main/java/common/BaseCommonTest.java | 15 +
.../java/common/ByteBufferAllocatorTest.java | 48 +
.../src/main/java/common/CommonSuiteTest.java | 15 +
.../main/java/common/KVByteBufferTest.java | 51 +
.../src/main/java/core/BaseCoreTest.java | 29 +
.../src/main/java/core/CoreSuiteTest.java | 49 +
.../src/main/java/core/CoreTest.java | 21 +
.../main/java/core/HgBusinessImplTest.java | 157 +++
.../src/main/java/core/HgCmdClientTest.java | 337 +++++
.../src/main/java/core/MetricServiceTest.java | 47 +
.../main/java/core/StoreEngineTestBase.java | 112 ++
.../core/raft/HgStoreStateMachineTest.java | 223 ++++
.../main/java/core/raft/MockStateMachine.java | 13 +
.../java/core/raft/RaftOperationTest.java | 58 +
.../main/java/core/raft/RaftUtilsTest.java | 161 +++
.../core/snapshot/HgSnapshotHandlerTest.java | 169 +++
.../java/core/store/HgStoreEngineTest.java | 157 +++
.../java/core/store/PartitionEngineTest.java | 75 ++
.../PartitionInstructionProcessorTest.java | 92 ++
.../store/meta/MetadataKeyHelperTest.java | 19 +
.../core/store/meta/PartitionManagerTest.java | 182 +++
.../java/core/store/meta/TaskManagerTest.java | 88 ++
.../store/meta/asynctask/CleanTaskTest.java | 31 +
.../core/store/util/MiscUtilClassTest.java | 78 ++
.../util/PartitionMetaStoreWrapperTest.java | 72 ++
.../java/core/store/util/ZipUtilsTest.java | 35 +
.../main/java/raftcore/BytesCarrierTest.java | 44 +
.../src/main/java/raftcore/RaftSuiteTest.java | 13 +
.../raftcore/ZeroByteStringHelperTest.java | 51 +
.../main/java/rocksdb/BaseRocksDbTest.java | 34 +
.../main/java/rocksdb/RocksDBFactoryTest.java | 62 +
.../main/java/rocksdb/RocksDbSuiteTest.java | 14 +
.../src/main/java/service/BaseServerTest.java | 16 +
.../main/java/service/ServerSuiteTest.java | 14 +
.../src/main/java/service/SessionTest.java | 17 +
.../main/java/util/CopyOnWriteCacheTest.java | 48 +
.../src/main/java/util/HgStoreTestUtil.java | 458 +++++++
.../src/main/java/util/UnitTestBase.java | 81 ++
.../src/main/java/util/UnsafeUtilTest.java | 162 +++
hg-store-test/src/main/resources/version.txt | 1 +
init.sh | 8 +
local-release.sh | 8 +
lombok.config | 2 +
mvnw | 310 +++++
mvnw.cmd | 182 +++
pom.xml | 238 ++++
run.sh | 5 +
settings.xml | 113 ++
start_server.sh | 38 +
430 files changed, 51316 insertions(+)
create mode 100644 .gitignore
create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java
create mode 100644 .mvn/wrapper/maven-wrapper.properties
create mode 100644 README-dev.md
create mode 100644 README.md
create mode 100644 build-change.sh
create mode 100644 build-pre.sh
create mode 100755 build.sh
create mode 100644 ci.yml
create mode 100644 conf/application-pd.yml
create mode 100755 deploy-release.sh
create mode 100644 deploy-snapshot.sh
create mode 100644 hg-store-cli/deploy-snapshot.sh
create mode 100644 hg-store-cli/pom.xml
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/AppConfig.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/StoreConsoleApplication.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/loader/HgThread2DB.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/GrpcShardScanner.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreCommitter.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreScanner.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgCliUtil.java
create mode 100644 hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgMetricX.java
create mode 100644 hg-store-cli/src/main/resources/application.yml
create mode 100644 hg-store-cli/src/main/resources/hg-store-client.properties
create mode 100644 hg-store-cli/src/main/resources/log4j2.xml
create mode 100644 hg-store-client/deploy-snapshot.sh
create mode 100644 hg-store-client/pom.xml
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvEntry.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvOrderedIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvPagingIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvStore.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgOwnerKey.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPageSize.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPrivate.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgScanQuery.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSeekAble.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionManager.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionProvider.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreSession.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTkvEntry.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTokvEntry.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartition.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartitionerBuilder.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgPrivate.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNode.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeBuilder.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeCandidates.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeManager.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeNotifier.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitioner.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitionerImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeProvider.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeSession.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNotice.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreService.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreSessionProvider.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTkvEntryImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTokvEntryImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/MultiNodeSessionFactory.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTkv.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxExecutor.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxSessionProxy.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/SequencedIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/ShiftWorkIteratorProxy.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/TopWorkIteratorProxy.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/AbstractGrpcClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcKvEntryImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcKvIteratorImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcNodeHealthyClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreNodeBuilder.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreNodeImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreNodeSessionImpl.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreSessionClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreStateClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcStoreStreamClient.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/GrpcUtil.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvBatchOneShotScanner.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvBatchScanner.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvBatchScanner5.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvBatchScannerMerger.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvBatchUtil.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvCloseableIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvListIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvOneShotScanner.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/KvPageScanner.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/NotifyingExecutor.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/ScanUtil.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/SeekAbleIterator.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/SwitchingExecutor.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/type/HgNodeStatus.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/type/HgStoreClientException.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/Base58.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/ExecutorPool.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgAssert.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgBufferProxy.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgStoreClientConfig.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgStoreClientConst.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgStoreClientUtil.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/HgUuid.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/MetricX.java
create mode 100644 hg-store-client/src/main/java/com/baidu/hugegraph/store/client/util/PropertyUtil.java
create mode 100644 hg-store-client/src/main/resources/hg-store-client.properties
create mode 100644 hg-store-client/src/main/resources/log4j2.xml
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/HgSessionManagerRaftFakePDTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/HgSessionManagerRaftPDTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/HgSessionManagerTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgKvStoreTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgStoreClientBase.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgStoreClientTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgStoreNodeSessionTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgStoreNodeStateTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/client/HgStoreNodeStreamTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/common/BitsTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/test/ChangeShardNumTest.java
create mode 100644 hg-store-client/src/test/java/com/baidu/hugegraph/store/util/HgStoreTestUtil.java
create mode 100644 hg-store-client/src/test/resources/log4j2.xml
create mode 100644 hg-store-client/src/test/resources/pd-server.yml
create mode 100644 hg-store-common/.mvn/wrapper/MavenWrapperDownloader.java
create mode 100644 hg-store-common/.mvn/wrapper/maven-wrapper.properties
create mode 100644 hg-store-common/mvnw
create mode 100644 hg-store-common/mvnw.cmd
create mode 100644 hg-store-common/pom.xml
create mode 100644 hg-store-common/src/main/java/com/baidu/hugegraph/store/buffer/ByteBufferAllocator.java
create mode 100644 hg-store-common/src/main/java/com/baidu/hugegraph/store/buffer/KVByteBuffer.java
create mode 100644 hg-store-common/src/main/java/com/baidu/hugegraph/store/term/Bits.java
create mode 100644 hg-store-common/src/main/java/com/baidu/hugegraph/store/term/HgPair.java
create mode 100644 hg-store-common/src/main/java/com/baidu/hugegraph/store/term/HgTriple.java
create mode 100755 hg-store-core/build.sh
create mode 100644 hg-store-core/pom.xml
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/HeartbeatService.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/HgStoreEngine.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/HgStoreStateListener.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/PartitionEngine.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/PartitionInstructionProcessor.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/PartitionStateListener.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/AbstractSelectIterator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/BusinessHandler.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/BusinessHandlerImpl.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/DataMover.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/DefaultDataMover.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/FilterIterator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/GraphStoreIterator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/InnerKeyCreator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/InnerKeyFilter.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/MultiPartitionIterator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/business/SelectIterator.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/BatchPutRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/BatchPutResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/CleanDataRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/CleanDataResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/CreateRaftRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/CreateRaftResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/DbCompactionRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/DbCompactionResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/DestroyRaftRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/DestroyRaftResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/FutureClosureAdapter.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/GetStoreInfoRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/GetStoreInfoResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/HgCmdBase.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/HgCmdClient.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/HgCmdProcessor.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/UpdatePartitionRequest.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/cmd/UpdatePartitionResponse.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/DeletedFileManager.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/Graph.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/GraphIdManager.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/GraphManager.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/MetadataKeyHelper.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/Partition.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/PartitionManager.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/PartitionRole.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/PartitionStats.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/Shard.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/ShardGroup.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/Store.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/StoreMetadata.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/TaskManager.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/asynctask/AbstractAsyncTask.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/asynctask/AsyncTask.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/asynctask/AsyncTaskState.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/asynctask/CleanTask.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/base/DBSessionBuilder.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/base/GlobalMetaStore.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/base/MetaStoreBase.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/meta/base/PartitionMetaStore.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/metric/HgMetricService.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/metric/HgStoreMetric.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/metric/SystemMetricService.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/options/HgStoreEngineOptions.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/options/MetadataOptions.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/options/PartitionEngineOptions.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/options/RaftRocksdbOptions.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/pd/DefaultPdProvider.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/pd/FakePdServiceProvider.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/pd/PartitionInstructionListener.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/pd/PdProvider.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/HgStoreStateMachine.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/RaftClosure.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/RaftOperation.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/RaftStateListener.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/RaftTaskHandler.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/raft/util/RaftUtils.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/snapshot/HgSnapshotHandler.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/Asserts.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/CopyOnWriteCache.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/FutureClosure.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/HgRaftError.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/HgStoreConst.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/HgStoreException.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/IpUtil.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/Lifecycle.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/ManualResetEvent.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/PartitionMetaStoreWrapper.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/UnsafeUtf8Util.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/UnsafeUtil.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/Version.java
create mode 100644 hg-store-core/src/main/java/com/baidu/hugegraph/store/util/ZipUtils.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/HgBusinessImplTest.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/PartitionEngineTest.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/UnitTestBase.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/meta/GraphIDManagerTest.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/meta/GraphManagerTest.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/util/CopyOnWriteCacheTest.java
create mode 100644 hg-store-core/src/test/java/com/baidu/hugegraph/store/util/FutureClosureTest.java
create mode 100644 hg-store-core/src/test/resources/log4j2.xml
create mode 100644 hg-store-core/src/test/resources/version.txt
create mode 100644 hg-store-dist/pom.xml
create mode 100644 hg-store-dist/src/assembly/descriptor/server-assembly.xml
create mode 100644 hg-store-dist/src/assembly/static/bin/libjemalloc.so
create mode 100644 hg-store-dist/src/assembly/static/bin/libjemalloc_aarch64.so
create mode 100644 hg-store-dist/src/assembly/static/bin/restart-hugegraph-store.sh
create mode 100644 hg-store-dist/src/assembly/static/bin/start-hugegraph-store.sh
create mode 100644 hg-store-dist/src/assembly/static/bin/stop-hugegraph-store.sh
create mode 100644 hg-store-dist/src/assembly/static/bin/util.sh
create mode 100644 hg-store-dist/src/assembly/static/conf/application-pd.yml
create mode 100644 hg-store-dist/src/assembly/static/conf/application.yml
create mode 100644 hg-store-dist/src/assembly/static/conf/log4j2.xml
create mode 100644 hg-store-grpc/.gitignore
create mode 100644 hg-store-grpc/build.sh
create mode 100644 hg-store-grpc/pom.xml
create mode 100644 hg-store-grpc/src/main/dev/com/baidu/hugegraph/store/grpc/stream/HgStoreStreamGrpc.java
create mode 100644 hg-store-grpc/src/main/dev/com/baidu/hugegraph/store/grpc/stream/HgStoreStreamProto.java
create mode 100644 hg-store-grpc/src/main/dev/com/baidu/hugegraph/store/grpc/stream/KvStream.java
create mode 100644 hg-store-grpc/src/main/dev/com/baidu/hugegraph/store/grpc/stream/KvStreamOrBuilder.java
create mode 100644 hg-store-grpc/src/main/dev/com/baidu/hugegraph/store/grpc/stream/store_stream.proto
create mode 100644 hg-store-grpc/src/main/proto/graphpb.proto
create mode 100644 hg-store-grpc/src/main/proto/healthy.proto
create mode 100644 hg-store-grpc/src/main/proto/store_common.proto
create mode 100644 hg-store-grpc/src/main/proto/store_session.proto
create mode 100644 hg-store-grpc/src/main/proto/store_state.proto
create mode 100644 hg-store-grpc/src/main/proto/store_stream_meta.proto
create mode 100644 hg-store-node/banner.txt
create mode 100644 hg-store-node/pom.xml
create mode 100755 hg-store-node/src/assembly/static/bin/app.sh
create mode 100644 hg-store-node/src/assembly/static/bin/hg-get-release.sh
create mode 100644 hg-store-node/src/assembly/static/bin/hg-update.sh
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/AppConfig.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/AppShutdownHook.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/StoreNodeApplication.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/controller/HgStoreMetricsController.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/controller/HgStoreStatusController.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/controller/HgTestController.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/controller/IndexAPI.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/controller/PartitionAPI.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/entry/RestResult.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/BatchGrpcClosure.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/BatchScanIterator.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/EmptyIterator.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/FusingScanIterator.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/GRpcServerConfig.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/GrpcClosure.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreNodeService.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreNodeState.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreSessionImpl.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreStateService.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreStateSubject.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreStreamImpl.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/HgStoreWrapperEx.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ParallelScanIterator.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/QueryCondition.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanBatchOneShotResponse.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanBatchResponse.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanBatchResponse3.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanBatchResponseFactory.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanOneShotResponse.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanQuery.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanQueryProducer.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanStreamResponse.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/ScanUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/scan/GraphStoreImpl.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/grpc/scan/ScanResponseObserver.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/listener/ContextClosedListener.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/listener/PdConfigureListener.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/DriveMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/GRpcExMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/JRaftMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/MetricsConfig.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/MetricsUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/ProcfsEntry.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/ProcfsMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/ProcfsReader.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/ProcfsSmaps.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/RocksDBMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/RocksDBMetricsConst.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/StoreMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/metrics/SystemMetrics.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/model/HgNodeStatus.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/Base58.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/Err.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgAssert.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgBufferProxy.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgChannel.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgExecutorUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgGrpc.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgRegexUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgStoreConst.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/HgStoreNodeUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/PropertyUtil.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/Result.java
create mode 100644 hg-store-node/src/main/java/com/baidu/hugegraph/store/node/util/TkEntry.java
create mode 100644 hg-store-node/src/main/resources/application-pd.yml
create mode 100644 hg-store-node/src/main/resources/application.yml
create mode 100644 hg-store-node/src/main/resources/banner.txt
create mode 100644 hg-store-node/src/main/resources/log4j2-dev.xml
create mode 100644 hg-store-node/src/main/resources/version.txt
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer00.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer01.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer02.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer03.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer04.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer05.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/boot/StoreNodeServer06.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/node/HgStoreNodeServiceTest.java
create mode 100644 hg-store-node/src/test/java/com/baidu/hugegraph/store/node/metrics/JraftMetricsTest.java
create mode 100644 hg-store-node/src/test/resources/application-pd.yml
create mode 100644 hg-store-node/src/test/resources/application-server00.yml
create mode 100644 hg-store-node/src/test/resources/application-server01.yml
create mode 100644 hg-store-node/src/test/resources/application-server02.yml
create mode 100644 hg-store-node/src/test/resources/application-server03.yml
create mode 100644 hg-store-node/src/test/resources/application-server04.yml
create mode 100644 hg-store-node/src/test/resources/application-server05.yml
create mode 100644 hg-store-node/src/test/resources/application-server06.yml
create mode 100644 hg-store-node/src/test/resources/log4j2-dev.xml
create mode 100644 hg-store-rocksdb/pom.xml
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/DBSnapshotMeta.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/DBStoreException.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/RocksDBFactory.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/RocksDBOptions.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/RocksDBScanIterator.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/RocksDBSession.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/ScanIterator.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/SessionOperator.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/SessionOperatorImpl.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/util/Asserts.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/util/CRC64.java
create mode 100644 hg-store-rocksdb/src/main/java/com/baidu/hugegraph/rocksdb/access/util/ZipUtils.java
create mode 100644 hg-store-rocksdb/src/main/java/place-holder.txt
create mode 100644 hg-store-rocksdb/src/test/java/com/baidu/hugegraph/rocksdb/access/RocksDBFactoryTest.java
create mode 100644 hg-store-rocksdb/src/test/java/com/baidu/hugegraph/rocksdb/access/RocksDBSessionTest.java
create mode 100644 hg-store-rocksdb/src/test/java/com/baidu/hugegraph/rocksdb/access/RocksdbDump.java
create mode 100644 hg-store-rocksdb/src/test/java/com/baidu/hugegraph/rocksdb/access/SnapshotManagerTest.java
create mode 100644 hg-store-rocksdb/src/test/java/place-holder.txt
create mode 100644 hg-store-rocksdb/src/test/resources/hugegraph-2.properties
create mode 100644 hg-store-rocksdb/src/test/resources/hugegraph.properties
create mode 100644 hg-store-rocksdb/src/test/resources/log4j2.xml
create mode 100644 hg-store-test/pom.xml
create mode 100644 hg-store-test/src/main/java/client/BaseClientTest.java
create mode 100644 hg-store-test/src/main/java/client/ChangeShardNumTest.java
create mode 100644 hg-store-test/src/main/java/client/ClientSuiteTest.java
create mode 100644 hg-store-test/src/main/java/client/ClientTest.java
create mode 100644 hg-store-test/src/main/java/client/HgAssertTest.java
create mode 100644 hg-store-test/src/main/java/client/HgKvStoreTest.java
create mode 100644 hg-store-test/src/main/java/client/HgPairTest.java
create mode 100644 hg-store-test/src/main/java/client/HgSessionManagerRaftPDTest.java
create mode 100644 hg-store-test/src/main/java/client/HgStoreClientTest.java
create mode 100644 hg-store-test/src/main/java/client/HgStoreNodeStateTest.java
create mode 100644 hg-store-test/src/main/java/client/graph/GraphStoreClientTest.java
create mode 100644 hg-store-test/src/main/java/common/BaseCommonTest.java
create mode 100644 hg-store-test/src/main/java/common/ByteBufferAllocatorTest.java
create mode 100644 hg-store-test/src/main/java/common/CommonSuiteTest.java
create mode 100644 hg-store-test/src/main/java/common/KVByteBufferTest.java
create mode 100644 hg-store-test/src/main/java/core/BaseCoreTest.java
create mode 100644 hg-store-test/src/main/java/core/CoreSuiteTest.java
create mode 100644 hg-store-test/src/main/java/core/CoreTest.java
create mode 100644 hg-store-test/src/main/java/core/HgBusinessImplTest.java
create mode 100644 hg-store-test/src/main/java/core/HgCmdClientTest.java
create mode 100644 hg-store-test/src/main/java/core/MetricServiceTest.java
create mode 100644 hg-store-test/src/main/java/core/StoreEngineTestBase.java
create mode 100644 hg-store-test/src/main/java/core/raft/HgStoreStateMachineTest.java
create mode 100644 hg-store-test/src/main/java/core/raft/MockStateMachine.java
create mode 100644 hg-store-test/src/main/java/core/raft/RaftOperationTest.java
create mode 100644 hg-store-test/src/main/java/core/raft/RaftUtilsTest.java
create mode 100644 hg-store-test/src/main/java/core/snapshot/HgSnapshotHandlerTest.java
create mode 100644 hg-store-test/src/main/java/core/store/HgStoreEngineTest.java
create mode 100644 hg-store-test/src/main/java/core/store/PartitionEngineTest.java
create mode 100644 hg-store-test/src/main/java/core/store/PartitionInstructionProcessorTest.java
create mode 100644 hg-store-test/src/main/java/core/store/meta/MetadataKeyHelperTest.java
create mode 100644 hg-store-test/src/main/java/core/store/meta/PartitionManagerTest.java
create mode 100644 hg-store-test/src/main/java/core/store/meta/TaskManagerTest.java
create mode 100644 hg-store-test/src/main/java/core/store/meta/asynctask/CleanTaskTest.java
create mode 100644 hg-store-test/src/main/java/core/store/util/MiscUtilClassTest.java
create mode 100644 hg-store-test/src/main/java/core/store/util/PartitionMetaStoreWrapperTest.java
create mode 100644 hg-store-test/src/main/java/core/store/util/ZipUtilsTest.java
create mode 100644 hg-store-test/src/main/java/raftcore/BytesCarrierTest.java
create mode 100644 hg-store-test/src/main/java/raftcore/RaftSuiteTest.java
create mode 100644 hg-store-test/src/main/java/raftcore/ZeroByteStringHelperTest.java
create mode 100644 hg-store-test/src/main/java/rocksdb/BaseRocksDbTest.java
create mode 100644 hg-store-test/src/main/java/rocksdb/RocksDBFactoryTest.java
create mode 100644 hg-store-test/src/main/java/rocksdb/RocksDbSuiteTest.java
create mode 100644 hg-store-test/src/main/java/service/BaseServerTest.java
create mode 100644 hg-store-test/src/main/java/service/ServerSuiteTest.java
create mode 100644 hg-store-test/src/main/java/service/SessionTest.java
create mode 100644 hg-store-test/src/main/java/util/CopyOnWriteCacheTest.java
create mode 100644 hg-store-test/src/main/java/util/HgStoreTestUtil.java
create mode 100644 hg-store-test/src/main/java/util/UnitTestBase.java
create mode 100644 hg-store-test/src/main/java/util/UnsafeUtilTest.java
create mode 100644 hg-store-test/src/main/resources/version.txt
create mode 100644 init.sh
create mode 100644 local-release.sh
create mode 100644 lombok.config
create mode 100644 mvnw
create mode 100644 mvnw.cmd
create mode 100644 pom.xml
create mode 100644 run.sh
create mode 100644 settings.xml
create mode 100644 start_server.sh
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..4e6b7780d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,53 @@
+**/target/
+**/output/
+.DS_Store
+**/tmp/
+**/tmp*/
+
+*.log
+.idea/
+*.iml
+**[^storage]/log/
+**/rocksdb-data/
+dist/
+.settings/
+.project
+.classpath
+.factorypath
+
+# vscode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+/logs/
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed 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.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..642d572ce
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/README-dev.md b/README-dev.md
new file mode 100644
index 000000000..9240f6284
--- /dev/null
+++ b/README-dev.md
@@ -0,0 +1,38 @@
+## 启用无PD模式
+- hgstore设置yml文件 **app.fake-pd: true**
+- hugegraph设置properties文件 **pd.fake=true**,设置**hstore.peers=** 指向hgstore的grpc地址,多个地址逗号分割
+
+````
+ backend=hstore
+ serializer=binary
+ pd.peers=localhost:9000
+ pd.fake=true
+ hstore.peers=127.0.0.1:9081,127.0.0.1:9082,127.0.0.1:9083
+ store=hugegraph
+````
+
+###FakePD集群配置
+如果启用fakePD模式的集群部署,需要在hgstore的yml文件增加fake-pd配置
++ **store-list:** store集群列表
++ **peers-list:** raft集群列表
+
+````
+ fake-pd:
+ store-list: 127.0.0.1:9080,127.0.0.1:9081,127.0.0.1:9082
+ peers-list: 127.0.0.1:8080,127.0.0.1:8081,127.0.0.1:8082
+````
+
+###本地打包
+
+项目根目录下执行:
+````
+./mvnw -Dmaven.test.skip=true package
+````
+文件保存在项目根目录下的 dist 文件夹中。
+
+###本地单测
+- 在跑单测之前需要启动一个pd和store服务
+- 所以的单测统一在hg-store-test模块中撰写,client、common、core等与项目的模块一一对应,相应模块下的单测写到对应的文件夹下
+- 保持目录结构与项目模块对应,文件命名必须包含"Test"字样,把编写好的类加到对应的SuiteTest类中,由Suite调度执行
+- 单测可以用编译工具单个执行,也可以到代码的根目录下执行:mvn verify -Pjacoco
+- 代码覆盖率查看,需要先执行:mvn verify -Pjacoco 后,在到根目录的target->site->jacoco->index.html
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..920af665a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,521 @@
+# HStore存储部署说明
+##安装etcd
+- 配置etcd时需要确保其他服务器可以访问,注意配置文件中以下修改
+````
+ name: etcd-1 #节点名称
+ data-dir: default.etcd/ #节点数据存储目录
+ listen-client-urls: http://0.0.0.0:2379 #监听etcd客户发送信息的地址
+ advertise-client-urls: http://0.0.0.0:2379 #客户与本节点交互信息所用地址
+````
+## PD配置
+- 配置文件在application.yml
+````
+ grpc:
+ port: 9000 #内部grpc通信用端口,如心跳等使用
+ max-inbound-message-size: 100MB #grpc最大入参的大小
+ server:
+ port : 9001 #restful端口,如通过http的get方法获取storeNode信息(/v1/stores)等
+ etcd:
+ address: http://localhost:2379 #etcd地址
+ timeout: 3 #etcd连接超时时间
+ store:
+ keepAlive-timeout: 60 #store心跳超时时间,超过该时间,认为store临时不可用,转移Leader到其他副本,单位秒
+ down-time: 1800 #store下线时间。超过该时间,认为store永久不可用,分配副本到其他机器,单位秒
+ partition:
+ default-total-count: 12 #默认分区总数
+ default-shard-count: 3 #默认每个分区副本数
+````
+## StoreNode配置
+````
+ grpc:
+ port: 9080
+ host: 127.0.0.1 #grpc的服务地址,给HugeServer使用
+ netty-server:
+ max-inbound-message-size: 100MB #grpc最大入参的大小
+ server:
+ port : 9090 #restful端口,如通过http的get方法获取监控统计信息(/metrics)等
+ app:
+ rocks:
+ config-path: "/hugegraph.properties" #写入Rocksdb的参数配置文件
+ raft:
+ address: 127.0.0.1:8081 #raft通信地址
+ data-path: /test/raft/8081 #raft日志写入目录
+ timeout: 10 #raft读写超时时间,单位秒
+ metrics: false #统计raft监控统计信息,打开可能对性能有影响
+ pdserver:
+ address: localhost:9000 #PD的grpc地址
+````
+ StoreNode在启动后,如果在PD的日志中打印出其注册信息,则代表注册成功,如:Store register, id = **** address = ****
+## Hugegraph配置
+- 配置文件在properties文件,如hugegraph.properties
+````
+ backend=hstore #后端分布式存储类型,固定为hstore
+ serializer=binary #序列化器,固定为binary
+ pd.peers=localhost:9000 #PD的grpc地址
+````
+## RESTFUL API
+- pd提供了一些restful API可以获取分区、存储节点等一系列信息
+
+###图相关
+
+#### 获取图的partition、shard信息
+
+###### Method & Url
+```
+GET http://localhost:9001/v1/graphs
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+
+```json
+{
+ "status": 0,
+ "graphs": [
+ {
+ "graphName": "default/hugegraph/g",
+ "partitionCount": 60,
+ "shardCount": 3
+ },
+ {
+ "graphName": "default/hugegraph/m",
+ "partitionCount": 60,
+ "shardCount": 3
+ },
+ {
+ "graphName": "default/hugegraph/s",
+ "partitionCount": 60,
+ "shardCount": 3
+ },
+ {
+ "graphName": "default/system/g",
+ "partitionCount": 60,
+ "shardCount": 3
+ },
+ {
+ "graphName": "default/system/m",
+ "partitionCount": 60,
+ "shardCount": 3
+ },
+ {
+ "graphName": "default/system/s",
+ "partitionCount": 60,
+ "shardCount": 3
+ }
+ ]
+}
+```
+#### 获取指定图的partition、shard信息
+
+###### Method & Url
+```
+GET http://localhost:9001/v1/graph/default/hugegraph/g
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+
+```json
+{
+ "status": 0,
+ "graph": {
+ "graphName": "default/hugegraph/g",
+ "partitionCount": 60,
+ "shardCount": 3
+ }
+}
+```
+#### 修改指定图的partition、shard信息
+
+###### Method & Url
+```
+POST http://localhost:9001/v1/graph/default/hugegraph/g
+```
+###### Request Body
+
+```json
+{
+ "partitionCount":90,
+ "shardCount": 4,
+ "workMode":"Batch_Import"
+}
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+
+```json
+{
+ "status": 0,
+ "graph": {
+ "graphName": "default/hugegraph/g",
+ "partitionCount": 60,
+ "shardCount": 4,
+ "workMode": "Batch_Import"
+ }
+}
+```
+### 分区相关
+#### 获取分区信息
+
+###### Method & Url
+```
+GET http://localhost:9001/v1/partitions
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+
+```json
+{
+ "partitions": [
+ {
+ "endKey": 2731,
+ "graphName": "DEFAULT/hugegraph18e1/g",
+ "id": 0,
+ "shards": [
+ {
+ "address": "10.14.139.56:8500",
+ "committedIndex": "7396553",
+ "role": "Follower",
+ "state": "online",
+ "storeId": "6140115507143799097"
+ },
+ {
+ "address": "10.14.139.61:8500",
+ "committedIndex": "7399964",
+ "role": "Follower",
+ "state": "online",
+ "storeId": "3661113370728329034"
+ },
+ {
+ "address": "10.14.139.57:8500",
+ "committedIndex": "7394615",
+ "role": "Leader",
+ "state": "online",
+ "storeId": "3384290400781292563"
+ }
+ ],
+ "startKey": 0,
+ "timestamp": "2022-03-28 17:29:56",
+ "version": 23,
+ "workMode": "Normal",
+ "workState": "State_Normal"
+ }
+ ],
+ "status": 0
+}
+```
+###存储节点相关
+#### 获取存储节点信息
+
+###### Method & Url
+```
+GET http://localhost:9001/v1/stores
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+
+```json
+{
+ "status": 0,
+ "stores": [
+ {
+ "address": "10.14.139.60:8500",
+ "dataVersion": 1,
+ "id": "1779882393067551022",
+ "labels": [
+ {
+ "key": "rest.port",
+ "value": "8520"
+ }
+ ],
+ "lastHeartbeat": "1648459470389",
+ "raftAddress": "10.14.139.60:8510",
+ "startTimestamp": "1648395903516",
+ "state": "Up",
+ "stats": {
+ "available": "4081010491392",
+ "capacity": "7545950388224",
+ "graphStats": [
+ {
+ "approximateKeys": "1933169027",
+ "approximateSize": "191628815980",
+ "committedIndex": "7301460",
+ "graphName": "DEFAULT/hugegraph18e1/g",
+ "partitionId": 1,
+ "role": "Leader",
+ "workMode": "Normal",
+ "workState": "State_Normal"
+ },
+ {
+ "approximateKeys": "1919472248",
+ "approximateSize": "189192672333",
+ "committedIndex": "7301705",
+ "graphName": "DEFAULT/hugegraph18e1/g",
+ "partitionId": 2,
+ "role": "Leader",
+ "workMode": "Normal",
+ "workState": "State_Normal"
+ }
+ ],
+ "partitionCount": 12,
+ "startTime": 1648395902,
+ "storeId": "1779882393067551022",
+ "usedSize": "4851786575920"
+ },
+ "version": "3.6.3"
+ }
+ ]
+}
+```
+#### 删除存储节点
+
+###### Method & Url
+```
+DELETE http://localhost:9001/v1/store/2549332866463202176
+```
+
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+````
+OK
+````
+#### 服务注册
+
+###### Method & Url
+```
+post http://127.0.0.1:8620/v1/registry
+```
+###### Request Body
+
+```json
+{
+ "appName":"aaaa",
+ "version":"version1",
+ "address":"address1",
+ "interval":"9223372036854775807",
+ "labels": {
+ "aaa": "aaaavalue"
+ }
+}
+```
+````
+appName:所属服务名
+version:所属服务版本号
+address:服务实例地址+端口
+interval:实例心跳间隔,字符串,最大9223372036854775807
+labels: 自定义标签
+````
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+```json
+{
+ "errorType": "OK",
+ "message": "",
+ "data": null
+}
+````
+````
+errorType:状态码
+message:状态码为错误时的具体出错信息
+data:无返回数据
+````
+#### 服务实例获取
+
+###### Method & Url
+```
+post http://127.0.0.1:8620/v1/registryInfo
+```
+###### Request Body
+
+```json
+{
+ "appName":"aaaa",
+ "version":"version1",
+ "labels": {
+ "aaa": "aaaavalue"
+ }
+}
+```
+````
+以下三项可全部为空,则获取所有服务节点的信息
+ appName:过滤所属服务名的条件
+ version:过滤所属服务版本号的条件,此项有值,则appName不能为空
+ labels: 过滤自定义标签的条件
+````
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+```json
+{
+ "errorType": "OK",
+ "message": null,
+ "data": [
+ {
+ "id": null,
+ "appName": "aaaa",
+ "version": "version1",
+ "address": "address1",
+ "interval": "9223372036854775807",
+ "labels": {
+ "aaa": "aaaavalue"
+ }
+ }
+ ]
+}
+```
+````
+errorType:状态码
+message:状态码为错误时的具体出错信息
+data:获取的服务节点信息
+````
+#### 服务注册
+
+###### Method & Url
+```
+post http://127.0.0.1:8620/v1/registry
+```
+###### Request Body
+
+```json
+{
+ "appName":"aaaa",
+ "version":"version1",
+ "address":"address1",
+ "interval":"9223372036854775807",
+ "labels": {
+ "aaa": "aaaavalue"
+ }
+}
+```
+````
+appName:所属服务名
+version:所属服务版本号
+address:服务实例地址+端口
+interval:实例心跳间隔,字符串,最大9223372036854775807
+labels: 自定义标签
+````
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+```json
+{
+ "errorType": "OK",
+ "message": "",
+ "data": null
+}
+````
+````
+errorType:状态码
+message:状态码为错误时的具体出错信息
+data:无返回数据
+````
+#### 获取pd成员
+
+###### Method & Url
+```
+GET http://127.0.0.1:8620/v1/members
+```
+###### Response Status
+
+```json
+200
+```
+
+###### Response Body
+```json
+{
+ "status": 0,
+ "graphs": {
+ "members": [
+ {
+ "clusterId": "1",
+ "raftUrl": "10.14.139.56:8620",
+ "grpcUrl": "10.14.139.56:8686",
+ "restUrl": "10.14.139.56:8620",
+ "dataPath": "./pd_data",
+ "state": "Up"
+ },
+ {
+ "clusterId": "1",
+ "raftUrl": "10.14.139.57:8620",
+ "grpcUrl": "10.14.139.57:8686",
+ "restUrl": "10.14.139.57:8620",
+ "dataPath": "./pd_data",
+ "state": "Up"
+ },
+ {
+ "clusterId": "1",
+ "raftUrl": "10.14.139.58:8620",
+ "grpcUrl": "10.14.139.58:8686",
+ "restUrl": "10.14.139.58:8620",
+ "dataPath": "./pd_data",
+ "state": "Up"
+ }
+ ],
+ "leader": {
+ "clusterId": "1",
+ "raftUrl": "10.14.139.56:8610",
+ "grpcUrl": "10.14.139.56:8686",
+ "dataPath": "./pd_data",
+ "state": "Up"
+ }
+ }
+}
+```
+````
+clusterId:pd集群ID
+raftUrl、grpcUrl、restUrl:pd节点的地址信息
+dataPath:pd数据存储目录
+state: 节点当前状态
+````
+#### Store Mertics 地址
+```
+GET http://127.0.0.1:8520/actuator/prometheus
+
+```
\ No newline at end of file
diff --git a/build-change.sh b/build-change.sh
new file mode 100644
index 000000000..e6c2fb30f
--- /dev/null
+++ b/build-change.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+export PATH=$MAVEN_3_5_3_BIN:$ORACLEJDK_11_0_7_BIN:$PATH
+export JAVA_HOME=$ORACLEJDK_11_0_7_HOME
+export MAVEN_HOME=$MAVEN_3_5_3_HOME
+
+readonly VER=3.6.3
+readonly REPO_URL=http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local_Snapshots
+
+$MAVEN_3_5_3_BIN/mvn clean install -Dmaven.test.skip=true -DaltDeploymentRepository=Baidu_Local_Snapshots::default::${REPO_URL}
+
+echo "mv dist...."
+mv dist output
+ls output
+echo "mv dist done"
+echo "show output...."
+ls output
+echo "show output done"
\ No newline at end of file
diff --git a/build-pre.sh b/build-pre.sh
new file mode 100644
index 000000000..86f9d4c29
--- /dev/null
+++ b/build-pre.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+mkdir output
+touch output/1
+export JAVA_HOME=$ORACLEJDK_1_8_0_HOME
+
+readonly VER=3.6.3
+readonly REPO_URL=http://10.14.139.8:8081/artifactory/star-local
+
+$MAVEN_3_5_3_BIN/mvn -DremoveSnapshot=true -DprocessAllModules=true -DgenerateBackupPoms=true versions:set
+$MAVEN_3_5_3_BIN/mvn --settings ./settings.xml -Dmaven.test.skip=true -DaltDeploymentRepository=star-local::default::${REPO_URL} clean deploy
+$MAVEN_3_5_3_BIN/mvn versions:revert
+
+#------------------repo-server-----------------------
+readonly FILE_NAME=hugegraph-store-3.6.3.tar.gz
+readonly REPO_URL_FILE=http://10.14.139.8:8081/artifactory/star-file
+
+localFilePath=dist/${FILE_NAME}
+targetFolder="${REPO_URL_FILE}/dist/$(date '+%Y-%m-%d')/"
+artifactoryUser="admin"
+artifactoryPassword="JFrog12345"
+
+md5Value="$(md5sum "$localFilePath")"
+md5Value="${md5Value:0:32}"
+sha1Value="$(sha1sum "$localFilePath")"
+sha1Value="${sha1Value:0:40}"
+sha256Value="$(sha256sum "$localFilePath")"
+sha256Value="${sha256Value:0:65}"
+
+#curl -X PUT -u admin:JFrog12345 -T ${localFilePath} "${REPO_URL_FILE}/dist/${data_folder}/"
+echo "INFO: Uploading $localFilePath to $targetFolder"
+curl -i -X PUT -u "$artifactoryUser:$artifactoryPassword" \
+ -H "X-Checksum-Md5: $md5Value" \
+ -H "X-Checksum-Sha1: $sha1Value" \
+ -H "X-Checksum-Sha256: $sha256Value" \
+ -T "$localFilePath" \
+ "$targetFolder"
+
+
+ #------------------repo-client-----------------------
+readonly REPO_SNAPSHOT_PATH=http://10.14.139.8:8082/artifactory/star
+readonly REPO_FILE_PATH=http://10.14.139.8:8082/artifactory/star-file
+readonly REPO_BAIDU_LOCAL_PATH=http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local
+readonly PACKAGE_PATH=${REPO_SNAPSHOT_PATH}/com/baidu/hugegraph
+
+dest=store-client-${VER}
+mkdir ${dest}
+
+curl ${PACKAGE_PATH}/hg-store-client/${VER}/hg-store-client-${VER}.jar -o ./${dest}/hg-store-client-${VER}.jar
+curl ${PACKAGE_PATH}/hg-store-client/${VER}/hg-store-client-${VER}.pom -o ./${dest}/hg-store-client-pom.xml
+
+curl ${PACKAGE_PATH}/hg-store-grpc/${VER}/hg-store-grpc-${VER}.jar -o ./${dest}/hg-store-grpc-${VER}.jar
+curl ${PACKAGE_PATH}/hg-store-grpc/${VER}/hg-store-grpc-${VER}.pom -o ./${dest}/hg-store-grpc-pom.xml
+
+curl ${PACKAGE_PATH}/hg-store-common/${VER}/hg-store-common-${VER}.jar -o ./${dest}/hg-store-common-${VER}.jar
+curl ${PACKAGE_PATH}/hg-store-common/${VER}/hg-store-common-${VER}.pom -o ./${dest}/hg-store-common-pom.xml
+
+curl ${PACKAGE_PATH}/hg-pd-client/${VER}/hg-pd-client-${VER}.jar -o ./${dest}/hg-pd-client-${VER}.jar
+curl ${PACKAGE_PATH}/hg-pd-client/${VER}/hg-pd-client-${VER}.pom -o ./${dest}/hg-pd-client-pom.xml
+
+curl ${PACKAGE_PATH}/hg-pd-grpc/${VER}/hg-pd-grpc-${VER}.jar -o ./${dest}/hg-pd-grpc-${VER}.jar
+curl ${PACKAGE_PATH}/hg-pd-grpc/${VER}/hg-pd-grpc-${VER}.pom -o ./${dest}/hg-pd-grpc-pom.xml
+
+curl ${PACKAGE_PATH}/hg-pd-common/${VER}/hg-pd-common-${VER}.jar -o ./${dest}/hg-pd-common-${VER}.jar
+curl ${PACKAGE_PATH}/hg-pd-common/${VER}/hg-pd-common-${VER}.pom -o ./${dest}/hg-pd-common-pom.xml
+
+tar -cvf ${dest}.tar ${dest}
+
+localFilePath=${dest}.tar
+targetFolder="${REPO_URL_FILE}/dist/$(date '+%Y-%m-%d')/"
+artifactoryUser="admin"
+artifactoryPassword="JFrog12345"
+
+md5Value="$(md5sum "$localFilePath")"
+md5Value="${md5Value:0:32}"
+sha1Value="$(sha1sum "$localFilePath")"
+sha1Value="${sha1Value:0:40}"
+sha256Value="$(sha256sum "$localFilePath")"
+sha256Value="${sha256Value:0:65}"
+
+#curl -X PUT -u admin:JFrog12345 -T ${localFilePath} "${REPO_URL_FILE}/dist/${data_folder}/"
+echo "INFO: Uploading $localFilePath to $targetFolder"
+curl -i -X PUT -u "$artifactoryUser:$artifactoryPassword" \
+ -H "X-Checksum-Md5: $md5Value" \
+ -H "X-Checksum-Sha1: $sha1Value" \
+ -H "X-Checksum-Sha256: $sha256Value" \
+ -T "$localFilePath" \
+ "$targetFolder"
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 000000000..995600db7
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+export PATH=$MAVEN_3_5_3_BIN:$ORACLEJDK_11_0_7_BIN:$PATH
+export JAVA_HOME=$ORACLEJDK_11_0_7_HOME
+export MAVEN_HOME=$MAVEN_3_5_3_HOME
+
+readonly VER=3.6.3
+readonly REPO_URL=http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local_Snapshots
+
+$MAVEN_3_5_3_BIN/mvn -Dmaven.test.skip=true -DaltDeploymentRepository=Baidu_Local_Snapshots::default::${REPO_URL} -U clean deploy
+echo "mv dist...."
+mv dist output
+ls output
+echo "mv dist done"
+echo "show output...."
+ls output
+echo "show output done"
\ No newline at end of file
diff --git a/ci.yml b/ci.yml
new file mode 100644
index 000000000..81f2058a6
--- /dev/null
+++ b/ci.yml
@@ -0,0 +1,26 @@
+Global:
+ tool : build_submitter
+ languages:
+ # Java Version: 1.7, 1.8, 9, 10
+ - language : java
+ version : 11
+ envs:
+ # Maven Version: 3.0.4, 3.1.1, 3.2.5, 3.3.9, 3.5.3
+ - env : maven
+ version : 3.5.3
+Default:
+ profile : [dev]
+Profiles:
+ - profile:
+ name : dev
+ tool : build_submitter
+ env : DECK_CENTOS7U5_K3
+ command : sh build.sh
+ release : true
+
+ - profile:
+ name : change
+ tool : build_submitter
+ env : DECK_CENTOS7U5_K3
+ command : sh build-change.sh
+ release : true
\ No newline at end of file
diff --git a/conf/application-pd.yml b/conf/application-pd.yml
new file mode 100644
index 000000000..59c677d92
--- /dev/null
+++ b/conf/application-pd.yml
@@ -0,0 +1,17 @@
+management:
+ metrics:
+ export:
+ prometheus:
+ enabled: true
+ endpoints:
+ web:
+ exposure:
+ include: "*"
+
+rocksdb:
+ # rocksdb使用的总内存大小,达到该值强制写盘
+ total_memory_size: 32000000000
+ # rocksdb使用的memtable大小
+ write_buffer_size: 32000000
+ # 对于每个rocksdb来说,memtable个数达到该值进行写盘
+ min_write_buffer_number_to_merge: 16
diff --git a/deploy-release.sh b/deploy-release.sh
new file mode 100755
index 000000000..3712135c5
--- /dev/null
+++ b/deploy-release.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+readonly VER=3.6.3
+readonly REPO_URL=http://10.14.139.8:8081/artifactory/star-local
+#mvn -DnewVersion=${VER}-SNAPSHOT -DprocessAllModules=true -DgenerateBackupPoms=false versions:set
+
+./mvnw -DremoveSnapshot=true -DprocessAllModules=true -DgenerateBackupPoms=true versions:set
+./mvnw --settings ./settings.xml -Dmaven.test.skip=true -DaltDeploymentRepository=star-local::default::${REPO_URL} clean deploy
+./mvnw versions:revert
diff --git a/deploy-snapshot.sh b/deploy-snapshot.sh
new file mode 100644
index 000000000..5cd2e9519
--- /dev/null
+++ b/deploy-snapshot.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+readonly REPO_URL=http://10.14.139.8:8081/artifactory/star-snapshot
+
+mvn --settings ./settings.xml -Dmaven.test.skip=true -DaltDeploymentRepository=star-snapshot::default::${REPO_URL} clean deploy
+
diff --git a/hg-store-cli/deploy-snapshot.sh b/hg-store-cli/deploy-snapshot.sh
new file mode 100644
index 000000000..c17b7dc34
--- /dev/null
+++ b/hg-store-cli/deploy-snapshot.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+readonly REPO_URL=http://10.14.139.8:8081/artifactory/star-snapshot
+
+mvn --settings ../settings.xml -Dmaven.test.skip=true -DaltDeploymentRepository=star-local::default::${REPO_URL} clean deploy
+
diff --git a/hg-store-cli/pom.xml b/hg-store-cli/pom.xml
new file mode 100644
index 000000000..62640a112
--- /dev/null
+++ b/hg-store-cli/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+ hugegraph-store-root
+ com.baidu.hugegraph
+ 3.6.3-SNAPSHOT
+
+ 4.0.0
+
+ hg-store-cli
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+ com.baidu.hugegraph
+ hg-store-client
+ ${project.version}
+
+
+ com.baidu.hugegraph
+ hg-store-grpc
+ ${project.version}
+
+
+ com.baidu.hugegraph
+ hg-pd-client
+ ${project.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+ com.baidu.hugegraph.store.cli.StoreConsoleApplication
+
+
+
+
+
+
+
+
+
+ Baidu_Local
+ http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local
+
+
+ Baidu_Local_Snapshots
+ http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local_Snapshots
+
+
+
+
\ No newline at end of file
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/AppConfig.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/AppConfig.java
new file mode 100644
index 000000000..cf795c8fe
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/AppConfig.java
@@ -0,0 +1,40 @@
+package com.baidu.hugegraph.store.cli;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/2/15
+ */
+@Data
+@Component
+public class AppConfig {
+
+ @Value("${pd.address}")
+ private String pdAddress;
+
+ @Value("${net.kv.scanner.page.size}")
+ private int scannerPageSize;
+
+ @Value("${scanner.graph}")
+ private String scannerGraph;
+
+ @Value("${scanner.table}")
+ private String scannerTable;
+
+ @Value("${scanner.max}")
+ private int scannerMax;
+
+ @Value("${scanner.mod}")
+ private int scannerModNumber;
+
+ @Value("${committer.graph}")
+ private String committerGraph;
+
+ @Value("${committer.table}")
+ private String committerTable;
+
+ @Value("${committer.amount}")
+ private int committerAmount;
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/StoreConsoleApplication.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/StoreConsoleApplication.java
new file mode 100644
index 000000000..db6fc9e6d
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/StoreConsoleApplication.java
@@ -0,0 +1,102 @@
+package com.baidu.hugegraph.store.cli;
+
+import com.baidu.hugegraph.pd.client.PDClient;
+import com.baidu.hugegraph.pd.client.PDConfig;
+import com.baidu.hugegraph.pd.common.PDException;
+import com.baidu.hugegraph.store.HgStoreClient;
+import com.baidu.hugegraph.store.cli.loader.HgThread2DB;
+import com.baidu.hugegraph.store.cli.scan.GrpcShardScanner;
+import com.baidu.hugegraph.store.cli.scan.HgStoreCommitter;
+import com.baidu.hugegraph.store.cli.scan.HgStoreScanner;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import java.io.IOException;
+
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/2/14
+ */
+@SpringBootApplication
+@Slf4j
+public class StoreConsoleApplication implements CommandLineRunner {
+
+ @Autowired
+ private AppConfig appConfig;
+
+ public static void main(String[] args) {
+ log.info("Starting StoreConsoleApplication");
+ SpringApplication.run(StoreConsoleApplication.class, args);
+ log.info("StoreConsoleApplication finished.");
+ }
+
+ @Override
+ public void run(String... args) throws IOException, InterruptedException, PDException {
+ if (args.length <= 0){
+ // HgThread2DB hB = new HgThread2DB("localhost:8686");
+ // hB.startMultiprocessQuery("12", "10");
+ System.out.println("参数类型 cmd[-load, -query, -scan]");
+ }else {
+ switch (args[0]) {
+ case "-load":
+ HgThread2DB hgThread2DB = new HgThread2DB(args[1]);
+ if (!args[3].isEmpty()) {
+ hgThread2DB.setGraphName(args[3]);
+ }
+ try {
+ if (args[2].equals("order")){
+ hgThread2DB.testOrder(args[4]);
+ }else {
+ hgThread2DB.startMultiprocessInsert(args[2]);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ break;
+ case "-query":
+ HgThread2DB hgDB = new HgThread2DB(args[1]);
+ try {
+ hgDB.startMultiprocessQuery("12", args[2]);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ break;
+ case "-scan":
+ if ( args.length < 4){
+ System.out.println("参数类型 -scan pd graphName tableName");
+ }else {
+ doScan(args[1], args[2], args[3]);
+ }
+ break;
+ case "-shard":
+ GrpcShardScanner scanner = new GrpcShardScanner();
+ scanner.getData();
+ break;
+ case "-shard-single":
+ scanner = new GrpcShardScanner();
+ scanner.getDataSingle();
+ break;
+ default:
+ System.out.println("参数类型错误,未执行任何程序");
+ }
+ }
+ }
+
+ private void doCommit(){
+ HgStoreCommitter committer=HgStoreCommitter.of(appConfig.getCommitterGraph());
+ committer.put(appConfig.getScannerTable(),appConfig.getCommitterAmount());
+ }
+
+ private void doScan(String pd, String graphName, String tableName) throws PDException {
+ HgStoreClient storeClient = HgStoreClient.create(PDConfig.of(pd)
+ .setEnableCache(true));
+
+ HgStoreScanner storeScanner = HgStoreScanner.of(storeClient, graphName);
+ storeScanner.scanTable2(tableName);
+ // storeScanner.scanHash();
+ }
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/loader/HgThread2DB.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/loader/HgThread2DB.java
new file mode 100644
index 000000000..c374f3e02
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/loader/HgThread2DB.java
@@ -0,0 +1,545 @@
+package com.baidu.hugegraph.store.cli.loader;
+
+import com.baidu.hugegraph.pd.client.PDClient;
+import com.baidu.hugegraph.pd.client.PDConfig;
+import com.baidu.hugegraph.store.HgStoreClient;
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgStoreSession;
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgKvIterator;
+import com.baidu.hugegraph.store.HgScanQuery;
+import com.baidu.hugegraph.store.client.grpc.KvCloseableIterator;
+import com.baidu.hugegraph.store.client.util.MetricX;
+import com.baidu.hugegraph.store.cli.util.HgCliUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+
+/**
+ * 使用pd,支持raft
+ * 读取文件并多线程进行入库
+ */
+@Slf4j
+public class HgThread2DB {
+ private static PDClient pdClient;
+ public String graphName = "hugegraphtest";
+ /*正在进行和在排队的任务的总数*/
+ private static AtomicInteger taskTotal = new AtomicInteger(0);
+ private static AtomicInteger queryTaskTotal = new AtomicInteger(0);
+ private static ThreadPoolExecutor threadPool = null;
+ private static ThreadPoolExecutor queryThreadPool = null;
+ private static AtomicLong insertDataCount = new AtomicLong();
+ private static AtomicLong queryCount = new AtomicLong();
+ private static AtomicLong totalQueryCount = new AtomicLong();
+ volatile long startTime = System.currentTimeMillis();
+ private static int limitScanBatchCount = 100;
+ private static ArrayBlockingQueue listQueue = null;
+ private static AtomicLong longId = new AtomicLong();
+
+ private static CountDownLatch countDownLatch = null;
+ private HgStoreClient storeClient;
+
+ public HgThread2DB(String pdAddr) {
+ int threadCount = Runtime.getRuntime().availableProcessors();
+
+ listQueue = new ArrayBlockingQueue>(100000000);
+ queryThreadPool = new ThreadPoolExecutor(500, 1000,
+ 200, TimeUnit.SECONDS, new ArrayBlockingQueue( 1000));
+ threadPool = new ThreadPoolExecutor(threadCount*2, threadCount * 3,
+ 200, TimeUnit.SECONDS, new ArrayBlockingQueue(threadCount + 100));
+ storeClient = HgStoreClient.create(PDConfig.of(pdAddr)
+ .setEnableCache(true));
+ pdClient = storeClient.getPdClient();
+ }
+
+ public void setGraphName(String graphName){
+ this.graphName = graphName;
+ log.info("setGraphName {}", graphName);
+ }
+
+ public boolean singlePut(String tableName
+ , List keys) throws InterruptedException {
+ HgStoreSession session = storeClient.openSession(graphName);
+ session.beginTx();
+
+ keys.forEach((strKey) -> {
+ insertDataCount.getAndIncrement();
+ int j = strKey.indexOf("\t");
+// byte[] key = HgCliUtil.toBytes(strKey.substring(0, j));
+ HgOwnerKey hgKey = HgCliUtil.toOwnerKey(strKey.substring(0, j), strKey);
+ byte[] value = HgCliUtil.toBytes(strKey.substring(j + 1));
+ session.put(tableName, hgKey, value);
+
+ });
+ if ( insertDataCount.get() > 10000000){
+ synchronized (insertDataCount){
+ long count = insertDataCount.get();
+ insertDataCount.set(0);
+ if (count > 10000000){
+ log.info("count : " + count + " qps : " + count * 1000 / (System.currentTimeMillis() - startTime)
+ +" threadCount : " + taskTotal);
+ startTime = System.currentTimeMillis();
+ }
+ }
+ }
+// Thread.sleep(2000);
+ if (!keys.isEmpty()) {
+ if (session.isTx()) {
+ session.commit();
+ } else {
+ session.rollback();
+ }
+ }
+
+ return true;
+ }
+
+ public boolean singlePut(String tableName) throws InterruptedException {
+ HgStoreSession session = storeClient.openSession(graphName);
+ session.beginTx();
+
+ int maxlist = 100;
+
+ for (int y = 0; y < maxlist; y++) {
+ insertDataCount.getAndIncrement();
+ String strLine = "" + getLong() + getLong() + getLong() + getLong();
+// log.info("========{}",strLine);
+ HgOwnerKey hgKey = HgCliUtil.toOwnerKey(strLine, strLine);
+ byte[] value = HgCliUtil.toBytes(strLine);
+ session.put(tableName, hgKey, value);
+ }
+
+ if ( insertDataCount.get() > 10000000){
+ synchronized (insertDataCount){
+ long count = insertDataCount.get();
+ insertDataCount.set(0);
+ if (count > 10000000){
+ log.info("count : " + count + " qps : " + count * 1000 / (System.currentTimeMillis() - startTime)
+ +" threadCount : " + taskTotal);
+ startTime = System.currentTimeMillis();
+ }
+ }
+ }
+
+ if (session.isTx()) {
+ session.commit();
+ } else {
+ session.rollback();
+ }
+
+
+ return true;
+ }
+
+ public boolean testOrder(String input) {
+ String tableName = "hugegraph02";
+ HgStoreSession session = storeClient.openSession(graphName);
+ session.beginTx();
+ int loop = Integer.parseInt(input);
+ if (loop == 0){
+ loop = 2000;
+ }
+ for (int i = 0; i < loop; i++) {
+ long startTime = System.currentTimeMillis();
+ HgOwnerKey hgOwnerKey = HgCliUtil.toOwnerKey(startTime + "owner:" + i, startTime + "k:" + i);
+ session.put(tableName, hgOwnerKey, HgCliUtil.toBytes(i));
+ }
+
+ if (session.isTx()) {
+ session.commit();
+ } else {
+ session.rollback();
+ }
+
+ 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);
+ } catch (Exception e) {
+ log.error("query error, message ");
+// e.printStackTrace();
+ }
+
+
+ return true;
+ }
+
+ /**
+ * 多线程读取文件入库
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public void startMultiprocessInsert(String filepath) throws IOException {
+ log.info("--- start startMultiprocessInsert---");
+ startTime = System.currentTimeMillis();
+ File readfile = new File(filepath);
+ MetricX metrics = null;
+ long dataCount = 0;
+ if (readfile.exists()) {
+ // 读取文件
+ InputStreamReader isr = new InputStreamReader(new FileInputStream(readfile), "UTF-8");
+ BufferedReader reader = new BufferedReader(isr);
+
+ String strLine = null;
+ String tableName = HgCliUtil.TABLE_NAME;
+ // 积攒到多少个后执行线程入库,10万
+ int maxlist = 100000;
+ List keys = new ArrayList<>(maxlist);
+ metrics = MetricX.ofStart();
+ try {
+ while ((strLine = reader.readLine()) != null) {
+ keys.add(strLine);
+ dataCount++;
+
+ // 读取文件中的10000条数据,启一个线程入库
+ if (dataCount % maxlist == 0) {
+ List finalKeys = keys;
+ Runnable task = new Runnable() {
+ public void run() {
+ try {
+ if (!finalKeys.isEmpty()) {
+ boolean ret = singlePut(tableName, finalKeys);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ taskTotal.decrementAndGet();
+ synchronized (taskTotal){
+ taskTotal.notifyAll();
+ }
+ }
+ };
+ taskTotal.getAndIncrement();
+ threadPool.execute(task);
+
+ while ( taskTotal.get() > 100){
+ synchronized (taskTotal){
+ taskTotal.wait();
+ }
+ }
+ // keys.remove(0);
+ keys = new ArrayList<>(maxlist);
+ }
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ isr.close();
+ reader.close();
+ // 把剩余的入库
+ if (!keys.isEmpty()){
+ List finalKeys1 = keys;
+ Runnable task = new Runnable() {
+ public void run() {
+ try {
+ boolean ret = singlePut(tableName, finalKeys1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ taskTotal.decrementAndGet();
+ synchronized (taskTotal){
+ taskTotal.notifyAll();
+ }
+ }
+ };
+ threadPool.execute(task);
+ taskTotal.getAndIncrement();
+ }
+ while ( taskTotal.get() > 0){
+ synchronized (taskTotal){
+ try {
+ taskTotal.wait(1000);
+ if ( taskTotal.get() > 0){
+ System.out.println("wait thread exit " + taskTotal.get());
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ threadPool.shutdown();
+
+ }else {
+ System.out.println("样本文件不存在:" + filepath);
+ }
+ metrics.end();
+ log.info("*************************************************");
+ log.info(" 主进程执行时间:" + metrics.past() / 1000 + "秒,一共执行:" + dataCount + "条");
+ log.info("*************************************************");
+ System.out.println(" 主进程执行时间 " + metrics.past() / 1000 + "秒");
+ System.out.println("-----主进程执行结束---------");
+ }
+
+ /**
+ * 多线程读取文件入库
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public void autoMultiprocessInsert() throws IOException {
+ log.info("--- start autoMultiprocessInsert---");
+ startTime = System.currentTimeMillis();
+
+
+ MetricX metrics = null;
+ long dataCount = 0;
+
+ String strLine = null;
+ String tableName = HgCliUtil.TABLE_NAME;
+ // 积攒到多少个后执行线程入库,10万
+ int maxlist = 100000;
+ List keys = new ArrayList<>(maxlist);
+ for (int x = 0; x < 10000000; x++) {
+ metrics = MetricX.ofStart();
+ try {
+ Runnable task = new Runnable() {
+ public void run() {
+ try {
+ boolean ret = singlePut(tableName);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ taskTotal.decrementAndGet();
+ synchronized (taskTotal) {
+ taskTotal.notifyAll();
+ }
+ }
+ };
+ taskTotal.getAndIncrement();
+ threadPool.execute(task);
+
+ while (taskTotal.get() > 100) {
+ synchronized (taskTotal) {
+ taskTotal.wait();
+ }
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ while ( taskTotal.get() > 0){
+ synchronized (taskTotal){
+ try {
+ taskTotal.wait(1000);
+ if ( taskTotal.get() > 0){
+ System.out.println("wait thread exit " + taskTotal.get());
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ threadPool.shutdown();
+
+
+ metrics.end();
+ log.info("*************************************************");
+ log.info(" 主进程执行时间:" + metrics.past() / 1000 + "秒,一共执行:" + dataCount + "条");
+ log.info("*************************************************");
+ System.out.println(" 主进程执行时间 " + metrics.past() / 1000 + "秒");
+ System.out.println("-----主进程执行结束---------");
+ }
+
+ public String getLong() {
+ //如果需要更长 或者更大冗余空间, 只需要 time * 10^n 即可
+ //当前可保证1毫秒 生成 10000条不重复
+ return String.format("%019x", longId.getAndIncrement());
+ }
+
+
+ /**
+ * 执行查询,并将查询的结果做为下一次迭代的点放入队列
+ */
+ private void queryAnd2Queue() {
+ try {
+ HgStoreSession session = storeClient.openSession(graphName);
+ HashSet hashSet = new HashSet();
+ while (!listQueue.isEmpty()) {
+
+ log.info(" ====== start scanBatch2 count:{} list:{}=============",
+ queryThreadPool.getActiveCount(), listQueue.size());
+ List keys = (List) listQueue.take();
+ List newQueryList = new ArrayList<>();
+
+ KvCloseableIterator> iterators =
+ session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(HgCliUtil.TABLE_NAME, keys.iterator())
+ );
+
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ int insertQueueCount = 0;
+ while (iterator.hasNext()) {
+ HgKvEntry entry = iterator.next();
+ String newPoint = HgCliUtil.toStr(entry.value());
+// log.info("query_key =" + newPoint);
+ // 统计查询次数
+ if (!newPoint.isEmpty() && hashSet.add(newPoint)) {
+ queryCount.getAndIncrement();
+ totalQueryCount.getAndIncrement();
+
+ HgOwnerKey hgKey = HgCliUtil.toOwnerKey(newPoint, newPoint);
+ newQueryList.add(hgKey);
+
+ if (queryCount.get() > 1000000) {
+ synchronized (queryCount) {
+ long count = queryCount.get();
+ queryCount.set(0);
+ if (count > 1000000) {
+ log.info("count : " + count + " qps : " + count * 1000 /
+ (System.currentTimeMillis() - startTime)
+ + " threadCount : " + queryThreadPool.getActiveCount() + " queueSize:"
+ + listQueue.size());
+ startTime = System.currentTimeMillis();
+ }
+ }
+ }
+ // 达到1万个点后,去查询一次
+ if (newQueryList.size() > 10000 && listQueue.size() < 10000) {
+ listQueue.put(newQueryList);
+ insertQueueCount++;
+ newQueryList = new ArrayList<>();
+ if (insertQueueCount > 2) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ // 一次查询如果不够1万,单独提交一次查询,确保所有的结果都能执行查询
+ if (!newQueryList.isEmpty() && listQueue.size() < 1000) {
+ listQueue.put(newQueryList);
+ }
+
+ iterators.close();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ log.info("============= thread done ==============");
+ countDownLatch.countDown();
+ }
+
+ /**
+ * 多线程查询
+ * @param point 起始查询点,后续根据这个点查询到的value做为下一次的查询条件进行迭代
+ * @param scanCount 允许启动的线程数量
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public void startMultiprocessQuery(String point, String scanCount) throws IOException, InterruptedException {
+ log.info("--- start startMultiprocessQuery---");
+ startTime = System.currentTimeMillis();
+ MetricX metrics = MetricX.ofStart();
+ limitScanBatchCount = Integer.parseInt(scanCount);
+
+ CountDownLatch latch = new CountDownLatch(limitScanBatchCount);
+ HgStoreSession session = storeClient.openSession(graphName);
+
+ final AtomicLong[] counter = {new AtomicLong()};
+ final long[] start = {System.currentTimeMillis()};
+
+ LinkedBlockingQueue[] queue = new LinkedBlockingQueue[limitScanBatchCount];
+ for(int i =0; i strKey = Arrays.asList(new String[]{"20727483", "50329304", "26199460", "1177521", "27960125",
+ "30440025", "15833920", "15015183", "33153097", "21250581"});
+ strKey.forEach(key->{
+ log.info("newkey:{}", key);
+ HgOwnerKey hgKey = HgCliUtil.toOwnerKey(key, key);
+ queue[0].add(hgKey);
+ });
+
+ for(int i =0; i> iterators =
+ session.scanBatch2(
+ HgScanQuery.prefixIteratorOf(HgCliUtil.TABLE_NAME, new Iterator() {
+ HgOwnerKey current = null;
+
+ @Override
+ public boolean hasNext() {
+ while (current == null) {
+ try {
+ current = (HgOwnerKey) queue[finalI].poll(1, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ //
+ }
+ }
+ if (current == null){
+ log.info("===== current is null ==========");
+ }
+ return current != null;
+ }
+
+ @Override
+ public HgOwnerKey next() {
+ return current;
+ }
+ })
+ );
+
+ new Thread(()->{
+ while (iterators.hasNext()) {
+ HgKvIterator iterator = iterators.next();
+ long c = 0;
+ while (iterator.hasNext()) {
+ String newPoint = HgCliUtil.toStr(iterator.next().value());
+ HgOwnerKey newHgKey = HgCliUtil.toOwnerKey(newPoint, newPoint);
+ if ( queue[(int) (c % limitScanBatchCount)].size() < 1000000) {
+ queue[(int) (c % limitScanBatchCount)].add(newHgKey);
+ }
+ c++;
+ }
+ if ( counter[0].addAndGet(c) > 1000000){
+ synchronized (counter) {
+ if ( counter[0].get() > 10000000) {
+ log.info("count {}, qps {}", counter[0].get(), counter[0].get() * 1000 / (System.currentTimeMillis() - start[0]));
+ start[0] = System.currentTimeMillis();
+ counter[0].set(0);
+ }
+ }
+ }
+ }
+ }, "client query thread:" + i ).start();
+ log.info("===== read thread exit ==========");
+ }
+ latch.await();
+
+
+ metrics.end();
+ log.info("*************************************************");
+ log.info(" 主进程执行时间:" + metrics.past() / 1000 + "秒; 查询:" + totalQueryCount.get()
+ + "次,qps:" + totalQueryCount.get() * 1000 / metrics.past());
+ log.info("*************************************************");
+ System.out.println("-----主进程执行结束---------");
+ }
+
+}
\ No newline at end of file
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/GrpcShardScanner.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/GrpcShardScanner.java
new file mode 100644
index 000000000..456d59bac
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/GrpcShardScanner.java
@@ -0,0 +1,156 @@
+package com.baidu.hugegraph.store.cli.scan;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.baidu.hugegraph.store.grpc.GraphStoreGrpc;
+import com.baidu.hugegraph.store.grpc.GraphStoreGrpc.GraphStoreStub;
+import com.baidu.hugegraph.store.grpc.Graphpb.ScanPartitionRequest;
+import com.baidu.hugegraph.store.grpc.Graphpb.ScanPartitionRequest.Reply;
+import com.baidu.hugegraph.store.grpc.Graphpb.ScanResponse;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.stub.StreamObserver;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author zhangyingjie
+ * @date 2022/11/1
+ **/
+
+@Slf4j
+public class GrpcShardScanner {
+ private volatile boolean closed = false;
+ private AtomicInteger sum = new AtomicInteger();
+ private ConcurrentHashMap>
+ observers = new ConcurrentHashMap<>();
+
+ public void getData() {
+ ExecutorService service = new ThreadPoolExecutor(500, Integer.MAX_VALUE,
+ 0L,
+ TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>());
+ long start = System.currentTimeMillis();
+
+ String[] addresses = new String[]{"10.14.139.71:8500",
+ "10.14.139.70:8500",
+ "10.14.139.69:8500"};
+ int pSize = 72;
+ int size = pSize * addresses.length;
+ CountDownLatch latch = new CountDownLatch(size);
+ for (int j = 0; j < pSize; j++) {
+ for (int i = 0; i < addresses.length; i++) {
+ String address = addresses[i];
+ int finalJ = j;
+ service.execute(() -> getData(finalJ, latch, address));
+ }
+ }
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ long end = System.currentTimeMillis();
+ long cost = end - start;
+ log.info("all rows are: {}, cost: {},avg: {}", sum.get(),
+ cost, sum.get() / cost * 1000);
+ }
+
+ public void getData(int pId, CountDownLatch latch, String address) {
+ try {
+ ScanPartitionRequest.Builder builder =
+ ScanPartitionRequest.newBuilder();
+ ScanPartitionRequest.Request.Builder srb =
+ ScanPartitionRequest.Request.newBuilder();
+ ScanPartitionRequest.Request request =
+ srb.setGraphName("DEFAULT/hugegraph2/g")
+ .setScanType(
+ ScanPartitionRequest.ScanType.SCAN_EDGE)
+ .setTable("g+oe").setBoundary(0x10)
+ .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) {
+ log.warn("调用grpc接口发生错误", t);
+ latch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ long time = System.currentTimeMillis() - start;
+ log.info("scan id : {}, complete: {} ,time:{}",
+ pId, count.get(), 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();
+ } finally {
+
+ }
+ }
+
+ 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();
+ }
+ log.info("all rows are: {}", sum.get());
+ }
+
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreCommitter.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreCommitter.java
new file mode 100644
index 000000000..2563681df
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreCommitter.java
@@ -0,0 +1,68 @@
+package com.baidu.hugegraph.store.cli.scan;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgSessionManager;
+import com.baidu.hugegraph.store.HgStoreSession;
+import com.baidu.hugegraph.store.client.HgStoreNodeManager;
+
+import static com.baidu.hugegraph.store.cli.util.HgCliUtil.*;
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/2/28
+ */
+public class HgStoreCommitter {
+
+ protected final static HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+
+ private final String graph;
+
+
+ public static HgStoreCommitter of(String graph) {
+ return new HgStoreCommitter(graph);
+ }
+
+ private HgStoreCommitter(String graph) {
+ this.graph = graph;
+ }
+
+ protected HgStoreSession getStoreSession() {
+ return HgSessionManager.getInstance().openSession(this.graph);
+ }
+
+ protected HgStoreSession getStoreSession(String graphName) {
+ return HgSessionManager.getInstance().openSession(graphName);
+ }
+
+ public void put(String tableName,int amount) {
+ //*************** Put Benchmark **************//*
+ String keyPrefix = "PUT-BENCHMARK";
+ HgStoreSession session = getStoreSession();
+
+ int length = String.valueOf(amount).length();
+
+ session.beginTx();
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < amount; i++) {
+ HgOwnerKey key = toOwnerKey(keyPrefix + "-" + padLeftZeros(String.valueOf(i), length));
+ byte[] value = toBytes(keyPrefix + "-V-" + i);
+
+ session.put(tableName, key, value);
+
+ if ((i + 1) % 100_000 == 0) {
+ println("---------- " + (i + 1) + " --------");
+ println("Preparing took: " + (System.currentTimeMillis() - start) + " ms.");
+ session.commit();
+ println("Committing took: " + (System.currentTimeMillis() - start) + " ms.");
+ start = System.currentTimeMillis();
+ session.beginTx();
+ }
+ }
+
+ if (session.isTx()) {
+ session.commit();
+ }
+
+
+ }
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreScanner.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreScanner.java
new file mode 100644
index 000000000..5fe2433a5
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/scan/HgStoreScanner.java
@@ -0,0 +1,203 @@
+package com.baidu.hugegraph.store.cli.scan;
+
+import com.baidu.hugegraph.pd.client.PDClient;
+import com.baidu.hugegraph.pd.common.PDException;
+import com.baidu.hugegraph.pd.grpc.Metapb;
+import com.baidu.hugegraph.store.*;
+import com.baidu.hugegraph.store.cli.util.HgCliUtil;
+import com.baidu.hugegraph.store.cli.util.HgMetricX;
+import com.baidu.hugegraph.store.client.grpc.KvCloseableIterator;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConfig;
+import com.baidu.hugegraph.store.client.util.MetricX;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/2/14
+ */
+@Slf4j
+public class HgStoreScanner {
+
+ private HgStoreClient storeClient;
+ private final String graphName;
+ private long modNumber = 1_000_000;
+ private int max = 10_000_000;
+
+ public long getModNumber() {
+ return modNumber;
+ }
+
+ public void setModNumber(int modNumber) {
+ if (modNumber <= 0) {
+ return;
+ }
+ this.modNumber = modNumber;
+ }
+
+ public int getMax() {
+ return max;
+ }
+
+ public void setMax(int max) {
+ if (modNumber <= 0) {
+ return;
+ }
+ this.max = max;
+ }
+
+ public static HgStoreScanner of(HgStoreClient storeClient, String graph) {
+ return new HgStoreScanner(storeClient, graph);
+ }
+
+ private HgStoreScanner(HgStoreClient storeClient, String graph) {
+ this.storeClient = storeClient;
+ this.graphName = graph;
+ }
+
+ protected HgStoreSession getStoreSession() {
+ return HgSessionManager.getInstance().openSession(this.graphName);
+ }
+
+ protected HgStoreSession getStoreSession(String graphName) {
+ return HgSessionManager.getInstance().openSession(graphName);
+ }
+
+ public void scanTable(String tableName) {
+ log.info("Starting scan table [{}] of graph [{}] ...", tableName, graphName);
+ HgMetricX hgMetricX = HgMetricX.ofStart();
+ HgStoreSession session = getStoreSession();
+ int count = 0;
+ KvCloseableIterator> iterator = session.scanBatch2(HgScanQuery.tableOf(tableName));
+
+ long start = System.currentTimeMillis();
+ while (iterator.hasNext()) {
+ HgKvIterator iterator2 = iterator.next();
+ while (iterator2.hasNext()) {
+
+ count++;
+ iterator2.next();
+ if (count % (modNumber) == 0) {
+ log.info("Scanning keys: " + count + " time is " + modNumber * 1000
+ / (System.currentTimeMillis() - start));
+ start = System.currentTimeMillis();
+ }
+ if (count == max) {
+ break;
+ }
+
+ }
+ }
+ iterator.close();
+
+ hgMetricX.end();
+ log.info("*************************************************");
+ log.info("************* Scanning Completed **************");
+ log.info("Graph: {}", graphName);
+ log.info("Table: {}", tableName);
+ log.info("Keys: {}", count);
+ log.info("Max: {}", max);
+ log.info("Waiting: {} seconds.", MetricX.getIteratorWait() / 1000);
+ log.info("Total: {} seconds.", hgMetricX.past() / 1000);
+ log.info("Iterator: [{}]", iterator.getClass().getSimpleName());
+ log.info("Page: {}", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("*************************************************");
+ }
+
+ public void scanHash() {
+
+ String tableName = "g+i";
+ HgMetricX hgMetricX = HgMetricX.ofStart();
+ String graphName = "/DEFAULT/graphs/hugegraph1/";
+ HgStoreSession session = getStoreSession(graphName);
+ int count = 0;
+ String query = "{\"conditions\":[{\"cls\":\"S\",\"el\":{\"key\":\"ID\",\"relation\":\"SCAN\",\"value\"" +
+ ":{\"start\":\"61180\",\"end\":\"63365\",\"length\":0}}}],\"optimizedType\":\"NONE\",\"ids\":[]," +
+ "\"mustSortByInput\":true,\"resultType\":\"EDGE\",\"offset\":0," +
+ "\"actualOffset\":0,\"actualStoreOffset\":" +
+ "0,\"limit\":9223372036854775807,\"capacity\":-1,\"showHidden\":false,\"showDeleting\":false," +
+ "\"showExpired\":false,\"olap\":false,\"withProperties\":false,\"olapPks\":[]}";
+ //HgKvIterator iterator = session.scanIterator(tableName,0,715827883, HgKvStore.SCAN_ANY,null);
+
+ //HgKvIterator iterator = session.scanIterator(tableName,61180,63365, 348, null);
+ //HgKvIterator iterator = session.scanIterator(tableName,0,65535, 348, null);
+ HgKvIterator iterator = session.scanIterator(tableName);
+ while (iterator.hasNext()) {
+
+ count++;
+ //iterator.next();
+ // if (count % (modNumber) == 0) {
+ // log.info("Scanning keys: " + count);
+ HgCliUtil.println(Arrays.toString(iterator.next().key()));
+ // }
+ if (count == max) {
+ break;
+ }
+
+ }
+
+ hgMetricX.end();
+ log.info("*************************************************");
+ log.info("************* Scanning Completed **************");
+ log.info("Graph: {}", this.graphName);
+ log.info("Table: {}", tableName);
+ log.info("Keys: {}", count);
+ log.info("Max: {}", max);
+ log.info("Waiting: {} seconds.", MetricX.getIteratorWait() / 1000);
+ log.info("Total: {} seconds.", hgMetricX.past() / 1000);
+ log.info("Iterator: [{}]", iterator.getClass().getSimpleName());
+ log.info("Page: {}", HgStoreClientConfig.of().getNetKvScannerPageSize());
+ log.info("*************************************************");
+ }
+
+ public static final byte[] EMPTY_BYTES = new byte[0];
+
+ public void scanTable2(String tableName) throws PDException {
+ // java -jar hg-store-cli-3.6.0-SNAPSHOT.jar -scan 10.45.30.212:8989 "DEFAULT/case_112/g" g+ie
+ PDClient pdClient = storeClient.getPdClient();
+ List partitions = pdClient.getPartitions(0, graphName);
+ HgStoreSession session = storeClient.openSession(graphName);
+ int count = 0;
+ byte[] position = null;
+ HgMetricX hgMetricX = HgMetricX.ofStart();
+ for (Metapb.Partition partition : partitions) {
+ while (true) {
+ try (HgKvIterator iterator = session.scanIterator(tableName,
+ (int) (partition.getStartKey()), (int) (partition.getEndKey()),
+ HgKvStore.SCAN_HASHCODE, EMPTY_BYTES)) {
+ if (position != null) {
+ iterator.seek(position);
+ }
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ if (count % 3000 == 0) {
+ if (iterator.hasNext()) {
+ iterator.next();
+ position = iterator.position();
+ System.out.println("count is " + count);
+ } else {
+ position = null;
+ }
+ break;
+ }
+ }
+ if (!iterator.hasNext()) {
+ position = null;
+ break;
+ }
+ }
+ }
+ }
+ hgMetricX.end();
+ log.info("*************************************************");
+ log.info("************* Scanning Completed **************");
+ log.info("Graph: {}", graphName);
+ log.info("Table: {}", tableName);
+ log.info("Keys: {}", count);
+ log.info("Total: {} seconds.", hgMetricX.past() / 1000);
+ log.info("*************************************************");
+ }
+
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgCliUtil.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgCliUtil.java
new file mode 100644
index 000000000..9358f807c
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgCliUtil.java
@@ -0,0 +1,219 @@
+package com.baidu.hugegraph.store.cli.util;
+
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgStoreSession;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.function.Function;
+
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/2/14
+ */
+public class HgCliUtil {
+
+ public final static String TABLE_NAME = "cli-table";
+
+
+ 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
+ , 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 void printNum(List list, String title) {
+ if (list == null) return;
+
+ println(title + " size: " + list.size());
+ }
+
+ public static void println(Iterator iterator) {
+ if (iterator == null) return;
+ while (iterator.hasNext()) {
+ println(iterator.next());
+ }
+
+ }
+
+ public static void printOwner(List list) {
+ if (list == null) return;
+
+ for (HgOwnerKey entry : list) {
+ println(entry);
+ }
+ }
+
+ 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("[ " + 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 HgOwnerKey toOwnerKey(String key) {
+ return new HgOwnerKey(getOwner(key), toBytes(key));
+ }
+
+ public static HgOwnerKey toOwnerKey(byte[] key) {
+ return new HgOwnerKey(getOwner(key), key);
+ }
+
+ 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 toOwnerKey(String owner, String key) {
+ return HgOwnerKey.of(toBytes(owner), 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(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 long 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()) {
+ iterator.next();
+ count++;
+ }
+ return count;
+ }
+}
diff --git a/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgMetricX.java b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgMetricX.java
new file mode 100644
index 000000000..6e610bed6
--- /dev/null
+++ b/hg-store-cli/src/main/java/com/baidu/hugegraph/store/cli/util/HgMetricX.java
@@ -0,0 +1,48 @@
+package com.baidu.hugegraph.store.cli.util;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/1/29
+ */
+public class HgMetricX {
+ private long start;
+ private long end;
+
+ private long waitStart = System.currentTimeMillis();
+ private long waitTotal;
+
+ public static HgMetricX ofStart() {
+ return new HgMetricX(System.currentTimeMillis());
+ }
+
+ private HgMetricX(long start) {
+ this.start = start;
+ }
+
+ ;
+
+ public long start() {
+ return this.start = System.currentTimeMillis();
+ }
+
+ public long end() {
+ return this.end = System.currentTimeMillis();
+ }
+
+ public long past() {
+ return this.end - this.start;
+ }
+
+ public long getWaitTotal() {
+ return this.waitTotal;
+ }
+
+ public void startWait() {
+ this.waitStart = System.currentTimeMillis();
+ }
+
+ public void appendWait() {
+ this.waitTotal += System.currentTimeMillis() - waitStart;
+ }
+}
diff --git a/hg-store-cli/src/main/resources/application.yml b/hg-store-cli/src/main/resources/application.yml
new file mode 100644
index 000000000..3f0e4be22
--- /dev/null
+++ b/hg-store-cli/src/main/resources/application.yml
@@ -0,0 +1,23 @@
+net:
+ kv:
+ scanner:
+ buffer.size: 10000
+ page.size: 20000
+ chan.size: 1
+
+pd:
+ address: 10.14.139.71:8686
+
+scanner:
+ #graph: 'default/icbc_hstoregraph/g'
+ graph: 'DEFAULT/hugegraph/g'
+
+ table: 'g+ie'
+ #table: 'g+v'
+ max: 10_000_000
+ mod: 1_000_000
+
+committer:
+ graph: 'STORE_CLI'
+ table: 'benchmark'
+ amount: 1_000_000
\ No newline at end of file
diff --git a/hg-store-cli/src/main/resources/hg-store-client.properties b/hg-store-cli/src/main/resources/hg-store-client.properties
new file mode 100644
index 000000000..61b464dc2
--- /dev/null
+++ b/hg-store-cli/src/main/resources/hg-store-client.properties
@@ -0,0 +1,7 @@
+#grpc.timeout.seconds=10
+#grpc.max.inbound.message.size=
+#grpc.max.outbound.message.size=
+net.kv.scanner.buffer.size=10000
+net.kv.scanner.page.size = 20000
+#Unit:second
+net.kv.scanner.have.next.timeout=1000
\ No newline at end of file
diff --git a/hg-store-cli/src/main/resources/log4j2.xml b/hg-store-cli/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..1f393358f
--- /dev/null
+++ b/hg-store-cli/src/main/resources/log4j2.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+ logs
+ hg-store-client
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hg-store-client/deploy-snapshot.sh b/hg-store-client/deploy-snapshot.sh
new file mode 100644
index 000000000..f35659e36
--- /dev/null
+++ b/hg-store-client/deploy-snapshot.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+readonly REPO_URL=http://10.14.139.8:8081/artifactory/star-snapshot
+
+mvn --settings ../settings.xml -Dmaven.test.skip=true -DaltDeploymentRepository=star-snapshot::default::${REPO_URL} clean deploy
+
diff --git a/hg-store-client/pom.xml b/hg-store-client/pom.xml
new file mode 100644
index 000000000..930a1ef30
--- /dev/null
+++ b/hg-store-client/pom.xml
@@ -0,0 +1,95 @@
+
+
+ 4.0.0
+
+ com.baidu.hugegraph
+ hg-store-client
+ 3.6.3-SNAPSHOT
+
+
+ 11
+ 11
+ true
+ 2.15.0
+ 1.18.20
+
+
+
+
+ com.baidu.hugegraph
+ hg-store-grpc
+ ${project.version}
+
+
+ com.baidu.hugegraph
+ hg-store-common
+ ${project.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ ${log4j2.version}
+
+
+ com.baidu.hugegraph
+ hg-pd-client
+ ${project.version}
+
+
+
+
+ com.baidu.hugegraph
+ hg-pd-grpc
+ ${project.version}
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+ com.google.protobuf
+ protobuf-java-util
+ 3.17.2
+
+
+
+ commons-io
+ commons-io
+ 2.7
+ test
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.13.0
+ test
+
+
+ commons-codec
+ commons-codec
+ 1.15
+ test
+
+
+
+
+ Baidu_Local
+ http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local
+
+
+ Baidu_Local_Snapshots
+ http://maven.baidu-int.com/nexus/content/repositories/Baidu_Local_Snapshots
+
+
+
\ No newline at end of file
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvEntry.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvEntry.java
new file mode 100644
index 000000000..68afae352
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvEntry.java
@@ -0,0 +1,14 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com
+ */
+public interface HgKvEntry {
+ byte[] key();
+
+ byte[] value();
+
+ default int code(){
+ return -1;
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvIterator.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvIterator.java
new file mode 100644
index 000000000..af2323aea
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvIterator.java
@@ -0,0 +1,17 @@
+package com.baidu.hugegraph.store;
+
+import java.io.Closeable;
+import java.util.Iterator;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/21
+ */
+public interface HgKvIterator extends Iterator, HgSeekAble, Closeable {
+
+ byte[] key();
+
+ byte[] value();
+
+ void close();
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvOrderedIterator.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvOrderedIterator.java
new file mode 100644
index 000000000..52cc5bc6c
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvOrderedIterator.java
@@ -0,0 +1,8 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2022/03/10
+ */
+public interface HgKvOrderedIterator extends HgKvIterator, Comparable {
+ long getSequence();
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvPagingIterator.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvPagingIterator.java
new file mode 100644
index 000000000..7b647ce22
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvPagingIterator.java
@@ -0,0 +1,7 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/24
+ */
+public interface HgKvPagingIterator extends HgKvIterator, HgPageSize {
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvStore.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvStore.java
new file mode 100644
index 000000000..b5b5954aa
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgKvStore.java
@@ -0,0 +1,99 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.store.client.grpc.KvCloseableIterator;
+import com.baidu.hugegraph.store.grpc.common.Kv;
+import com.baidu.hugegraph.store.grpc.stream.ScanStreamReq;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author lynn.bond@hotmail.com
+ * @version 0.2.0
+ */
+public interface HgKvStore {
+ /**
+ * CAUTION: THE CONST BELOW MUST KEEP CONSISTENCE TO ScanIterator.Trait.
+ */
+ int SCAN_ANY = 0x80;
+ int SCAN_PREFIX_BEGIN = 0x01;
+ int SCAN_PREFIX_END = 0x02;
+ int SCAN_GT_BEGIN = 0x04;
+ int SCAN_GTE_BEGIN = 0x0c;
+ int SCAN_LT_END = 0x10;
+ int SCAN_LTE_END = 0x30;
+ int SCAN_KEYONLY = 0x40;
+ int SCAN_HASHCODE = 0x100;
+
+ boolean put(String table, HgOwnerKey ownerKey, byte[] value);
+
+ /**
+ * 该版本被store内部使用。向分区写入数据,
+ * partitionId与key.keyCode必须与pd存储的分区信息保持一致。
+ */
+ boolean directPut(String table, int partitionId, HgOwnerKey key, byte[] value);
+ byte[] get(String table, HgOwnerKey ownerKey);
+
+ boolean clean(int partId);
+
+ boolean delete(String table, HgOwnerKey ownerKey);
+
+ boolean deleteSingle(String table, HgOwnerKey ownerKey);
+
+ boolean deletePrefix(String table, HgOwnerKey prefix);
+
+ boolean deleteRange(String table, HgOwnerKey start, HgOwnerKey end);
+
+ boolean merge(String table, HgOwnerKey key, byte[] value);
+ @Deprecated
+ List batchGetOwner(String table, List keyList);
+
+ HgKvIterator scanIterator(String table);
+
+ HgKvIterator scanIterator(String table, byte[] query);
+
+ HgKvIterator scanIterator(String table, long limit);
+
+ HgKvIterator scanIterator(String table, long limit, byte[] query);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix, long limit);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix, long limit, byte[] query);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey, long limit);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey, long limit, byte[] query);
+
+ HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey, long limit, int scanType, byte[] query);
+
+ HgKvIterator scanIterator(String table, int codeFrom, int codeTo, int scanType, byte[] query);
+
+ // HgKvIterator scanIterator(ScanStreamReq scanReq);
+
+ HgKvIterator scanIterator(ScanStreamReq.Builder scanReqBuilder);
+
+ boolean truncate();
+
+ default boolean existsTable(String table) {
+ return false;
+ }
+
+ boolean createTable(String table);
+
+ boolean deleteTable(String table);
+
+ boolean dropTable(String table);
+
+ boolean deleteGraph(String graph);
+ List> scanBatch(HgScanQuery scanQuery);
+
+ KvCloseableIterator> scanBatch2(HgScanQuery scanQuery);
+ KvCloseableIterator> scanBatch3(HgScanQuery scanQuery, KvCloseableIterator iterator);
+
+ HgKvIterator batchPrefix(String table, List prefixList);
+}
+
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgOwnerKey.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgOwnerKey.java
new file mode 100644
index 000000000..db60b6c28
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgOwnerKey.java
@@ -0,0 +1,127 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.store.client.util.HgStoreClientUtil;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import static com.baidu.hugegraph.store.client.util.HgAssert.isArgumentNotNull;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.EMPTY_BYTES;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.EMPTY_OWNER_KEY;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/14
+ * @version 1.1.0 add argument assertion.
+ * @version 1.2.0 add newEmpty
+ * @version 1.3.0 add canceled assert
+ */
+public class HgOwnerKey implements Serializable {
+ private int keyCode = 0;// TODO: Be here OK?
+ private final byte[] owner;
+ private byte[] key;
+ private int serialNo; //顺序号,用于批量查询保证返回结果的顺序性
+
+ public static HgOwnerKey emptyOf(){
+ return EMPTY_OWNER_KEY;
+ }
+
+ public static HgOwnerKey newEmpty(){
+ return HgOwnerKey.of(EMPTY_BYTES,EMPTY_BYTES);
+ }
+
+ public static HgOwnerKey ownerOf(byte[] owner){
+ return new HgOwnerKey(owner,EMPTY_BYTES);
+ }
+ public static HgOwnerKey codeOf(int code){
+ return HgOwnerKey.of(EMPTY_BYTES, EMPTY_BYTES).setKeyCode(code);
+ }
+
+ public static HgOwnerKey of(byte[] owner, byte[] key){
+ return new HgOwnerKey(owner,key);
+ }
+ public static HgOwnerKey of(int keyCode, byte[] key){
+ return new HgOwnerKey(keyCode, key);
+ }
+
+ /**
+ * @see HgOwnerKey:of(byte[] owner, byte[] key)
+ * @param owner
+ * @param key
+ */
+ @Deprecated
+ public HgOwnerKey(byte[] owner, byte[] key) {
+ if (owner == null) {
+ owner = EMPTY_BYTES;
+ }
+ if (key == null) {
+ key = EMPTY_BYTES;
+ }
+ this.owner = owner;
+ this.key = key;
+ }
+
+ public HgOwnerKey(int code, byte[] key) {
+ if (key == null) {
+ key = EMPTY_BYTES;
+ }
+ this.owner = EMPTY_BYTES;
+ this.key = key;
+ this.keyCode = code;
+ }
+
+ public byte[] getOwner() {
+ return owner;
+ }
+
+ public byte[] getKey() {
+ return key;
+ }
+
+ public int getKeyCode() {
+ return keyCode;
+ }
+
+ public HgOwnerKey setKeyCode(int keyCode) {
+ this.keyCode = keyCode;
+ return this;
+ }
+
+ public HgOwnerKey codeToKey(int keyCode) {
+ this.keyCode = keyCode;
+ this.key = HgStoreClientUtil.toIntBytes(keyCode);
+ return this;
+ }
+
+ public HgOwnerKey setSerialNo(int serialNo){
+ this.serialNo = serialNo;
+ return this;
+ }
+
+ public int getSerialNo(){
+ return this.serialNo;
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ HgOwnerKey that = (HgOwnerKey) o;
+ return Arrays.equals(owner, that.owner) && Arrays.equals(key, that.key);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Arrays.hashCode(owner);
+ result = 31 * result + Arrays.hashCode(key);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "HgOwnerKey{" +
+ "owner=" + Arrays.toString(owner) +
+ ", key=" + Arrays.toString(key) +
+ ", code=" + keyCode +
+ '}';
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPageSize.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPageSize.java
new file mode 100644
index 000000000..150d9924b
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPageSize.java
@@ -0,0 +1,13 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * Return the amount of records returned by one query in pageable-query.
+ *
+ * @author lynn.bond@hotmail.com created on 2021/10/24
+ */
+public interface HgPageSize {
+ long getPageSize();
+ default boolean isPageEmpty(){
+ return false;
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPrivate.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPrivate.java
new file mode 100644
index 000000000..898571696
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgPrivate.java
@@ -0,0 +1,17 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com
+ */
+public final class HgPrivate {
+
+ private static HgPrivate instance = new HgPrivate();
+
+ private HgPrivate() {
+ }
+
+ static HgPrivate of() {
+ return instance;
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgScanQuery.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgScanQuery.java
new file mode 100644
index 000000000..da1aed0c6
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgScanQuery.java
@@ -0,0 +1,305 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.store.client.util.HgAssert;
+import com.baidu.hugegraph.store.grpc.common.ScanOrderType;
+
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author lynn.bond@hotmail.com on 2022/3/4
+ * @version 0.5.0
+ */
+public interface HgScanQuery {
+ String getTable();
+
+ HgScanQuery.ScanMethod getScanMethod();
+
+ List getPrefixList();
+
+ Iterator getPrefixItr();
+
+ List getStartList();
+
+ List getEndList();
+
+ long getLimit();
+
+ long getPerKeyLimit();
+
+ long getPerKeyMax();
+
+ long getSkipDegree();
+
+ int getScanType();
+ ScanOrderType getOrderType();
+
+ boolean isOnlyKey();
+
+ byte[] getQuery();
+
+ enum ScanMethod {
+ ALL, PREFIX, RANGE
+ }
+
+ enum SortType {
+ UNSORTED, SORT_BY_EDGE, SORT_BY_VERTEX
+ }
+
+
+ ScanBuilder builder();
+
+ static HgScanQuery tableOf(String table) {
+ return ScanBuilder.tableOf(table).build();
+ }
+
+ static HgScanQuery rangeOf(String table, List startList, List endList) {
+ return ScanBuilder.rangeOf(table, startList, endList).build();
+ }
+
+ static HgScanQuery prefixOf(String table, List prefixList) {
+ return ScanBuilder.prefixOf(table, prefixList).build();
+ }
+
+ static HgScanQuery prefixOf(String table, List prefixList, ScanOrderType orderType) {
+ return ScanBuilder.prefixOf(table, prefixList).setOrderType(orderType).build();
+ }
+
+ static HgScanQuery prefixIteratorOf(String table, Iterator prefixItr) {
+ return ScanBuilder.prefixIteratorOf(table, prefixItr).build();
+ }
+
+ static HgScanQuery prefixIteratorOf(String table, Iterator prefixItr, ScanOrderType orderType) {
+ return ScanBuilder.prefixIteratorOf(table, prefixItr).setOrderType(orderType).build();
+ }
+
+ class ScanBuilder {
+ private final String table;
+ private final HgScanQuery.ScanMethod sanMethod;
+ private long limit = Integer.MAX_VALUE;
+ private long perKeyLimit = Integer.MAX_VALUE;
+ private long perKeyMax = Integer.MAX_VALUE;
+ private int scanType;
+ private ScanOrderType orderType;
+
+ private long skipDegree;
+
+ private boolean onlyKey;
+ private byte[] query;
+ private List prefixList;
+ private List startList;
+ private List endList;
+ private Iterator prefixItr;
+
+ public static ScanBuilder rangeOf(String table, List startList, List endList) {
+ HgAssert.isArgumentValid(table, "table");
+ HgAssert.isArgumentValid(startList, "startList");
+ HgAssert.isArgumentValid(endList, "endList");
+ HgAssert.isTrue(startList.size() == endList.size()
+ , "The size of startList not equals endList's.");
+
+ ScanBuilder res = new ScanBuilder(HgScanQuery.ScanMethod.RANGE, table);
+ res.startList = startList;
+ res.endList = endList;
+ res.scanType = HgKvStore.SCAN_GTE_BEGIN | HgKvStore.SCAN_LTE_END;
+ return res;
+ }
+
+ public static ScanBuilder prefixOf(String table, List prefixList) {
+ HgAssert.isArgumentValid(table, "table");
+ HgAssert.isArgumentValid(prefixList, "prefixList");
+
+ ScanBuilder res = new ScanBuilder(HgScanQuery.ScanMethod.PREFIX, table);
+ res.prefixList = prefixList;
+ return res;
+
+ }
+
+ public static ScanBuilder prefixIteratorOf(String table, Iterator prefixItr) {
+ HgAssert.isArgumentValid(table, "table");
+
+ ScanBuilder res = new ScanBuilder(HgScanQuery.ScanMethod.PREFIX, table);
+ res.prefixItr = prefixItr;
+ return res;
+
+ }
+
+ public static ScanBuilder tableOf(String table) {
+ HgAssert.isArgumentValid(table, "table");
+
+ return new ScanBuilder(HgScanQuery.ScanMethod.ALL, table);
+ }
+
+ ScanBuilder(HgScanQuery.ScanMethod sanMethod, String table) {
+ this.table = table;
+ this.sanMethod = sanMethod;
+ this.orderType = ScanOrderType.ORDER_NONE;
+ }
+
+ public ScanBuilder setLimit(long limit) {
+ this.limit = limit;
+ return this;
+ }
+
+ public ScanBuilder setPerKeyLimit(long limit) {
+ this.perKeyLimit = limit;
+ return this;
+ }
+
+ public ScanBuilder setPerKeyMax(long max) {
+ this.perKeyMax = max;
+ return this;
+ }
+
+ public ScanBuilder setScanType(int scanType) {
+ this.scanType = scanType;
+ return this;
+ }
+
+ public ScanBuilder setOrderType(ScanOrderType orderType){
+ this.orderType = orderType;
+ return this;
+ }
+
+ public ScanBuilder setQuery(byte[] query) {
+ this.query = query;
+ return this;
+ }
+ public ScanBuilder setSkipDegree(long skipDegree){
+ this.skipDegree = skipDegree;
+ return this;
+ }
+
+ public ScanBuilder setOnlyKey(boolean onlyKey){
+ this.onlyKey = onlyKey;
+ return this;
+ }
+
+
+ public HgScanQuery build() {
+ return this.new BatchScanQuery();
+ }
+
+ private class BatchScanQuery implements HgScanQuery {
+
+ @Override
+ public String getTable() {
+ return table;
+ }
+
+ @Override
+ public HgScanQuery.ScanMethod getScanMethod() {
+ return sanMethod;
+ }
+
+ @Override
+ public List getPrefixList() {
+ if (prefixList == null) {
+ return Collections.EMPTY_LIST;
+ } else {
+ return Collections.unmodifiableList(prefixList);
+ }
+ }
+
+ @Override
+ public Iterator getPrefixItr() {
+ return prefixItr;
+ }
+
+ @Override
+ public List getStartList() {
+ if (startList == null) {
+ return Collections.EMPTY_LIST;
+ } else {
+ return Collections.unmodifiableList(startList);
+ }
+ }
+
+ @Override
+ public List getEndList() {
+ if (endList == null) {
+ return Collections.EMPTY_LIST;
+ } else {
+ return Collections.unmodifiableList(endList);
+ }
+ }
+
+ @Override
+ public long getLimit() {
+ return limit;
+ }
+
+ @Override
+ public long getPerKeyLimit() {
+ return perKeyLimit;
+ }
+
+ @Override
+ public long getPerKeyMax() {
+ return perKeyMax;
+ }
+
+ @Override
+ public long getSkipDegree() {
+ return skipDegree;
+ }
+
+ @Override
+ public int getScanType() {
+ return scanType;
+ }
+
+ @Override
+ public ScanOrderType getOrderType() {
+ return orderType;
+ }
+
+ @Override
+ public boolean isOnlyKey() {
+ return onlyKey;
+ }
+
+ @Override
+ public byte[] getQuery() {
+ return query;
+ }
+
+ @Override
+ public ScanBuilder builder() {
+ return ScanBuilder.this;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("HgScanQuery{");
+ sb.append("table='").append(getTable()).append('\'');
+ sb.append(", scanMethod=").append(getScanMethod());
+ sb.append(", prefixList=").append(getPrefixList());
+ sb.append(", startList=").append(getStartList());
+ sb.append(", endList=").append(getEndList());
+ sb.append(", limit=").append(getLimit());
+ sb.append(", perKeyLimit=").append(getPerKeyLimit());
+ sb.append(", perKeyMax=").append(getPerKeyMax());
+ sb.append(", skipDegree=").append(getSkipDegree());
+ sb.append(", scanType=").append(getScanType());
+ sb.append(", orderType=").append(getOrderType());
+ sb.append(", onlyKey=").append(isOnlyKey());
+ sb.append(", query=");
+ if (query == null) sb.append("null");
+ else {
+ sb.append('[');
+ for (int i = 0; i < query.length; ++i)
+ sb.append(i == 0 ? "" : ", ").append(query[i]);
+ sb.append(']');
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+
+ }
+}
+
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSeekAble.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSeekAble.java
new file mode 100644
index 000000000..f26bc3e51
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSeekAble.java
@@ -0,0 +1,10 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2022/03/11
+ */
+public interface HgSeekAble {
+ byte[] position();
+
+ void seek(byte[] position);
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionManager.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionManager.java
new file mode 100644
index 000000000..a4aaf4bf7
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionManager.java
@@ -0,0 +1,38 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.store.client.HgStoreSessionProvider;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Maintain HgStoreSession instances.
+ * // TODO: Holding more than one HgSessionManager is available,if you want to connect multi HgStore-clusters.
+ *
+ * @author lynn.bond@hotmail.com
+ */
+
+@ThreadSafe
+public final class HgSessionManager {
+ private HgSessionProvider sessionProvider;
+ private final static HgSessionManager instance =new HgSessionManager();
+
+ private HgSessionManager(){
+ // TODO: constructed by SPI
+ this.sessionProvider=new HgStoreSessionProvider();
+ }
+
+
+ public static HgSessionManager getInstance(){
+ return instance;
+ }
+
+ /**
+ * Retrieve or create a HgStoreSession.
+ * @param graphName
+ * @return
+ */
+ public HgStoreSession openSession(String graphName){
+ return this.sessionProvider.createSession(graphName);
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionProvider.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionProvider.java
new file mode 100644
index 000000000..779c845be
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgSessionProvider.java
@@ -0,0 +1,11 @@
+package com.baidu.hugegraph.store;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ */
+@ThreadSafe
+public interface HgSessionProvider {
+ HgStoreSession createSession(String graphName);
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreClient.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreClient.java
new file mode 100644
index 000000000..131a6bac1
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreClient.java
@@ -0,0 +1,78 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.pd.client.PDClient;
+import com.baidu.hugegraph.pd.client.PDConfig;
+import com.baidu.hugegraph.store.client.HgStoreNodeManager;
+import com.baidu.hugegraph.store.client.HgStoreNodePartitionerImpl;
+import com.baidu.hugegraph.store.client.HgStoreSessionProvider;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Maintain HgStoreSession instances.
+ * // TODO: Holding more than one HgSessionManager is available,if you want to connect multi HgStore-clusters.
+ *
+ * @author lynn.bond@hotmail.com
+ */
+
+@ThreadSafe
+public final class HgStoreClient {
+ private HgSessionProvider sessionProvider;
+ private PDClient pdClient;
+
+ public HgStoreClient() {
+ this.sessionProvider = new HgStoreSessionProvider();
+ }
+
+ public HgStoreClient(PDConfig config) {
+ this.sessionProvider = new HgStoreSessionProvider();
+ pdClient = PDClient.create(config);
+ setPdClient(pdClient);
+ }
+ public HgStoreClient(PDClient pdClient) {
+ this.sessionProvider = new HgStoreSessionProvider();
+ setPdClient(pdClient);
+ }
+ public static HgStoreClient create(PDConfig config) {
+ return new HgStoreClient(config);
+ }
+
+ public static HgStoreClient create(PDClient pdClient) {
+ return new HgStoreClient(pdClient);
+ }
+
+ public static HgStoreClient create(){
+ return new HgStoreClient();
+ }
+
+ public void setPDConfig(PDConfig config) {
+ pdClient = PDClient.create(config);
+ setPdClient(pdClient);
+ }
+
+ public void setPdClient(PDClient client) {
+ this.pdClient = client;
+ HgStoreNodeManager nodeManager =
+ HgStoreNodeManager.getInstance();
+
+ HgStoreNodePartitionerImpl p = new HgStoreNodePartitionerImpl(pdClient, nodeManager);
+ nodeManager.setNodeProvider(p);
+ nodeManager.setNodePartitioner(p);
+ nodeManager.setNodeNotifier(p);
+ }
+
+ /**
+ * Retrieve or create a HgStoreSession.
+ *
+ * @param graphName
+ * @return
+ */
+ public HgStoreSession openSession(String graphName) {
+ return this.sessionProvider.createSession(graphName);
+ }
+
+ public PDClient getPdClient(){
+ return pdClient;
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreSession.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreSession.java
new file mode 100644
index 000000000..90bcc47d5
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgStoreSession.java
@@ -0,0 +1,25 @@
+package com.baidu.hugegraph.store;
+
+import com.baidu.hugegraph.store.client.type.HgStoreClientException;
+
+/**
+ * @author lynn.bond@hotmail.com
+ */
+public interface HgStoreSession extends HgKvStore {
+
+ void beginTx();
+
+ /**
+ * @throws IllegalStateException when the tx hasn't been beginning.
+ * @throws HgStoreClientException when failed to commit .
+ */
+ void commit();
+
+ /**
+ * @throws IllegalStateException when the tx hasn't been beginning.
+ * @throws HgStoreClientException when failed to rollback.
+ */
+ void rollback();
+
+ boolean isTx();
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTkvEntry.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTkvEntry.java
new file mode 100644
index 000000000..fd6699107
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTkvEntry.java
@@ -0,0 +1,10 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com
+ */
+public interface HgTkvEntry {
+ String table();
+ byte[] key();
+ byte[] value();
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTokvEntry.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTokvEntry.java
new file mode 100644
index 000000000..f2d1e264d
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/HgTokvEntry.java
@@ -0,0 +1,10 @@
+package com.baidu.hugegraph.store;
+
+/**
+ * @author lynn.bond@hotmail.com
+ */
+public interface HgTokvEntry {
+ String table();
+ HgOwnerKey ownerKey();
+ byte[] value();
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartition.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartition.java
new file mode 100644
index 000000000..8eff82d83
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartition.java
@@ -0,0 +1,75 @@
+package com.baidu.hugegraph.store.client;
+
+import java.util.Objects;
+
+/**
+ * Immutable Object Pattern
+ *
+ * @author lynn.bond@hotmail.com created on 2021/10/26
+ */
+public final class HgNodePartition {
+ private Long nodeId;
+ //当前key的hashcode
+ private Integer keyCode;
+
+ //分区的开始结束范围
+ private Integer startKey;
+ private Integer endKey;
+ private int hash = -1;
+
+ public static HgNodePartition of(Long nodeId, Integer keyCode) {
+ return new HgNodePartition(nodeId, keyCode);
+ }
+ public static HgNodePartition of(Long nodeId, Integer keyCode, Integer startKey, Integer endKey) {
+ return new HgNodePartition(nodeId, keyCode, startKey, endKey);
+ }
+
+ HgNodePartition(Long nodeId, Integer keyCode) {
+ this.nodeId = nodeId;
+ this.keyCode = keyCode;
+ this.startKey = this.endKey = keyCode;
+ }
+
+ HgNodePartition(Long nodeId, Integer keyCode, Integer startKey, Integer endKey) {
+ this.nodeId = nodeId;
+ this.keyCode = keyCode;
+ this.startKey = startKey;
+ this.endKey = endKey;
+ }
+ public Long getNodeId() {
+ return nodeId;
+ }
+
+ public Integer getKeyCode() {
+ return keyCode;
+ }
+
+ public Integer getStartKey(){
+ return startKey;
+ }
+
+ public Integer getEndKey(){
+ return endKey;
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ HgNodePartition that = (HgNodePartition) o;
+ return Objects.equals(nodeId, that.nodeId) && Objects.equals(keyCode, that.keyCode);
+ }
+
+ @Override
+ public int hashCode() {
+ if(this.hash==-1)this.hash=Objects.hash(nodeId, keyCode);
+ return this.hash;
+ }
+
+ @Override
+ public String toString() {
+ return "HgNodePartition{" +
+ "nodeId=" + nodeId +
+ ", partitionId=" + keyCode +
+ '}';
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartitionerBuilder.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartitionerBuilder.java
new file mode 100644
index 000000000..e706ad1ce
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgNodePartitionerBuilder.java
@@ -0,0 +1,50 @@
+package com.baidu.hugegraph.store.client;
+
+import javax.annotation.concurrent.NotThreadSafe;
+import java.net.CookieHandler;
+import java.util.*;
+
+import static com.baidu.hugegraph.store.client.util.HgAssert.isFalse;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/26
+ * @version 1.0.0
+ */
+@NotThreadSafe
+public final class HgNodePartitionerBuilder {
+
+ private Set partitions = null;
+ /**
+ *
+ * @param nodeId
+ * @param keyCode
+ * @return
+ * @see HgNodePartitionerBuilder:setPartitions(Set partitions)
+ */
+ @Deprecated
+ public HgNodePartitionerBuilder add(Long nodeId, Integer keyCode) {
+ isFalse(nodeId == null, "The argument is invalid: nodeId");
+ isFalse(keyCode == null, "The argument is invalid: keyCode");
+
+ if(this.partitions==null){
+ this.partitions=new HashSet<>(16,1);
+ }
+
+ this.partitions.add(HgNodePartition.of(nodeId, keyCode));
+ return this;
+ }
+
+ public void setPartitions(Set partitions) {
+ isFalse(partitions == null, "The argument is invalid: partitions");
+ this.partitions = partitions;
+ }
+
+ Collection getPartitions() {
+ return this.partitions;
+ }
+
+ static HgNodePartitionerBuilder resetAndGet() {
+ return new HgNodePartitionerBuilder();
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgPrivate.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgPrivate.java
new file mode 100644
index 000000000..184686c25
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgPrivate.java
@@ -0,0 +1,20 @@
+package com.baidu.hugegraph.store.client;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/26
+ */
+public class HgPrivate {
+ private final static HgPrivate instance = new HgPrivate();
+
+ static HgPrivate getInstance() {
+ return instance;
+ }
+
+ private HgPrivate() {
+
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNode.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNode.java
new file mode 100644
index 000000000..c9ab58577
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNode.java
@@ -0,0 +1,40 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgStoreSession;
+
+import java.util.Set;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/11
+ * @version 0.2.0
+ */
+public interface HgStoreNode {
+
+ /**
+ * Return boolean value of being online or not
+ * @return
+ */
+ default boolean isHealthy(){
+ return true;
+ }
+
+ /**
+ * Return the unique ID of store-node.
+ * @return
+ */
+ Long getNodeId();
+
+ /**
+ * A string value concatenated by host and port: "host:port"
+ * @return
+ */
+ String getAddress();
+
+ /**
+ * Return a new HgStoreSession instance, that is not Thread safe.
+ * Return null when the node is not in charge of the graph that was passed from argument.
+ * @return
+ */
+ HgStoreSession openSession(String graphName);
+
+}
\ No newline at end of file
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeBuilder.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeBuilder.java
new file mode 100644
index 000000000..0734ddb1f
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeBuilder.java
@@ -0,0 +1,19 @@
+package com.baidu.hugegraph.store.client;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/11
+ */
+public interface HgStoreNodeBuilder {
+
+ HgStoreNodeBuilder setNodeId(Long nodeId);
+
+ HgStoreNodeBuilder setAddress(String address);
+
+ /**
+ * To build a HgStoreNode instance.
+ *
+ * @return
+ */
+ HgStoreNode build();
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeCandidates.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeCandidates.java
new file mode 100644
index 000000000..3be9048ed
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeCandidates.java
@@ -0,0 +1,24 @@
+package com.baidu.hugegraph.store.client;
+
+import java.util.List;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ */
+public final class HgStoreNodeCandidates {
+
+ List nodeList;
+
+ HgStoreNodeCandidates(List nodeList){
+ this.nodeList=nodeList;
+ }
+
+ public int size(){
+ return this.nodeList.size();
+ }
+
+ public HgStoreNode getNode(int index){
+ return this.nodeList.get(index);
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeManager.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeManager.java
new file mode 100644
index 000000000..6600f271b
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeManager.java
@@ -0,0 +1,237 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.client.grpc.GrpcStoreNodeBuilder;
+import com.baidu.hugegraph.store.client.type.HgNodeStatus;
+import com.baidu.hugegraph.store.client.type.HgStoreClientException;
+import com.baidu.hugegraph.store.client.util.HgAssert;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * // TODO: Mapping to Store-Node-Cluster, one to one.
+ *
+ * @author lynn.bond@hotmail.com created on 2021/10/11
+ * @version 0.2.0
+ */
+@ThreadSafe
+@Slf4j
+public final class HgStoreNodeManager {
+ private final static Set CLUSTER_ID_SET = new HashSet<>();
+ private final static HgStoreNodeManager instance = new HgStoreNodeManager();
+
+ private final String clusterId;
+ private final Map addressMap = new ConcurrentHashMap<>();
+ private final Map nodeIdMap = new ConcurrentHashMap<>();
+ private final Map> graphNodesMap = new ConcurrentHashMap<>();
+
+ private HgStoreNodeProvider nodeProvider;
+ private HgStoreNodePartitioner nodePartitioner;
+ private HgStoreNodeNotifier nodeNotifier;
+
+ private HgStoreNodeManager() {
+ this.clusterId = HgStoreClientConst.DEFAULT_NODE_CLUSTER_ID;
+ }
+
+ private HgStoreNodeManager(String clusterId) {
+ synchronized (CLUSTER_ID_SET) {
+ if (CLUSTER_ID_SET.contains(clusterId)) {
+ throw new RuntimeException("The cluster [" + clusterId + "] has been existing.");
+ }
+ CLUSTER_ID_SET.add(clusterId);
+ this.clusterId = clusterId;
+ }
+ }
+
+ public static HgStoreNodeManager getInstance() {
+ return instance;
+ }
+
+ /**
+ * Return the HgStoreNodeBuilder
+ *
+ * @return
+ */
+ public HgStoreNodeBuilder getNodeBuilder() {
+ // TODO: Constructed by a provider that retrieved by SPI
+ return new GrpcStoreNodeBuilder(this, HgPrivate.getInstance());
+ }
+
+ /**
+ * Return an instance of HgStoreNode whose ID is matched to the argument.
+ *
+ * @param nodeId
+ * @return null when none of instance is matched to the argument,or argument is invalid.
+ */
+ public HgStoreNode getStoreNode(Long nodeId) {
+ if (nodeId == null) {
+ return null;
+ }
+ return this.nodeIdMap.get(nodeId);
+ }
+
+ /**
+ * Apply a HgStoreNode instance with graph-name and node-id.
+ * CAUTION:
+ * It won't work when user haven't set a HgStoreNodeProvider via setNodeProvider method.
+ *
+ * @param graphName
+ * @param nodeId
+ * @return
+ */
+ HgStoreNode applyNode(String graphName, Long nodeId) {
+ HgStoreNode node = this.nodeIdMap.get(nodeId);
+
+ if (node != null) {
+ return node;
+ }
+
+ if (this.nodeProvider == null) {
+ return null;
+ }
+
+ node = this.nodeProvider.apply(graphName, nodeId);
+
+ if (node == null) {
+
+ log.warn("Failed to apply a HgStoreNode instance form the nodeProvider [ "
+ + this.nodeProvider.getClass().getName() + " ].");
+ notifying(graphName, nodeId, HgNodeStatus.NOT_EXIST);
+ return null;
+ }
+
+ this.addNode(graphName, node);
+
+ return node;
+ }
+
+ private void notifying(String graphName, Long nodeId, HgNodeStatus status) {
+ if (this.nodeNotifier != null) {
+ try {
+ this.nodeNotifier.notice(graphName, HgStoreNotice.of(nodeId, status));
+ } catch (Throwable t) {
+ log.error("Failed to invoke " + this.nodeNotifier.getClass().getSimpleName() + ":notice(" + nodeId + "," + status + ")", t);
+ }
+ }
+ }
+
+ /**
+ * @param graphName
+ * @param notice
+ * @return null: when there is no HgStoreNodeNotifier in the nodeManager;
+ * @throws HgStoreClientException
+ */
+ public Integer notifying(String graphName, HgStoreNotice notice) {
+
+ if (this.nodeNotifier != null) {
+
+ synchronized (Thread.currentThread()) {
+ try {
+ return this.nodeNotifier.notice(graphName, notice);
+ } catch (Throwable t) {
+ String msg = "Failed to invoke " + this.nodeNotifier.getClass().getSimpleName() + ", notice: [ " + notice + " ]";
+ log.error(msg, t);
+ throw new HgStoreClientException(msg);
+ }
+ }
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Return a collection of HgStoreNode who is in charge of the graph passed in the argument.
+ *
+ * @param graphName
+ * @return null when none matched to argument or any argument is invalid.
+ */
+ public List getStoreNodes(String graphName) {
+ if (HgAssert.isInvalid(graphName)) {
+ return null;
+ }
+
+ return this.graphNodesMap.get(graphName);
+ }
+
+ /**
+ * Adding a new Store-Node, return the argument's value if the host+port was not existing,
+ * otherwise return the HgStoreNode-instance added early.
+ *
+ * @param storeNode
+ * @return
+ * @throws IllegalArgumentException when any argument is invalid.
+ */
+ public HgStoreNode addNode(HgStoreNode storeNode) {
+ HgAssert.isFalse(storeNode == null, "the argument: storeNode is null.");
+
+ Long nodeId = storeNode.getNodeId();
+
+ HgStoreNode node = null;
+
+ synchronized (this.nodeIdMap) {
+ node = this.addressMap.get(nodeId);
+ if (node == null) {
+ node = storeNode;
+ this.nodeIdMap.put(nodeId, node);
+ this.addressMap.put(storeNode.getAddress(), node);
+ }
+ }
+
+ return node;
+ }
+
+ /**
+ * @param graphName
+ * @param storeNode
+ * @return
+ * @throws IllegalArgumentException when any argument is invalid.
+ */
+ public HgStoreNode addNode(String graphName, HgStoreNode storeNode) {
+ HgAssert.isFalse(HgAssert.isInvalid(graphName), "the argument is invalid: graphName");
+ HgStoreNode node = this.addNode(storeNode);
+
+ List nodes = null;
+
+ synchronized (this.graphNodesMap) {
+ nodes = this.graphNodesMap.get(graphName);
+ if (nodes == null) {
+ nodes = new ArrayList<>();
+ this.graphNodesMap.put(graphName, nodes);
+ }
+ nodes.add(node);
+ }
+
+
+ return node;
+ }
+
+ public HgStoreNodePartitioner getNodePartitioner() {
+ return nodePartitioner;
+ }
+
+ public HgStoreNodeManager setNodePartitioner(HgStoreNodePartitioner nodePartitioner) {
+ HgAssert.isFalse(nodePartitioner == null, "the argument is invalid: nodePartitioner");
+ this.nodePartitioner = nodePartitioner;
+ return this;
+ }
+
+ public HgStoreNodeNotifier getNodeNotifier() {
+ return nodeNotifier;
+ }
+
+ public HgStoreNodeManager setNodeNotifier(HgStoreNodeNotifier nodeNotifier) {
+ HgAssert.isFalse(nodeNotifier == null, "the argument is invalid: nodeNotifier");
+ this.nodeNotifier = nodeNotifier;
+ return this;
+ }
+
+ public HgStoreNodeManager setNodeProvider(HgStoreNodeProvider nodeProvider) {
+ this.nodeProvider = nodeProvider;
+ return this;
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeNotifier.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeNotifier.java
new file mode 100644
index 000000000..3110b42d9
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeNotifier.java
@@ -0,0 +1,19 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.client.type.HgNodeStatus;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ * @version 1.0.0
+ */
+public interface HgStoreNodeNotifier {
+
+ /**
+ * It will be invoked by NodeManager, when some exception or issue was happened.
+ * @param graphName
+ * @param storeNotice
+ * @return return 0 please, for no matter what.
+ */
+ int notice(String graphName, HgStoreNotice storeNotice);
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitioner.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitioner.java
new file mode 100644
index 000000000..9979a4fd0
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitioner.java
@@ -0,0 +1,46 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ * @version 1.0.0
+ */
+public interface HgStoreNodePartitioner {
+
+ /**
+ * The partition algorithm implementation, that specialized by user.
+ *
+ * @param builder The builder of HgNodePartitionerBuilder. It's supposed to be invoked directly by user.
+ * e.g. builder.add(nodeId,address,partitionId);
+ * @param graphName
+ * @param startKey
+ * @param endKey
+ * @return status:
+ *
+ * - 0: The partitioner is OK.
+ * - 10: The partitioner is not work.
+ *
+ */
+ int partition(HgNodePartitionerBuilder builder, String graphName, byte[] startKey, byte[] endKey);
+
+ /**
+ * @param builder
+ * @param graphName
+ * @param startCode hash code
+ * @param endCode hash code
+ * @return
+ */
+ default int partition(HgNodePartitionerBuilder builder, String graphName, int startCode, int endCode) {
+ return this.partition(builder, graphName
+ , HgStoreClientConst.ALL_PARTITION_OWNER
+ , HgStoreClientConst.ALL_PARTITION_OWNER);
+ }
+
+ default int partition(HgNodePartitionerBuilder builder, String graphName, int partitionId) {
+ return this.partition(builder, graphName
+ , HgStoreClientConst.ALL_PARTITION_OWNER
+ , HgStoreClientConst.ALL_PARTITION_OWNER);
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitionerImpl.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitionerImpl.java
new file mode 100644
index 000000000..1aecdabf4
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodePartitionerImpl.java
@@ -0,0 +1,177 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.pd.client.PDClient;
+import com.baidu.hugegraph.pd.common.KVPair;
+import com.baidu.hugegraph.pd.common.PDException;
+import com.baidu.hugegraph.pd.common.PartitionUtils;
+import com.baidu.hugegraph.pd.grpc.Metapb;
+import com.baidu.hugegraph.store.client.type.HgNodeStatus;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+@Slf4j
+public class HgStoreNodePartitionerImpl implements HgStoreNodePartitioner,
+ HgStoreNodeProvider,
+ HgStoreNodeNotifier {
+ private PDClient pdClient;
+ private HgStoreNodeManager nodeManager;
+
+ protected HgStoreNodePartitionerImpl() {
+ }
+
+ public HgStoreNodePartitionerImpl(PDClient pdClient, HgStoreNodeManager nodeManager) {
+ this.pdClient = pdClient;
+ this.nodeManager = nodeManager;
+ }
+
+ /**
+ * 查询分区信息,结果通过HgNodePartitionerBuilder返回
+ */
+ @Override
+ public int partition(HgNodePartitionerBuilder builder, String graphName,
+ byte[] startKey, byte[] endKey) {
+ try {
+ HashSet partitions = null;
+ if (HgStoreClientConst.ALL_PARTITION_OWNER == startKey) {
+ List stores = pdClient.getActiveStores(graphName);
+ partitions = new HashSet<>(stores.size());
+ for (Metapb.Store store : stores) {
+ partitions.add(HgNodePartition.of(store.getId(), -1));
+ }
+
+ } else if (endKey == HgStoreClientConst.EMPTY_BYTES
+ || startKey == endKey || Arrays.equals(startKey, endKey)) {
+ KVPair partShard =
+ pdClient.getPartition(graphName, startKey);
+ Metapb.Shard leader = partShard.getValue();
+ partitions = new HashSet<>();
+ partitions.add(HgNodePartition.of(leader.getStoreId(),
+ pdClient.keyToCode(graphName, startKey)));
+ } else {
+ log.warn("StartOwnerkey is not equal to endOwnerkey, which is meaningless!!, It is a error!!");
+ List stores = pdClient.getActiveStores(graphName);
+ partitions = new HashSet<>(stores.size());
+ for (Metapb.Store store : stores) {
+ partitions.add(HgNodePartition.of(store.getId(), -1));
+ }
+ }
+ builder.setPartitions(partitions);
+ } catch (PDException e) {
+ log.error("An error occurred while getting partition information :{}", e.getMessage());
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ return 0;
+ }
+
+ @Override
+ public int partition(HgNodePartitionerBuilder builder, String graphName,
+ int startKey, int endKey) {
+ try {
+ HashSet partitions = new HashSet<>();
+ Metapb.Partition partition = null;
+ while ((partition == null || partition.getEndKey() < endKey)
+ && startKey < PartitionUtils.MAX_VALUE) {
+ KVPair partShard =
+ pdClient.getPartitionByCode(graphName, startKey);
+ if (partShard != null) {
+ partition = partShard.getKey();
+ Metapb.Shard leader = partShard.getValue();
+ partitions.add(HgNodePartition.of(leader.getStoreId(), startKey,
+ (int) partition.getStartKey(), (int) partition.getEndKey()));
+ startKey = (int) partition.getEndKey();
+ } else {
+ break;
+ }
+ }
+ builder.setPartitions(partitions);
+ } catch (PDException e) {
+ log.error("An error occurred while getting partition information :{}", e.getMessage());
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ return 0;
+ }
+
+
+ @Override
+ public int partition(HgNodePartitionerBuilder builder, String graphName,
+ int partitionId) {
+ try {
+ HashSet partitions = new HashSet<>();
+ Metapb.Partition partition = null;
+
+ KVPair partShard =
+ pdClient.getPartitionById(graphName, partitionId);
+ if (partShard != null) {
+ partition = partShard.getKey();
+ Metapb.Shard leader = partShard.getValue();
+ partitions.add(HgNodePartition.of(leader.getStoreId(), (int) partition.getStartKey()));
+ }
+ builder.setPartitions(partitions);
+ } catch (PDException e) {
+ log.error("An error occurred while getting partition information :{}", e.getMessage());
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ return 0;
+ }
+ /**
+ * 查询hgstore信息
+ *
+ * @return hgstore
+ */
+ @Override
+ public HgStoreNode apply(String graphName, Long nodeId) {
+ try {
+ Metapb.Store store = pdClient.getStore(nodeId);
+ return nodeManager.getNodeBuilder().setNodeId(store.getId())
+ .setAddress(store.getAddress()).build();
+ } catch (PDException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 通知更新缓存
+ */
+ @Override
+ public int notice(String graphName, HgStoreNotice storeNotice) {
+ log.warn(storeNotice.toString());
+ if (storeNotice.getPartitionLeaders() != null) {
+ storeNotice.getPartitionLeaders().forEach((partId, leader) -> {
+ pdClient.updatePartitionLeader(graphName, partId, leader);
+ log.warn("updatePartitionLeader:{}-{}-{}",
+ graphName, partId, leader);
+ });
+ }
+ if (storeNotice.getPartitionIds() != null) {
+ storeNotice.getPartitionIds().forEach(partId -> {
+ pdClient.invalidPartitionCache(graphName, partId);
+ });
+ }
+ if (!storeNotice.getNodeStatus().equals(
+ HgNodeStatus.PARTITION_COMMON_FAULT)
+ && !storeNotice.getNodeStatus().equals(
+ HgNodeStatus.NOT_PARTITION_LEADER)) {
+ pdClient.invalidPartitionCache();
+ log.warn("invalidPartitionCache:{} ", storeNotice.getNodeStatus());
+ }
+ return 0;
+ }
+
+ public Metapb.Graph delGraph(String graphName) {
+ try {
+ return pdClient.delGraph(graphName);
+ } catch (PDException e) {
+ log.error("delGraph {} exception, {}", graphName, e.getMessage());
+ }
+ return null;
+ }
+
+ public void setNodeManager(HgStoreNodeManager nodeManager) {
+ this.nodeManager = nodeManager;
+ }
+}
+
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeProvider.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeProvider.java
new file mode 100644
index 000000000..9775ce6f8
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeProvider.java
@@ -0,0 +1,16 @@
+package com.baidu.hugegraph.store.client;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/27
+ */
+public interface HgStoreNodeProvider {
+
+ /**
+ * Applying a new HgStoreNode instance
+ * @param graphName
+ * @param nodeId
+ * @return
+ */
+ HgStoreNode apply(String graphName, Long nodeId);
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeSession.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeSession.java
new file mode 100644
index 000000000..c1565da4b
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNodeSession.java
@@ -0,0 +1,24 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgStoreSession;
+
+/**
+ * @version 0.1.0
+ * @author lynn.bond@hotmail.com created on 2021/10/11
+ */
+public interface HgStoreNodeSession extends HgStoreSession {
+
+ /**
+ * Return the name of graph.
+ * @return
+ */
+ String getGraphName();
+
+ /**
+ * Return an instance of HgStoreNode, which provided the connection of Store-Node machine.
+ * @return
+ */
+ HgStoreNode getStoreNode();
+
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNotice.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNotice.java
new file mode 100644
index 000000000..627b8a872
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreNotice.java
@@ -0,0 +1,82 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.client.type.HgNodeStatus;
+import com.baidu.hugegraph.store.client.util.HgAssert;
+
+import javax.annotation.concurrent.NotThreadSafe;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author lynn.bond@hotmail.com on 2021/11/16
+ */
+@NotThreadSafe
+public class HgStoreNotice {
+ private Long nodeId;
+ private HgNodeStatus nodeStatus;
+ private String message;
+ private Map partitionLeaders;
+ private List partitionIds;
+
+ public static HgStoreNotice of(Long nodeId, HgNodeStatus nodeStatus) {
+ HgAssert.isArgumentNotNull(nodeId, "nodeId");
+ HgAssert.isArgumentNotNull(nodeStatus, "nodeStatus");
+ return new HgStoreNotice(nodeId, nodeStatus, "");
+ }
+
+ public static HgStoreNotice of(Long nodeId, HgNodeStatus nodeStatus, String message) {
+ HgAssert.isArgumentNotNull(nodeId, "nodeId");
+ HgAssert.isArgumentNotNull(nodeStatus, "nodeStatus");
+ HgAssert.isArgumentNotNull(message, "message");
+
+ return new HgStoreNotice(nodeId, nodeStatus, message);
+ }
+
+ private HgStoreNotice(Long nodeId, HgNodeStatus nodeStatus, String message) {
+ this.nodeId = nodeId;
+ this.nodeStatus = nodeStatus;
+ this.message = message;
+ }
+
+ public Long getNodeId() {
+ return nodeId;
+ }
+
+ public HgNodeStatus getNodeStatus() {
+ return nodeStatus;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public Map getPartitionLeaders() {
+ return partitionLeaders;
+ }
+
+ public HgStoreNotice setPartitionLeaders(Map partitionLeaders) {
+ this.partitionLeaders = partitionLeaders;
+ return this;
+ }
+
+ public List getPartitionIds() {
+ return partitionIds;
+ }
+
+ public HgStoreNotice setPartitionIds(List partitionIds) {
+ this.partitionIds = partitionIds;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "HgStoreNotice{" +
+ "nodeId=" + nodeId +
+ ", nodeStatus=" + nodeStatus +
+ ", message='" + message + '\'' +
+ ", partitionLeaders=" + partitionLeaders +
+ ", partitionIds=" + partitionIds +
+ '}';
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreService.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreService.java
new file mode 100644
index 000000000..0ce220655
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreService.java
@@ -0,0 +1,13 @@
+package com.baidu.hugegraph.store.client;
+
+
+public class HgStoreService {
+ private static HgStoreService instance=new HgStoreService();
+ private HgStoreService(){}
+
+ static HgStoreService of(){
+ return instance;
+ }
+
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreSessionProvider.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreSessionProvider.java
new file mode 100644
index 000000000..0e8d2c637
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgStoreSessionProvider.java
@@ -0,0 +1,19 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgSessionProvider;
+import com.baidu.hugegraph.store.HgStoreSession;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ */
+@ThreadSafe
+public class HgStoreSessionProvider implements HgSessionProvider {
+ private MultiNodeSessionFactory sessionFactory=MultiNodeSessionFactory.getInstance();
+
+ @Override
+ public HgStoreSession createSession(String graphName) {
+ return this.sessionFactory.createStoreSession(graphName);
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTkvEntryImpl.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTkvEntryImpl.java
new file mode 100644
index 000000000..f51d37f86
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTkvEntryImpl.java
@@ -0,0 +1,63 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgTkvEntry;
+import com.baidu.hugegraph.store.HgTokvEntry;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/14
+ */
+class HgTkvEntryImpl implements HgTkvEntry {
+ private String table;
+ private byte[] key;
+ private byte[] value;
+
+ HgTkvEntryImpl(String table, byte[] key, byte[] value) {
+ this.table = table;
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public String table() {
+ return this.table;
+ }
+
+ @Override
+ public byte[] key() {
+ return this.key;
+ }
+
+ @Override
+ public byte[] value() {
+ return this.value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ HgTkvEntryImpl that = (HgTkvEntryImpl) o;
+ return Objects.equals(table, that.table) && Arrays.equals(key, that.key) && Arrays.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(table);
+ result = 31 * result + Arrays.hashCode(key);
+ result = 31 * result + Arrays.hashCode(value);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "HgTkvEntryImpl{" +
+ "table='" + table + '\'' +
+ ", key=" + Arrays.toString(key) +
+ ", value=" + Arrays.toString(value) +
+ '}';
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTokvEntryImpl.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTokvEntryImpl.java
new file mode 100644
index 000000000..2fc9255b0
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/HgTokvEntryImpl.java
@@ -0,0 +1,62 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgTokvEntry;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/14
+ */
+class HgTokvEntryImpl implements HgTokvEntry {
+
+ private String table;
+ private HgOwnerKey ownerKey;
+ private byte[] value;
+
+ HgTokvEntryImpl(String table, HgOwnerKey ownerKey, byte[] value) {
+ this.table = table;
+ this.ownerKey = ownerKey;
+ this.value = value;
+ }
+
+ @Override
+ public String table() {
+ return this.table;
+ }
+
+ @Override
+ public HgOwnerKey ownerKey() {
+ return this.ownerKey;
+ }
+
+ @Override
+ public byte[] value() {
+ return this.value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ HgTokvEntryImpl that = (HgTokvEntryImpl) o;
+ return Objects.equals(table, that.table) && Objects.equals(ownerKey, that.ownerKey) && Arrays.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(table, ownerKey);
+ result = 31 * result + Arrays.hashCode(value);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "HgTokvEntryImpl{" +
+ "table='" + table + '\'' +
+ ", okv=" + ownerKey +
+ ", value=" + Arrays.toString(value) +
+ '}';
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/MultiNodeSessionFactory.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/MultiNodeSessionFactory.java
new file mode 100644
index 000000000..6fa80d8c2
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/MultiNodeSessionFactory.java
@@ -0,0 +1,39 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgStoreSession;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.util.List;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/12
+ */
+@ThreadSafe
+public final class MultiNodeSessionFactory {
+ // TODO multi-instance ?
+ private final static MultiNodeSessionFactory instance = new MultiNodeSessionFactory();
+ // TODO multi-instance ?
+ private HgStoreNodeManager nodeManager = HgStoreNodeManager.getInstance();
+ // TODO: to be a chain assigned to each graph
+ //private HgStoreNodeDispatcher storeNodeDispatcher;
+
+ private MultiNodeSessionFactory() {
+
+ //this.storeNodeDispatcher = new KeyHashStoreNodeDispatcher();
+ }
+
+ static MultiNodeSessionFactory getInstance() {
+ return instance;
+ }
+
+ HgStoreSession createStoreSession(String graphName) {
+ return buildProxy(graphName);
+ }
+
+ private HgStoreSession buildProxy(String graphName) {
+ //return new MultiNodeSessionProxy(graphName, nodeManager, storeNodeDispatcher);
+ //return new NodePartitionSessionProxy(graphName,nodeManager);
+ //return new NodeRetrySessionProxy(graphName,nodeManager);
+ return new NodeTxSessionProxy(graphName, nodeManager);
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTkv.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTkv.java
new file mode 100644
index 000000000..a081478fb
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTkv.java
@@ -0,0 +1,99 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgStoreSession;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/26
+ */
+@ThreadSafe
+class NodeTkv {
+ private final HgNodePartition nodePartition;
+ private final String table;
+ private final HgOwnerKey key;
+ private final HgOwnerKey endKey;
+ private HgStoreSession session;
+ NodeTkv(HgNodePartition nodePartition, String table, HgOwnerKey key) {
+ this.nodePartition = nodePartition;
+ this.table = table;
+ this.key = key;
+ this.endKey = key;
+ this.key.setKeyCode(this.nodePartition.getKeyCode());
+ }
+ NodeTkv(HgNodePartition nodePartition, String table, HgOwnerKey key, int keyCode) {
+ this.nodePartition = nodePartition;
+ this.table = table;
+ this.key = key;
+ this.endKey = key;
+
+ this.key.setKeyCode(keyCode);
+ }
+ NodeTkv(HgNodePartition nodePartition, String table, HgOwnerKey startKey,
+ HgOwnerKey endKey) {
+ this.nodePartition = nodePartition;
+ this.table = table;
+ this.key = startKey;
+ this.endKey = endKey;
+ this.key.setKeyCode(nodePartition.getStartKey());
+ this.endKey.setKeyCode(nodePartition.getEndKey());
+ }
+
+ public Long getNodeId() {
+ return this.nodePartition.getNodeId();
+ }
+
+ public String getTable() {
+ return table;
+ }
+
+ public HgOwnerKey getKey() {
+ return key;
+ }
+
+ public HgOwnerKey getEndKey() {
+ return endKey;
+ }
+
+ public NodeTkv setKeyCode(int code){
+ this.key.setKeyCode(code);
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NodeTkv nptKv = (NodeTkv) o;
+ return Objects.equals(nodePartition, nptKv.nodePartition) && Objects.equals(table, nptKv.table)
+ && Objects.equals(key, nptKv.key)
+ && Objects.equals(endKey, nptKv.endKey);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(nodePartition, table, key, endKey);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "NptKv{" +
+ "nodePartition=" + nodePartition +
+ ", table='" + table + '\'' +
+ ", key=" + key +
+ ", endKey=" + endKey +
+ '}';
+ }
+
+ public HgStoreSession getSession() {
+ return session;
+ }
+
+ public void setSession(HgStoreSession session) {
+ this.session = session;
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxExecutor.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxExecutor.java
new file mode 100644
index 000000000..888d558a0
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxExecutor.java
@@ -0,0 +1,401 @@
+package com.baidu.hugegraph.store.client;
+
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.EMPTY_LIST;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.NODE_MAX_RETRYING_TIMES;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.TX_SESSIONS_MAP_CAPACITY;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgStoreSession;
+import com.baidu.hugegraph.store.client.type.HgStoreClientException;
+import com.baidu.hugegraph.store.client.util.HgAssert;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+import com.baidu.hugegraph.store.term.HgPair;
+import com.baidu.hugegraph.store.term.HgTriple;
+
+import lombok.extern.slf4j.Slf4j;
+
+
+/**
+ * @author lynn.bond@hotmail.com on 2021/11/18
+ */
+@Slf4j
+@NotThreadSafe
+final class NodeTxExecutor {
+ private String graphName;
+ private Map sessions = new HashMap<>(TX_SESSIONS_MAP_CAPACITY, 1);
+ private boolean isTx;
+ NodeTxSessionProxy proxy;
+ private List,
+ Function>> entries = new LinkedList<>();
+ Collector>> collector = Collectors.groupingBy(
+ nkv -> nkv.getNodeId(), Collectors.mapping(NodeTkv::getKey, Collectors.toList()));
+ private static String maxTryMsg = "the number of retries reached the upper limit : " + NODE_MAX_RETRYING_TIMES +
+ ",caused by:";
+ private static String msg = "Not all tx-data delivered to real-node-session successfully.";
+ static {
+ System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism",
+ String.valueOf(Runtime.getRuntime().availableProcessors() * 2));
+ }
+
+
+
+ static NodeTxExecutor graphOf(String graphName, NodeTxSessionProxy proxy) {
+ return new NodeTxExecutor(graphName, proxy);
+ }
+
+ private NodeTxExecutor(String graphName, NodeTxSessionProxy proxy) {
+ this.graphName = graphName;
+ this.proxy = proxy;
+ }
+
+ public boolean isTx() {
+ return isTx;
+ }
+
+ void setTx(boolean tx) {
+ isTx = tx;
+ }
+
+ void commitTx() {
+ if (!this.isTx) {
+ throw new IllegalStateException("It's not in tx state");
+ }
+
+ this.doCommit();
+ }
+
+ void rollbackTx() {
+ if (!this.isTx) {
+ return;
+ }
+ try {
+ this.sessions.values().stream().filter(HgStoreSession::isTx)
+ .forEach(HgStoreSession::rollback);
+ } catch (Throwable t) {
+ throw t;
+ } finally {
+ this.isTx = false;
+ this.sessions.clear();
+ }
+ }
+
+ void doCommit() {
+ try {
+ this.retryingInvoke(() -> {
+ if (this.entries.isEmpty()) {
+ return true;
+ }
+ AtomicBoolean allSuccess = new AtomicBoolean(true);
+ for (HgPair, Function> e : this.entries) {
+ doAction(e.getKey(), e.getValue());
+ }
+ if (!allSuccess.get()) {
+ throw HgStoreClientException.of(msg);
+ }
+ AtomicReference throwable = new AtomicReference<>();
+ Collection sessions = this.sessions.values();
+ sessions.parallelStream().forEach(e -> {
+ if (e.isTx()) {
+ try {
+ e.commit();
+ } catch (Throwable t) {
+ throwable.compareAndSet(null, t);
+ allSuccess.set(false);
+ }
+ }
+ });
+ if (!allSuccess.get()) {
+ if (isTx) {
+ try {
+ sessions.stream().forEach(HgStoreSession::rollback);
+ } catch (Exception e) {
+
+ }
+ }
+ Throwable cause = throwable.get();
+ if (cause.getCause() != null) {
+ cause = cause.getCause();
+ }
+ if (cause instanceof HgStoreClientException) {
+ throw (HgStoreClientException) cause;
+ }
+ throw HgStoreClientException.of(cause);
+ }
+ return true;
+ });
+
+ } catch (Throwable t) {
+ throw t;
+ } finally {
+ this.isTx = false;
+ this.entries = new LinkedList<>();
+ this.sessions = new HashMap<>(TX_SESSIONS_MAP_CAPACITY, 1);
+ }
+ }
+
+ // private Function,
+ // List>> nodeStreamWrapper = nodeParams -> {
+ // if (nodeParams.getZ() == null) {
+ // return this.proxy.getNode(nodeParams.getX(),
+ // nodeParams.getY());
+ // } else {
+ // if (nodeParams.getZ() instanceof HgOwnerKey) {
+ // return this.proxy.getNode(nodeParams.getX(),
+ // nodeParams.getY(),
+ // (HgOwnerKey) nodeParams.getZ());
+ // } if ( nodeParams.getZ() instanceof Integer ){
+ // return this.proxy.doPartition(nodeParams.getX(), (Integer) nodeParams.getZ())
+ // .stream()
+ // .map(e -> new NodeTkv(e, nodeParams.getX(), nodeParams.getY(), nodeParams.getY()
+ // .getKeyCode()))
+ // .map(
+ // e -> new HgPair<>(this.proxy.getStoreNode(e.getNodeId()), e)
+ // );
+ // }else {
+ // HgAssert.isTrue(nodeParams.getZ() instanceof byte[],
+ // "Illegal parameter to get node id");
+ // throw new NotImplementedException();
+ // }
+ // }
+ // };
+
+ // private Function,
+ // List>> nodeStreamWrapper = nodeParams -> {
+ // if (nodeParams.getZ() == null) {
+ // return this.proxy.getNode(nodeParams.getX(), nodeParams.getY());
+ // } else {
+ // if (nodeParams.getZ() instanceof HgOwnerKey) {
+ // return this.proxy.getNode(nodeParams.getX(), nodeParams.getY(),
+ // (HgOwnerKey) nodeParams.getZ());
+ // }
+ // if (nodeParams.getZ() instanceof Integer) {
+ // Collection nodePartitions = this.proxy.doPartition(nodeParams.getX(),
+ // (Integer) nodeParams.getZ());
+ // ArrayList> hgPairs = new ArrayList<>(nodePartitions.size());
+ // for (HgNodePartition nodePartition : nodePartitions) {
+ // NodeTkv nodeTkv = new NodeTkv(nodePartition, nodeParams.getX(), nodeParams.getY(),
+ // nodeParams.getY().getKeyCode());
+ // hgPairs.add(new HgPair<>(this.proxy.getStoreNode(nodeTkv.getNodeId()), nodeTkv));
+ //
+ // }
+ // return hgPairs;
+ // } else {
+ // HgAssert.isTrue(nodeParams.getZ() instanceof byte[], "Illegal parameter to get node id");
+ // throw new RuntimeException("not implemented");
+ // }
+ // }
+ // };
+
+ private boolean doAction(HgTriple nodeParams,
+ Function action) {
+ if (nodeParams.getZ() == null) {
+ return this.proxy.doAction(nodeParams.getX(), nodeParams.getY(), nodeParams.getY(), action);
+ } else {
+ if (nodeParams.getZ() instanceof HgOwnerKey) {
+ boolean result = this.proxy.doAction(nodeParams.getX(), nodeParams.getY(),
+ (HgOwnerKey) nodeParams.getZ(), action);
+ return result;
+ }
+ if (nodeParams.getZ() instanceof Integer) {
+ return this.proxy.doAction(nodeParams.getX(), nodeParams.getY(), (Integer) nodeParams.getZ(), action);
+ } else {
+ HgAssert.isTrue(nodeParams.getZ() instanceof byte[], "Illegal parameter to get node id");
+ throw new RuntimeException("not implemented");
+ }
+ }
+ }
+
+ boolean prepareTx(HgTriple nodeParams,
+ Function sessionMapper) {
+ if (this.isTx) {
+ return this.entries.add(new HgPair(nodeParams, sessionMapper));
+ } else {
+ return this.isAllTrue(nodeParams, sessionMapper);
+ }
+ }
+
+ public HgStoreSession openNodeSession(HgStoreNode node) {
+ HgStoreSession res = this.sessions.get(node.getNodeId());
+ if (res == null) {
+ this.sessions.put(node.getNodeId(), (res = node.openSession(this.graphName)));
+ }
+ if (this.isTx) {
+ res.beginTx();
+ }
+
+ return res;
+ }
+
+ R limitOne(
+ Supplier>> nodeStreamSupplier,
+ Function, R> sessionMapper, R emptyObj) {
+
+ Optional res = retryingInvoke(
+ () -> nodeStreamSupplier.get()
+ .parallel()
+ .map(
+ pair -> new SessionData(
+ openNodeSession(pair.getKey()),
+ pair.getValue())
+ ).map(sessionMapper)
+ .filter(
+ r -> isValid(r)
+ )
+ .findAny()
+ .orElseGet(() -> emptyObj)
+ );
+ return res.orElse(emptyObj);
+ }
+
+ List toList(Function nodeFunction
+ , List keyList
+ , Function> flatMapper
+ , Function>, List> sessionMapper) {
+ Optional> res = retryingInvoke(
+ () -> keyList.stream()
+ .flatMap(flatMapper)
+ .collect(collector)
+ .entrySet()
+ .stream()
+ .map(
+ e -> new SessionData>
+ (
+ openNodeSession(nodeFunction.apply(e.getKey())), e.getValue()
+ )
+ )
+ .parallel()
+ .map(sessionMapper)
+ .flatMap(
+ e -> e.stream()
+ )
+ //.distinct()
+ .collect(Collectors.toList())
+ );
+
+ return res.orElse(EMPTY_LIST);
+ }
+
+ private boolean isAllTrue(HgTriple nodeParams,
+ Function action) {
+ Optional res = retryingInvoke(() -> doAction(nodeParams, action));
+ return res.orElse(false);
+ }
+
+ boolean isAllTrue(Supplier>> dataSource,
+ Function, Boolean> action) {
+ Optional res = retryingInvoke(
+ () -> dataSource.get()
+ .parallel()
+ .map(
+ pair -> new SessionData(
+ openNodeSession(pair.getKey()),
+ pair.getValue())
+ ).map(action)
+ .allMatch(Boolean::booleanValue)
+ );
+
+ return res.orElse(false);
+ }
+
+ boolean ifAnyTrue(Supplier>> nodeStreamSupplier
+ , Function, Boolean> sessionMapper) {
+
+ Optional res = retryingInvoke(
+ () -> nodeStreamSupplier.get()
+ .parallel()
+ .map(
+ pair -> new SessionData(
+ openNodeSession(pair.getKey()),
+ pair.getValue())
+ )
+ .map(sessionMapper)
+ .anyMatch(Boolean::booleanValue)
+ );
+
+ return res.orElse(false);
+ }
+
+ Optional retryingInvoke(Supplier supplier) {
+ return IntStream.rangeClosed(0, NODE_MAX_RETRYING_TIMES).boxed()
+ .map(
+ i -> {
+ T buffer = null;
+ try {
+ buffer = supplier.get();
+ } catch (Throwable t) {
+ if (i + 1 <= NODE_MAX_RETRYING_TIMES) {
+ try {
+ int sleepTime;
+ // 前三次每隔一秒做一次尝试
+ if (i < 3) {
+ sleepTime = 1;
+ } else {
+ // 后面逐次递增
+ sleepTime = i - 1;
+ }
+ log.info("Waiting {} seconds " +
+ "for the next try.",
+ sleepTime);
+ Thread.sleep(sleepTime * 1000L);
+ } catch (InterruptedException e) {
+ log.error("Failed to sleep", e);
+ }
+ } else {
+ log.error(maxTryMsg, t);
+ throw HgStoreClientException.of(
+ t.getMessage(), t);
+ }
+ }
+ return buffer;
+ }
+ )
+ .filter(e -> e != null)
+ .findFirst();
+
+ }
+
+ private boolean isValid(Object obj) {
+ if (obj == null) return false;
+
+ if (HgStoreClientConst.EMPTY_BYTES.equals(obj)) {
+ return false;
+ }
+
+ if (EMPTY_LIST.equals(obj)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ class SessionData {
+ HgStoreSession session;
+ T data;
+
+ SessionData(HgStoreSession session, T data) {
+ this.session = session;
+ this.data = data;
+ }
+
+ }
+}
+
+
+
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxSessionProxy.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxSessionProxy.java
new file mode 100644
index 000000000..78b3e0c1b
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/NodeTxSessionProxy.java
@@ -0,0 +1,837 @@
+package com.baidu.hugegraph.store.client;
+
+import static com.baidu.hugegraph.store.client.util.HgAssert.isArgumentNotNull;
+import static com.baidu.hugegraph.store.client.util.HgAssert.isArgumentValid;
+import static com.baidu.hugegraph.store.client.util.HgAssert.isFalse;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientConst.EMPTY_STRING;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientUtil.err;
+import static com.baidu.hugegraph.store.client.util.HgStoreClientUtil.toStr;
+import static java.util.stream.Collectors.groupingBy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgKvIterator;
+import com.baidu.hugegraph.store.HgKvOrderedIterator;
+import com.baidu.hugegraph.store.HgOwnerKey;
+import com.baidu.hugegraph.store.HgScanQuery;
+import com.baidu.hugegraph.store.HgStoreSession;
+import com.baidu.hugegraph.store.client.grpc.KvBatchScanner;
+import com.baidu.hugegraph.store.client.grpc.KvCloseableIterator;
+import com.baidu.hugegraph.store.client.util.HgAssert;
+import com.baidu.hugegraph.store.client.util.HgStoreClientConst;
+import com.baidu.hugegraph.store.client.util.HgStoreClientUtil;
+import com.baidu.hugegraph.store.grpc.stream.ScanStreamReq.Builder;
+import com.baidu.hugegraph.store.term.HgPair;
+import com.baidu.hugegraph.store.term.HgTriple;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2022/01/19
+ * @version 0.6.0 added batch scan on 2022/03/03
+ */
+@Slf4j
+@NotThreadSafe
+class NodeTxSessionProxy implements HgStoreSession {
+ private final HgStoreNodeManager nodeManager;
+ private final HgStoreNodePartitioner nodePartitioner;
+ private final String graphName;
+ private final NodeTxExecutor txExecutor;
+
+ NodeTxSessionProxy(String graphName, HgStoreNodeManager nodeManager) {
+ this.nodeManager = nodeManager;
+ this.graphName = graphName;
+ this.nodePartitioner = this.nodeManager.getNodePartitioner();
+ this.txExecutor = NodeTxExecutor.graphOf(this.graphName, this);
+
+ isFalse(this.nodePartitioner == null,
+ "Failed to retrieve the node-partitioner from node-manager.");
+ }
+
+ @Override
+ public void beginTx() {
+ this.txExecutor.setTx(true);
+ }
+
+ @Override
+ public void commit() {
+ this.txExecutor.commitTx();
+ }
+
+ @Override
+ public void rollback() {
+ this.txExecutor.rollbackTx();
+ }
+
+ @Override
+ public boolean isTx() {
+ return this.txExecutor.isTx();
+ }
+
+ @Override
+ public boolean put(String table, HgOwnerKey ownerKey, byte[] value) {
+ // isArgumentValid(table, "table");
+ // isArgumentNotNull(ownerKey, "ownerKey");
+ // log.info("put -> graph: {}, table: {}, key: {}, value: {}",
+ // graphName, table, ownerKey, toByteStr(value));
+ // return this.txExecutor.prepareTx(
+ // () -> getNodeStream(table, ownerKey),
+ // e -> e.session.put(table, e.data.getKey(), value)
+ // );
+ return this.txExecutor.prepareTx(new HgTriple(table, ownerKey, null),
+ e -> e.getSession().put(table,
+ e.getKey(),
+ value));
+ }
+
+ @Override
+ public boolean directPut(String table, int partitionId, HgOwnerKey ownerKey, byte[] value) {
+ isArgumentValid(table, "table");
+ isArgumentNotNull(ownerKey, "ownerKey");
+
+ return this.txExecutor.prepareTx(
+ new HgTriple(table, ownerKey, (Integer) partitionId),
+ e -> e.getSession().put(table, e.getKey(), value)
+ );
+ }
+
+ @Override
+ public boolean delete(String table, HgOwnerKey ownerKey) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(ownerKey == null, "The argument is invalid: ownerKey");
+
+ if (log.isDebugEnabled()) {
+ log.debug("delete -> graph: {}, table: {}, key: {}"
+ , graphName, table, toStr(ownerKey));
+ }
+
+ return this.txExecutor
+ .prepareTx(
+ new HgTriple(table, ownerKey, null),
+ e -> e.getSession().delete(table, e.getKey())
+ );
+ }
+
+
+ @Override
+ public boolean deleteSingle(String table, HgOwnerKey ownerKey) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(ownerKey == null, "The argument is invalid: ownerKey");
+
+ if (log.isDebugEnabled()) {
+ log.debug("deleteSingle -> graph: {}, table: {}, key: {}"
+ , graphName, table, toStr(ownerKey));
+ }
+
+ return this.txExecutor
+ .prepareTx(
+ new HgTriple(table, ownerKey, null),
+ e -> e.getSession().deleteSingle(table, e.getKey())
+ );
+ }
+
+
+ @Override
+ public boolean deletePrefix(String table, HgOwnerKey prefix) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(prefix == null, "The argument is invalid: prefix");
+
+ if (log.isDebugEnabled()) {
+ log.debug("deletePrefix -> graph: {}, table: {}, prefix: {}"
+ , graphName, table, toStr(prefix));
+ }
+
+ return this.txExecutor
+ .prepareTx(
+ new HgTriple(table, prefix, null),
+ e -> e.getSession().deletePrefix(table, e.getKey())
+ );
+ }
+
+
+ @Override
+ public boolean deleteRange(String table, HgOwnerKey start, HgOwnerKey end) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(start == null, "The argument is invalid: start");
+ HgAssert.isFalse(end == null, "The argument is invalid: end");
+
+ if (log.isDebugEnabled()) {
+ log.debug("deleteRange -> graph: {}, table: {}, start: {}, end: {}"
+ , graphName, table, toStr(start), toStr(end));
+ }
+
+ return this.txExecutor
+ .prepareTx(
+ new HgTriple(table, start, end),
+ e -> e.getSession().deleteRange(table, e.getKey(), e.getEndKey())
+ );
+ }
+
+ @Override
+ public boolean merge(String table, HgOwnerKey key, byte[] value) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(key == null, "The argument is invalid: key");
+ HgAssert.isFalse(value == null, "The argument is invalid: value");
+
+ if (log.isDebugEnabled()) {
+ log.debug("merge -> graph: {}, table: {}, key: {}, value: {}"
+ , graphName, table, toStr(key), toStr(value));
+ }
+
+ return this.txExecutor
+ .prepareTx(
+ new HgTriple(table, key, value),
+ e -> e.getSession().merge(table, e.getKey(), value)
+ );
+ }
+
+ /*--- tx end ---*/
+
+ @Override
+ public byte[] get(String table, HgOwnerKey ownerKey) {
+ isArgumentValid(table, "table");
+ isArgumentNotNull(ownerKey, "ownerKey");
+
+ return this.txExecutor
+ .limitOne(
+ () -> this.getNodeStream(table, ownerKey),
+ e -> e.session.get(table, e.data.getKey()), HgStoreClientConst.EMPTY_BYTES
+ );
+ }
+
+ @Override
+ public boolean clean(int partId) {
+ Collection nodes = this.doPartition("", partId);
+ return nodes.parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .clean(partId)
+ ).findFirst().get();
+ }
+
+ @Override
+ @Deprecated
+ public List batchGetOwner(String table, List keyList) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(HgAssert.isInvalid(keyList), "The argument is invalid: keyList");
+
+ return this.txExecutor
+ .toList(
+ (l) -> this.getStoreNode(l),
+ keyList,
+ key -> this.toNodeTkvList(table, key, key).stream(),
+ e -> e.session.batchGetOwner(table, e.data)
+ );
+ }
+
+ @Override
+ public HgKvIterator batchPrefix(String table, List keyList) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(HgAssert.isInvalid(keyList), "The argument is invalid: keyList");
+ return this.toHgKvIteratorProxy(
+ this.txExecutor
+ .toList(
+ (l) -> this.getStoreNode(l),
+ keyList,
+ key -> this.toNodeTkvList(table, key, key).stream(),
+ e -> Collections.singletonList(e.session.batchPrefix(table, e.data))
+ )
+ , Long.MAX_VALUE);
+ }
+
+ @Override
+ public boolean truncate() {
+ return this.txExecutor
+ .isAllTrue(
+ () -> this.getNodeStream(EMPTY_STRING),
+ e -> e.session.truncate()
+ );
+ }
+
+ @Override
+ public boolean existsTable(String table) {
+ return this.txExecutor
+ .ifAnyTrue(
+ () -> this.getNodeStream(EMPTY_STRING),
+ e -> e.session.existsTable(table)
+ );
+ }
+
+ @Override
+ public boolean createTable(String table) {
+ return this.txExecutor
+ .isAllTrue(
+ () -> this.getNodeStream(EMPTY_STRING),
+ e -> e.session.createTable(table)
+ );
+ }
+
+ @Override
+ public boolean deleteTable(String table) {
+ return this.txExecutor
+ .isAllTrue(
+ () -> this.getNodeStream(EMPTY_STRING),
+ e -> e.session.deleteTable(table)
+ );
+ }
+
+ @Override
+ public boolean dropTable(String table) {
+ return this.txExecutor
+ .isAllTrue(
+ () -> this.getNodeStream(table),
+ e -> e.session.dropTable(table)
+ );
+ }
+
+ @Override
+ public boolean deleteGraph(String graph) {
+ return this.txExecutor
+ .isAllTrue(
+ () -> this.getNodeStream(EMPTY_STRING),
+ e -> e.session.deleteGraph(graph)
+ );
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table) {
+ return scanIterator(table, 0);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, byte[] query) {
+ return scanIterator(table, 0, query);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, long limit) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), limit)
+ )
+ .collect(Collectors.toList())
+ , limit);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, long limit, byte[] query) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), limit, query)
+ )
+ .collect(Collectors.toList())
+ , limit);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix) {
+ return scanIterator(table, keyPrefix, 0);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix, long limit) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(keyPrefix == null, "The argument is invalid: keyPrefix");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, keyPrefix)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), limit)
+ )
+ .collect(Collectors.toList())
+ , limit);
+
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey keyPrefix, long limit, byte[] query) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(keyPrefix == null, "The argument is invalid: keyPrefix");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, keyPrefix)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), limit, query)
+ )
+ .collect(Collectors.toList())
+ , limit);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey) {
+ return this.scanIterator(table, startKey, endKey, 0, null);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey, long limit) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(startKey == null, "The argument is invalid: startKey");
+ HgAssert.isFalse(endKey == null, "The argument is invalid: endKey");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, startKey, endKey)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), e.getEndKey(), limit)
+ )
+ .collect(Collectors.toList())
+ , limit);
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey
+ , long limit, byte[] query) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(startKey == null, "The argument is invalid: startKey");
+ HgAssert.isFalse(endKey == null, "The argument is invalid: endKey");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, startKey, endKey)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), e.getEndKey(), limit, query)
+ )
+ .collect(Collectors.toList())
+ , limit);
+
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, HgOwnerKey startKey, HgOwnerKey endKey
+ , long limit, int scanType, byte[] query) {
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ HgAssert.isFalse(startKey == null, "The argument is invalid: startKey");
+ HgAssert.isFalse(endKey == null, "The argument is invalid: endKey");
+
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, startKey, endKey)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable(), e.getKey(), e.getEndKey(), limit, scanType, query)
+ )
+ .collect(Collectors.toList())
+ , limit);
+
+ }
+
+ @Override
+ public HgKvIterator scanIterator(String table, int codeFrom, int codeTo, int scanType, byte[] query) {
+ if (log.isDebugEnabled()) {
+ log.debug("graph: {}, table: {}, codeFrom: {}, codeTo: {}, scanType: {}, query: {}"
+ , graphName, table, codeFrom, codeTo, scanType, HgStoreClientUtil.toStr(query));
+ }
+
+ HgAssert.isFalse(HgAssert.isInvalid(table), "The argument is invalid: table");
+ return this.toHgKvIteratorProxy(
+ this.toNodeTkvList(table, codeFrom, codeTo)
+ .parallelStream()
+ .map(
+ e -> this.getStoreNode(e.getNodeId()).openSession(this.graphName)
+ .scanIterator(e.getTable()
+ , e.getKey().getKeyCode()
+ , e.getEndKey().getKeyCode(),
+ scanType, query)
+ )
+ .collect(Collectors.toList())
+ , 0);
+
+ }
+
+ @Override
+ public HgKvIterator scanIterator(Builder scanReqBuilder) {
+ List nodeTKvs = this.toNodeTkvList(scanReqBuilder);
+ Function> hgKvIteratorFunction = e -> {
+ HgStoreSession session = this.getStoreNode(e.getNodeId())
+ .openSession(this.graphName);
+ return session.scanIterator(scanReqBuilder);
+ };
+ List iterators = nodeTKvs.parallelStream()
+ .map(hgKvIteratorFunction)
+ .collect(Collectors.toList());
+ return this.toHgKvIteratorProxy(iterators, scanReqBuilder.getLimit());
+ }
+
+ @Override
+ public List> scanBatch(HgScanQuery scanQuery) {
+ HgAssert.isArgumentNotNull(scanQuery, "scanQuery");
+
+ return this.toTkvMapFunc(scanQuery.getScanMethod())
+ .apply(scanQuery)
+ .entrySet()
+ .stream()
+ .map(e ->
+ this.getStoreNode(e.getKey())
+ .openSession(this.graphName)
+ .scanBatch(toScanQueryFunc(scanQuery.getScanMethod())
+ .apply(scanQuery.getTable(), e.getValue())
+ .setQuery(scanQuery.getQuery())
+ .setLimit(scanQuery.getLimit())
+ .setPerKeyLimit(scanQuery.getPerKeyLimit())
+ .setPerKeyMax((scanQuery.getPerKeyMax()))
+ .setScanType(scanQuery.getScanType())
+ .build()
+ )
+ )
+ //.peek(e->log.info("{}",e))
+ .flatMap(List::stream)
+ .collect(Collectors.toList());
+
+ }
+
+ @Override
+ public KvCloseableIterator> scanBatch2(HgScanQuery scanQuery) {
+ return scanBatch3(scanQuery, null);
+ }
+
+ @Override
+ public KvCloseableIterator> scanBatch3(HgScanQuery scanQuery,
+ KvCloseableIterator iterator) {
+ KvCloseableIterator notifierWrap = KvBatchScanner.ofMerger(scanQuery, (query, notifier) -> {
+ Map> nodeTkvs = this.toTkvMapFunc(scanQuery.getScanMethod())
+ .apply(query);
+
+ nodeTkvs.forEach((storeId, tkvs) -> {
+ this.getStoreNode(storeId)
+ .openSession(this.graphName)
+ .scanBatch3(toScanQueryFunc(scanQuery.getScanMethod())
+ .apply(scanQuery.getTable(), tkvs)
+ .setQuery(scanQuery.getQuery())
+ .setLimit(scanQuery.getLimit())
+ .setSkipDegree(scanQuery.getSkipDegree())
+ .setPerKeyLimit(scanQuery.getPerKeyLimit())
+ .setPerKeyMax((scanQuery.getPerKeyMax()))
+ .setScanType(scanQuery.getScanType())
+ .setOrderType(scanQuery.getOrderType())
+ .build(), notifier
+ );
+ });
+ return true;
+ });
+ return notifierWrap;
+ }
+
+ private Function>> toTkvMapFunc(HgScanQuery.ScanMethod scanMethod) {
+ switch (scanMethod) {
+ case RANGE:
+ return scanQuery -> {
+ List starts = scanQuery.getStartList();
+ List ends = scanQuery.getEndList();
+ int size = starts.size();
+ return IntStream.range(0, size)
+ .boxed()
+ .map(i -> this.toNodeTkvList(scanQuery.getTable(), starts.get(i), ends.get(i)))
+ .flatMap(List::stream)
+ .collect(groupingBy(NodeTkv::getNodeId));
+ };
+ case PREFIX:
+ return scanQuery ->
+ scanQuery.getPrefixList()
+ .stream()
+ .map(keyPrefix -> this.toNodeTkvList(scanQuery.getTable(), keyPrefix))
+ .flatMap(List::stream)
+ .collect(groupingBy(NodeTkv::getNodeId));
+
+ default:
+ return scanQuery -> this.toNodeTkvList(scanQuery.getTable())
+ .stream()
+ .collect(groupingBy(NodeTkv::getNodeId));
+ }
+ }
+
+ private BiFunction, HgScanQuery.ScanBuilder> toScanQueryFunc(
+ HgScanQuery.ScanMethod scanMethod) {
+ switch (scanMethod) {
+ case RANGE:
+ return (table, tkvList) -> {
+ List startList = new LinkedList();
+ List endList = new LinkedList();
+
+ tkvList.stream().forEach(e -> {
+ startList.add(e.getKey());
+ endList.add(e.getEndKey());
+ });
+
+ return HgScanQuery.ScanBuilder.rangeOf(table, startList, endList);
+ };
+ case PREFIX:
+ return (table, tkvList) ->
+ HgScanQuery.ScanBuilder.prefixOf(table,
+ tkvList.stream()
+ .map(e -> e.getKey())
+ .collect(Collectors.toList())
+ );
+ default:
+ return (table, tkvList) -> HgScanQuery.ScanBuilder.tableOf(table);
+ }
+
+ }
+
+ /*-- common --*/
+ private HgKvIterator toHgKvIteratorProxy(List iteratorList, long limit) {
+ boolean isAllOrderedLimiter = iteratorList.stream()
+ .allMatch(e -> HgKvOrderedIterator.class.isInstance(e));
+
+ HgKvIterator iterator;
+ if (isAllOrderedLimiter) {
+ iterator = new SequencedIterator(iteratorList.stream()
+ .map(e -> (HgKvOrderedIterator) e)
+ .collect(Collectors.toList()), limit);
+ } else {
+ iterator = new TopWorkIteratorProxy(iteratorList, limit);
+ }
+
+ return iterator;
+ }
+
+ HgStoreNode getStoreNode(Long nodeId) {
+ HgStoreNode res = this.nodeManager.applyNode(this.graphName, nodeId);
+
+ if (res == null) {
+ throw err("Failed to apply for an instance of HgStoreNode from node-manager.");
+ }
+
+ return res;
+ }
+
+ public boolean doAction(String table, HgOwnerKey startKey, HgOwnerKey endKey, Function action) {
+ Collection partitions = doPartition(table, startKey.getOwner(), endKey.getOwner());
+ for (HgNodePartition partition : partitions) {
+ HgStoreNode storeNode = this.getStoreNode(partition.getNodeId());
+ HgStoreSession session = this.txExecutor.openNodeSession(storeNode);
+ NodeTkv data = new NodeTkv(partition, table, startKey, endKey);
+ data.setSession(session);
+ if (!action.apply(data)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean doAction(String table, HgOwnerKey startKey, Integer code, Function action) {
+ Collection partitions = this.doPartition(table, code);
+ for (HgNodePartition partition : partitions) {
+ HgStoreNode storeNode = this.getStoreNode(partition.getNodeId());
+ HgStoreSession session = this.txExecutor.openNodeSession(storeNode);
+ NodeTkv data = new NodeTkv(partition, table, startKey, code);
+ data.setSession(session);
+ if (!action.apply(data)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private List toNodeTkvList(Builder scanReqBuilder) {
+ // TODO 使用builder获取owner
+ String table = scanReqBuilder.getTable();
+ HgOwnerKey ownerKey = HgStoreClientConst.ALL_PARTITION_OWNER_KEY;
+ byte[] allOwner = ownerKey.getOwner();
+ Collection partitions = doPartition(table,
+ allOwner,
+ allOwner);
+ List nodeTkvs = new ArrayList<>(partitions.size());
+ for (HgNodePartition partition : partitions) {
+ nodeTkvs.add(new NodeTkv(partition, table, ownerKey, ownerKey));
+ }
+ return nodeTkvs;
+ }
+
+ private List toNodeTkvList(String table) {
+ Collection partitions = doPartition(table,
+ HgStoreClientConst.ALL_PARTITION_OWNER_KEY.getOwner(),
+ HgStoreClientConst.ALL_PARTITION_OWNER_KEY.getOwner());
+ ArrayList nodeTkvs = new ArrayList<>(partitions.size());
+ for (HgNodePartition partition : partitions) {
+ nodeTkvs.add(new NodeTkv(partition, table, HgStoreClientConst.ALL_PARTITION_OWNER_KEY,
+ HgStoreClientConst.ALL_PARTITION_OWNER_KEY));
+ }
+ return nodeTkvs;
+ }
+
+ private List toNodeTkvList(String table, HgOwnerKey ownerKey) {
+ Collection partitions = doPartition(table, ownerKey.getOwner(), ownerKey.getOwner());
+ ArrayList nodeTkvs = new ArrayList<>(partitions.size());
+ for (HgNodePartition partition : partitions) {
+ nodeTkvs.add(new NodeTkv(partition, table, ownerKey, ownerKey));
+ }
+
+ return nodeTkvs;
+ }
+
+ private List toNodeTkvList(String table, HgOwnerKey startKey, HgOwnerKey endKey) {
+ Collection partitions = doPartition(table, startKey.getOwner(), endKey.getOwner());
+ ArrayList nodeTkvs = new ArrayList<>(partitions.size());
+ for (HgNodePartition partition : partitions) {
+ nodeTkvs.add(new NodeTkv(partition, table, startKey, endKey));
+ }
+ return nodeTkvs;
+ }
+
+
+ private List toNodeTkvList(String table, int startCode, int endCode) {
+ Collection partitions = this.doPartition(table, startCode, endCode);
+ ArrayList nodeTkvs = new ArrayList<>(partitions.size());
+ for (HgNodePartition partition : partitions) {
+ nodeTkvs.add(
+ new NodeTkv(partition, table, HgOwnerKey.codeOf(startCode), HgOwnerKey.codeOf(endCode)));
+ }
+ return nodeTkvs;
+ }
+ /**
+ * @return not null
+ */
+ private Collection doPartition(String table, byte[] startKey, byte[] endKey) {
+ HgNodePartitionerBuilder partitionerBuilder = HgNodePartitionerBuilder.resetAndGet();
+
+ int status = this.nodePartitioner.partition(partitionerBuilder, this.graphName, startKey, endKey);
+
+ if (status != 0) {
+ throw err("The node-partitioner is not work.");
+ }
+
+ Collection partitions = partitionerBuilder.getPartitions();
+
+ if (partitions.isEmpty()) {
+ throw err("Failed to get the collection of HgNodePartition from node-partitioner.");
+ }
+
+ return partitions;
+ }
+
+ /**
+ * @return @return not null
+ */
+ private Collection doPartition(String table, int startCode, int endCode) {
+ HgNodePartitionerBuilder partitionerBuilder = HgNodePartitionerBuilder.resetAndGet();
+ int status = this.nodePartitioner.partition(partitionerBuilder, this.graphName, startCode, endCode);
+
+ if (status != 0) {
+ throw err("The node-partitioner is not work.");
+ }
+
+ Collection partitions = partitionerBuilder.getPartitions();
+
+ if (partitions.isEmpty()) {
+ throw err("Failed to get the collection of HgNodePartition from node-partitioner.");
+ }
+
+ return partitions;
+ }
+
+ Collection doPartition(String table, int partitionId) {
+ HgNodePartitionerBuilder partitionerBuilder = HgNodePartitionerBuilder.resetAndGet();
+ int status = this.nodePartitioner.partition(partitionerBuilder, this.graphName, partitionId);
+
+ if (status != 0) {
+ throw err("The node-partitioner is not work.");
+ }
+
+ Collection partitions = partitionerBuilder.getPartitions();
+
+ if (partitions.isEmpty()) {
+ throw err("Failed to get the collection of HgNodePartition from node-partitioner.");
+ }
+
+ return partitions;
+ }
+ private Stream> getNodeStream(String table) {
+ return this.toNodeTkvList(table)
+ .stream()
+ .map(
+ e -> new HgPair<>(this.getStoreNode(e.getNodeId()), e)
+ );
+ }
+
+ Stream> getNodeStream(String table,
+ HgOwnerKey ownerKey) {
+ return this.toNodeTkvList(table, ownerKey)
+ .stream()
+ .map(
+ e -> new HgPair<>(this.getStoreNode(e.getNodeId()), e)
+ );
+ }
+
+ Stream> getNodeStream(String table, HgOwnerKey startKey, HgOwnerKey endKey) {
+ return this.toNodeTkvList(table, startKey, endKey)
+ .stream()
+ .map(
+ e -> new HgPair<>(this.getStoreNode(e.getNodeId()), e)
+ );
+
+ }
+
+ // private List> getNode(String table) {
+ // List nodeTkvList = this.toNodeTkvList(table);
+ // return nodeTkv2Node(nodeTkvList);
+ // }
+
+ List> getNode(String table, HgOwnerKey ownerKey) {
+ List nodeTkvList = this.toNodeTkvList(table, ownerKey);
+ return nodeTkv2Node(nodeTkvList);
+ }
+
+ List> getNode(String table, HgOwnerKey startKey, HgOwnerKey endKey) {
+ List nodeTkvList = this.toNodeTkvList(table, startKey, endKey);
+ return nodeTkv2Node(nodeTkvList);
+
+ }
+ //
+ //boolean doAction(String table, HgOwnerKey startKey, HgOwnerKey endKey,
+ // Function action) {
+ // return this.doAction(table, startKey, endKey, action);
+ //
+ //}
+
+ // List> getNode(String table, Integer endKey) {
+ // .stream()
+ // .map(e -> new NodeTkv(e, nodeParams.getX(), nodeParams.getY(), nodeParams.getY().getKeyCode()))
+ // .map(
+ // e -> new HgPair<>(this.proxy.getStoreNode(e.getNodeId()), e)
+ // );
+ // Collection nodePartitions = this.doPartition(table, endKey);
+ // for (HgNodePartition nodePartition: nodePartitions) {
+ //
+ // }
+ // return nodeTkv2Node(nodeTkvList);
+ //
+ // }
+
+ private List> nodeTkv2Node(Collection nodeTkvList) {
+ ArrayList> hgPairs = new ArrayList<>(nodeTkvList.size());
+ for (NodeTkv nodeTkv : nodeTkvList) {
+ hgPairs.add(new HgPair<>(this.getStoreNode(nodeTkv.getNodeId()), nodeTkv));
+ }
+ return hgPairs;
+ }
+
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/SequencedIterator.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/SequencedIterator.java
new file mode 100644
index 000000000..9c3e0a4cc
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/SequencedIterator.java
@@ -0,0 +1,133 @@
+package com.baidu.hugegraph.store.client;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgKvIterator;
+import com.baidu.hugegraph.store.HgKvOrderedIterator;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Proxy iterator orderly, to switch next one will happen when the current one is empty.
+ *
+ * @author lynn.bond@hotmail.com created on 2022/03/10
+ * @version 0.1.0
+ */
+@Slf4j
+public class SequencedIterator implements HgKvIterator {
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private HgKvOrderedIterator iterator;
+ private Queue queue;
+ private HgKvEntry entry;
+ private long limit;
+ private int count;
+ private byte[] position = EMPTY_BYTES;
+ private byte[] position4Seeking = EMPTY_BYTES;
+
+ SequencedIterator(List iterators, long limit) {
+ Collections.sort(iterators);
+ this.queue = new LinkedList(iterators);
+ this.limit = limit <= 0 ? Integer.MAX_VALUE : limit;
+ }
+
+ private HgKvOrderedIterator getIterator() {
+ if (this.queue.isEmpty()) return null;
+ HgKvOrderedIterator buf;
+ while ((buf = this.queue.poll()) != null) {
+ buf.seek(this.position4Seeking);
+ if (buf.hasNext()) {
+ break;
+ }
+ }
+ if (buf == null) {
+ return null;
+ }
+ return buf;
+ }
+
+ private void closeIterators() {
+ if (this.queue.isEmpty()) return;
+ HgKvOrderedIterator buf;
+ while ((buf = this.queue.poll()) != null) {
+ buf.close();
+ }
+
+ }
+
+ @Override
+ public byte[] key() {
+ if (this.entry != null) {
+ return this.entry.key();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] value() {
+ if (this.entry != null) {
+ return this.entry.value();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] position() {
+ return this.position;
+ }
+
+ @Override
+ public void seek(byte[] pos) {
+ if (pos != null) {
+ this.position4Seeking = pos;
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (this.count >= this.limit) {
+ return false;
+ }
+ if (this.iterator == null) {
+ this.iterator = this.getIterator();
+ } else if (!this.iterator.hasNext()) {
+ this.iterator.close();
+ this.iterator = this.getIterator();
+ }
+ if (this.iterator == null) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public Object next() {
+ if (this.iterator == null) {
+ hasNext();
+ }
+ if (this.iterator == null) {
+ throw new NoSuchElementException();
+ }
+ this.entry = this.iterator.next();
+ this.position = this.iterator.position();
+ if (!this.iterator.hasNext()) {
+ this.iterator.close();
+ this.iterator = null;
+ }
+ this.count++;
+ return this.entry;
+ }
+
+ @Override
+ public void close() {
+ if (this.iterator != null) {
+ this.iterator.close();
+ }
+ this.closeIterators();
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/ShiftWorkIteratorProxy.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/ShiftWorkIteratorProxy.java
new file mode 100644
index 000000000..795f13e0b
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/ShiftWorkIteratorProxy.java
@@ -0,0 +1,144 @@
+package com.baidu.hugegraph.store.client;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgKvIterator;
+import com.baidu.hugegraph.store.HgKvPagingIterator;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/24
+ * @version 0.1.1
+ */
+@Slf4j
+public class ShiftWorkIteratorProxy implements HgKvIterator {
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private HgKvPagingIterator iterator;
+ private Queue queue = new LinkedList<>();
+ private HgKvEntry entry;
+ private int limit;
+ private int count;
+ private int shiftCount;
+
+ ShiftWorkIteratorProxy(List iterators, int limit) {
+ this.queue = new LinkedList<>(iterators);
+ this.limit = limit <= 0 ? Integer.MAX_VALUE : limit;
+ }
+
+ private HgKvPagingIterator getIterator() {
+ if (this.queue.isEmpty()) return null;
+
+ HgKvPagingIterator buf = null;
+
+ while ((buf = this.queue.poll()) != null) {
+ if (buf.hasNext()) {
+ break;
+ }
+ }
+
+ if (buf == null) {
+ return null;
+ }
+
+ this.queue.add(buf);
+
+ return buf;
+ }
+
+ private void closeIterators() {
+ if (this.queue.isEmpty()) return;
+
+ HgKvPagingIterator buf;
+
+ while ((buf = this.queue.poll()) != null) {
+ buf.close();
+ }
+
+ }
+
+ private void setIterator() {
+
+ // if (++this.shiftCount >= this.iterator.getPageSize() / 2) {
+ if (++this.shiftCount >= this.iterator.getPageSize()) {
+ this.iterator = null;
+ this.shiftCount = 0;
+ }
+
+ }
+
+ private void doNext() {
+
+ }
+
+ @Override
+ public byte[] key() {
+ if (this.entry != null) {
+ return this.entry.key();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] value() {
+ if (this.entry != null) {
+ return this.entry.value();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] position() {
+ return this.iterator != null ? this.iterator.position() : EMPTY_BYTES;
+ }
+
+ @Override
+ public void seek(byte[] position) {
+ if (this.iterator != null) {
+ this.iterator.seek(position);
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (this.count >= this.limit) {
+ return false;
+ }
+ if (this.iterator == null
+ || !this.iterator.hasNext()) {
+ this.iterator = this.getIterator();
+ }
+ if (this.iterator == null) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public Object next() {
+ if (this.iterator == null) {
+ hasNext();
+ }
+ if (this.iterator == null) {
+ throw new NoSuchElementException();
+ }
+ this.entry = this.iterator.next();
+ this.setIterator();
+ this.count++;
+ //log.info("next - > {}",this.entry);
+ return this.entry;
+ }
+
+ @Override
+ public void close() {
+ if (this.iterator != null) {
+ this.iterator.close();
+ }
+ this.closeIterators();
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/TopWorkIteratorProxy.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/TopWorkIteratorProxy.java
new file mode 100644
index 000000000..80b0d8a28
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/TopWorkIteratorProxy.java
@@ -0,0 +1,120 @@
+package com.baidu.hugegraph.store.client;
+
+import com.baidu.hugegraph.store.HgKvEntry;
+import com.baidu.hugegraph.store.HgKvIterator;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author lynn.bond@hotmail.com created on 2021/10/21
+ * @version 0.1.0
+ */
+class TopWorkIteratorProxy implements HgKvIterator {
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private HgKvIterator iterator;
+ private Queue queue;
+ private HgKvEntry entry;
+ private long limit;
+ private int count;
+
+ TopWorkIteratorProxy(List iterators, long limit) {
+ this.queue = new LinkedList<>(iterators);
+ this.limit = limit <= 0 ? Integer.MAX_VALUE : limit;
+ }
+
+ private HgKvIterator getIterator() {
+ if (this.queue.isEmpty()) return null;
+
+ HgKvIterator buf = null;
+
+ while ((buf = this.queue.poll()) != null) {
+ if (buf.hasNext()) {
+ break;
+ }
+ }
+
+ if (buf == null) {
+ return null;
+ }
+
+ this.queue.add(buf);
+
+ return buf;
+ }
+ private void closeIterators() {
+ if (this.queue.isEmpty()) return;
+
+ HgKvIterator buf;
+
+ while ((buf = this.queue.poll()) != null) {
+ buf.close();
+ }
+
+ }
+ private void setIterator() {
+ this.iterator = null;
+ }
+
+ @Override
+ public byte[] key() {
+ if (this.entry != null) {
+ return this.entry.key();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] value() {
+ if (this.entry != null) {
+ return this.entry.value();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] position() {
+ return this.iterator != null ? this.iterator.position() : EMPTY_BYTES;
+ }
+
+ @Override
+ public void seek(byte[] position) {
+ if(this.iterator!=null)this.iterator.seek(position);
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (this.count >= this.limit) {
+ return false;
+ }
+ if (this.iterator == null) {
+ this.iterator = this.getIterator();
+ }
+ if (this.iterator == null) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ @Override
+ public Object next() {
+ if (this.iterator == null) {
+ hasNext();
+ }
+ if (this.iterator == null) {
+ throw new NoSuchElementException();
+ }
+ this.entry = this.iterator.next();
+ this.setIterator();
+ this.count++;
+ return this.entry;
+ }
+
+ @Override
+ public void close() {
+ if(this.iterator!=null)this.iterator.close();
+ this.closeIterators();
+ }
+}
diff --git a/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/AbstractGrpcClient.java b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/AbstractGrpcClient.java
new file mode 100644
index 000000000..fd8090e9d
--- /dev/null
+++ b/hg-store-client/src/main/java/com/baidu/hugegraph/store/client/grpc/AbstractGrpcClient.java
@@ -0,0 +1,126 @@
+package com.baidu.hugegraph.store.client.grpc;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.IntStream;
+
+import com.baidu.hugegraph.store.client.util.HgStoreClientConfig;
+import com.baidu.hugegraph.store.term.HgPair;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.stub.AbstractAsyncStub;
+import io.grpc.stub.AbstractBlockingStub;
+
+/**
+ * @author zhangyingjie
+ * @date 2023/3/28
+ **/
+public abstract class AbstractGrpcClient {
+
+ private static Map channels = new ConcurrentHashMap<>();
+ private static int n = 5;
+ private static int concurrency = 1 << n;
+ private static AtomicLong counter = new AtomicLong(0);
+ private static long limit = Long.MAX_VALUE >> 1;
+ private Map[]> blockingStubs = new ConcurrentHashMap<>();
+ private Map[]> asyncStubs = new ConcurrentHashMap<>();
+ private static HgStoreClientConfig config = HgStoreClientConfig.of();
+
+ public AbstractGrpcClient() {
+
+ }
+
+ public ManagedChannel[] getChannels(String target) {
+ ManagedChannel[] tc;
+ if ((tc = channels.get(target)) == null) {
+ synchronized (channels) {
+ if ((tc = channels.get(target)) == null) {
+ ManagedChannel[] value = new ManagedChannel[concurrency];
+ IntStream.range(0, concurrency).parallel().forEach(i -> value[i] = getManagedChannel(target));
+ channels.put(target, tc = value);
+ }
+ }
+ }
+ return tc;
+ }
+
+ public abstract AbstractBlockingStub getBlockingStub(ManagedChannel channel);
+
+ public AbstractBlockingStub getBlockingStub(String target) {
+ ManagedChannel[] channels = getChannels(target);
+ HgPair